FuzzyOcr-3.6.0/0000755000175000001440000000000011207337751012645 5ustar decoderusersFuzzyOcr-3.6.0/Utils/0000755000175000001440000000000011207335727013746 5ustar decoderusersFuzzyOcr-3.6.0/Utils/README0000644000175000001440000000230311207335640014616 0ustar decoderusersfuzzy-utils If you have chosen to use the second hasing method (i.e. BerkeleyDB), then you also have the following at your disposal: fuzzy-find [--delete] hash|filename This utility searches the DB files for the digest hash (from debug output) and prints out the information stored in the DB file. It is usefull to check how many times an image has matched. Also, with the optional --delete option, you can remove the image from the DB file fuzzy-stats [days] [images] This utility generates basic statistics taken from the DB files regarding matches made [days] ago (0 by default == today) and shows some information of the top [images] (5 by default) fuzzy-cleantmp [hours] If you decide to keep debug information of the work SpamAssassin is doing, tempfiles tend to pile up. This utility can help by removing 'old' files (older than [hours] hours (12 by default)). This can safely be placed in CRON to keep your tempdir manageable TODO: Right now, the names for each DB file is hardcoded. If you change the default settings in FuzzyOcr.cf, you must update these utilities so that they can process the 'right' files. FuzzyOcr-3.6.0/Utils/fuzzy-stats0000644000175000001440000000616311207335640016214 0ustar decoderusers#!/usr/local/bin/perl # # <@LICENSE> # Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to you under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at: # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # use MLDBM qw(DB_File Storable); use POSIX qw(strftime); my %Files = ( db_hash => '/etc/mail/spamassassin/FuzzyOcr.db', db_safe => '/etc/mail/spamassassin/FuzzyOcr.safe.db', ); my %Stats = (); #Days my $diff = shift @ARGV || 0; my $gctr = shift @ARGV || 5; my $time = time; my $days = int($time/86400) - $diff; foreach my $f (keys %Files) { my %DB; my $err = 0; tie %DB, 'MLDBM', $Files{$f} or ++$err; next if $err; my @Top = (); foreach my $k (keys %DB) { my $db = $DB{$k}; $Stats{$f}{'images'}++; $Stats{$f}{'score'} += $db->{score}; if (int($db->{check}/86400) == $days) { $Stats{$f}{'today'}++; $Stats{$f}{'score2'} += $db->{score}; my @basic = split(':',$db->{basic}); my $line; if ($db->{score}) { $line = sprintf "%5d Time(s) -> %8.3f %9d %dx%dx%d" ,$db->{match}+1,$db->{score},@basic; } else { $line = sprintf "%5d Time(s) -> %9d %dx%dx%d" ,$db->{match}+1,@basic; } foreach my $t (qw/fname ctype/) { $line .= sprintf ' %s',$db->{$t} if defined $db->{$t}; } push @Top,$line; } $Stats{$f}{'oldest'} = $db->{input} unless $Stats{$f}{'oldest'}; $Stats{$f}{'oldest'} = $db->{input} if ($Stats{$f}{'oldest'} > $db->{input}); } my $s = $Stats{$f}; next unless $$s{'images'}; my $p1 = sprintf "%6.2f%%",$$s{'today'}/($$s{'images'}/100); my $p2 = sprintf "%12.2f",$$s{'score'}/$$s{'images'} if ($$s{'images'}); my $p3 = sprintf "%12.2f",$$s{'score2'}/$$s{'today'} if ($$s{'today'}); my @stat = stat($Files{$f}); printf "\n<<%s>>\n",$f; printf "File Size : %9d Bytes\n",$stat[7]; printf "File Name : %s\n",$Files{$f}; printf "Oldest Hash : %s\n",scalar(localtime($$s{'oldest'})); printf "Average Score: %s\n",$p2 if ($$s{'score'}); printf "Images in DB : %9d\n",$$s{'images'}; printf "\n%s\n",strftime("%a, %b %d, %Y",localtime($time)); printf "Matched : %9d [%s]\n",$$s{'today'},$p1; printf "Avg. Score: %s\n",$p3 if ($$s{'score2'}); my $count = $gctr; foreach (reverse sort @Top) { printf "%s\n",$_; last if (--$count == 0); } } FuzzyOcr-3.6.0/Utils/fuzzy-cleantmp0000644000175000001440000000277311207335640016664 0ustar decoderusers#!/usr/local/bin/perl # # <@LICENSE> # Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to you under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at: # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # opendir TMP, "/tmp" or die "Cannot read /tmp\n"; my @files = grep {m/spamassassin/} readdir TMP; closedir TMP; my $hours = shift @ARGV || 12; my $limit = time - ($hours * 3600); printf "Removing tempfiles older than %s\n",scalar(localtime($limit)); foreach my $d (@files) { my $df = "/tmp/" . $d; next unless -d $df; my @stat = stat $df; next if $stat[9] > $limit; printf "$d -> %s\n",scalar(localtime($stat[9])); opendir TMP, $df or die "Cannot read $df\n"; my @dfs = readdir TMP; closedir TMP; foreach my $f (@dfs) { next if $f eq '.'; next if $f eq '..'; my $fn = sprintf "%s/%s",$df,$f; unlink $fn; } rmdir $df; } FuzzyOcr-3.6.0/Utils/fuzzy-find0000644000175000001440000002421211207335727015777 0ustar decoderusers#!/usr/local/bin/perl # # <@LICENSE> # Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to you under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at: # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # use Getopt::Long; use DBI; use MLDBM qw(DB_File Storable); my %Files = ( db_hash => '/etc/mail/spamassassin/FuzzyOcr.db', db_safe => '/etc/mail/spamassassin/FuzzyOcr.safe.db', ); my %MySQL = ( db => 'FuzzyOcr' ,hash => 'Hash' ,safe => 'Safe' ,user => 'fuzzyocr' ,pass => 'fuzzyocr' ,host => 'localhost' ,port => 3306 ); # defaults my $cfgfile = "/etc/mail/spamassassin/FuzzyOcr.cf"; my %App; my @bin_utils = qw/pamfile ppmhist jpegtopnm giftopnm pngtopnm bmptopnm/; my $delete = 0; my $verbose = 0; my $learn_ham = 0; my $learn_spam = 0; my $score; GetOptions( 'verbose' => \$verbose, 'delete' => \$delete, 'config=s' => \$cfgfile, 'score=f' => \$score, 'learn-ham' => \$learn_ham, 'learn-spam' => \$learn_spam, ); unless (@ARGV) { print "Usage: fuzzy-find.pl [Options] (imagehash|imagefile) \n"; print "\n"; print "Available options:\n"; print "--config=s Specify location of FuzzyOcr.cf\n"; print " Default: /etc/mail/spamassassin/FuzzyOcr.cf\n"; print "--delete Removes the hash from the database\n"; print "--learn-ham Add the hash as ham to the database\n"; print "--learn-spam Add the hash as spam to the database\n"; print "--score=i Score to use when adding ham/spam\n"; print "--verbose Show more informations\n"; print "\n"; exit 1; } # Setup default score unless (defined $score) { $score = $learn_ham ? 10 : 0; } # Read custom paths from FuzzyOcr.cf my $app_path = q(/usr/local/netpbm/bin:/usr/local/bin:/usr/bin); open CONFIG, "< $cfgfile" or warn "Can't read configuration file, using defaults...\n"; while () { chomp; if ($_ =~ m/^focr_bin_(\w+) (.+)/) { $App{$1} = $2; printf "Found custom path \"$2\" for application \"$1\"\n" if $verbose; } if ($_ =~ m/^focr_path_bin (.+)/) { $app_path = $1; printf "Found new path: \"$1\"\n" if $verbose; } if ($_ =~ m/^focr_enable_image_hashing (\d)/) { $App{hashing_type} = $1; printf "Found DB Hashing\n" if ($verbose and $1 == 2); printf "Found MySQL Hashing\n" if ($verbose and $1 == 3); } if ($_ =~ m/^focr_mysql_(\w+) (.+)/) { $MySQL{$1} = $2; printf "Found MySQL option $1 => '$2'\n" if $verbose; } if ($_ =~ m/^focr_threshold_max_hash (.+)/) { $App{max_hash} = $1; printf "Updated Thresold{max_hash} = $1\n" if $verbose; } } close CONFIG; # make shure we have this threshold set $App{max_hash} = 5 unless defined $App{max_hash}; # search path for bin_util unless already specified in configuration file foreach my $app (@bin_utils) { next if defined $App{$app}; foreach my $d (split(':',$app_path)) { if (-x "$d/$app") { $App{$app} = "$d/$app"; last; } } } sub get_ddb { my %dopts = ( AutoCommit => 1 ); my $dsn = "dbi:mysql:database=".$MySQL{db}; if (defined $MySQL{socket}) { $dsn .= ";mysql_socket=$MySQL{socket}"; } else { $dsn .= ";host=$MySQL{host}"; $dns .= ";port=$MySQL{port}" unless $MySQL{port} == 3306; } printf "Connecting to: $dsn\n" if $verbose; return DBI->connect($dsn,$MySQL{user},$MySQL{pass},\%dopts); } while (@ARGV) { my $file = shift @ARGV; my @data = (); if ($file =~ m/(\d+):(\d+):(\d+):(\d+)/) { push @data, $1,$2,$3,$4; } elsif ($file eq ':::0') { $key = $file; $data[3] = 0; } else { next unless -r $file; } my $key = ''; my $ctype = ''; my $ftype = 0; unless (@data) { my $app; if (($file =~ m/\.jpg$/i) or ($file =~ m/\.jpeg$/i)) { $app = $App{jpegtopnm}; $ctype = "image/jpeg"; $ftype = 2; } elsif ($file =~ m/\.png$/i) { $app = $App{pngtopnm}; $ctype = "image/png"; $ftype = 3; } elsif ($file =~ m/\.bmp$/i) { $ctype = "image/bmp"; $app = $App{bmptopnm}; $ftype = 4; } elsif ($file =~ m/\.tiff?$/i) { $app = $App{tifftopnm}; $ctype = "image/tiff"; $ftype = 5; } elsif ($file =~ m/\.gif$/i) { $app = $App{giftopnm}; $ctype = "image/gif"; $ftype = 1; } elsif ($file =~ m/\.pnm$/i) { $app = '/bin/cat'; $ctype = "image/pnm"; } else { print "Unknown extension given in \"$file\", aborting...\n"; exit 1; } my @hist = `$app $file 2>/dev/null |$App{ppmhist} -noheader -`; my @res = `$app $file 2>/dev/null |$App{pamfile} -`; my ($h,$w) = (0,0); if ($res[0] =~ m/(\d+) by (\d+)/) { $w = $1; $h = $2; printf "Found ($h,$w)\n" if $verbose } my $c = scalar(@hist); my $cnt = 0; printf "Colors: %d\n",$c if $verbose; push @data, (stat($file))[7],$h,$w,$c; foreach (@hist) { $_ =~ s/ +/ /g; my @d = split(' ',$_); $hash .= sprintf("::%d:%d:%d:%d:%d",@d); last if ($cnt++ ge $App{max_hash}); } $key = substr($hash,2); } printf "Img = %9d %dx%dx%d\n",@data; printf "key = <$key>\n" if ($key); if ($learn_spam || $learn_ham) { if ($App{hashing_type} == 2) { my %DB; my $ff = $learn_spam ? 'db_hash' : 'db_safe'; my $dfscore = $learn_spam ? 5 : -5; $score = $score ? $score : $dfscore; tie %DB, 'MLDBM', $Files{$ff} or die "Can't open $ff"; print "Adding key to database...\n"; if (defined $key) { my $dbm = $DB{$key}; $dbm->{fname} = $file; $dbm->{ctype} = $ctype; $dbm->{dinfo} = "Manually added to the database\n"; $dbm->{basic} = join(':', @data); $dbm->{score} = $score; $dbm->{input} = $dbm->{check} = time; $dbm->{match} = $learn_spam ? 0 : 1; $DB{$key} = $dbm; } untie %DB; exit 0; } elsif ($App{hashing_type} == 3) { my $ddb = get_ddb(); if ($ddb) { my $now = time; my $tab = $learn_spam ? 'hash' : 'safe'; my $sql = "INSERT INTO $MySQL{$tab} VALUES ('" . $key . "','" . join(':',@data) . "','" . $file . "','" . $ctype . "','" . $ftype . "','" . ($learn_spam ? 0 : 1) . "','" . $now . "','" . $now . "','" . $score . "','" . "Manually added to the database\n" . "')"; $ddb->do($sql); $ddb->disconnect; } else { printf "Cannot connect to $dsn\n"; exit 1; } exit 0; } } else { if ($App{hashing_type} == 2) { foreach my $ff (keys %Files) { my %DB; tie %DB, 'MLDBM', $Files{$ff} or next; printf "Searching $Files{$ff}...\n"; foreach my $kk (keys %DB) { my $db = $DB{$kk}; my @dd = split('::',$kk); shift @dd if ($dd[0] !~ m/:/); my $dd = join('::',@dd); if ($key eq '') { next unless ($db->{basic} eq join(':',@data)); } else { next unless ($dd eq $key); } printf "%s HASH\n",($delete)?'Removing':'Found'; if ($delete) { delete $DB{$kk}; } else { printf "ImageInfo : %9d:%d:%d:%d\n",split(':',$db->{basic}); printf "Matched : %4d Time(s)\n",$db->{match}; printf "Calc.Score : %9.3f\n",$db->{score}; printf "in DB since: %s\n",scalar(localtime($db->{input})); printf "Last Match : %s\n",scalar(localtime($db->{check})); } } untie %DB; } } elsif ($App{hashing_type} == 3) { my $ddb = get_ddb(); if ($ddb) { foreach my $ff (sort keys %Files) { my $tab = $ff; $tab =~ s/db_//; my $sql; if ($delete) { $sql = "DELETE FROM $MySQL{$tab} WHERE $MySQL{$tab}.key=?"; $ddb->do($sql,undef,$key); } else { $sql = "SELECT * FROM $MySQL{$tab} WHERE $MySQL{$tab}.key=?"; my @data = $ddb->selectrow_array($sql,undef,$key); if (scalar(@data)) { printf "ImageInfo : %9d:%d:%d:%d\n",split(':',$data[1]); printf "Matched : %4d Time(s)\n",$data[5]; printf "Calc.Score : %9.3f\n",$data[8]; printf "in DB since: %s\n",scalar(localtime($data[6])); printf "Last Match : %s\n",scalar(localtime($data[7])); } } } $ddb->disconnect; } } } } FuzzyOcr-3.6.0/FuzzyOcr.preps0000644000175000001440000000127211207335640015510 0ustar decoderusers# This file contains the preprocessors # Do not modify this on your own unless you have read the manual and know what you're doing # Normalizes a PNM preprocessor normalize { command = pnmnorm } # Inverts a PNM preprocessor invert { command = pnminvert } # Converts PPM (Color PNM) to PGM (Greyscale PNM) preprocessor ppmtopgm { command = ppmtopgm } # Converts PAM to PNM preprocessor pamtopnm { command = pamtopnm } # Uses thresholding on the PAM file preprocessor pamthreshold { command = pamthreshold args = -simple -threshold 0.5 } # converts PNM to TIFF (this is used for tesseract) preprocessor maketiff { command = pnmtotiff args = -color -truecolor } FuzzyOcr-3.6.0/INSTALL0000644000175000001440000000017411207337710013673 0ustar decoderusersThe installation manual for the 3.6.x branch is maintained online at: http://fuzzyocr.own-hero.net/wiki/Installation-3.6.x FuzzyOcr-3.6.0/samples/0000755000175000001440000000000011207337604014306 5ustar decoderusersFuzzyOcr-3.6.0/samples/README0000644000175000001440000000677011207335640015176 0ustar decoderusersThese eml files are sample spam emails to test your installation of FuzzyOCR. Use spamassassin -t < samplefile.eml to test :) ATTENTION: If FuzzyOcr does not trigger on one of the messages, then make sure you have the focr_autodisable_score set high enough. Otherwise, if a message gets enough hits by SA, FuzzyOcr will not scan it. This is generally depending on your other SA rules. ocr-gif.eml: Contains a corrupted gif image, additionally I changed the content-type to jpeg, so the output should show: 1.5 FUZZY_OCR_WRONG_CTYPE BODY: Mail contains an image with wrong content-type set Image has format "GIF" but content-type is "image/jpeg" 2.5 FUZZY_OCR_CORRUPT_IMG BODY: Mail contains a corrupted image Corrupt image: GIF-LIB error: Image is defective, decoding aborted. 8.8 FUZZY_OCR BODY: Mail contains an image with common spam text inside Words found: "target" in 1 lines "service" in 1 lines "stock" in 2 lines "price" in 2 lines "company" in 1 lines "recommendation" in 1 lines (12 word occurrences found) ocr-animated.eml: Contains an animated gif. If all deanimation routines are working properly on your system, the output should contain: 6.5 FUZZY_OCR BODY: Mail contains an image with common spam text inside Words found: "price" in 1 lines "company" in 1 lines "alert" in 1 lines "news" in 1 lines ocr-obfuscated.eml: Contains an obfuscated gif image, to test the ocrad-decolorize scansets. If you want to test this scanset, either set the minimal_scanset option to 0 or put the decolorize scanset temporarily at the beginning of the scansets file. The output should be: 5.9 FUZZY_OCR BODY: Mail contains an image with common spam text inside Words found: "target" in 1 lines "profit" in 1 lines "trade" in 1 lines (4.5 word occurrences found) ocr-jpg.eml: Contains a jpeg file. Output should show: 5.9 FUZZY_OCR BODY: Mail contains an image with common spam text inside Words found: "levitra" in 1 lines "viagra" in 2 lines (4.5 word occurrences found) ocr-png.eml: Contains a png file. Output should show: 14 FUZZY_OCR BODY: Mail contains an image with common spam text inside Words found: "buy" in 1 lines "target" in 2 lines "service" in 1 lines "stock" in 1 lines "investor" in 1 lines "price" in 3 lines "company" in 2 lines "trade" in 1 lines "software" in 1 lines "recommendation" in 1 lines "news" in 3 lines (25.5 word occurrences found) FuzzyOcr-3.6.0/samples/ocr-multi.eml0000644000175000001440000006630211207335640016725 0ustar decoderusersFCC: imap://decoder%40own-hero.de@imap.own-hero.net/Sent X-Identity-Key: id2 Message-ID: <45773C1A.3070603@own-hero.net> Date: Wed, 06 Dec 2006 22:54:34 +0100 From: decoder X-Mozilla-Draft-Info: internal/draft; vcard=0; receipt=0; uuencode=0 User-Agent: Thunderbird 1.5.0.8 (X11/20061116) MIME-Version: 1.0 To: blah@blub.com Subject: blubber X-Enigmail-Version: 0.94.1.0 Content-Type: multipart/mixed; boundary="------------040203000101060002010600" This is a multi-part message in MIME format. --------------040203000101060002010600 Content-Type: text/html; charset=ISO-8859-1 Content-Transfer-Encoding: 7bit blubber kekeke --------------040203000101060002010600 Content-Type: image/gif; name="rubblein9.gif" Content-Transfer-Encoding: base64 Content-Disposition: inline; filename="rubblein9.gif" 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 AAA7 --------------040203000101060002010600 Content-Type: image/gif; name="seductive.gif" Content-Transfer-Encoding: base64 Content-Disposition: inline; filename="seductive.gif" R0lGODdhSAJKAYQAAOGjB80uIh51EgCFOm49XCV4S3hw337Q35iB9LOifqm/yqzCnphytKWm cqSvTUgCuZiv+NG1g12zvzoBcGB4YUsGuxczAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA ACwAAAAASAJKAQAF/qAgjmRpnmiqrmzrvnAsz3Rt33iu73zv/8CgcEgsGo/IpHLJbDqfuQZ0 Sq1ar9isdruVcr/gsHhMLpvP6LR6zW673/C4HDuZ2+/4vH6PqvP/gIGCg1R+hIeIiYqLjI2O j5CRkpOUlZaXmJmam5ydnp+goaKjpKWmp6ipqqusra6vsLGys7S1tre4ubq7vL2+v8DBwsPE xcbHyMnKkwHLzmYE0dLT1NXW19jZ2tvc3d7f4OHi1AHj5ufo6errz2Tr7/Dx8vP09fb3+N/t Y/n9/v8AAwocWG+fGIIIEypcyLChOYNhHEqcSLGiRXkQwVzcyLGjR4sZv3wcSbKkSXoh/rmc XMmypUtrKbe8nOkRAE2XMbXc3OkQgM+fNnmWzJlFqNGAQJMCPeqRKBamUOcpnao06kWnV6xq NUe1K9WtErFaAUtWm9ezXssqFFtFrVsCaOOifSuQLRW6VuXq1YvXn90pfYXuHTw48L2/UAy/ JMyYsGKUiHsYmEx5corHJhtrbowZXuQZlSmbsFyCtIjOHDerVo06nabQplHAHjFbQGzSoSXX vm2gdG/fJFpPXE2cuPBxkmBXJhHb9m/ntJ9Dj/7csunmsqVPZ65dBG/g4E8fT1i8fPnx+ihd l84bN/vq791jZ7E8+mgIEEa/D29/BHqk5gV43n/bVLIed/1Z/refd/H9Vt8L7vWHoH658cdg cATeI+CGAmaIjYHwVbidc99daJ+C86VQIna1kZgii9J5GA+HNNIoIzUgUtdcewuOqKCL1Kmw YnfzRajfkf7deE6NTDKpJAE5mlgig1MO+eCISEpJZHfbwZilAE+C0+SYY94YZZchKjehj2n2 eIJyDm75pptYnhDmNmTmmaeHZFCgxIEJNighm0ECmt2EXn6ZIn93VqPno49mWIafSBg6HY8P 7ragiIcGSuGVOTQKF6SkQvrfpEksumadRVgJKhBPliqrrON91oSHs+aaq3C2MjGersAGi1qv S6AW7LHHdgbJlJwohuyzzz627H5q/tLHKR941ajcT9sCMBlQ30Krq2HTIqjqnOa2KIdaXoXr k7tTdeutAeDSO2+87sIr7qx9lXsil0JyWaS6KgJcA7MwhKNcQnA6Khe8ENv7rsT3VjzxxUpV hvG+wNJV7o/nfjnoyNaqWi2bopkoAzeTSdOyy3AaEA1sLFfmzcvSTKwvVRFzS5nP9W5c8c7z hks0x6W+9XFvKKZccsoDw2Akup7qOHV2mS4M88s4E4Bz1zBT03XLX8tc86hAW9xVz0Pby7a8 sAH97dFIJ13W0tCFvELTlu5N56BXaxrwhGGLbTbZZs+cONiKG744ZeKorTbdOoc2Ob1wUxx0 xph3Xne0/mBNO5vegw/8Kn8vbirojwWjUPjrXjcM++w2x874NZwnxfbaFM/du+f48qw5xhp/ DrpVolPJqtRMC2ywogCfzGPez6dIe+K21z7N7WDXrr017Wq+u/BB93z0+cNb/LPx0CL/yHek A9481S3AifWOggIZ8IPXbw957IazRvdkhriypS94mxMaAi8GJ8mlLXcQLJruDsi+SDElEyfb H9ScB6G/aWlVWXsekq4nOwDOrnH+A2DtFMi7CSaQfHL7nQNZWLn1ja94FeTXUWpRrfghTEKW CiHzxGNC2H2vbALEngnj9sCz6Gt8C7yX+Si4IcrlUE9G8UUGodcplUXoh4MD/hMKjfi/MXJP iS3Tmfqo+ELisTF8bbyiHI2zk8gw63T1W1D/ThhA/60wX0bDoWYEOcdCto8mxApCi/gIDxc2 0ZCM6Za8ytNAJhbtjUibSSKTgA9I5mmKL8Th29bnyFC6DXg0PGRLQIRHSkiFc6T05CV/BsUI SlGGblSjBANpy41FjJRPxCSpVmkJTDktDZq6VoVoho2xKRFmmwMkWgjJpClazoHSdKIMR1m+ mLVxZ9ms4SlLKa6VXCJqvhEhaKi1zC1miXX0O9AYVYjEuAETlQ8b5yxjSRxQ9rJtcZGkJUHp OyiCU2K/tKH4hKlDkpyTg+m0mjqpBB/u3HGiKIue/sEso7jHZU9xDyye7/biT8JYUWgj/WdK p5m+azZxpAXF5SPXWC+YLpR9Di0mROW3Kr/Jz2QYPVDqWtfRwxFQoSFF6klNOUOWYrKkNVXo UmnIy5d6LqbfHF44L3lLcn7uIw+lXxdlEMRjiqxg9VHXojj60dh1NZw2XSMVoZrPpcZ1oFrl JxwjuNWVcvWRB7VqIIN5xaboVKyIHaLKqAcq0glVo0G6UOPuikppxnWmTLVkQJ96VXzO1K97 JWdVGfg7g+Y1mpUlrBw5Etazfip+aOopofJoUcgCsTcgvawoEXpKv1KOrnqxa2dnGNimehWl vM1lDFmYUECOlp9TLSdI/g7r2jDSdrGJWqx19cdFBqVNY85Nqs/0adzLlTe04bNnS0+byn7e E7XR3WwcZVkRVpoVtsuL59/AqN/8rke8agyvL3lL4JNWNb7zhWWA12u5WsqSpAzNZFg+gd9z VdRTF3VBMhsr0gYT2LwDTvBmtwph+cbQpQ9OMZkmvAr+/utTErUQELQp4n2OCcGYVbGOjWcr gmHNDDsesV6DTOR9bVIPRU6ykmV55Dws+clQrmCT8RDlKlsZWlO+w5W3zOVSZVnLXQ6zmGv0 ZTuM+cxoLk6Z5ZDmNruZMGuOw5vnTOeuxBkOdc5znu+MZz372c18fsOfB43mQLuB0IgOs6Hb /pDoRl950WxwtKSfDOlIT/rSREYFAjbN6U3rwNOYcHQCElCjUY96KqfG9IZSAeodtFoGnX41 leeYap/Umka3DlCqc21qUqum16oGyilkjQNiv6DVxjbzFU39k1xvyNnFuXWtd+3rxlAbKNDO NrMLTYpXe7rTJYg1CTgtgGS3wNsIsMOoSQBtxrTbPMAGwLvlXW1623rbpD71tPM9b3vHWy7X bna99yJtX//73rw2+MDFPApZk7vc6RYBsiMO6odL3OIqQDcLzH0CjhvB1CIAuQBW02/ixLvg Ab+3vf3N75Xju97/fjnAq13waLd85S6nOcwBHQqHR3wF3/45xEdQ/nGho0DjF8c4scE9bowv ode9JsFm2l1zd7d83yrPOc7pre+bVz3gJVdK1bP+65ur/OsLfzMofH70WKcb6UhPAdx/HnSm D/3uRDf60xMggHWvu+/bPruzmU1twsM87XHputYFrnWoQ53lZIc848OO7YGPXTMpl3zWu454 bnOC7SbQ+NzdDnShG3viTU/9FfzOd9aHXOcKrzzCcX5wyotd4ZkvfOyTovjc89vxW0eLtiNv bZ3LHu27r/PnjX56uhc96RePwejtjm7Sr7712P/760eOdtnzPvDB18u+k59zrCP86rjffNpt /+6Dn3/m3he89y9PZ02APvTknvjbnZ/3/tL3H+94F3cdp3dKoH2AZ4B/132T53iX536oBnuM t3UJZ3iSx3nxp3iJx4Df94Cdt4EeaH7mR3z11wviVnrU53z8p3oB6HQFyHcjEHUv6ILrFoEo d3jlV3kdGIGR54C4xoMcwn4ayHWWB36LN2hEAW6od3cl+H9OgIDYt31QyH3GJ4QQyHW0l4PB dhbDd3u212afYXdg4ISvJ4YxiIMsZ4Hxl4VqmCeVZmkE93hrGId60oZrIId2yGOOsIT7gDQK 0Id+eIfB1ghJ+At+2IctwIcKAIhrqAgO9wqF6IcC8IiGGIkKMAKTqAKP+Cx92BUR0ImKmGiI 4HHHtn+mh4Sk/siEACiKYnCJlMiKhRgDl7iJqvEAD1AcsvgTm/iHSZGJnzhmgkiASUd3Q6d/ 0beCD/d8TAiGaeCKkGiJzegCrCgCApKLtxgX1QgAuliNt3iNvQhlkZBsyBh0SliK+Cd65IiK asCM6liJLxCNI0AY2piI2CiL3NgV1xiPPlGP3bhkltB8qSeOyBh9bqd0+6eCcSCJlYiQlOiM 7IgC7igC1LiNupiP8kiRFomLFXkW95iR9JiR+5hk9sd8qViQ4jiS1UeOAggH7viIzkgCD9mS EBmLHTmPF0mTGFmTNokWGwkUM/mRQbZ2/GeOw0hxz6d/cwd96LiMDQmTk8iMmLiU/jL5jjlp k/g4lfqoFDt5kzWZlT5ZN40gATewhOFIkkQJcShIiudolsYIjGWwkg3ZlG+5lCbglDEpdVV5 lz2pkbxolRxZiLs4kV15LJMAlj5wgkNZjDXAfGm5Bm7pkuzIkisQlXXpmDxZkR0pjxE5K1cZ mI+CCYTZBKpogiz4Bo0JkzIAmZNJmVM5j4mYl5ypaHToCQ/pl9boka8ZZbEJC7fJc7lJC7sJ m75gfTAQmuVICArZiq/IBHvCEpdGDCm5cWwJncYJlQlJnY75jMjZA3IRJluGDMTZdokZnXjg lHS5kKl5njvwE6LiDTr2DEuHkodZd+VIgP44ntZJly9p/po+sJ7f4EkZQXpCWXebVgAFMKAE WqAIQKAGeqAIyqAKymkOGqESOqEUWqEWeqEYWgAISaAbyqEKYKF9mKEZagL8yQ1zZBdgCJBo yaAGuqANyqIJGqEuKqI0WqM2iqEhGqGP6KA5SqE9eqMRmgJVESv+GRkpSpZmGaMPuqQHOqMz CqRQGqVSqqEfqqNV+qM96oc8WqVTSqArMCAr0Z2JdKTxCaFNGqMu6qRK2qVs2qYgyqUMmqVc iqVwSqVueoi/yYa9IpRqqaJmmqZouqZM6qBP6qaGCqQ/eqB06qFx+qFzWqdS+gJ5yiFZJpz5 h6SdhqCCqqmbmqkwWqiHGqoZ/pqojKqoj2qqdkqqkQoDk0oclaaYK3CooCqqtBqqO+qhkDql M9Cqg9GbSSqKtRqswjqswUoDvHoWvmoDxLqszNqsN2oDx/oTyaoDzlqt1nqtB4oDeTqtPoCt 3vqtwqoDgcmtQdCsA5mhswqu6uqgPPCJ5Cp3yigD5rqm6Xqm63qvFeoDcfiu/idxAKCsUVqv hEqvm4qvFLoABsuuP9Cc/HpuzOcTBqkCFjqgZgqjNAqoDeqpD1qwNiqwF7oAIAuyDiqyzHoA B8CgJlsAQoBoDSt9eneSSTqUC6qxf6qkboeuN7uxg/qiA1uxGruxHJuhIouwJFsAISu0IYuw UJqy/geasib7tCarncYDsnPYsjTwnv9YlEX3oi1KsBYroqA6q086swnatQMrpUM7skf7sUpr tG2btG1boUxLoE57ACQQtVI7FVQLFEmrtwvAIXtLIyYAtVDbAniLAofLZ1jbf4srADtLsV5r r2DLsWIrqGMbuW2atBJatDQ6tG8btxM6twVQt3drtyuwACgAskKaFCHLt38LAIHrE7H7E7EL t60Lu66bu+axAon7Ar1bAr+7Zo17mOH2c0CbqRgruTg7oZV7tj0ba4cKt2pro5zLoNUboaJL uiMQvCMAtyWQtCpAu7cLu68ru+U7u+Zbvn5Lvq87u+jLGL5ruj3AvV/W/ohFV5DFOwI7q7w8 278XGrZBq6YyGrT+C6Wae6DXW6FrG6EJ7KDZe7KES78CoLqoq7oiYMEWvLrkK766u8GsO77r e7vo+75oQQMSjLgmGwAqvMJPGwApvMLNEGdJeKkAiJjKC7lfy6QCC8ASmrODisM/XLFRSrRx 28AKDLoLLLcn27QQLL8sQMHfi7rdK8XhW7vtu7ck7MHrK7vmu8VeUbgiELVP6wIRHMZ2C7Uw rMIvzMIHoMYvTLhuHMMCcMJOoYf4d8ci8KkeC7TVCr3H67wGTLRua72gi7QMXMjYu8R028Qv AL4kkMETTMUq4L5Ui8Xq+8FUMcKXzMF2hree/vzJhuvE2/vGbQzDa+zCpRzHa5zCp0zHkJaw sEzISTzI1IvIRszEi7zIMOC9FyzJkJwCqpvJV9wV71vMm9zFSVG6ypy4dJy4bJzGadzKqYzK 0MzK07zG0xrL2kygSCy9hPzN3IzItGyhUMvEMuDIkPzLqSvFXMzJWazJW3zJe5sCzHzGTtzM dlvN06zPpnzNbRzB/+zP0Nyb21zQSMu53jzOt0zOotwCFUzFGCzJk+zLw8zJSkHJ8WzFvHvP 9ly6A/DRIB3SH33KzwzNJV3ScPzM0mzSKkyHBv3SFrrQCHzAQBoDUJzOIWsCv2y7U4zRXqzF mMy+UxzKZlzUoyzS/kg9ACab1Ett0hHczwG9yqTsxvts0q8M01gNrufsyI8s0ZGszuF70fIM t8iMyd071GQ8xkZtxknd1ki91G7N0k7dwlId0HKdxoaW1XqNrTTg1afr1ywg1vC7BG5d2IZt 2HcdzdFc1Yl9Z0A6kAS815LNoGGgGVBw2Jid2W1910+d2Cy9ZlK6x5O9pTUKpx2Ko7lKoWMg F1eg2a792iLt2bJt1VkW2p36s20q2oaqqhN6q7x9ob8toWVAFVsA28Z93LOd3GIhnCZg24CM w7hdo7rtpsHdqBqaqqkN3Nkt3EAmBsf93d+d3I1dDHYMnohZAs5NoV0bqH9MsOstxPy7/tvb bd2m7ajVTdoiygrgvd/ILd6fLQyDCK+q58fJO7GWm7OXe6Y2y977q+CRDaX3jav1faXzbd35 LQAhbQr8veH97d8r7J3iyacQ178eW+Bce9s3HLnNK6oRLuGp3eItTqBIreEcXuOv7eEwTN7i OZL4R+IP7uMK3uBk6+CeOt1tGuMSLqEwXuEMOuOlYONQfuM4DuCqaI7Qa+LqfeBAXKh+3OBe PqxIft0huqioTaNOTgpRnuaajeNy/Av3W4Iwm3dA/r8/XsArfuL7a+S26qh22udhbuYiTeNq PuiI7eFU3q/BmHcMDt+06sN/7ODPy+JM7uKNiuRIfuajQOia/l7YUw4MHjfDlxrket6xmPvY dU6sk36omC4Km97qSc3muRDgbRev+luggBysjj7a4LrqoeDqvh7SsI4L5Q2wnDrqun7sDsrr oPDrzD4AwU4UyC7Zfw7oGf7kzf7rz24LAxmejhvtyzrtfk6q4B6hyv4J147t2U4Lzxmx/eft qK6qwZ2jhbil497kgW7t597qbN7S2n6OYime9sro7g7hWkrv2U3mpVrvMn7vaJ7vm77vH14L Ig7ZxZtuQe7jEHrgA++jdSrvuZqocmrhUFrunuDwmg7xOa7uzP1/4Gjxj8vgmqrHG6/k9S3y pSryCA+kJN8JJj/oKI/Xs6CH217D/u3+8kE8wDNP8zYP8pAa8qgapTvPCT2f5j8/0LIwlgMO jJ7Gv2b75UlvpUtf82B/830+8gyf6VNv41VP27CAesRI9NHH9Qsu8F+v9E9/87xN5gpfAFG/ CWnP4Wsv17Fg5fgbkEMn916f+O7O9GQv7rdKpXvP92fP6n8P3oE/3q6w7k1nlCXe5Xxc95JY 6WIvopEv+dXe8JUv5ZeP+c6AoVhu7NFe+mwqAqeP9qmf2auv3M+As9Fd95Ot37fP6blv6K3v +8av2qsQ/K8+/Pte/Mf//JSd/MrP/Gvv/NAP/cD/99Sf+8sg2bB//Nl/7ts//m1eCkOPA9YK +99/o6Gv/s3hr+/kH//8PmyLWQPp/+C63ftTuqgIad+Pb/cgUBSKIponmpoC27ovHMszXds3 ntMD3/s/MPgLEIvGIzKpXDKbzqQuKp1SqzkEwoW1tlTeLxiMDRfGKSwCZV6n0WQwCV4yxelz Un2Uz+vx78ILiYsgV6HhoZSQYtBTo+MjZCQRImWlZc1WSybXX+eY24mbmQjaZ2maGiqpalkb W+ofXwofbUndrZ+e3a4XHl4LIYtgsADx5TGyzGKPZLPzM3RA8jQ11ekmS2kUaWv3W+kq6iib 6rg4ayjraPe6+bqcL0rtSfxuPW5nXbGCMD8wPzFj1QZSimbwIMJIBBcy1KLt/kWmTac0oRGw ip04jCZetXOVzssrFR0/jtyILt8cEbV82UqpKw7MOy7D6Ntn81+/nA13ckno8yfQSTyHJouY haJDARKzGL1oyqnHjiNLtjp1USS6kFQ79XK5co/Xli9lohRxM6C/fQKJsq0R9C3cZ23nHlpK 8Rq2bEf1auQYFe9Udec+ejtzEtzVxFxVzOOFz57Mx32+sEyLdlBauppjxO3s+cnm0FKwGYWR V+le1H0HP31X2Bu5xKC0WhUjmDCZxirDQqYndjdZXoznnM18WTRyAZ+XMz+S/PkM0nuXnpa+ GirscqBkPw3n0fviP4hzs5TH2848sMF3UyZu87hO/uiam9NfLv/+lYd2m17vX9V1eAEKiNuA 7Ak3loG6gdWeWcXF9yB+RNU3YWcRWqjDRHptQUZrJxX4IYghBljPG+UxCAhaAq114UIUuhgU izFyIiKNNdp4I459/ILDijJS8yKQPvk4pA45GnkkkkmqQOR9QTppEJNR0qAklVVa+aGUzz25 pVxZesnClWGKOeaSX4bGJZoKmZklmW26WeWam6U5ZyNxSvkmnnneaCdddPrZBJ9E6jkooQMG 2tafiUJxqIyFOvooGYxKqCilQkl6IaSZarrCpTtV+mmnFm466qOhfnoqc6FGSCqrg5qKKqxx qYpfq7W+2WmsucI1q3y2/vo6Jq66Ciskr8/9eqyVwQ67bDRWEPAstNFKC22x2yB7LZLKMrut JDhM+y240lZbJLbl4qgtt+nWGUO47br77Lg5mDtvjZeqe+8jAry7777x4kAvwCDaiy/BS/B7 8LtmHnCACwsXEjDEAg5cMMEIW8yvwgy34PCMEXusAgMpTExxuhebnDAivgzFMQssV/ExzCeE LLIOC2vcsMtnTrgwyQlFu/DJQUNbWWYzsCRDj9S4nPMUBS682NMx/2Hz1AeA7IUUTAugddY2 F7TzAWny/OS3QAsdNAkE4EQ0ThC6TZDDcWts883yDhh1J3jjSPcJT1Odo95vBP7F4GB0HQPX /jXPXbcVLo79CM90G0H345BUPqG7Zp9tctprGwdQ0UiHDjfDcm+9eA1LWy0C5WBQvnoYr6PA NxmtmxA13n/jzjfsAhbueu+s8257pFFonfgLdMPAMfI6ACU5E5FfHgD0RdhMxNiVT//E9tZf DxQBlENrc/gHbP6z+XSH23lOlyXd9k6mK78x48nXvfvtVP+dP9TBF4A/8Pj3v94BUHi5wx/t 8qc74g2wb7AL3AGFp4IENmh586Mf4uqXwZYxrnkWZJnqpNc961EvbI/LnglLqMIShm2F2Guh 9lp4hBEmIYYq/J73XtgEEcrwhTwbn/meBTSzke9d6hNiEJFYviBq/k5abLtJ+0YHg/cl43VW 9NoM5Oe/AS7Qgf2bHQG3KMEJhnGMBnxgGFcXQTMOTm9r9EIBBai3DXIQZ3SkgersmAPmoY5+ LNThEqR3wx5KTpA2dKELu/e6HRLShCjMISQD+UhANhF9Taxk2ZioSfSVb1/sw8zRoLijQEix GliknOJOd7ozMvCNVQOjF+EoRjeqMY1ojGXsbglLATbQgbaDYBkrmMX7adCDeTzdBfFITFX6 kYYzdOQgrzhIRKJwkYBkZPSgKUhIHlKSNUxiJ5f4Ok6265LpA+cQwbk+BaiNlKOEoijh15A8 glCDGJRbL8+Iy98RLni07CdA8/lPBuYT/ozEa2MwC/rPgnKReBlEJQYtaINj1hEH9CQmIrFp yB7qcKOTgyFHP/pNkXrTo9xsJDaRcMVwItGcmUPnOTmJyW99sm3BgM8wSskWiA5Tdgfcn0Br KTih9pKfbLQlLhsa0F0eNQULVSgaieo3MQLCfnqsqFUn2seI3uCiOMtoNqeZyOttFKQkHasS rFlSbaKUkiFVaUhZSs4lhrOI4XIpXtUJrprG56aW+ZxOL8RHBVqNgrQ0qkGRWjsKhkd2vNzn GiPrSqX+VJf5lCgHb5ZMZNrTfkzzoB7rmVmwrnWsZGVrNOGKw4RIs5ssfCtciyAtzRGRfLWN 6UuVqFvb6pWm/uyc4uf+8c5D5TKpyHrq74bnS39OVZ93o+BDS9fBZRrCdMPM7HQLCduRbpO7 0Ezran+yzUlec6TgDQC4xLevmabXri2V68FwBp9iSa2fjLUSYgM0BYrud7rKtOh2G+FMyJk1 KAN2BA3X29tMng+IJruqv1wQs/y6iZ8UppnxqEuFnIG2qwGO7VmjQV5d8Yu90zJxgzEW4RoM 9UgXDtCLldpYK34oxpzKMIQVd0G5ZfeeHC5wWEP8zAOD1YYiRDCRnfC9x7F0nOJEsRLdK05L DhGIC5Yp0OinWel2VlJOZa6RGAvUGd+XjGOcKlUZuliqIpaW/VUlHzuM1czOmZnI/pxzd8Fb vSOflHshNfKIU/rR6inZrA6WK22vPNvaHprR7z10lG+LxKuekphe6/I8rWiFLz9Xf8VlKIXR nNBPS7CLsjSzYZlb2Ki6Us521GKd/wthitI6vN4ctFuFPOTVAlrX5w0xkVFIThNDGdKdzKux Ec1oc3L1mPXENE9cPQNOm6ACFSjj/n4awMci9LBNbTH/nspUg377zAWMo7TryGMNp86/XLVz rYPNUUCr9dbA/m55gxxJy4F0rk7WrRFh+mTeJtulVoZps6krWuT8mLM3MCCo02jux5qZ22AO 6qnBXepRL1fckDXuxPPX3yu+DsBZxfOWKY1vfZc3zwL+/jNKXctyH9ram8pub7LvKnD2qneu ymY2Vp2dcobXr9I4w6JFdndxMzZwstRmurjjCPKAonuWVs84VFlZ9ZFjF9oy4KOdw77woAPZ 3i0H8oC3V01qfnjf5i10ox0NcLlncpNzxy3OjX3ESZNd5UgXzWftuXCPR72WYyajY6FOYzWH HHitvnrFnz7QhCo9x19f5ti1CvaIlrzWbgdxnk9IaLPjOvRtV6vMz2pOvP+7pYo+diV7/m8n rx7hnVe419sSeA9z0LiFZ/xSs07x4RPWdxwnvpodq/SgSvzZub/83xFF4BEnmUv1BjF8U3w+ g+cd4NHaME9Ds/voVtr3o1b6/uHHTXhd2hhwkB/qqvWJOzD6XPv2vz/+869/nUt5/ydrvdC8 2btpxvidHDMVVWVVnfBh3QISVpqNSfuFiOz4HwVWoAVeIAZmYP6B32YRYNEV05ZpDMRFoNY5 TfrV14dooAquIAu2oAviX6C4mvJwDArWoAi8IA7moA7u4AtWS4fRSJs9YLkkXpjwoBEeIRIm 4dn4IAjiDIwtHQNGjNNRyf5hUrEpIRZmoRZ+34q9WwQCE7aQoMVVSdRUoV5d4RamoRryoJ3E m2eVH1ckHpp9mRBWWB1uG9MhSRkGnL/tXXv5oQVaIRquISEeYRuy2/EQExfljarlYcSVGSPG YQKJ/qHiFd9iLeJyaZ2CDVsSJdoZvt7Z8FxvDWL2FaIpZuAhwhm7eaHUBV8DNmAQphodLh0A fWEwtSIdftsabWI6MVjOXaHBpZM6kWIp6twpXkz/bR8o1h8FpqJ1xZrYHV/kVWJSxdjkTSJR AV9zPaEXedzTNd0trg4v4pYVMSMwChxd1VXPPdqibQ4pEqMvmuEmHowontgyap8zSpflRePU feMrAhMkIh8sZmNiPVc3SmM1xp8crQ7vwRorYla7hZaGcY3atZ33wByBiZhFMsE85taiCWL3 5Zz/HWLJDWBFyeIlgqP54aEsoSQ1JtcJapwCsuQ2hpyH3Z6WWd7m3REz/tXa5b2dnw1azT0P 5TRDib3e7NmdSGYfPC5hKsJb+GHXKglkQS6g8iEk1v2eLipkP3ZcOKZkyEmWVpHdM4adlnWZ 0KncT4LYy7FloTXS6JHeRc7b9RzlRyaaz3FfO+7lBXbh5XXl3hDUN06W1B0UQQYk/NUhco1Z B1ZXVO7R4mwVVK7lM2VkZSLZvh1YRV6TsHVkkynlwOmlOd5jivmlDNQKEdZiTDKVN0KKfFya ZA4eRrllodGmoFXf5/Wa93jmXoomX/6m91WgacYAvSAmCsbJjhXlXGLmZbblXMqbW3ZXMf5m OcIXXi4lSGLgcMKADdbgrEBDvQUaUDZnkFHf/ncFZ/cFo92to0e64Ha+QHce53ca2FA2Z+rp WVuJHnrWnVLaFSCGJB9q53t2gSTGp6/wCpBY0/VJwuj9Jz0SnP015f0NKIFGooHWSrH0jMEc owZSKJgU6IW2SoZqaBJwaIeuiaa9TIGupkGOmz9yo7lUC4kigYmiIoquIrlMkEqamoy1KGBS oiMeCyVUhnwYBNEsR2UUgS8YAQkQwbOkTY02443O2t/pIw3KoqgdZFMhZmreoQN6qZVUBnqY CFfYQCgZzV/JExXFANs8kQ0cQZMqqQIEQJwSQZzWqZwy6ZxGAtHsaZ7+aZ3iAXoRAJRG6f4h 50RuFaydW/yl2mIS/uQ0blwjjqHjJdaFCeaByIKmiilwEMdx+BUNfCpgBVeojiqajtKS2umd Nqmg0umqIkGruqqqpqqewqqfwqmf4umqQmmhGuoG3ihPpeW6xVJzOeriAV8UYiIYUiUDtiZr ipEszMJMpAdZqIXn6ACoPojKyBObmmq3Xus+zCpLuGqSyiquvqq5piu53qq61qqquqsvPCk7 +ar+IWr0XZG6cdniFSvt1OSLsiQ15iERBh+Q/k60mgfCjqlvqIU/5BS2nik8OSw8iQ4ojY4x jJKssuqcamzG7mm5piq6vqu56iq7/qm6riqhslOv0qv9ISrKXZ4qwiQ4zmG5WaP/aGWy/vrj wLZkQHKqbyRspy7stkosj6SptjbscInO0RCp26BFxz4tx7Yr1HrsrUatyErt1ZKsqqYs17Is DE7py56klUrXQqqkfTlrxs1kwCIrVQYhYP4s3I6pH9TCe4COKCWNqGIGt55qtpIScGHG1Aau 1HJsyD6tyeKpu54s1crrygLofnqty7Ii0sFaQ4HpK52AAziA41nWP2LqYGLlUd3hpppHLuiC HdQt6u6t3toUqU4smurEWqjI5ygu7Q4u1Rau1aYr4h5u1S4u4wZc7CWjhCJh5ELjv1yJ5s4Y sXrummUb82bihY0u3EqGHhQH0bru6t5t9q6p9sZu6Dit1mqt/u3KKdXWap+aLK7Ca67Oa8qy bzmNIvwOrxF6qEWEaJvohoEIR0wI7V8hreoK13ARwnyVasV+KygBbvj2rrgKaqDi7sYq8NWS b6zSqqtGS+M2mPzOr4far5v47IGYLnvgw932L/fyrd/eQIowbff6b7jmqfgqgfg2cATLMDR4 rQVuBhfSBQfXSmPUQ8QGViWUsBSc6bayQGeUa+0ihA0LJ0+4y2bscMT4ZcUssZROw4NpBhRD jGniCxVX8SGUJhZnMcAM57108UhWwaGGsRjPy3aqixmnsQ2cqA6vMRuTccm88a++AA4+MR3H aBtzCx4HcjvNcR9jy4ACsiC/MR8X/vK1UOi2JLIiqzEjC6kjLwskm/EiT/Kv0K8lXzIVZ7Im 2wr9KoewePInS3IoY+goD4sp2zAopzKrjLIRk1grs+wrw/KoyPIsx0ot2zIq43Iu6zIpw0ov 0+stA3OmCPMun0ox++oxI3OpDIQFWECW8HIz1+gzQ3OhKLMLoMo1Y/Mva3M0c/MyK8o3m2g2 i7OekHM3f8o5H2M6qzOesPMLVMo7n2I8y7Ob0HM9U8o9F2I+6zOZ8DMMmPM/r2FAC7SYEHRB J8pBq2FCK/SVMDRn+MlDp2FESzScUHRFp8lFb2FGa7SScLQM0MlHZ2FIi3S2kHRJo8lJY2FK q7SRsDQNwbj0SxNvOMs0sNC0W5DNTWswIev0PvP0mzrJT7NhTgv1RBM1DgDJUe9gTCt1vTC1 81DIU+dgVEu1iFD1FNTHVe9xUmv1SHN1FTDHV7tnWIv1SpN1T8BIC5w1C2a1WhcIW19Ct9QA XKugXM+1xNQ1fuS1jfq1YA+2FAB2XxI2Yic2Xhu2Fyu2Yz82Y5/xY0+2Y0d2vVI2Zie2ZX9t Zne2YG92y3q2aNc1aIPxaJ82VZf2+aA2a6e2ar82bMe2bHdxCAAAOw== --------------040203000101060002010600-- FuzzyOcr-3.6.0/samples/ocr-jpg.eml0000644000175000001440000006556211207335640016362 0ustar decoderusersX-Mozilla-Status: 0001 X-Mozilla-Status2: 00000000 Received: from [58.186.156.15] (helo=localhost) by mx19.web.de with smtp (WEB.DE 4.107 #114) id 1G8oLr-0001kH-00 for christian_holler@web.de; Fri, 04 Aug 2006 03:19:48 +0200 Message-ID: <000001c6b760$e0a08f00$0100007f@localhost> From: "Collin Cox" To: Subject: Hello Date: Fri, 04 Aug 2006 08:23:04 -0900 MIME-Version: 1.0 Content-Type: multipart/related; boundary="----=_NextPart_000_0001_01C6B760.E0A08F00" X-Priority: 3 (Normal) X-MSMail-Priority: Normal X-Mailer: Microsoft Outlook, Build 10.0.3416 Importance: Normal X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2800.1506 Sender: proftechn@noeldrennan.net This is a multi-part message in MIME format. ------=_NextPart_000_0001_01C6B760.E0A08F00 Content-Type: multipart/alternative; boundary="----=_NextPart_001_000E_01C6B760.E0A08F00" ------=_NextPart_001_000E_01C6B760.E0A08F00 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Langdon looked again at the fax an ancient myth confirmed in black and white. The implications were frightening. He gazed absently through the bay window. The first hint of dawn was sifting through the birch trees in his backyard, but the view looked somehow different this morning. As an odd combination of fear and exhilaration settled over him, Langdon knew he had no choice The man led Langdon the length of the hangar. They rounded the corner onto the runway. ------=_NextPart_001_000E_01C6B760.E0A08F00 Content-Type: text/html; charset="us-ascii" Content-Transfer-Encoding: quoted-printable ------=_NextPart_001_000E_01C6B760.E0A08F00-- ------=_NextPart_000_0001_01C6B760.E0A08F00 Content-Type: image/jpeg; name="image001.jpg" Content-Transfer-Encoding: base64 Content-ID: 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 IQgBCEIAQhCAEIQgBCEIB//Z ------=_NextPart_000_0001_01C6B760.E0A08F00-- FuzzyOcr-3.6.0/samples/ocr-obfuscated.eml0000644000175000001440000006012111207335640017703 0ustar decoderusersReturn-path: Envelope-to: censored@not-disclosed.net Received: from s01060016b6d825ef.ed.shawcable.net ([68.149.250.56]) by mail.not-disclosed.net with smtp (Exim 4.60) (envelope-from ) id 1Gqwpf-0001Jh-QK for censored@not-disclosed.net; Sun, 03 Dec 2006 19:17:07 +0000 Received: from bguozv ([68.149.174.147]) by S01060016b6d825ef.ed.shawcable.net (8.13.4/8.13.4) with SMTP id kB3JHTMe030231; Sun, 3 Dec 2006 12:17:29 -0700 Message-ID: <000801c7170f$95f35910$93ae9544@bguozv> From: "Brandon Elsie" To: Subject: People don't search on single keywords alone, unless they are looking for a name brand or high profile site that's well known through other avenues of advertising and marketing. Date: Sun, 3 Dec 2006 12:10:52 -0700 MIME-Version: 1.0 Content-Type: multipart/related; type="multipart/alternative"; boundary="----=_NextPart_000_0004_01C716D4.E9898490" X-Priority: 3 X-MSMail-Priority: Normal X-Mailer: Microsoft Outlook Express 6.00.2800.1807 X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2800.1807 This is a multi-part message in MIME format. ------=_NextPart_000_0004_01C716D4.E9898490 Content-Type: multipart/alternative; boundary="----=_NextPart_001_0005_01C716D4.E98C43B0" ------=_NextPart_001_0005_01C716D4.E98C43B0 Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: quoted-printable We are Microsoft Certified Partners and IBM e-Business Solution = Providers. htm' or whatever page extension you're using, . Aside from major editorial review differences, there are many minor = things as well. Please go through our profile below, reviews on = Guru. I look forward to working with you and making your Pay-Per-Click = program a success. I've included a complete break down of dates, price = and what you can expect along with a few recent clients of mine you = can test out. I have removed the company detail and replaced it by = XXXXX. The Project Scope will be adjusted to reflect the price change if = the project is awarded. At a minimum you can see what your expectations should be if anyone = asks. how to pitch clients by using Elance. PPC is not just about traffic, it is about driving targeted = customers to your website. XXXXX provides the research, implementation, delivery and most = important of all, the management and analysis of your entire online = enterprise - maximizing your return on investment. Results will begin to show from the second month onwards. Particularly target resources related to perfume, luxury accessories = and personal care. I have experience in bidding and can give you a good estimate of = what you would need to spend to achieve results. This is far less than what I normal charge, but I want to prove to you = that PPC will work for you and any business for that matter. Please = note that this bid is subject to change when more details about your = project becomes available. During that time we will build your search = engine presence. Just targeting the keyword 'cats' is too broad and = competitive to bring you any real results from people who might contact = you to make a purchase. You're halfway there to getting more targeted = traffic now. We offer you a money back guarantee- if after the first two months, = if your site does not show appreciable progress, we will refund your = advance. Aside from major editorial review differences, there are = many minor things as well. Kindly see our feedback. I have removed the company detail and replaced it by XXXXX. Study = page titles, keywords, description and content of every page of your = site and then modify them in relation to the keywords you want to have = the site promoted on. so the website can be tweaked to improve = performance and conversions. Submit your site to search engines, = directories, yellow pages, blogs, link exchanges and other = resources. It can make the difference in generating the greatest amount = of targeted traffic to your site or just getting more hits for related = queries. The Project Scope will be adjusted to reflect the price change if the = project is awarded. Study page titles, keywords, description and content of every page of = your site and then modify them in relation to the keywords you want to = have the site promoted on. ------=_NextPart_001_0005_01C716D4.E98C43B0 Content-Type: text/html; charset="iso-8859-1" Content-Transfer-Encoding: quoted-printable
3D"panicky"
We are Microsoft Certified Partners and = IBM=20 e-Business Solution Providers. htm' or whatever page extension = you're using,=20
Aside from major editorial review = differences,=20 there are many minor things as well. Please go through our profile = below, =20 reviews on Guru.
I look forward to working with you = and making=20 your Pay-Per-Click program a success. I've included a complete break = down of dates,=20 price and what you can expect along with a few recent clients of = mine you can=20 test out. I have removed the company detail and replaced it by = XXXXX. The=20 Project Scope will be adjusted to reflect the price change if the = project is=20 awarded.
At a minimum you can see what your = expectations =20 should be if anyone asks. how to pitch clients by using = Elance.
PPC is not just about traffic, it is = about driving =20 targeted customers to your website.
XXXXX provides the research, = implementation,=20 delivery and most important of all, the management and analysis of = your entire=20 online enterprise - maximizing your return on = investment.
Results will begin to show from the = second=20 month onwards.
Particularly target resources related = to =20 perfume, luxury accessories and personal care.
I have experience in bidding and = can give you a=20 good estimate of what you would need to spend to achieve = results.
This is far less than what I normal = charge, but I=20 want to prove to you that PPC will work for you and any business for = that=20 matter. Please note that this bid is subject to change when more = details about=20 your project becomes available. During that time we will build your = search engine =20 presence. Just targeting the keyword 'cats' is too broad and = competitive to bring=20 you any real results from people who might contact you to make a = purchase. You're=20 halfway there to getting more targeted traffic now.
We offer you a money back guarantee- if = after the=20 first two months, if your site does not show appreciable progress, = we will=20 refund your advance. Aside from major editorial review = differences, there=20 are many minor things as well. Kindly see our feedback.
I have removed the company detail and = replaced=20 it by XXXXX. Study page titles, keywords, description and content of = every page of =20 your site and then modify them in relation to the keywords you want to = have =20 the site promoted on. so the website can be tweaked to improve = performance and=20 conversions. Submit your site to search engines, directories, yellow = pages, blogs, =20 link exchanges and other resources. It can make the difference in = generating the=20 greatest amount of targeted traffic to your site or just getting more = hits for=20 related queries.
The Project Scope will be adjusted to = reflect the=20 price change if the project is awarded.
Study page titles, keywords, = description and=20 content of every page of your site and then modify them in relation = to the=20 keywords you want to have the site promoted on. =
------=_NextPart_001_0005_01C716D4.E98C43B0-- ------=_NextPart_000_0004_01C716D4.E9898490 Content-Type: image/gif; name="know.gif" Content-Transfer-Encoding: base64 Content-ID: <000301c7170f$95e59d70$93ae9544@bguozv> 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 CAAAOw== ------=_NextPart_000_0004_01C716D4.E9898490-- FuzzyOcr-3.6.0/samples/ocr-gif.eml0000644000175000001440000003735411207335640016345 0ustar decoderusersReturn-Path: X-Original-To: decoder@own-hero.net Delivered-To: decoder@mindfields.own-hero.net Received: from mellox (pD9E2D1ED.dip.t-dialin.net [217.226.209.237]) by mindfields.own-hero.net (Postfix) with ESMTP id 3BA7A120C1AC for ; Tue, 8 Aug 2006 10:04:01 +0200 (CEST) Resent-From: Sascha Just Resent-To: Christian Holler Resent-Date: Tue, 8 Aug 2006 02:04:00 -0600 Resent-Message-ID: <200608081004.00363.M7zmendelian@alexalvarez.com> X-Original-To: methos@mindfields.own-hero.net Delivered-To: methos@mindfields.own-hero.net Received: by mindfields.own-hero.net (Postfix, from userid 500) id 5C9B812080C2; Tue, 8 Aug 2006 02:22:37 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.1.3-gr0 (2006-06-01) on mindfields.own-hero.net X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=HTML_MESSAGE autolearn=disabled version=3.1.3-gr0 X-Spam-Report: * 0.0 HTML_MESSAGE BODY: HTML included in message Received: from fmmailgate03.web.de (fmmailgate03.web.de [217.72.192.234]) by mindfields.own-hero.net (Postfix) with ESMTP id 0A142120C1AC for ; Tue, 8 Aug 2006 02:21:20 +0200 (CEST) Received: from mx30.web.de (mx30.dlan.cinetic.de [172.20.6.145]) by fmmailgate03.web.de (Postfix) with ESMTP id ED4F9FC29FF for ; Tue, 8 Aug 2006 02:21:19 +0200 (CEST) Received: from [61.64.147.123] (helo=61-64-147-123-adsl-kao.dynamic.so-net.net.tw) by mx30.web.de with smtp (WEB.DE 4.107 #114) id 1GAFL2-0007C4-00; Tue, 08 Aug 2006 02:20:55 +0200 X-MID: Date: Mon, 07 Aug 2006 19:20:44 -0600 Message-Id: From: Clifton Ballard To: naraya_a@web.de Subject: To take on supplier MIME-Version: 1.0 Content-Type: multipart/related; boundary="----=_NextPart_000_00BD_01C5163C.78C70EB0" X-WEBDE-FORWARD: narayan@web.de -> web.de@nmg.own-hero.de X-UID: 3354 X-Length: 15790 This is a multi-part message in MIME format. ------=_NextPart_000_00BD_01C5163C.78C70EB0 Content-Type: multipart/alternative; boundary="----=_NextPart_001_00A0_01C5042E.12A32EA0" ------=_NextPart_001_00A0_01C5042E.12A32EA0 Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7Bit with a noiseless step, when we were close to them, addressed brains against - against mantelpieces, said my aunt; an idea which run up and down stairs for me, all day long. You never sit and again in the old country. Do not frown, Micawber. I do not now ------=_NextPart_001_00A0_01C5042E.12A32EA0 Content-Type: text/html; charset=us-ascii Content-Transfer-Encoding: 7Bit
Of the pair of hired post-horses being ready, and of Doras going
Put my meaning into any words you like, said I. You know what know; far from that. - but if you will sometimes think - just to
never should have been got into my present state if I hadnt come in my memory, pervaded it again. When dinner was done, Mr.
No, no. please. cried Dora, with a kiss, dont be a naughty Blue morning, when she requested an immediate settlement of the same,
have not known my partner, Mr. jorkins, as long as I have. Nothing Anywhere. Im a going to seek my niece through the wureld. Im
thats lived along with her and had her for their all in all, these is not in Traddless way. He is perfectly good-humoured respecting
he cherished an artistic admiration of their style of composition, being mentioned, I recognized it, however, and said as much.
finishing touch to that renunciation of mankind in which she had gracious to Peggotty, except when I inadvertently called her by
of him never wandering in that better mind of his to which stimulant, having little room in his system for any other article
finding himself as comfortable as he expected, or being a little perfect country gentleman to follow lustily with the same cry.
say as much for her bonnet and resumed her seat composedly. solicitude; and my poor mother herself could not have loved me
with us. Who knows when we may meet again, else? Come. Say the avoid the subject. All I desire, Mr. Copperfield, is, that it
she was so much disturbed in mind as to find it necessary to open Still, resumed Miss Murdstone, I found no proof until last
Yes. she said. I beg and pray that no one will leave the room. I cannot do with ampial satisfaction to my own feelings. But, in
every morning, took away our bread; and also how he himself had rest - and touched, on the horizon, with a strip of silvery light
said Mr. Chillip; but she is quite a shadow now. Would it be certain. Dont mistrust me. Our wants are not many. If I rent
slumbering echoes in the caverns of Memory awakened; what a kind and all gentlemen with anything bashful in their appearance, and
to be useful to the family; and that if I got on in the world, and I hope its enough, child, said my aunt. If there had been more
------=_NextPart_001_00A0_01C5042E.12A32EA0-- ------=_NextPart_000_00BD_01C5163C.78C70EB0 Content-Type: image/jpeg; name="sbillet" Content-Transfer-Encoding: base64 Content-ID: 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 ------=_NextPart_000_00BD_01C5163C.78C70EB0-- FuzzyOcr-3.6.0/samples/ocr-animated.eml0000644000175000001440000003250111207335640017347 0ustar decoderusersX-Account-Key: account3 Return-Path: X-Original-To: engelchen@mindfields.own-hero.net Delivered-To: engelchen@mindfields.own-hero.net Received: by mindfields.own-hero.net (Postfix, from userid 500) id B9618120C1C4; Tue, 24 Oct 2006 15:03:34 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.1.3-gr0 (2006-06-01) on mindfields.own-hero.net X-Spam-Level: X-Spam-Status: No, score=0.6 required=5.0 tests=HTML_IMAGE_ONLY_16, HTML_MESSAGE,MIME_HTML_ONLY autolearn=disabled version=3.1.3-gr0 X-Spam-Report: * 0.0 HTML_MESSAGE BODY: HTML included in message * 0.0 MIME_HTML_ONLY BODY: Message only has text/html MIME parts * 0.6 HTML_IMAGE_ONLY_16 BODY: HTML: images with 1200-1600 bytes of words Received: from fmmailgate03.web.de (fmmailgate03.web.de [217.72.192.234]) by mindfields.own-hero.net (Postfix) with ESMTP id D362B120C1BA for ; Tue, 24 Oct 2006 15:03:23 +0200 (CEST) Received: from mx32.web.de (mx32.dlan.cinetic.de [172.20.6.245]) by fmmailgate03.web.de (Postfix) with ESMTP id C4C172D68C42 for ; Tue, 24 Oct 2006 15:02:38 +0200 (CEST) Received: from [200.49.216.227] (helo=jla9s2m.ouokw5.verizon.net) by mx32.web.de with esmtp (WEB.DE 4.107 #114) id 1GcLvE-0003Zm-00; Tue, 24 Oct 2006 15:02:26 +0200 Message-ID: <24093949423257.26DD01090B@0EB1V5O> From: "Investor.com credulous" To: Subject: We know it'll go off tomorrow, important information Date: Tue, 24 Oct 2006 10:00:49 -0300 MIME-Version: 1.0 X-Mailer: Microsoft Office Outlook, Build 11.0.5510 X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2800.1106 Content-type: multipart/related; boundary="----=_NextPart_000_0005_B9B571F3.BB2896EE" X-WEBDE-FORWARD: heaven.7th@web.de -> engelchen@own-hero.net ------=_NextPart_000_0005_B9B571F3.BB2896EE Content-Type: text/html; charset="Windows-1252" Content-Transfer-Encoding: 7bit

of the tournament to add to its illustrious squad, who would it choose?
McClaren was a key coaching figure, and to suggest Eriksson ignored all his advice is


His last act as a footballer was to shove his head into the chest of Marco Materazzi,Ricardo did well to keep out, with Lennon scuffing his attempt to put in the rebound.

was huge relief for England to see Tiago slip with the goal at his mercy.Goals dried up and players stopped shooting from 30 yards, preferring instead to pass

England's best hope of a goal was a set-piece and Lampard fired in a free-kick thatIf the world's richest club in the transfer market, Chelsea, was looking for the playerunder pressure because he was part of England's downfall in Germany.

again on television archive to show the World Cup finals in all its glory.A deep Luis Figo free-kick was not dealt with by Gary Neville or Lampard and there

------=_NextPart_000_0005_B9B571F3.BB2896EE Content-Type: image/gif; name="CIMG0980.gif" Content-Transfer-Encoding: base64 Content-ID: R0lGODlhvwFpAaIHAMwAAAAA//8AAJkAADMAmQAAAP///////yH/C05FVFNDQVBFMi4wAwEAAAAh +QQFCgAHACwAAAAAvwFpAQAD/2i63P4wykmrvTjrzbv/YCiOZGmeaKqubOu+cCzPdG3feK7vfO// wKBwSCwaj8ikcslsOp/QqHRKrVqv2Kx2y+16v+CweEwum8/otHrNbrvf8Lh8Tq/b7/i8fs/v+/+A gYKDhIWGh4iJiouMjY6PkJGSk5SVlpeYmZqbnJ2en6ChoqOkpaanqKmqq6ytrq+wsbKztLW2t7i5 uru8vb6/wMHCw8TFxsfIycrLzM3Oz9DR0tPU1dbX2Nna29zd3t/g4eLj5OXm5+jp6uvs7e7v8PHy 8/T19vf4+fr7/P3+/wADChxIsKDBgwgTKlzIsKHDhxAjSpxIsaLFixgzatzIsf+jx48gQ4ocSbKk yZMoU6pcybKly5cwY8qcSbOmzZs4c+rcybOnz59AgwodSrSo0aNIkypdyrSp06dQo0qdSrWq1atY s2rdyrWr169gw4odS7as2bNo06pdy7at27dw48qdS7eu3bt48+rdy7ev37+AAwseTLiw4cOIEyte zLix48eQI0ueTLmy5cuYM2vezLmz58+gQ4seTbq06dOoU6tezbq169ewY8ueTbu27du4c+vezbu3 79/AgwsfTry48ePIkytfzry58+fQo0ufTr269evYs2vfzr279+/gw4sfT768+fPo06tfz769+/fw 48ufT7++/fv48+vfz7+/////AAYo4IAEFmjggQgmqOCCDDbo4IMQRijhhBRWaOGFGGao4YYcdujh hyCGKOKIJJZo4okopqjiiiy26OKLMMYo44w01mjjjYEdYEABAigAQAEGHPDjAAL0aKQBAQxAgAAA DGAAAQMAIAABAQgwAI86TgkAAQAYMGUBVSJJQAEFEHDAAWAOEACSAKzpJJBM6ohmkwGsaSWXZAYw Jo8GAHDAlF4OcCaSBRwgaJlRCmCongGQqSaTBThZ5ZSKMuqnknUy+WSSekZKQJB9FnqlmkkWKmSh UPbYpgB8KinoAUsqBGSVUf4JJZQHBHAmkH6C2SWVrBLZo5ljekknq5GWSWaQ/0K2CauZdQqpa5sE cPkplI0qAOSSgkbZaLVmKuoll4M+emWSQQqr55x9QnnplFd2GamafSa55ZM9DiDoqmtueqa+foZq KJW5Kkrkkrr+yWqfXe6okKE9MsxkkwoQqSuY2KL56b1bAiuvvlcuWq+URBYAgJ+7nlwynDwm6ueW bf4Y6Y4Yn1zknop2KUAAJ+c5M6IqP7mnlMtSOmaTVJZ5dJ1eMlnnmt82qSiYk1b7Jqtd5lpmk4OG yXO2J9+bENJKwqrAn64imSSVXn695qc8fxokrzwmqaWb/b5JpJRoF0ykmmdGzOq0PRb6pL5ULilk oCbXSXSdekOu5OFWB/vywv9LUguyqnrubHDBMVf7stZoLtyzmluyuuSskZ4Zd8AKNZppmUmeSSXI en7a7M7nmvynlFZWWXSvU/teuJ7a6tgmmZo77mepXAbPbZuv1v4nA3DC+jzkYBpcqK7Gwoxmme3G a7OujUJ8p59Ho71mk102qWbIMScL8ZiGrgrm9Qm1Tjy0WGvTjmTWJ2TtrGkdyxWbUKYrK+HrUOyL UrJ8tCNK0WlMuRuXlNw1JidZqUdfA6HjXEemIpmwUFby1ZVyJqlIoWxHiEOg7swkQSGZ6VTholoJ 2/Wn9JHJalKaG5r2xanYzatacGJSkYAUKi7xzQBvup2qNoUpUf3oS3eLVJ3/lsSqXOkphlC8Weem hK0tNYp3fjsZ23iWwB/dC3JJotewAmcmGMJxZy3bUbUg16c+Xc9Ko6rS2+LkpGfZDEqYEpLZSMWj xDmpfzsT3s5udzJm7RGPjuKarvbIJSjazoEK6CIT9YXGrHWOSg2DXJbmp6esPSl/Cnjfp3iEQssB jm9r8l3umiQqQILKS2BSQPTiJ70ewcpzYTLTsqwnOjRd7Gh6JNbxFBarhMTRiYr64MAMF0xaRamQ GlNSpKakPbjpa2tzalQQgaQ1MqFpXKwy5tSgViVqxWyT2xKXkjaorzoVamtREtrAhBmqebERg0HS ktAA1jJXXcmTsdQVkTY1ba0/eXFx49LYlgLZMISYLHW2w53JPIUpGuKphII6mrtWScZc9ZBtcxKU RMkFOS6tsGSVquP1yMS8IVHNTeniog3zyM1hEe2jRBof8pCoIyApa4naAtsXnzQuROXPdXFsqsl2 dKaGvclLOkpIAgAAIfkEBRQABwAsCwANAE0BDgAAA/94etC9ykHoqmT24qwpmI83QUFpluR5psG4 sirqyoupxPSY6vlt67WXr9cbhRbHyAeIrICSHs5SutxIo9AONqO8WjkgDGP8+JjNPFxriAuu2UJ1 8fBzw4XAuh02d9Nkf286Z2RiaGVMX09Vi2BfFl1ekYwbQFRTl4+QW2dOXDNqdypDfqOient7coJ8 rap9qHRrgYlctpuWTlG5XpedkhIdWk2Uu8bEiWIiy2mCP6jPgW8vsXlEgDnVMaXO2KxBaT7iycpN T8nBScNdTFruUOzC8Oy8i/btGrpW1t2z1/4AJ0gjR4pFwYM76qCohtDVOGzk9Elch0xeMXqDsmi8 mI7/EcVMmvRhNIJJWZmSoNrIklOQ4ak50LypFHgwYDMm2/yMq1UyxEkl+Doda/TJ171j+eaF9EmF 5EWCUF9yi+Mt0aqbBlfmxFmEodeq1qKKDYpsJCddIIdOmvgUpKSjY8WGmsoq2jc+pgT+O0UulrY+ oMLGHUzsU6WMvRw5dWr4o9LDIssShurSbr+GAwnGtBnVb1fAgcNpnQy1qVnJi/elLuzI8dPDqtWS 5nq3psLMo1dSvg228+dvLkPrfVh79tpNrslGWm32gmm36uBRNJ4Vq+1pc7Vu1TszuPVUDXWL/0uc ej1jz9N7lL7xnvrW0dubp01fp3i+L2uzDJ/Mcz9TRLyRV958cEGW2IFYwLVOR0Wp14hsBPKHmQ3+ 1bUfP3vJ9RteveU2AziyRIhaRQfCR4lI04mo4oostuhihP8U9+KMySQAACH5BAUyAAcALA4AMQA1 AR4AAAP/WLp1zssdqB6VOMurbf+fIGCiI55jmEoleXZo+x7rV2F3l4N8z9ayGKj1I9JmR2Sy5iLO mBNKI8qRWiC+DSfLdXmXymKzGQanRmdfbqdhd9/GoFCjjJ2F9juKPkeb2lMeUThTboNvWomDFTsR hIEZcXc/fE5Ilnx0NH89a4GOgp4ejGygkUCTJlB7qpRPaCslmGNHf2kZjYWQN4aGWaJUpFqgWJmU ta2RyJuzy6qszJtqn7rEuopS1qbHyc0sy5hGMLDcycp+gMXB2gxX251VwLzXgl/ddiqn45WsL1A2 DeYFnFeP4CGDh+why5PPGD5aCp9dkqVD3bpd8dqlg3RR/1EojhdBSpIoLmLJkuCYwPpH6CC1j9jo CdSoUE6ZcuYY6sNJUtzKllRivgQErxTIhC43vhvpbIjKp1l8RuMhLKFBeTKr0SwXJCpUbrJiiW3Y 1E8NYFaH4jr662gumEjH6THHwycqpzjNTqM2MOsVuAhVzG1KtuzYV3R3lp1aEKEjK3G79MI4zNPW IhO9KtYZFhondL5MqZv52K87Qw8J7+up55Xrfq3j2HL3CGkEyL6mVQT69xHbJRELp+zTWlOSems5 iuabtDltwXd9WJoDXAzrnGEG50bEvbv37+DDdxJPvrz584h+o1/Pvv159e7jy5cPf779+/jz69/P v7////8ABijggAQWaOCBCCao4IIMNujggxBGKOF3o9UH3lbbXUgZdxZS1eGEIGpokXtbZEjhhm+Y CE+ILLaH1ShGKReaQMhtc9k7MdXm22nDtCSKZfRE1uKQRBUJ2TqVubWLRxXSNOKOSSbZF2lRdtQR WkRmmZw1vV0VpBsz/lVakUIGw2SQZwrV4zsEqahliPE0htxpYLLlmFZ8XcZbSDw2VsxbNY7p5pst epnjlmwuCVdapT3pEZ99AjlmmjBWSuilL6YFGHyNftSXkR0CCsKdu61p6CIfXvogbl/m6aqSTroq 5awAIYqnVnTOmZE2qqpaoZw9QlmRqEEJ+1ytWxrLzqMblgZFY6/QRishjtJWa+2Ag16r7bYkZstt gQkAACH5BAUKAAcALA0AVACKARkAAAP/eFqs/jDKeQq1E2PK4b5LJ47OR3onOJody0qmtqop99bl euPktvMwWuTHI1ZCQJyxlczNTq6nc9msUaXCag+1aIS83eNR42VYfMhKueEDnz9mzzrGVj/iJbA6 5hzb8y94YmddcHp1aHeEhX0yboCKYoxviomLSJSSZIabY2SVOXOMoIuCmXopN5Yyg5+amFNprKyt sGm2kpizsbhwjX+0fLZlvINhibqyysC9yXdhxsPCxGiWvGvNzNG5ta/AtKkZxcG318Xm3tbi3uPL UeWEpe3r5OXbjlz37uj6z+n88+ThmtdP3Y56/bhtCZJNXaFdvfBATCiIYMNGbszwibfP/57GiKYk xhJWMOBDhA0/bjO5KaPDVSJBDllGsQiXlx3/6TSY853Fkh7thfKjkxvPoBdJ1sO5kubFmzP/gYuK cGrRPtlq2qS5FNqqp64mdoXnFKhZn8hQdqvqLG3Us16fGu05MKvbnb+KioVKV2gPVKYwrqzzjdix w6PYVfSKyk7aQ5AD5dXU2PHAioT3IKvUhpOjx57lKH6kkC2k05a5kl7bGFzgslqsxJ5Nu7bt2wxx 697Nu7dvHZV/Cx9OnEnx48iTK1/OvLnz59CjS59Ovbr169iza9/Ovbv371ixLLx1pYlGlyFVnq/t E4jVdbOnLimfxOo03AersKHvD4qSof9+2XafP5Lh95Z7AeYTm3zi6ZZfbuxlIZtiie0xSmCfdFZW NbK09seFk80lYoFvwZRXG3N1gho+8Fyy2F2vbeQWZt+A8kUgAqUWCmCGtcLhhaupKEdLPbrY0Vdr AVjaF1nF9cpdZI0IYX8/AuVKHn2xmEtYWM0IkDYOMZZSlIZdWVeVRn4I1oYA5WhfX0sShcKPm+nF 5CUndZaeRIv54eaR4UGJDp52PsMRXlTmxBVVgfIz4IlmhWeMoIgyqZmGusQ0GjVB0KnSier5mY8v 5E1pKFFMqaWnnsOImNCdPpY5qqIUPsRmq2QOyemlSGmW2HqJDtYUX2ix1CmADw7LEUmZ7DQr6VB/ VqpUia1O6+yySFkbZq1MQXptlKfGSeCgNEy0qLTnXpnsud7W2l+zdSYI5Vh1wuhkvN1OdhSWkXLr pKt7jRusv8RCVO+XnNhYWJchXQWuhbNWiC9fUwD7w2aYafopeZBFE6+vFYYY45yhqTlvtJx1CBg0 qG25Gr+EmTgEaeYexx944N2M886+6Rwfz0AbF/TQyiUAACH5BAUUAAcALA4AegDNAEMAAAP/eFqs /jDKSSu7pb68MddQs4DHR04mlZ4r+LVnLJchmd4y7s4SzPczXUlEExEzxOFrOBoJm8oObVNbJC9W Uwvr1B6n3PAX6eBmIxykt4ouW9/gNDQtX7apUzDcjbf72XxxTX5yg3NwhXpQg4WJeWyJf4uGhjAe doqPSmaSmZNVnY58kYd5on2jQKqZoWVhqZaBm6R4jx5ZRoCuuZSeGL20t2egqXfFrMfBsCi1K5iL z59Ppa2mxdU+msqrmLSCirzWzIHVst3Uut+82I3J6JPbzklRpXpXZOL58Lsd80Jm9LQJa1DHyzOC iL7MueesnsIfq3hkg0ixosWLGDNqmKhC/6PHjyBDihxJsqTJkyhTqlzJsqXLlzBXCgvCcR4uIwNv zYzJM+QRjmhqbnmhxhUTKT2TivRHlKDTNz9xHt3zFOoNoEqz5uDU1GlRLFWf3jP6c+oerWgt5mQi lS2do1VD5Pw1Sw3AtHhpii0Kl29YvnITCkaatzDEvX2tKnbbg+jUuGcNS1bhmF5br4wZj12c2ejk z5S5vk0cly5khgZ1YgXN2ibr17Dvwp5Nu7bt27hz697Nu7fv3TtjrBbOsLHB3y618CTj7Z0m5CeV Fxm2pCk5fvuka3MHXaX0cPimiytXQ/u/et2j081XB5hzCw/lnUuPcsuuXO3cD+vYfLws+v8k2ScN ONzVUh4yzaAH4EgCsscdeVTgEw2EC/oUEUDdoIbdcxjGV1yFIP4X4ogklmjiiSimqOKKIMmmkQ93 DSUai0uJmFEs4bl23Sc0qkVMJeJx0ld4TkRowY493jiOOsHk10ZDS+qTpI/cOPRgaOmYY+OUP8Si 3yzvPWkgINFwediPCHJ4zIHa6VKmmV0i6Q02zBDpJZJwVhTjK9DEB1VQT5TpYp6vDUfooYgmquii jDbq6KP1ZWmoXtZtGNClgyI6DY8vQuLcNs8pSgidbe23KSoDqsmppm5IQggiCt6niqBd4MloddcU 2B+eH3oGFyOQBpnrl3RkKuKucxLZqIQjw6Z5ypFoQklrsPOBSuGn2Pq3aqLHLQQeOQ9Z2mG3+13K aAIAIfkEBTIABwAsDwDLAJ8BNgAAA/9Yt6fsLC4oq3036+zo3I3kXaNVlNwHcuepeZ26buhs33hV p/kryr5I7AZRFGm9X9I2xO14QeJSSCVZQ1NMdsudPnMwIFT1VYaaLd3DhcWmhey3iD2hN+x3412b V39idi4jb3J1FHGCa0d4VWQYhUaJhmqBiDBxWnJ6jUd9Px2VcIuZoYd8oKN7h4mVqIpnq2hus21h tbedmXwysrdVmLRtjm5DoGZNvMPFpGK7vba2wnvByLiPzMfXYsC0z9bKpsmdwHjG1Nt1w2fXqbnq gMm/u9K+7ufBlLrv2fT6+uPzFBHyp67ZqXjR4NWzoqfXwYIL10WU1vBeLmgBq3lzpFD/YotyCIkV uidKICqQE0d6sjgP4BxuyvyhCOeS4CR+NUOerMZOJMo8MIEu2xmv50ZfMgWiq/fxj9OnNbzxTHpl EI+cS5ft47QUXzeqfrZivPIQK0CeM9dNLdrSzyar6CqmbDuXYshPdJFuRTrWrli6Lu1prZkw6+C/ BoUdhSiYauGia/nmDXxXsl7IYPsW01jZXbSVpwKVnHPz5ejSa1Iyahd6NZ1Bm6apelXZUCtzZC7B rfVad6OVaJ2tPi0buPBYu2Mdv8T37arm4bpIn069uvXr2K2Xyc69e5ft3sOLH0++PBjz6NMjUc++ vfv38OPLn0+/vv37+PPr38+/v////wDOoFVAS4BHlhRmlGcggAsm0WBY0j3oRDNffDbGeX5xIWEW G2oXoHwdJuZFd5FFgaAJBw34h3J4GYcaJK+tCIddMaYTRiuYgeaJJtPg6JRzDpmCyGkV1RjJjLAt 8lx04wznIyzE7cgIaDD6diQvw0FVnCQoisPYgMxFRNhd5KQz41fF9ejlmn41aeYz5qSi15AWxZkb ODgNxqQ2FIH5JlskdQaonYGiWWaaeL3FGFg5OmQTS135ydVCckUlKGKWFckPpGIyqsSYVFQ62aWN XZbcoGSmAKo9iRqa50hFNOVTrL2tOmqhTQ4kl46c2tqoWpseRdleStVllG2PrSqrp//AyfqRZlgm 6RiBx6JZFhRwnfrppdea+qimCfY67a+7/rqXpKWKG6pH2JJ6FbVe9YMpYJg+cdGXxGZK5kaBhakn Tg9ZNm5d9+Y4qbrWbvapsGEV3C0x+TpKML0xZVXvep2GyuJvPL4YW8cXxSYjlhnSejCvlgRsMluQ ZKRyjRnzRo8kIWepmM0rQ0nbmSpR+WRqhOFM0rIfathDiEWbh3R4SyfttBc9szDl0yBGTV/TVGet 9dZcd+3112CHLfbYZJdt9tlop6322l1PXdV3Ih4tYHUP9kVe3SuUmPeF+WENL4kYRhh34BizZ3ff e8vLBN9o+01DysSlnPOVphVUcJX/AXd5Fm6U6zIlIbXqjNrOnfNo5JYii+6itCPbqMPHnz955c87 Gwe7wz1zOdDgcy9aMbqcVYyZr/YiRGhQhD58J67YwIlnN/6mOumhKHGTbPOSPnz8wNDIwqrcEMkj Pqiax8XuXxVyK7HE4nMP8MUIu6s4w9Pnpb2n2voab+YcwR2+s9syVrE4UylnGTB9xlofoIBisdzA yjEAFJ4CHXgoUdDvfpVLILJeRyvrqU9otnnKFsxiE3TdioDn+034JsatiJWwNu+L17CY979ItVCA ARwa72TovnDZqmkkVJOrXChEbbGwBPpzU5sAEzzyGQ9+/IpezJbnRBwmEX89vGL9+GTjt44hKTWu Kw2raEah4xCJTx7zIEeylRHnfDFaJoiR7P4RGhptDC2KilaSchY5mNUsjndsjQVrV6zZ7JBt6HEc dhSpQkT2h5GOHOF+FEm0SPIHkpbMpCY3yclOevKToAylKEW5IL0ZbWajTKUqT9Q775hylbCMZR+A 9EZALImDj7ASFwkpRtRhUpbAjE/yFAYx6OXJMBI8ZqGCycysTYVfWCTiDBt2w2ZaM2nIiGDCUCVN mYAwV267pjgvaa5tequbNdzi/sbJTv84L2bExOC40nXBdtpTP1wyJAOHljoX9Uk1SPQj6e5JULX9 sqAIDWYlE8pQVSYAACH5BAXYWQcALA8ADwFvAS4AAAP/SLp8ejDCJ6slkV5su5fal3EgOS0l04Ri 675wLM90bd/4raqOWcYa1ig3hAmDO04SJSQ6n9CodEptsZo0ZFXn6xVPmwp2Sy6bz2jZFdMAn1Di FRvu9bZH8/C7eVR213FpgoOEhVVrO25JcUyLdUt4d0WOP4F1lV9uhpucnZ6WeJN+mZp0FKdaPX5/ o5qRiZekgJ+0tbZks4qrXV8hqK6/pI90G5Cxrsdjt8vMzSK5w68dqbrArciXPHqVfaDYzuDhztDB kdu+rejW23vs1d7JvOLz9J3k6STd69Giq3rUwgDqq0ewIK17urSlyCNqnypJCSEey0ZJljyDGDNG QUiR/1iKWMHUhRqoEJNFLNA0qlzJ0ogJZS1jypxZyxjNmzhzGoKls6fPn0CDCh1KtKjRo0iTKl3K tKnTp1CjSp1KtarVq1izat3KtavXr2DDih1LtqzZs2jTql3Ltq3bt3Djyp1Lt67du2UH4K0wQG+E vn/9ahQM2EJhKIfTFE5cpq9jCY4F840MmTHkmJZvLCa8eeXhzDI7nwGsdzNlw6cPRJYcGDNrHKJV x049OXFq0plp635cG7dszhBoVy7t93Zx4pIf2z7e+jdw2R1OLw/OG/p01rErT6be+/hn4twDf7cO 3nn48b2bm+deff157+WdW14N37Rw+tSlr+4uvzP+7v/1MddfgNtBZ+B/2eWn3HMItuceaqhVl+B+ DdJnn30KKujbga81qGGABBpI3ogiMsbbfN6Fp56KG4qo3onMgfYbe6KZRqOArcFYooAm+scjg69l WFt0FD6n3YwcIkfej0ci6ZuOH/j4Y4xAXvakePcF6aGKGn6InHA7Noebg2GiN1t8Pc54YY3YAcfm fi6mN1wLLaLIIpMkctjkeGPG+SGNYrq5ZX5C+tlkoC9quSCEIqCnZ6F3hvlonvOpZmmC7xV4oKSa GuanjIAaemamlOLI6WKXfopjnavGd9mcSEZ6JJuyesAqp7VimqaaKY6aZISx8mnqeykmKmppj9rJ K5eQsi6abK/JRUsor4qSaqOZRmra3n/DwajfigP292d62Ibb7ZqkJknmr+PqCmes4h57aX2B6rcu ZVu+CSWX3NoYIZSDohuno1jaum15BHcJKZiElisfkRJGnCvDE0p87HRyGvpwwXcuF+S0xqUbMri7 MavdmY5+l/BVK8vQckEf78UytzVYKPPNm7yrGcM4a5QAADs= ------=_NextPart_000_0005_B9B571F3.BB2896EE-- FuzzyOcr-3.6.0/samples/ocr-png.eml0000644000175000001440000004347411207335640016364 0ustar decoderusersX-Mozilla-Status: 0001 X-Mozilla-Status2: 00000000 Received: from [80.237.161.201] (helo=hq.cyberarmy.de) by mx07.web.de with esmtp (WEB.DE 4.107 #114) id 1G8VvK-0000PU-00 for christian_holler@web.de; Thu, 03 Aug 2006 07:39:10 +0200 Received: by hq.cyberarmy.de (Postfix, from userid 2527) id 772B56574038; Thu, 3 Aug 2006 07:39:10 +0200 (CEST) X-Spam-Flag: YES X-Spam-Checker-Version: SpamAssassin 3.1.3 (2006-06-01) on hq.cyberarmy.de X-Spam-Level: ************ X-Spam-Status: Yes, score=12.8 required=1.5 tests=BAYES_50, DATE_IN_FUTURE_03_06,EXTRA_MPART_TYPE,FORGED_MUA_OUTLOOK,HTML_40_50, HTML_MESSAGE,LONGWORDS,MSGID_FROM_MTA_ID autolearn=no version=3.1.3 X-Spam-Report: * 1.1 EXTRA_MPART_TYPE Header has extraneous Content-type:...type= entry * 1.4 MSGID_FROM_MTA_ID Message-Id for external message added locally * 2.0 DATE_IN_FUTURE_03_06 Date: is 3 to 6 hours after Received: date * 0.5 HTML_40_50 BODY: Message is 40% to 50% HTML * 0.0 HTML_MESSAGE BODY: HTML included in message * 0.0 BAYES_50 BODY: Bayesian spam probability is 40 to 60% * [score: 0.4859] * 3.8 LONGWORDS Long string of long words * 4.1 FORGED_MUA_OUTLOOK Forged mail pretending to be from MS Outlook Received: from thuan-bf45dbaa6 (unknown [125.234.128.39]) by hq.cyberarmy.de (Postfix) with ESMTP id 4E4E36574037 for ; Thu, 3 Aug 2006 07:39:03 +0200 (CEST) From: "Beatrice Cole" To: Subject: Your monte-jus Date: Thu, 3 Aug 2006 05:39:04 -0420 MIME-Version: 1.0 Content-Type: multipart/related; type="multipart/alternative"; boundary="----=_NextPart_000_006A_01C6B6F9.CDE95250" X-Priority: 3 X-MSMail-Priority: Normal X-Mailer: Microsoft Outlook Express 6.00.2720.3000 X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2720.3000 Message-Id: <20060803053903.4E4E36574037@hq.cyberarmy.de> Sender: aln@0451.com This is a multi-part message in MIME format. ------=_NextPart_000_006A_01C6B6F9.CDE95250 Content-Type: multipart/alternative; boundary="----=_NextPart_001_006B_01C6B6F9.CDE95250" ------=_NextPart_001_006B_01C6B6F9.CDE95250 Content-Type: text/plain; charset="iso-8859-2" Content-Transfer-Encoding: quoted-printable his webbed feet, lifted=20 his beak, and strained to hold a painful hardwant him. Or is it all=20 right?"know my opinion of the incomparable Godi Muller?" Pmber, =20 We recently reI wouldn't be going into the Zone that day.=20 But what would be the nicest wayunt, and suspect that yoone. Watch where=20 it goes and don't take your eyes off it again."accessesee it. The man=20 thinks he knows and understands the Zone completely. Thatbars on the=20 windows just like a police station. Willy was sitting at=20 hislieutenants. I don't like those trucks! They've been exposed to the=20 elementsd by an unauthoripassion-proudnet tonpaper-fillednote shaverN=20 electronrd party. Protthings any lighter. In fact, the bastards made it=20 seem even darker. And now, "Here," he said. "From a grateful=20 humanity.ecting the seo "OK," I said, "we had our =20 fun, now let's go. Watch closely. I'mwould be in the way as far as=20 he was concerned. We would run down, just theunt and o "That's what=20 we in Harmont call the thieves who risk their lives in thencern. =20 Therefore, as prevention measure, because=20 he looked away immediately.were parked on the paved lot next to it. He=20 was right about the trucks--hisAnd as soon as he was quiet, I heard it.=20 Trrr, trrr, trrr... =B7 Kirill lookedcount features.We encourage would=20 shiver with ecstasy. For now, as I saw it, he had a long way to go. He =20 A word of appreciation must be extended to Ms. Antonina W. Bouis,=20 the Paynickel steelpaper knifeOld guardnigh-naked=20 has asspaper-usingmorro castlemilk testeroak treenique tracmotuca=20 flymonk sakipassenger locomotiveoak thistleking number. =20 brickhard sea.: by knowing that you have already=20 arrived ..." getting a start on building his own=20 bitter hell out on the Far Cliffs. And uniquwanted to sec Guta right=20 then and there. just like that. To look at her andwanted to shout=20 "Stop! Freeze!" but I couldn't. And I probably wouldn't havee Ufour at a=20 time, not even letting me finish my smoke. In short, I told hims: =20 =20 For more i "Well, what happens from here?=20 Where are we going? Is there no suchreturn to the Flock.concentration,=20 held his breath, forced one... single... more... inch...nformation =20 like an electric shock. "Wait, Kirill. Come out here."of the=20 entire Shame in the sight of your fellow gulls!"attaining new peaks =20 in Germany and the Netherlands. New writers arenot Heinlein or =20 Bradbury or Clarke, but Stanislaw Lem, a Pole; that theem. Thank=20 yoYou won't forget it.their practicing and their striving to understand=20 more of the perfectwell. They can help you bring the newcomers=20 along."u for your=20 proNon-brahmanicalnarrow-headedmonkey-balloff-goNon-germanis matter. =20 ------=_NextPart_001_006B_01C6B6F9.CDE95250 Content-Type: text/html; charset="iso-8859-2" Content-Transfer-Encoding: quoted-printable =20 =20 =20 =20 =20 =20 =20 =20 =20 =20 =20 =20 =20 =20 3D""
his webbed feet, lifted his beak, and=20 strained to hold a painful hardwant him. Or is it all right?"know=20 my opinion of the incomparable Godi Muller?" Pmber,
=20
We recently reI wouldn't be going into the Zone that=20 day. But what would be the nicest wayunt, and suspect that yoone. Watch=20 where it goes and don't take your eyes off it again."accessesee it. The =20 man thinks he knows and understands the Zone completely. Thatbars on=20 the windows just like a police station. Willy was sitting at=20 hislieutenants. I don't like those trucks! They've been exposed to the=20 elementsd by an unauthoripassion-proudnet tonpaper-fillednote shaverN=20 electronrd party. Protthings any lighter. In fact, the bastards made it=20 seem even darker. And now, "Here," he said. "From a grateful=20 humanity.ecting the seo "OK," I said, "we had our =20 fun, now let's go. Watch closely. I'mwould be in the way as far as=20 he was concerned. We would run down, just theunt and o "That's what=20 we in Harmont call the thieves who risk their lives in=20 thencern.
Therefore, as prevention measure,=20 because he looked away immediately.were parked on the paved lot next to=20 it. He was right about the trucks--hisAnd as soon as he was quiet, I=20 heard it. Trrr, trrr, trrr... =B7 Kirill lookedcount features.We=20 encourage would shiver with ecstasy. For now, as I saw it, he had a long=20 way to go. He A word of appreciation must be extended to Ms. =20 Antonina W. Bouis, the

Paynickel steelpaper knifeOld guardnigh-naked =20 has asspaper-usingmorro castlemilk testeroak treenique tracmotuca=20 flymonk sakipassenger locomotiveoak thistleking=20 number.
brickhard sea.:
by knowing that you have already arrived=20 ."

getting a start on=20 building his own bitter hell out on the Far Cliffs. And uniquwanted to=20 sec Guta right then and there. just like that. To look at her andwanted=20 to shout "Stop! Freeze!" but I couldn't. And I probably wouldn't havee=20 Ufour at a time, not even letting me finish my smoke. In short, I=20 told hims:




=20
=20 For more i =20 "Well, what happens from here? Where are we going? Is there no =20 suchreturn to the Flock.concentration, held his breath, forced one... =20 single... more... inch...nformation like an electric shock.=20 "Wait, Kirill. Come out here."of the entire Shame in the sight of your=20 fellow gulls!"attaining new peaks in Germany and the Netherlands.=20 New writers arenot Heinlein or Bradbury or Clarke, but Stanislaw=20 Lem, a Pole; that theem. Thank yoYou won't forget it.their practicing=20 and their striving to understand more of the perfectwell. They can=20 help you bring the newcomers along."u for your=20 proNon-brahmanicalnarrow-headedmonkey-balloff-goNon-germanis matter.
=20
------=_NextPart_001_006B_01C6B6F9.CDE95250-- ------=_NextPart_000_006A_01C6B6F9.CDE95250 Content-Type: image/png; name="4WQUDM.PNG" Content-Transfer-Encoding: base64 Content-ID: <006901c6b6bf$218a7a50$6c822ecf@DQ72967B> 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 T3ryf07+G6YjQVEJceAdAAAAAElFTkSuQmCC ------=_NextPart_000_006A_01C6B6F9.CDE95250-- FuzzyOcr-3.6.0/samples/ocr-wrongext.eml0000644000175000001440000003736111207335640017453 0ustar decoderusersReturn-Path: X-Original-To: decoder@own-hero.net Delivered-To: decoder@mindfields.own-hero.net Received: from mellox (pD9E2D1ED.dip.t-dialin.net [217.226.209.237]) by mindfields.own-hero.net (Postfix) with ESMTP id 3BA7A120C1AC for ; Tue, 8 Aug 2006 10:04:01 +0200 (CEST) Resent-From: Sascha Just Resent-To: Christian Holler Resent-Date: Tue, 8 Aug 2006 02:04:00 -0600 Resent-Message-ID: <200608081004.00363.M7zmendelian@alexalvarez.com> X-Original-To: methos@mindfields.own-hero.net Delivered-To: methos@mindfields.own-hero.net Received: by mindfields.own-hero.net (Postfix, from userid 500) id 5C9B812080C2; Tue, 8 Aug 2006 02:22:37 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.1.3-gr0 (2006-06-01) on mindfields.own-hero.net X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=HTML_MESSAGE autolearn=disabled version=3.1.3-gr0 X-Spam-Report: * 0.0 HTML_MESSAGE BODY: HTML included in message Received: from fmmailgate03.web.de (fmmailgate03.web.de [217.72.192.234]) by mindfields.own-hero.net (Postfix) with ESMTP id 0A142120C1AC for ; Tue, 8 Aug 2006 02:21:20 +0200 (CEST) Received: from mx30.web.de (mx30.dlan.cinetic.de [172.20.6.145]) by fmmailgate03.web.de (Postfix) with ESMTP id ED4F9FC29FF for ; Tue, 8 Aug 2006 02:21:19 +0200 (CEST) Received: from [61.64.147.123] (helo=61-64-147-123-adsl-kao.dynamic.so-net.net.tw) by mx30.web.de with smtp (WEB.DE 4.107 #114) id 1GAFL2-0007C4-00; Tue, 08 Aug 2006 02:20:55 +0200 X-MID: Date: Mon, 07 Aug 2006 19:20:44 -0600 Message-Id: From: Clifton Ballard To: naraya_a@web.de Subject: To take on supplier MIME-Version: 1.0 Content-Type: multipart/related; boundary="----=_NextPart_000_00BD_01C5163C.78C70EB0" X-WEBDE-FORWARD: narayan@web.de -> web.de@nmg.own-hero.de X-UID: 3354 X-Length: 15790 This is a multi-part message in MIME format. ------=_NextPart_000_00BD_01C5163C.78C70EB0 Content-Type: multipart/alternative; boundary="----=_NextPart_001_00A0_01C5042E.12A32EA0" ------=_NextPart_001_00A0_01C5042E.12A32EA0 Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7Bit with a noiseless step, when we were close to them, addressed brains against - against mantelpieces, said my aunt; an idea which run up and down stairs for me, all day long. You never sit and again in the old country. Do not frown, Micawber. I do not now ------=_NextPart_001_00A0_01C5042E.12A32EA0 Content-Type: text/html; charset=us-ascii Content-Transfer-Encoding: 7Bit
Of the pair of hired post-horses being ready, and of Doras going
Put my meaning into any words you like, said I. You know what know; far from that. - but if you will sometimes think - just to
never should have been got into my present state if I hadnt come in my memory, pervaded it again. When dinner was done, Mr.
No, no. please. cried Dora, with a kiss, dont be a naughty Blue morning, when she requested an immediate settlement of the same,
have not known my partner, Mr. jorkins, as long as I have. Nothing Anywhere. Im a going to seek my niece through the wureld. Im
thats lived along with her and had her for their all in all, these is not in Traddless way. He is perfectly good-humoured respecting
he cherished an artistic admiration of their style of composition, being mentioned, I recognized it, however, and said as much.
finishing touch to that renunciation of mankind in which she had gracious to Peggotty, except when I inadvertently called her by
of him never wandering in that better mind of his to which stimulant, having little room in his system for any other article
finding himself as comfortable as he expected, or being a little perfect country gentleman to follow lustily with the same cry.
say as much for her bonnet and resumed her seat composedly. solicitude; and my poor mother herself could not have loved me
with us. Who knows when we may meet again, else? Come. Say the avoid the subject. All I desire, Mr. Copperfield, is, that it
she was so much disturbed in mind as to find it necessary to open Still, resumed Miss Murdstone, I found no proof until last
Yes. she said. I beg and pray that no one will leave the room. I cannot do with ampial satisfaction to my own feelings. But, in
every morning, took away our bread; and also how he himself had rest - and touched, on the horizon, with a strip of silvery light
said Mr. Chillip; but she is quite a shadow now. Would it be certain. Dont mistrust me. Our wants are not many. If I rent
slumbering echoes in the caverns of Memory awakened; what a kind and all gentlemen with anything bashful in their appearance, and
to be useful to the family; and that if I got on in the world, and I hope its enough, child, said my aunt. If there had been more
------=_NextPart_001_00A0_01C5042E.12A32EA0-- ------=_NextPart_000_00BD_01C5163C.78C70EB0 Content-Type: image/jpeg; name="sbillet.jpeg" Content-Transfer-Encoding: base64 Content-ID: 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 ------=_NextPart_000_00BD_01C5163C.78C70EB0-- FuzzyOcr-3.6.0/CHANGES0000644000175000001440000000017211207337641013636 0ustar decoderusersThe changelog for the 3.6.x branch is maintained online at: http://fuzzyocr.own-hero.net/wiki/Changelog-3.x#version3.6.0 FuzzyOcr-3.6.0/FuzzyOcr.words0000644000175000001440000000067011207335640015516 0ustar decoderusers# Here we defined the words to scan for # Stock alert charts profit news::0.2 breaking symbol alert stock investor international company money::0.01 million thousand buy price::0.2 trade target banking service recommendation # Pills viagra cialis xanax valium meridia zanaflex levitra medicine legal::0.2 penis::0.01 medication growth drugs pharmacy prescription # Misc gratis::0.2 oferta click here software kunde::0.2 volksbank sparkasse FuzzyOcr-3.6.0/FuzzyOcr/0000755000175000001440000000000011207335640014433 5ustar decoderusersFuzzyOcr-3.6.0/FuzzyOcr/Preprocessor.pm0000644000175000001440000000361111207335637017466 0ustar decoderusers# <@LICENSE> # Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to you under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at: # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package FuzzyOcr::Preprocessor; sub new { my ($class, $label, $command, $args) = @_; bless { "label" => $label, "command" => $command, "args" => $args }, $class; } sub run { my ($self, $input) = @_; my $tmpdir = FuzzyOcr::Config::get_tmpdir(); my $label = $self->{label}; my $output = "$tmpdir/prep.$label.out"; my $stderr = ">$tmpdir/prep.$label.err"; my $stdin = undef; my $stdout = undef; my $args = $self->{args}; my $rcmd = $self->{command}; if (defined $args) { $rcmd .= ' ' . $args; } # Does the processor expect input from file or from stdin? if(defined $args and $args =~ /\$input/) { $rcmd =~ s/\$input/$input/; } else { $stdin = "<$input"; } # Does it output to file or to stdout? if(defined $args and $args =~ /\$output/) { $rcmd =~ s/\$output/$output/; } else { $stdout = ">$output"; } # Run processor my $retcode = FuzzyOcr::Misc::save_execute($rcmd, $stdin, $stdout, $stderr); # Return code return $retcode; } 1; FuzzyOcr-3.6.0/FuzzyOcr/Deanimate.pm0000644000175000001440000001146711207335637016677 0ustar decoderusers# <@LICENSE> # Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to you under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at: # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # use strict; package FuzzyOcr::Deanimate; use base 'Exporter'; our @EXPORT_OK = qw(deanimate); use lib qw(..); use FuzzyOcr::Config qw(get_config set_config get_tmpdir); use FuzzyOcr::Misc qw(save_execute); use FuzzyOcr::Logging qw(errorlog warnlog infolog); # Provide functions to deanimate gifs sub deanimate { my $conf = get_config(); my $imgdir = get_tmpdir(); my $tfile = shift; my $efile = $tfile . ".err"; my $tfile2 = $tfile; my $tfile3 = $tfile; if ($tfile2 =~ m/\.gif$/i) { $tfile2 =~ s/\.gif$/-multi.gif/i; $tfile3 =~ s/\.gif$/-reduced.gif/i; } else { $tfile2 .= ".gif"; $tfile3 .= "-reduced.gif"; } my $info = gif_info($tfile); my $index = find_dominant_image($info); # Pick frame number $index from the animation and spew to stdout: if ($info->{'has_local_color_table'}) { infolog("deanimate: Image has local_color_table, reducing to 255 colors"); my $retcode = save_execute( "$conf->{focr_bin_gifsicle} --colors=255 $tfile", undef, ">$tfile3", ">>$efile"); if ($retcode == 0) { $tfile = $tfile3; } else { warnlog("$conf->{'focr_bin_gifsicle'}: ". ($retcode<0) ? 'Timed out' : 'Error' ." [$retcode], image not reduced!"); } } my $retcode = save_execute( "$conf->{focr_bin_gifsicle} -o $tfile2 --unoptimize $tfile #$index", undef, undef, ">>$efile"); return $tfile2 if ($retcode == 0); warnlog("$conf->{focr_bin_gifsicle}: cannot extract image#${index}"); return $tfile; } sub gif_info { my $conf = get_config(); my $imgdir = get_tmpdir(); my $giffile = $_[0]; my $fd = new IO::Handle; my $retcode; my @stdout_data; my @stderr_data; my %info = ( 'error' => 0, 'loop' => 0, 'loop_count' => 0, 'delays' => [], 'has_local_color_table' => 0 ); ($retcode, @stdout_data) = save_execute( "$conf->{focr_bin_gifsicle} --info $giffile", undef, ">$imgdir/gifsicle.info", ">>$imgdir/gifsicle.err", 1); if ($retcode) { errorlog("$conf->{'focr_bin_gifsicle'}: ". ($retcode<0) ? 'Timed out' : 'Error' ." [$retcode], data unavailable..."); return \%info; } my $output = join("", @stdout_data); my ($globalinfo, @frameinfo) = split /^ \s+ \+ \s+ (?=image \s+ \#\d+)/mx, $output; if ($globalinfo =~ /^ \s* loop \s+ (forever|count \s+ (\d+))/mx) { $info{'loop'} = 1; $info{'loop_count'} = $2 ? ($2 + 0) : 0; } my $frameno = 0; foreach my $info (@frameinfo) { # We could just match the delays, but we'll also check the image#'s # as a sanity check. my ($n, $delay) = $info =~ m{ image \s+ \#(\d+) (?: .* \b delay \s+ (\d+(?:\.\d+)?) s)? }sx; if ($n != $frameno) { warnlog ( "Trouble parsing 'gifsicle --info' output.\n" . " Expected 'image \#$frameno', found 'image \#$n', skipping..." ); $info{'error'}++; } else { $info{'delays'}->[$frameno++] = $delay ? $delay + 0.0 : 0.0; $info{'has_local_color_table'} ||= $output =~ /local\s+color\s+table/; } } return \%info; } sub find_dominant_image ($) { my ($info) = @_; my ($loop, $loop_count, $delays) = @$info{qw(loop loop_count delays)}; # Pick out the frame with the longest delay. my $maxdelay = -1e6; my $maxn = @$delays - 1; for (my $n = 0; $n < @$delays; $n++) { $delays->[$n] > $maxdelay and ($maxn, $maxdelay) = ($n, $delays->[$n]); } if ($maxdelay < 15.0 && !$loop) { # In non-looped (or finitely-looped) images, the last frame # gets displayed forever at the end of the animation. # Therefore the last frame is the dominant frame. return @$delays - 1; } return $maxn; } FuzzyOcr-3.6.0/FuzzyOcr/Scoring.pm0000644000175000001440000001006711207335637016407 0ustar decoderusers# <@LICENSE> # Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to you under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at: # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # use strict; package FuzzyOcr::Scoring; use base 'Exporter'; our @EXPORT_OK = qw(wrong_ctype corrupt_img known_img_hash wrong_extension); use lib qw(..); use FuzzyOcr::Config qw(get_pms get_config); use FuzzyOcr::Logging qw(infolog); # Provide custom scoring functions sub wrong_ctype { my $conf = get_config(); my $pms = get_pms(); my ( $format, $ctype ) = @_; if ($conf->{'focr_wrongctype_score'}) { my $debuginfo = ""; if ( $conf->{"focr_verbose"} > 0 ) { $debuginfo = ("Image has format \"$format\" but content-type is \"$ctype\""); } infolog($debuginfo); my $ws = sprintf( "%0.3f", $conf->{'focr_wrongctype_score'} ); for my $set ( 0 .. 3 ) { $pms->{conf}->{scoreset}->[$set]->{"FUZZY_OCR_WRONG_CTYPE"} = $ws; } my @dinfo = split('\n', $debuginfo); foreach (@dinfo) { $pms->test_log($_); } $pms->_handle_hit( "FUZZY_OCR_WRONG_CTYPE", $conf->{'focr_wrongctype_score'}, "BODY: ", "BODY", $pms->{conf}->get_description_for_rule("FUZZY_OCR_WRONG_CTYPE")); } } sub wrong_extension { my $conf = get_config(); my $pms = get_pms(); my ( $format, $suffix ) = @_; if ($conf->{'focr_wrongext_score'}) { my $debuginfo = ""; if ( $conf->{"focr_verbose"} > 0 ) { $debuginfo = ("Image has format \"$format\" but file extension is \"$suffix\""); } infolog($debuginfo); my $ws = sprintf( "%0.3f", $conf->{'focr_wrongext_score'} ); for my $set ( 0 .. 3 ) { $pms->{conf}->{scoreset}->[$set]->{"FUZZY_OCR_WRONG_EXTENSION"} = $ws; } my @dinfo = split('\n', $debuginfo); foreach (@dinfo) { $pms->test_log($_); } $pms->_handle_hit( "FUZZY_OCR_WRONG_EXTENSION", $conf->{'focr_wrongext_score'}, "BODY: ", "BODY", $pms->{conf}->get_description_for_rule("FUZZY_OCR_WRONG_EXTENSION")); } } sub corrupt_img { my $conf = get_config(); my $pms = get_pms(); my ($score, $err) = @_; if ($score>0) { my $debuginfo = ""; if ( $conf->{"focr_verbose"} > 0 ) { chomp($err); $debuginfo = ("Corrupt image: $err"); } infolog($debuginfo); my $ws = sprintf( "%0.3f", $score ); for my $set ( 0 .. 3 ) { $pms->{conf}->{scoreset}->[$set]->{"FUZZY_OCR_CORRUPT_IMG"} = $ws; } my @dinfo = split('\n', $debuginfo); foreach (@dinfo) { $pms->test_log($_); } $pms->_handle_hit( "FUZZY_OCR_CORRUPT_IMG", $score, "BODY: ", "BODY", $pms->{conf}->get_description_for_rule("FUZZY_OCR_CORRUPT_IMG")); } } sub known_img_hash { my $conf = get_config(); my $pms = get_pms(); my $score = $_[0] || $conf->{'focr_base_score'}; my $debuginfo = $_[1] ? "\n$_[1]" : ''; my $ws = sprintf( "%0.3f", $score ); for my $set ( 0 .. 3 ) { $pms->{conf}->{scoreset}->[$set]->{"FUZZY_OCR_KNOWN_HASH"} = $ws; } my @dinfo = split('\n', $debuginfo); foreach (@dinfo) { $pms->test_log($_); } $pms->_handle_hit( "FUZZY_OCR_KNOWN_HASH", $score, "BODY: ", "BODY", $pms->{conf}->get_description_for_rule("FUZZY_OCR_KNOWN_HASH")); } 1; FuzzyOcr-3.6.0/FuzzyOcr/Scanset.pm0000644000175000001440000001065011207335637016401 0ustar decoderusers# <@LICENSE> # Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to you under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at: # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package FuzzyOcr::Scanset; use lib qw(..); use FuzzyOcr::Logging qw(errorlog); sub new { my ($class, $label, $preprocessors, $command, $args, $output_in) = @_; bless { "label" => $label, "preprocessors" => $preprocessors, "command" => $command, "args" => $args, "force_output_in" => $output_in, "hit_counter" => 0 }, $class; } sub run { my ($self, $input) = @_; my $conf = FuzzyOcr::Config::get_config(); my $tmpdir = FuzzyOcr::Config::get_tmpdir(); my $label = $self->{label}; my $output = "$tmpdir/scanset.$label.out"; my $stderr = ">$tmpdir/scanset.$label.err"; my @result; my $retcode; my $stdin = undef; my $stdout = undef; my $rcmd = $self->{command}; #Replace supported scanner macros by full path if ($rcmd =~ m/^\$/) { my $t = 'focr_bin_'.substr($rcmd,1); $rcmd = $conf->{$t} if defined $conf->{$t}; } if (defined $self->{args}) { $rcmd .= ' ' . $self->{args}; } # First, run all preprocessors my $preprocessors = $self->{preprocessors}; if ($preprocessors) { $preprocessors =~ s/ //g; my @prep = split(',', $preprocessors); foreach (@prep) { my $proc = FuzzyOcr::Config::get_preprocessor($_); my $plabel = $proc->{label}; my $command = $proc->{command}; if (defined $proc->{args}) { $command .= ' ' . $proc->{args}; } $retcode = $proc->run($input); if ($retcode<0) { errorlog("Cannot find/execute preprocessor($plabel): $command"); return ($retcode,@result); } elsif ($retcode>0) { errorlog("Error running preprocessor($plabel): $command"); open ERR, "<$tmpdir/prep.$plabel.err"; @result = ; close ERR; return ($retcode,@result); } # Input of next processor is output of last $input = "$tmpdir/prep.$plabel.out"; } } # All preprocessors done, filename with result of last is in $input # Does the scanner expect input from file or from stdin? if($rcmd =~ /\$input/) { $rcmd =~ s/\$input/$input/; } else { $stdin = "<$input"; } # Does it output to file or to stdout? if($rcmd =~ /\$output/) { $rcmd =~ s/\$output/$output/; } else { $stdout = ">$output"; } # Run scanner my $out_in = $self->{force_output_in}; # Scanset enforces OCR output in file $out_in (for example TesserAct has multiple files as output) if ($out_in) { $out_in =~ s/\$output/$output/; $out_in =~ s/\$tmpdir/$tmpdir/; $retcode = FuzzyOcr::Misc::save_execute($rcmd, $stdin, $stdout, $stderr); unless ( open(INFILE, "<$out_in") ) { errorlog("Unable to read output from \"$out_in\" for scanset $self->{label}"); $stderr =~ tr/>|; close(INFILE); return ($retcode, @result); } } @result = ; close(INFILE); } else { ($retcode, @result) = FuzzyOcr::Misc::save_execute($rcmd, $stdin, $stdout, $stderr, 1); } # If there were errors in the scan, return the errors instead of OCR results if ($retcode>0) { $stderr =~ tr/>|; close(INFILE); } # Return scanner results and return code return ($retcode, @result); } 1; FuzzyOcr-3.6.0/FuzzyOcr/Hashing.pm0000644000175000001440000003557311207335637016375 0ustar decoderusers# <@LICENSE> # Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to you under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at: # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # use strict; package FuzzyOcr::Hashing; use base 'Exporter'; our @EXPORT_OK = qw(check_image_hash_db add_image_hash_db calc_image_hash); use lib qw(..); use FuzzyOcr::Config qw(get_thresholds get_config set_config get_tmpdir get_mysql_ddb); use FuzzyOcr::Misc qw(save_execute); use FuzzyOcr::Logging qw(debuglog errorlog warnlog infolog); use Fcntl; use Fcntl ':flock'; #Implements all functions related to Image Hashing sub within_threshold { my $thresref = get_thresholds(); my %Threshold = %$thresref; my $digest = shift; my $record = shift; my ($dimg,$dkey) = split('::',$digest); my ($rimg,$rkey) = split('::',$record); my ($ds, $dh, $dw, $dcn) = split(':',$dimg); my ($rs, $rh, $rw, $rcn) = split(':',$rimg); return(0) unless $rs; return(0) unless $rh; return(0) unless $rw; return(0) unless $rcn; return(0) unless $rkey; return(0) if ((abs($ds - $rs ) / $rs ) > $Threshold{s}); return(0) if ((abs($dh - $rh ) / $rh ) > $Threshold{h}); return(0) if ((abs($dw - $rw ) / $rw ) > $Threshold{w}); return(0) if ((abs($dcn - $rcn) / $rcn) > $Threshold{cn}); my @rcf = split('::',$rkey); my @dcf = split('::',$dkey); my (@dcfs, @rcfs); foreach (@dcf) { push @dcfs,split(':',$_); } foreach (@rcf) { push @rcfs,split(':',$_); } my $total = scalar(@rcfs); if ($total == scalar(@dcfs)) { my $match = 0; foreach (0 .. ($total-1)) { $match++ if (abs($dcfs[$_] - $rcfs[$_]) <= $Threshold{c}); } infolog("image matched <$match> of <$total> colors"); return(1) if ($match == $total); } return(0); } sub check_image_hash_db { my $conf = get_config(); if ($conf->{focr_enable_image_hashing} == 0) { warnlog("Image Hashing is disabled"); return (0,''); } my $digest = $_[0]; my $dbfile = $_[1] || $conf->{focr_db_hash}; my $fname = $_[2]; my $ctype = $_[3]; my $ftype = $_[4] || 0; my ($img, $key) = split('::', $digest,2); return (0,'') unless defined $key; my $now = time; my $hash = $digest; my $ret = 0; my $txt = 'Exact'; my $dinfo; if ($conf->{focr_enable_image_hashing} == 3) { unless (defined $conf->{focr_mysql_ddb}) { warnlog("Connection to MySQL server unavailable"); return (0,''); } my $ddb = $conf->{focr_mysql_ddb}; my $db = $conf->{focr_mysql_db}; my $sql = qq(select * from $db.$dbfile where $dbfile.key='$key'); my @data = $ddb->selectrow_array($sql); my $next = 0; my $when = 0; my $match = 0; if ((scalar(@data)>0) and ($img eq $data[1])) { $match++; infolog("Found[$dbfile]: Score='$data[8]' Info: '$data[9]'"); $next = $data[5]; $next++; $when = $data[7]; $data[8] += 0; $ret = $data[8] == 0 ? 0.001 : $data[8]; $dinfo = $data[9] || ''; if ($data[2] eq '') { infolog("Updating $txt info File-Name:'$fname'"); $ddb->do(qq(update $db.$dbfile set $dbfile.fname=? where $dbfile.key='$key'),undef,$fname); } if ($data[3] eq '') { infolog("Updating $txt info Content-Type:'$ctype'"); $ddb->do(qq(update $db.$dbfile set $dbfile.ctype=? where $dbfile.key='$key'),undef,$ctype); } if ($data[4] != $ftype) { infolog("Updating $txt info File-Type:'$ftype'"); $ddb->do(qq(update $db.$dbfile set $dbfile.ftype=? where $dbfile.key='$key'),undef,$ftype); } } unless ($match) { my $then = time - ($conf->{focr_db_max_days}*86400); $sql = qq(select * from $db.$dbfile order by $dbfile.check); my $sth = $ddb->prepare($sql); $sth->execute; while (my @row = $sth->fetchrow_array) { my $hash2 = $row[1] || "0:0:0:0"; $hash2 .= "::$row[0]"; if (within_threshold($digest,$hash2)) { $txt = 'Approx'; $key = $row[0]; $next = $row[5] + 1; $when = $row[7] || $now; $ret = $dbfile eq $conf->{focr_mysql_hash} ? $row[8] : $row[5]; $dinfo = $row[9] || ''; infolog("Found[$dbfile]: Score='$row[8]' Info: '$row[9]'"); last; } } # Expire old records... $sql = qq(delete from $db.$dbfile where $dbfile.check < $then); debuglog($sql,2); $ddb->do($sql); } if ($ret > 0) { if ($dbfile eq $conf->{focr_mysql_hash}) { infolog("Found Score <$ret> for $txt Image Hash"); } infolog("Matched [$next] time(s). Prev match: ".fmt_time($now - $when)); $sql = qq(update $db.$dbfile set $dbfile.match='$next',$dbfile.check='$now' where $dbfile.key='$key'); $ddb->do($sql); debuglog($sql); } return ($ret,$dinfo); } elsif ($conf->{focr_enable_image_hashing} == 2) { import MLDBM qw(DB_File Storable); my %DB = (); my $dbm; my $sdbm; $sdbm = tie %DB, 'MLDBM::Sync', $dbfile, O_CREAT|O_RDWR or $ret++; if ($ret>0) { warnlog("No Image Hash database found at \"$dbfile\", or permissions wrong."); return (0,''); } $sdbm->Lock; if (defined $DB{$key}) { $dbm = $DB{$key}; if ($img eq $dbm->{basic}) { $ret = $dbm->{score} || 0.001; $dinfo = $dbm->{dinfo} || ''; $dbm->{fname} = $fname; $dbm->{ctype} = $ctype; infolog("Updating $txt info File:'$fname' Type:'$ctype'"); $DB{$key} = $dbm; } } if ($ret == 0) { my $then = time - ($conf->{focr_db_max_days}*86400); foreach my $k (keys %DB) { $dbm = $DB{$k}; $hash = $dbm->{basic} ? $dbm->{basic} : "0:0:0:0::$k"; if (within_threshold($digest,$hash)) { $ret = $dbfile eq $conf->{focr_db_hash} ? $dbm->{score} : $dbm->{match}; $txt = 'Approx'; $dinfo = $dbm->{dinfo} || ''; infolog("Found in: <$dbfile>"); last; } # Has the record expired?? $dbm->{check} = $now - 1 unless defined $dbm->{check}; if ($dbm->{check} < $then) { infolog("Expiring <$k> older than $conf->{focr_db_max_days} days"); delete $DB{$k}; } } } if ($ret>0) { $dbm->{match}++; if ($dbfile eq $conf->{focr_db_hash}) { $ret = sprintf("%0.3f",$dbm->{score}); infolog("Found Score <$ret> for $txt Image Hash"); } infolog("Matched [$dbm->{match}] time(s). Prev match: ".fmt_time(time - $dbm->{check})); $dbm->{check} = time; $DB{$key} = $dbm; } $sdbm->UnLock; undef $sdbm; untie %DB; return ($ret,$dinfo); } elsif ($conf->{focr_enable_image_hashing} == 1) { $ret = open HASH, $conf->{focr_digest_db}; unless($ret) { warnlog("No Image Hash database found at \"$conf->{focr_digest_db}\", or permissions wrong."); return (0,''); } while () { chomp; ($ret,$hash) = split('::',$_,2); if (within_threshold($digest,$hash)) { infolog("Found Score <$ret> for Hash <$hash>"); return ($ret,''); } } close HASH; return (0,''); } } sub add_image_hash_db { my $conf = get_config(); return if ($conf->{focr_enable_image_hashing} == 0); my $digest = $_[0]; my $score = $_[1]; my $ret = 0; if ($conf->{focr_enable_image_hashing} == 3) { unless (defined $conf->{focr_mysql_ddb}) { warnlog("Connection to MySQL server unavailable"); return; } my $db = $conf->{focr_mysql_db}; my $ddb = $conf->{focr_mysql_ddb}; my $table = $_[2] || $conf->{focr_mysql_hash}; my $fname = $_[3] || ''; my $ctype = $_[4] || 'image'; my $ftype = $_[5] || 0; my $dinfo = $_[6] || ''; infolog("Adding Hash to table: \"$db.$table\" with score \"$score\""); my $sql; my ($img,$key) = split('::',$digest,2); if (defined $key) { $sql = "select basic from $db.$table where $table.key='$key'"; my @data = $ddb->selectrow_array($sql); if (scalar(@data)>0) { if ($conf->{focr_mysql_update_hash}) { infolog("Hash already in $db.$table updating..."); $sql = "update $db.$table set "; my @params; unless ($data[1] eq $img) { $sql .= "basic=?,"; push @params,$img; } unless ($data[2] eq $fname) { $sql .= "fname=?,"; push @params,$fname; } unless ($data[3] eq $ctype) { $sql .= "ctype=?,"; push @params,$ctype; } unless ($data[4] == $ftype) { $sql .= "ftype=?,"; push @params,$ftype; } unless ($data[8] == $score) { $sql .= "score=?,"; push @params,$score; } unless ($data[9] == $dinfo) { $sql .= "dinfo=?,"; push @params,$dinfo; } $sql =~ s/,$//; $sql .= " where $table.key='$key'"; $ddb->do($sql,undef,@params); foreach my $p (@params) { $sql =~ s/\?/$p/; } debuglog($sql); } else { infolog("Hash already in $db.$table skipping..."); } } else { my @params = ( $key, $img, $fname, $ctype, $ftype, ($table eq $conf->{focr_mysql_hash} ? 0 : 1), time, time, $score, $dinfo); $sql = "insert into $db.$table values (?,?,?,?,?,?,?,?,?,?)"; $ddb->do($sql,undef,@params); foreach my $p (@params) { $sql =~ s/\?/$p/; } debuglog($sql); } } } elsif ($conf->{focr_enable_image_hashing} == 2) { import MLDBM qw(DB_File Storable); my $dbfile = $_[2] || $conf->{focr_db_hash}; my %DB = (); my $sdbm; $sdbm = tie %DB, 'MLDBM::Sync', $dbfile, O_CREAT|O_RDWR or $ret++; if ($ret>0) { warnlog("Unable to open/create Image Hash database at \"$dbfile\", check permissions."); return; } $sdbm->Lock; infolog("Adding Hash to \"$dbfile\" with score \"$score\""); my ($img,$key) = split('::',$digest,2); if (defined $key) { my $dbm = $DB{$key}; $dbm->{fname} = $_[3]; $dbm->{ctype} = $_[4]; $dbm->{ftype} = $_[5]; $dbm->{dinfo} = $_[6]; $dbm->{basic} = $img; $dbm->{score} = $score; $dbm->{input} = $dbm->{check} = time; $dbm->{match} = $dbfile eq $conf->{focr_db_hash} ? 0 : 1; $DB{$key} = $dbm; } $sdbm->UnLock; undef $sdbm; untie %DB; } elsif ($conf->{focr_enable_image_hashing} == 1) { if (-e $conf->{focr_digest_db}) { $ret = open DB, ">>$conf->{focr_digest_db}"; } else { $ret = open DB, ">$conf->{focr_digest_db}"; } unless ($ret) { warnlog("Unable to open/create Image Hash database at \"$conf->{focr_digest_db}\", check permissions."); return; } infolog("Adding Hash to \"$conf->{focr_digest_db}\""); flock( DB, LOCK_EX ); seek( DB, 0, 2 ); print DB "${score}::${digest}\n"; close(DB); } debuglog("Digest: $digest"); } sub calc_image_hash { my $conf = get_config(); my $imgdir = get_tmpdir(); my $thresref = get_thresholds(); my %Threshold = %$thresref; my $pfile = $_[0]; my $pic = $_[1]; my $hash; foreach my $a (qw/ppmhist/) { #pamfile unless (defined $conf->{"focr_bin_$a"}) { errorlog("calc_image_hash cannot exec $a"); return (1, ''); } } unless (-r $pfile) { errorlog("Cannot read $pfile"); return(1, ''); } my ($r, @stdout_data) = save_execute( "$conf->{focr_bin_ppmhist} -noheader $pfile", undef, ">$imgdir/ppmhist.info", ">/dev/null", 1); if ($r) { chomp $r; errorlog("$conf->{focr_bin_ppmhist}: ". ($r<0) ? 'Timed out' : 'Error' ." [$r], skipping..."); return (1, ''); } my $cnt = 0; my $c = scalar(@stdout_data); my $s = (stat($pfile))[7] || 0; $hash = sprintf "%d:%d:%d:%d",$s, defined $pic->{height} ? $pic->{height} : 0, defined $pic->{width} ? $pic->{width} : 0, $c; if ($Threshold{max_hash}) { foreach (@stdout_data) { $_ =~ s/ +/ /g; my(@d) = split(' ', $_); $hash .= sprintf("::%d:%d:%d:%d:%d",@d); if ($cnt++ ge $Threshold{max_hash}) { last; } } } debuglog("Got: <$hash>"); return(0, $hash); } sub fmt_time { my $when = $_[0]; my $ret; if ($when>86400) { my $d = int($when/86400); $when -= $d*86400; $ret = "$d days,"; } if ($when>3600) { my $h = int($when/3600); $when -= $h*3600; $ret .= " $h hrs."; } if ($when>60) { my $m = int($when/60); $when -= $m*60; $ret .= " $m min."; } if ($when>0) { $ret .= " $when sec."; } $ret .= " ago"; return $ret; } 1; FuzzyOcr-3.6.0/FuzzyOcr/Logging.pm0000644000175000001440000000523311207335640016362 0ustar decoderusers# <@LICENSE> # Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to you under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at: # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # package FuzzyOcr::Logging; use base 'Exporter'; our @EXPORT_OK = qw(debuglog errorlog infolog warnlog logfile); use Mail::SpamAssassin::Logger qw(log_message would_log); use FileHandle; use Fcntl ':flock'; use POSIX qw(strftime); sub logfile { my $conf = FuzzyOcr::Config::get_config(); my $logtext = $_[0]; my $time = strftime("%Y-%m-%d %H:%M:%S",localtime(time)); $logtext =~ s/\n/\n /g; unless ( open LOGFILE, ">>", $conf->{focr_logfile} ) { warn "Can't open $conf->{focr_logfile} for writing, check permissions"; return; } flock( LOGFILE, LOCK_EX ); seek( LOGFILE, 0, 2 ); print LOGFILE "$time [$$] $logtext\n"; close LOGFILE; } sub _not_debug { return $Mail::SpamAssassin::Logger::LOG_SA{level} != 3; } sub _log { my $conf = FuzzyOcr::Config::get_config(); my $type = $_[0]; my @lines = split('\n',$_[1]); foreach (@lines) { log_message($type,"FuzzyOcr: $_"); } } sub errorlog { my $conf = FuzzyOcr::Config::get_config(); _log("error",$_[0]) if $conf->{focr_log_stderr}; if (defined $conf->{focr_logfile}) { logfile($_[0]); } } sub warnlog { my $conf = FuzzyOcr::Config::get_config(); _log("warn",$_[0]) if $conf->{focr_log_stderr}; if (defined $conf->{focr_logfile} and ($conf->{focr_verbose} >= 1)) { logfile($_[0]); } } sub infolog { my $conf = FuzzyOcr::Config::get_config(); unless (_not_debug()) { _log("info",$_[0]) if $conf->{focr_log_stderr}; } if (defined $conf->{focr_logfile} and ($conf->{focr_verbose} >= 2)) { logfile($_[0]); } } sub debuglog { my $conf = FuzzyOcr::Config::get_config(); unless (_not_debug()) { _log("dbg",$_[0]) if $conf->{focr_log_stderr}; } if (defined $conf->{focr_logfile} and ($conf->{focr_verbose} >= 3)) { logfile($_[0]); } } 1; FuzzyOcr-3.6.0/FuzzyOcr/Misc.pm0000644000175000001440000002161211207335640015666 0ustar decoderusers# <@LICENSE> # Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to you under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at: # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # use strict; package FuzzyOcr::Misc; use base 'Exporter'; our @EXPORT_OK = qw(max removedirs removedir save_execute); use lib qw(..); use FuzzyOcr::Config qw(set_pid unset_pid get_config get_timeout kill_pid); use FuzzyOcr::Logging qw(debuglog errorlog warnlog infolog); use Time::HiRes qw( gettimeofday tv_interval ); use POSIX qw(WIFEXITED WIFSIGNALED WIFSTOPPED WEXITSTATUS WTERMSIG WSTOPSIG); # Provide some misc helper functions sub max { unless ( defined( $_[0] ) and defined( $_[1] ) ) { return 0 } unless ( defined( $_[0] ) ) { return $_[1] } unless ( defined( $_[1] ) ) { return $_[0] } if ( $_[0] < $_[1] ) { return $_[1] } else { return $_[0] } } sub removedirs { my @dirs = @_; foreach my $dir (@dirs) { removedir($dir); } } sub removedir { my $dir = $_[0]; return unless -d $dir; opendir D, $dir; my @files = readdir D; closedir D; foreach my $f (@files) { next if $f eq '.'; next if $f eq '..'; my $ff = Mail::SpamAssassin::Util::untaint_file_path("$dir/$f"); unless (unlink $ff) { errorlog("Cannot remove: $ff"); } } debuglog("Remove DIR: $dir"); unless(rmdir $dir) { errorlog("Cannot remove DIR: $dir"); } } # map process termination status number to a string, and append optional # user error mesage, returning the resulting string sub exit_status_str($;$) { my($stat,$err) = @_; my($str); if (WIFEXITED($stat)) { $str = sprintf("exit %d", WEXITSTATUS($stat)); } elsif (WIFSTOPPED($stat)) { $str = sprintf("stopped, signal %d", WSTOPSIG($stat)); } else { $str = sprintf("DIED on signal %d (%04x)", WTERMSIG($stat),$stat); } $str .= ', '.$err if defined $err && $err != 0; $str; } # POSIX::open a file or dup an existing fd (Perl open syntax), with a # requirement that it gets opened on a prescribed file descriptor $fd_target; # this subroutine is usually called from a forked process prior to exec sub open_on_specific_fd($$) { my($fd_target,$fname) = @_; my($flags) = 0; my($mode) = 0640; $fname =~ s/^< *//; $fname =~ s/^>> *// and $flags |= POSIX::O_CREAT|POSIX::O_WRONLY|POSIX::O_APPEND; $fname =~ s/^> *// and $flags |= POSIX::O_CREAT|POSIX::O_WRONLY; POSIX::close($fd_target); # ignore error, we may have just closed a log my($fd_got) = POSIX::open($fname,$flags,$mode); defined $fd_got or die "Can't open $fname, flags=$flags: $!"; $fd_got = 0 + $fd_got; # turn into numeric, avoid: "0 but true" if ($fd_got != $fd_target) { # dup, ensuring we get a specified descriptor # POSIX mandates we got the lowest fd available (but some kernels have # bugs), let's be explicit that we require a specified file descriptor defined POSIX::dup2($fd_got,$fd_target) or die "Can't dup2 from $fd_got to $fd_target: $!"; if ($fd_got > 2) { # let's get rid of the original fd, unless 0,1,2 my($err); defined POSIX::close($fd_got) or $err = $!; $err = defined $err ? ": $err" : ''; } } $fd_got; } sub save_execute { my $conf = get_config(); my $t = get_timeout(); my ($cmd, $stdin, $stdout, $stderr, $return_stdout) = @_; my ($pgm,@args) = split(' ',$cmd); $stdout = '>/dev/null' unless $stdout; $stderr = '>/dev/null' unless $stderr; my $retcode; my $begin = [gettimeofday]; if ($conf->{'focr_global_timeout'}) { my $pid = fork(); if (not defined $pid) { errorlog("Can't fork to execute external programs! Aborting"); return -1; } elsif (not $pid) { eval { # must not use die in forked process, or we end up with # two running daemons! debuglog("Exec : $cmd"); debuglog("Stdin : $stdin") if (defined $stdin); debuglog("Stdout: $stdout") if (defined $stdout); debuglog("Stderr: $stderr") if (defined $stderr); # there is no guarantee that Perl file handles STDIN, STDOUT # and STDERR are on file descriptors 0, 1, 2. Let's make sure # the exec'd program receives the right files on file descr 0,1,2 if (defined $stdin) { open_on_specific_fd(0, $stdin); } if (defined $stdout) { open_on_specific_fd(1, $stdout); } if (defined $stderr) { open_on_specific_fd(2, $stderr); } exec {$pgm} ($pgm,@args); die "failed to exec $cmd: $!"; }; # couldn't open file descriptors or exec failed chomp($@); my($msg) = "save_execute: $@\n"; # try to get some attention, log and stderr may be closed POSIX::write(2,$msg,length($msg)); print STDERR $msg; POSIX::_exit(8); # must avoid END and destructor processing! } else { set_pid($pid); wait(); $retcode = $?; debuglog(sprintf("Elapsed [%s]: %.6f sec. (%s: %s)", $pid, tv_interval($begin, [gettimeofday]), $pgm, exit_status_str($retcode))); unset_pid(); if ($return_stdout and $stdout !~ m,/dev/null,i) { $stdout =~ tr/>|; close(INFILE); return($retcode, @stdout_data); } return $retcode; } } else { my @stdout_data; my $pid; $t->run_and_catch(sub { $pid = fork(); if (not defined $pid) { errorlog("Can't fork to execute external programs! Aborting"); return -1; } elsif (not $pid) { eval { # must not use die in forked process, or we end up with # two running daemons! debuglog("Exec : $cmd"); debuglog("Stdin : $stdin") if (defined $stdin); debuglog("Stdout: $stdout") if (defined $stdout); debuglog("Stderr: $stderr") if (defined $stderr); if (defined $stdin) { open_on_specific_fd(0, $stdin); } if (defined $stdout) { open_on_specific_fd(1, $stdout); } if (defined $stderr) { open_on_specific_fd(2, $stderr); } exec {$pgm} ($pgm,@args); die "failed to exec $cmd: $!"; }; # couldn't open file descriptors or exec failed chomp($@); my($msg) = "save_execute: $@\n"; # try to get some attention, log and stderr may be closed POSIX::write(2,$msg,length($msg)); print STDERR $msg; POSIX::_exit(8); # must avoid END and destructor processing! } else { set_pid($pid); wait(); $retcode = $?; debuglog(sprintf("Elapsed [%s]: %.6f sec. (%s: %s)", $pid, tv_interval($begin, [gettimeofday]), $pgm, exit_status_str($retcode))); unset_pid(); if ($return_stdout and $stdout !~ m,/dev/null,i) { $stdout =~ tr/>|; close(INFILE); } } }); if ($t->timed_out()) { errorlog("Command \"$cmd\" timed out after $conf->{focr_timeout} seconds."); errorlog("Consider decreasing your load and/or increasing the timeout."); errorlog("Killing possibly running pid..."); my ($ret, $pid) = kill_pid(); if ($ret > 0) { infolog("Successfully killed PID $pid"); } elsif ($ret < 0) { warnlog("No processes left... this shouldn't happen..."); } else { warnlog("Failed to kill PID $pid, possibly stale process"); } return -1; } else { if ($return_stdout) { return($retcode, @stdout_data); } else { return $retcode; } } } } 1; FuzzyOcr-3.6.0/FuzzyOcr/Config.pm0000644000175000001440000007755611207335640016222 0ustar decoderusers# <@LICENSE> # Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to you under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at: # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # use strict; package FuzzyOcr::Config; use lib qw(..); use FuzzyOcr::Logging qw(debuglog infolog warnlog errorlog); use FuzzyOcr::Scanset; use FuzzyOcr::Preprocessor; use Mail::SpamAssassin::Logger; use Fcntl qw(O_RDWR O_CREAT); use base 'Exporter'; our @EXPORT_OK = qw/ parse_config finish_parsing_end get_config set_config set_pid unset_pid kill_pid set_tmpdir get_tmpdir get_all_tmpdirs get_pms save_pms get_timeout get_scansets get_preprocessor get_thresholds get_wordlist get_mysql_ddb get_db_ref set_db_ref read_words /; use constant HAS_DBI => eval { require DBI; }; use constant HAS_DBD_MYSQL => eval { require DBD::mysql; }; use constant HAS_MLDBM => eval { require MLDBM; require MLDBM::Sync;}; use constant HAS_DB_FILE => eval { require DB_File; }; use constant HAS_STORABLE => eval { require Storable; }; #Defines the defaults and reads the configuration and wordlists our %Threshold = (); our %words = (); our @scansets; our @preprocessors; our $conf; our $pms; our $timeout; our $pid; our $tmpdir; our @tmpdirs; our $dbref; # State of the plugin, already initialized? our $initialized = 0; our @bin_utils = qw/gifsicle giffix giftext gifinter giftopnm jpegtopnm pngtopnm bmptopnm tifftopnm ppmhist pamfile ocrad gocr/; our @paths = qw(/usr/local/netpbm/bin /usr/local/bin /usr/bin); my @img_types = qw/gif png jpeg bmp tiff/; sub get_timeout { unless (defined $timeout) { $timeout = Mail::SpamAssassin::Timeout->new({ secs => $conf->{focr_timeout} }); } return $timeout; } sub set_pid { $pid = shift; debuglog("Saved pid: $pid"); } sub unset_pid { $pid = 0; } sub kill_pid { if ($pid) { infolog("Sending SIGTERM to pid: $pid",2); my $ret = kill POSIX::SIGTERM, $pid; # Wait for zombie process if the process is a zombie (i.e. SIGTERM didn't work) wait(); return ($ret, $pid); } else { return (-1, 0); } } sub set_tmpdir { $tmpdir = shift; push(@tmpdirs, $tmpdir); } sub get_tmpdir { return $tmpdir; } sub get_all_tmpdirs { return @tmpdirs; } sub save_pms { $pms = shift; } sub get_pms { return $pms; } sub get_config { return $conf; } sub get_wordlist { return \%words; } sub get_scansets { if ($conf->{focr_autosort_scanset}) { @scansets = sort { $b->{hit_counter} <=> $a->{hit_counter} } @scansets; } return \@scansets; } sub get_preprocessor { my ($label) = @_; foreach (@preprocessors) { if ($_->{label} eq $label) { return $_; } } return 0; } sub get_thresholds { return \%Threshold; } sub set_db_ref { $dbref = shift; } sub get_db_ref { return $dbref; } sub get_mysql_ddb { return undef unless (HAS_DBI and HAS_DBD_MYSQL); my $conf = get_config(); my %dopts = ( AutoCommit => 1 ); my $dsn = "dbi:mysql:database=".$conf->{focr_mysql_db}; if (defined($conf->{focr_mysql_socket})) { $dsn .= ";mysql_socket=".$conf->{focr_mysql_socket}; } else { $dsn .= ";host=".$conf->{focr_mysql_host}; $dsn .= ";port=".$conf->{focr_mysql_port} if $conf->{focr_mysql_port} != 3306; } debuglog("Connecting to: $dsn"); my $ddb = DBI->connect($dsn, $conf->{focr_mysql_user}, $conf->{focr_mysql_pass}, \%dopts); return $ddb; } sub set_config { my($self, $conf) = @_; my @cmds = (); foreach my $t (qw/s h w cn/) { push (@cmds, { setting => 'focr_threshold_'.$t, default => 0.01, type => $Mail::SpamAssassin::Conf::CONF_TYPE_NUMERIC }); } foreach my $t (qw/c max_hash/) { push (@cmds, { setting => 'focr_threshold_'.$t, default => 5, type => $Mail::SpamAssassin::Conf::CONF_TYPE_NUMERIC }); } foreach my $t (qw/height width/) { push (@cmds, { setting => 'focr_min_'.$t, default => 4, type => $Mail::SpamAssassin::Conf::CONF_TYPE_NUMERIC }); push (@cmds, { setting => 'focr_max_'.$t, default => 800, type => $Mail::SpamAssassin::Conf::CONF_TYPE_NUMERIC }); } push (@cmds, { setting => 'focr_threshold', default => 0.25, type => $Mail::SpamAssassin::Conf::CONF_TYPE_NUMERIC }); push (@cmds, { setting => 'focr_counts_required', default => 2, type => $Mail::SpamAssassin::Conf::CONF_TYPE_NUMERIC }); push (@cmds, { setting => 'focr_verbose', default => 1, code => sub { my ($self, $key, $value, $line) = @_; unless (defined $value && $value !~ m/^$/) { return $Mail::SpamAssassin::Conf::MISSING_REQUIRED_VALUE; } unless ($value =~ m/^[0-9]+$/) { return $Mail::SpamAssassin::Conf::INVALID_VALUE; } $self->{focr_verbose} = $value+0; } }); push (@cmds, { setting => 'focr_timeout', default => 10, type => $Mail::SpamAssassin::Conf::CONF_TYPE_NUMERIC }); push (@cmds, { setting => 'focr_global_timeout', default => 0, type => $Mail::SpamAssassin::Conf::CONF_TYPE_BOOL }); push (@cmds, { setting => 'focr_logfile', type => $Mail::SpamAssassin::Conf::CONF_TYPE_STRING }); push (@cmds, { setting => 'focr_log_stderr', default => 1, type => $Mail::SpamAssassin::Conf::CONF_TYPE_BOOL }); push (@cmds, { setting => 'focr_log_pmsinfo', default => 1, type => $Mail::SpamAssassin::Conf::CONF_TYPE_BOOL }); push (@cmds, { setting => 'focr_enable_image_hashing', default => 0, code => sub { my ($self, $key, $value, $line) = @_; unless (defined $value && $value !~ m/^$/) { return $Mail::SpamAssassin::Conf::MISSING_REQUIRED_VALUE; } unless ($value =~ m/^[0123]$/) { return $Mail::SpamAssassin::Conf::INVALID_VALUE; } $self->{focr_enable_image_hashing} = $value+0; } }); push (@cmds, { setting => 'focr_hashing_learn_scanned', default => 1, type => $Mail::SpamAssassin::Conf::CONF_TYPE_BOOL }); push (@cmds, { setting => 'focr_skip_updates', default => 0, type => $Mail::SpamAssassin::Conf::CONF_TYPE_BOOL }); push (@cmds, { setting => 'focr_digest_db', default => "/etc/mail/spamassassin/FuzzyOcr.hashdb", type => $Mail::SpamAssassin::Conf::CONF_TYPE_STRING }); push (@cmds, { setting => 'focr_global_wordlist', default => "/etc/mail/spamassassin/FuzzyOcr.words", type => $Mail::SpamAssassin::Conf::CONF_TYPE_STRING }); push (@cmds, { setting => 'focr_personal_wordlist', default => "__userstate__/FuzzyOcr.words", type => $Mail::SpamAssassin::Conf::CONF_TYPE_STRING }); push (@cmds, { setting => 'focr_no_homedirs', default => 0, type => $Mail::SpamAssassin::Conf::CONF_TYPE_BOOL }); push (@cmds, { setting => 'focr_db_hash', default => "/etc/mail/spamassassin/FuzzyOcr.db", type => $Mail::SpamAssassin::Conf::CONF_TYPE_STRING }); push (@cmds, { setting => 'focr_db_safe', default => "/etc/mail/spamassassin/FuzzyOcr.safe.db", type => $Mail::SpamAssassin::Conf::CONF_TYPE_STRING }); push (@cmds, { setting => 'focr_db_max_days', default => 35, type => $Mail::SpamAssassin::Conf::CONF_TYPE_NUMERIC }); push (@cmds, { setting => 'focr_keep_bad_images', default => 0, code => sub { my ($self, $key, $value, $line) = @_; unless (defined $value && $value !~ m/^$/) { return $Mail::SpamAssassin::Conf::MISSING_REQUIRED_VALUE; } unless ($value =~ m/^[012]$/) { return $Mail::SpamAssassin::Conf::INVALID_VALUE; } $self->{focr_keep_bad_images} = $value+0; } }); push (@cmds, { setting => 'focr_strip_numbers', default => 1, type => $Mail::SpamAssassin::Conf::CONF_TYPE_NUMERIC }); push (@cmds, { setting => 'focr_twopass_scoring_factor', default => 1.5, type => $Mail::SpamAssassin::Conf::CONF_TYPE_NUMERIC }); push (@cmds, { setting => 'focr_unique_matches', default => 0, type => $Mail::SpamAssassin::Conf::CONF_TYPE_BOOL }); push (@cmds, { setting => 'focr_score_ham', default => 0, type => $Mail::SpamAssassin::Conf::CONF_TYPE_BOOL }); push (@cmds, { setting => 'focr_base_score', default => 5, type => $Mail::SpamAssassin::Conf::CONF_TYPE_NUMERIC }); push (@cmds, { setting => 'focr_add_score', default => 1, type => $Mail::SpamAssassin::Conf::CONF_TYPE_NUMERIC }); push (@cmds, { setting => 'focr_corrupt_score', default => 2.5, type => $Mail::SpamAssassin::Conf::CONF_TYPE_NUMERIC }); push (@cmds, { setting => 'focr_corrupt_unfixable_score', default => 5, type => $Mail::SpamAssassin::Conf::CONF_TYPE_NUMERIC }); push (@cmds, { setting => 'focr_wrongctype_score', default => 1.5, type => $Mail::SpamAssassin::Conf::CONF_TYPE_NUMERIC }); push (@cmds, { setting => 'focr_wrongext_score', default => 1.5, type => $Mail::SpamAssassin::Conf::CONF_TYPE_NUMERIC }); push (@cmds, { setting => 'focr_autodisable_score', default => 10, type => $Mail::SpamAssassin::Conf::CONF_TYPE_NUMERIC }); push (@cmds, { setting => 'focr_autodisable_negative_score', default => -5, type => $Mail::SpamAssassin::Conf::CONF_TYPE_NUMERIC }); push (@cmds, { setting => 'focr_path_bin', default => '/usr/local/netpbm/bin:/usr/local/bin:/usr/bin', type => $Mail::SpamAssassin::Conf::CONF_TYPE_STRING }); foreach (@bin_utils) { push (@cmds, { setting => 'focr_bin_'.$_, type => $Mail::SpamAssassin::Conf::CONF_TYPE_STRING }); } foreach (@img_types) { push (@cmds, { setting => 'focr_skip_'.$_, default => 0, type => $Mail::SpamAssassin::Conf::CONF_TYPE_BOOL }); push (@cmds, { setting => 'focr_max_size_'.$_, type => $Mail::SpamAssassin::Conf::CONF_TYPE_NUMERIC }); } push (@cmds, { setting => 'focr_scan_pdfs', default => 0, type => $Mail::SpamAssassin::Conf::CONF_TYPE_BOOL }); push (@cmds, { setting => 'focr_pdf_maxpages', default => 1, type => $Mail::SpamAssassin::Conf::CONF_TYPE_NUMERIC }); push (@cmds, { setting => 'focr_scanset_file', default => '/etc/mail/spamassassin/FuzzyOcr.scansets', type => $Mail::SpamAssassin::Conf::CONF_TYPE_STRING }); push (@cmds, { setting => 'focr_preprocessor_file', default => '/etc/mail/spamassassin/FuzzyOcr.preps', type => $Mail::SpamAssassin::Conf::CONF_TYPE_STRING }); push (@cmds, { setting => 'focr_minimal_scanset', default => 1, type => $Mail::SpamAssassin::Conf::CONF_TYPE_BOOL }); push (@cmds, { setting => 'focr_autosort_scanset', default => 1, type => $Mail::SpamAssassin::Conf::CONF_TYPE_BOOL }); push (@cmds, { setting => 'focr_autosort_buffer', default => 10, type => $Mail::SpamAssassin::Conf::CONF_TYPE_NUMERIC }); push (@cmds, { setting => 'focr_mysql_host', default => 'localhost', type => $Mail::SpamAssassin::Conf::CONF_TYPE_STRING }); push (@cmds, { setting => 'focr_mysql_port', default => 3306, type => $Mail::SpamAssassin::Conf::CONF_TYPE_NUMERIC }); push (@cmds, { setting => 'focr_mysql_socket', type => $Mail::SpamAssassin::Conf::CONF_TYPE_STRING }); push (@cmds, { setting => 'focr_mysql_db', default => 'FuzzyOcr', type => $Mail::SpamAssassin::Conf::CONF_TYPE_STRING }); push (@cmds, { setting => 'focr_mysql_hash', default => 'Hash', type => $Mail::SpamAssassin::Conf::CONF_TYPE_STRING }); push (@cmds, { setting => 'focr_mysql_safe', default => 'Safe', type => $Mail::SpamAssassin::Conf::CONF_TYPE_STRING }); push (@cmds, { setting => 'focr_mysql_update_hash', default => 0, type => $Mail::SpamAssassin::Conf::CONF_TYPE_BOOL }); foreach (qw/user pass/) { push (@cmds, { setting => 'focr_mysql_'.$_, default => 'fuzzyocr', type => $Mail::SpamAssassin::Conf::CONF_TYPE_STRING }); } $conf->{parser}->register_commands(\@cmds); } sub parse_config { my ($self, $opts) = @_; # Don't parse a config twice if ($initialized) { return 1; } if ($opts->{key} eq 'focr_end_config') { $conf = $opts->{conf}; my $main = $self->{main}; my $retcode; # Parse preprocessor file my $pfile = $conf->{'focr_preprocessor_file'}; infolog("Starting preprocessor parser for file \"$pfile\"..."); ($retcode, @preprocessors) = parse_preprocessors($pfile); if ($retcode) { errorlog("Error parsing preprocessor file \"$pfile\", aborting..."); return 0; } # Parse scanset file my $sfile = $conf->{'focr_scanset_file'}; infolog("Starting scanset parser for file \"$sfile\"..."); ($retcode, @scansets) = parse_scansets($sfile); if ($retcode) { errorlog("Error parsing scanset file \"$sfile\", aborting..."); return 0; } return 1; } elsif ($opts->{key} eq 'focr_bin_helper') { my @cmd; $conf = $opts->{conf}; my $val = $opts->{value}; $val =~ s/[\s]*//g; debuglog("focr_bin_helper: '$val'"); foreach my $bin (split(',',$val)) { unless (grep {m/$bin/} @bin_utils) { push @bin_utils, $bin; push (@cmd, { setting => 'focr_bin_'.$bin, type => $Mail::SpamAssassin::Conf::CONF_TYPE_STRING }); } else { warnlog("$bin is already defined, skipping..."); } } if (scalar(@cmd)>0) { infolog("Adding <".scalar(@cmd)."> new helper apps"); $conf->{parser}->register_commands(\@cmd) } return 1; } return 0; } sub finish_parsing_end { my ($self, $opts) = @_; # Don't call this function twice if ($initialized) { return 1; } my $main = $self->{main}; $conf = $opts->{conf}; # find external binaries @paths = split(/:/, $conf->{focr_path_bin}); infolog("Searching in: $_") foreach @paths; foreach my $a (@bin_utils) { my $b = "focr_bin_$a"; if (defined $conf->{$b} and ! -x $conf->{$b}) { infolog("cannot exec $a, removing..."); delete $conf->{$b}; } if (defined $conf->{$b}) { debuglog("Using $a => $conf->{$b}"); } else { foreach my $p (@paths) { my $f = "$p/$a"; next unless -x $f; $conf->{$b} = $f; last; } if (defined $conf->{$b}) { infolog("Using $a => $conf->{$b}"); } else { warnlog("Cannot find executable for $a"); } } } # Allow scanning if in debug mode? $conf->{focr_autodisable_score} = 1000 if $Mail::SpamAssassin::Logger::LOG_SA{level} == 3; # Extract Thresholds foreach my $k (keys %{$conf}) { if ($k =~ m/^focr_threshold_(\S+)/) { $Threshold{$1} = $conf->{$k}; debuglog("Threshold[$1] => $conf->{$k}"); } } # Display All Options foreach my $k (sort keys %{$conf}) { next unless $k =~ m/^focr_/; next if $k =~ m/^focr_bin_/; next if $k =~ m/^focr_mysql_pass/; next if $k =~ m/^focr_threshold_/; debuglog(" $k => ".$conf->{$k}); } unless (@scansets) { warn("No scansets loaded, did you remove the \"focr_config_end\" line at the end of the .cf file?"); } foreach my $prep (@preprocessors) { my $preplabel = $prep->{label}; my $off = ($prep->{command} =~ m/^\$/) ? 1 : 0; my $t = 'focr_bin_'.substr($prep->{command},$off); #Replace command with full path if known $prep->{command} = $conf->{$t} if defined $conf->{$t}; my $prepcmd = $prep->{command}; if (defined $prep->{args}) { $prepcmd .= ' ' . $prep->{args}; } infolog("Loaded preprocessor $preplabel: $prepcmd"); } foreach my $scan (@scansets) { my $scanlabel = $scan->{label}; my $off = ($scan->{command} =~ m/^\$/) ? 1 : 0; my $t = 'focr_bin_'.substr($scan->{command},$off); #Replace command with full path if known $scan->{command} = $conf->{$t} if defined $conf->{$t}; my $scancmd = $scan->{command}; if (defined $scan->{args}) { $scancmd .= ' ' . $scan->{args}; } infolog("Using scan $scanlabel: $scancmd"); } if ($conf->{focr_enable_image_hashing} == 3) { unless (HAS_DBI and HAS_DBD_MYSQL) { $conf->{focr_enable_image_hashing} = 0; errorlog("Disable Image Hashing"); errorlog("Missing DBI") unless HAS_DBI; errorlog("Missing DBD::mysql") unless HAS_DBD_MYSQL; } # Warn if MLDBM databases are present, but can't be imported unless (HAS_MLDBM and HAS_DB_FILE and HAS_STORABLE and (-r $conf->{focr_db_hash} or -r $conf->{focr_db_safe})) { infolog("Importing for MLDBM databases not available (dependencies missing)"); } } if ($conf->{focr_enable_image_hashing} == 2) { unless (HAS_MLDBM and HAS_DB_FILE and HAS_STORABLE) { $conf->{focr_enable_image_hashing} = 0; errorlog("Disable Image Hashing"); errorlog("Missing MLDBM and/or MLDBM::Sync") unless HAS_MLDBM; errorlog("Missing DB_File") unless HAS_DB_FILE; errorlog("Missing Storable") unless HAS_STORABLE; } } unless ($conf->{focr_skip_updates}) { if ($conf->{focr_enable_image_hashing} == 2 and -r $conf->{focr_digest_db}) { import MLDBM qw(DB_File Storable); my %DB; my $dbm; my $sdbm; my $err = 0; my $now = time - ($conf->{focr_db_max_days}*86400); $sdbm = tie %DB, 'MLDBM::Sync', $conf->{focr_db_hash} or $err++; if ($err) { errorlog("Could not open \"$conf->{focr_db_hash}\""); } else { $sdbm->Lock; my $hash = 0; infolog("Expiring records prior to: ".scalar(localtime($now))); foreach my $k (keys %DB) { my $db = $DB{$k}; if ($db->{check} < $now) { infolog("Expire: <$k> Reason: $db->{check} < $now"); delete $DB{$k}; $hash++; } } infolog("Expired <$hash> Image Hashes after $conf->{focr_db_max_days} day(s)") if ($hash>0); $hash = 0; open HASH, $conf->{focr_digest_db}; while () { chomp; my($score,$basic,$key) = split('::',$_,3); next if (defined $DB{$key}); $dbm = $DB{$key}; $dbm->{score} = $score; $dbm->{basic} = $basic; $dbm->{input} = $dbm->{check} = time; $dbm->{match} = 1; $DB{$key} = $dbm; $hash++; } close HASH; infolog("Imported <$hash> Image Hashes from \"$conf->{focr_digest_db}\"") if ($hash>0); $hash = scalar(keys %DB); infolog("<$hash> Known BAD Image Hashes Available"); $sdbm->UnLock; undef $sdbm; untie %DB; } $err = 0; $sdbm = tie %DB, 'MLDBM::Sync', $conf->{focr_db_safe} or $err++; if ($err) { errorlog("Could not open \"$conf->{focr_db_safe}\""); } else { $sdbm->Lock; my $hash = 0; foreach my $k (keys %DB) { my $db = $DB{$k}; if ($db->{check} < $now) { infolog("Expire: <$k> Reason: $db->{check} < $now"); delete $DB{$k}; $hash++; } } infolog("Expired <$hash> Image Hashes after $conf->{focr_db_max_days} day(s)") if ($hash>0); $hash = scalar(keys %DB); infolog("<$hash> Known GOOD Image Hashes Available"); $sdbm->UnLock; undef $sdbm; untie %DB; } } if ($conf->{focr_enable_image_hashing} == 3 and defined (my $ddb = get_mysql_ddb()) and (-r $conf->{focr_db_hash} or -r $conf->{focr_db_safe}) and HAS_MLDBM and HAS_DB_FILE and HAS_STORABLE) { import MLDBM qw(DB_File Storable); my $db = $conf->{focr_mysql_db}; my $tab = $conf->{focr_mysql_hash}; my $file = $conf->{focr_db_hash}; my %DB; my $dbm; my $sdbm; my $err = 0; $sdbm = tie %DB, 'MLDBM::Sync', $file or $err++; if ($err) { errorlog("Could not open \"$file\""); } else { $sdbm->ReadLock; foreach my $k (keys %DB) { my $dbm = $DB{$k}; my $sql = qq(select score from $db.$tab where $tab.key='$k'); my @data = $ddb->selectrow_array($sql); unless (scalar(@data)>0) { $sql = "insert into $db.$tab values ('$k'"; foreach my $y (qw/basic fname ctype/) { my $val = defined($dbm->{$y}) ? $dbm->{$y} : ''; $sql .= ",'$val'"; } if ($dbm->{ctype} =~ m/gif/i) { $sql .= ",'1'"; } elsif ($dbm->{ctype} =~ m/jpg|jpeg/i) { $sql .= ",'2'"; } elsif ($dbm->{ctype} =~ m/png/i) { $sql .= ",'3'"; } elsif ($dbm->{ctype} =~ m/bmp/i) { $sql .= ",'4'"; } elsif ($dbm->{ctype} =~ m/tiff/i) { $sql .= ",'5'"; } else { $sql .= ",'0'"; } foreach my $y (qw/match input check score dinfo/) { my $val = defined($dbm->{$y}) ? $dbm->{$y} : ''; $sql .= ",'$val'"; } $sql .= ")"; debuglog($sql); $ddb->do($sql); $err++; } } $sdbm->UnLock; undef $sdbm; untie %DB; infolog("Stored [$err] Hashes in $db.$tab") if $err>0; } $tab = $conf->{focr_mysql_safe}; $file = $conf->{focr_db_safe}; $err = 0; $sdbm = tie %DB, 'MLDBM::Sync', $file or $err++; if ($err) { errorlog("Could not open \"$file\""); } else { $sdbm->ReadLock; foreach my $k (keys %DB) { my $dbm = $DB{$k}; my $sql = qq(select score from $db.$tab where $tab.key='$k'); my @data = $ddb->selectrow_array($sql); unless (scalar(@data)>0) { $sql = "insert into $db.$tab values ('$k'"; foreach my $y (qw/basic fname ctype/) { my $val = defined($dbm->{$y}) ? $dbm->{$y} : ''; $sql .= ",'$val'"; } if ($dbm->{ctype} =~ m/gif/i) { $sql .= ",'1'"; } elsif ($dbm->{ctype} =~ m/jpg|jpeg/i) { $sql .= ",'2'"; } elsif ($dbm->{ctype} =~ m/png/i) { $sql .= ",'3'"; } elsif ($dbm->{ctype} =~ m/bmp/i) { $sql .= ",'4'"; } elsif ($dbm->{ctype} =~ m/tiff/i) { $sql .= ",'5'"; } else { $sql .= ",'0'"; } foreach my $y (qw/match input check score dinfo/) { my $val = defined($dbm->{$y}) ? $dbm->{$y} : ''; $sql .= ",'$val'"; } $sql .= ")"; debuglog($sql); $ddb->do($sql); $err++; } } $sdbm->UnLock; undef $sdbm; untie %DB; infolog("Stored [$err] Hashes in $db.$tab") if $err>0; } debuglog("done updating MySQL database"); $ddb->disconnect; } } read_words( $conf->{focr_global_wordlist} , 'Global'); 1; # Important: We parsed the config now and did all post config parsing stuff # don't do it again (for amavisd and other 3rd party applications using the SA API directly) $initialized = 1; } sub read_words { my $wfile = $_[0]; return unless ( -e $wfile ); my $tfile = $_[1] || 'Personal'; unless ( -r $wfile ) { warnlog("Cannot read $tfile wordlist: \"$wfile\"\n Please check file path and permissions are correct."); return; } my $cnt = 0; open WORDLIST, "<$wfile"; while(my $w = ) { chomp($w); $w =~ s/\s*//; $w =~ s/#(.*)//; next unless $w; my $wt = $conf->{focr_threshold}; if ($w =~ /^(.*?)::(0(\.\d+){0,1})/) { ($w, $wt) = (lc($1), $2); $wt = $conf->{focr_threshold} unless ($wt =~ m/[\d\.]+/); } else { $wt *= 0.750 if length($w) == 5; $wt *= 0.500 if length($w) == 4; $wt *= 0.250 if length($w) < 4; } $words{$w} = $wt; $cnt++; } close WORDLIST; infolog("Added <$cnt> words from \"$wfile\"") if ($cnt>0); } sub parse_scansets { my ($file) = @_; unless (open(SFILE, "<$file")) { warnlog("Failed to open scanset file \"$file\", aborting..."); return 1; } my @slabels; my @scanlist; my $scanset; while() { # We are in the middle of a scanset if(defined $scanset) { # Strip comments and ignore blank lines chomp($_); $_ =~ s/(\s)*#(.*)//; unless ($_) { next; } debuglog("line $_"); if ($_ =~ /^(\s)*preprocessors(\s)*=(\s)*(.*)$/i) { my $prep = $4; $scanset->{preprocessors} = $prep; $prep =~ s/ //g; my @preps = split(',', $prep); foreach (@preps) { unless(get_preprocessor($_)) { errorlog("Unknown preprocessor \"$_\" used in scansets line $., aborting..."); return 1; } } } elsif ($_ =~ /^(\s)*(command|args)(\s)*=(\s)*(.*)$/i) { my $tag = $2; my $val = $5; if ($val =~ /(<|>|\||;)/) { errorlog("OCR $tag may not contain \"< > | ;\", aborting..."); return 1; } $scanset->{$tag} = $val; } elsif ($_ =~ /^(\s)*force_output_in(\s)*=(\s)*(.*)$/i) { $scanset->{force_output_in} = $4; # Scanset is closing } elsif ($_ =~ /^(\s)*\}/) { foreach my $tag (qw/command args/) { unless ($scanset->{$tag}) { my $l = $scanset->{label}; errorlog("Scanset \"$l\" is missing $tag line, aborting..."); return 1; } } push(@scanlist, $scanset); $scanset = undef; } else { errorlog("Unknown token at line $., aborting..."); return 1; } # Start a new scanset } elsif ($_ =~ /^(\s)*scanset(\s)+(.+?)(\s)+\{$/i) { debuglog("line $_"); if (grep $_ eq $3, @slabels) { errorlog("Label already used earlier in line $., aborting..."); return 1; } $scanset = FuzzyOcr::Scanset->new($3); push(@slabels, $3); } } close(SFILE); return (0, @scanlist); } sub parse_preprocessors { my ($file) = @_; unless (open(PFILE, "<$file")) { errorlog("Failed to open preprocessor file \"$file\", aborting..."); return 1; } my @plabels; my @preplist; my $preprocessor; while() { chomp($_); $_ =~ s/(\s)*#(.*)//; unless ($_) { next; } # We are in the middle of a preprocessor if(defined $preprocessor) { debuglog("line: $_"); if ($_ =~ /^(\s)*(command|args)(\s)*=(\s)*(.*)$/i) { my $tag = $2; my $val = $5; if ($val =~ /(<|>|\||;)/) { errorlog("Preprocessor $tag may not contain \"< > | ;\", aborting..."); return 1; } $preprocessor->{$tag} = $val; # Preprocessor is closing } elsif ($_ =~ /^(\s)*\}/) { foreach my $tag (qw/command/) { unless ($preprocessor->{$tag}) { my $l = $preprocessor->{label}; errorlog("Preprocessor \"$l\" is missing $tag line, aborting..."); return 1; } } push(@preplist, $preprocessor); $preprocessor = undef; } else { errorlog("Unknown token at line $., aborting..."); return 1; } # Start a new preprocessor } elsif ($_ =~ /^(\s)*preprocessor(\s)+(.+?)(\s)+\{$/i) { debuglog("line: $_"); if (grep $_ eq $3, @plabels) { errorlog("Error, label already used earlier in line $., aborting..."); return 1; } $preprocessor = FuzzyOcr::Preprocessor->new($3); push(@plabels, $3); } } close(PFILE); return (0, @preplist); } 1; FuzzyOcr-3.6.0/FuzzyOcr.mysql0000644000175000001440000000225211207335640015523 0ustar decoderusersCREATE DATABASE FuzzyOcr; use FuzzyOcr; CREATE TABLE `Hash` ( `key` varchar(255) NOT NULL default '', `basic` varchar(64) NOT NULL default '', `fname` varchar(160) NOT NULL default '', `ctype` varchar(64) NOT NULL default '', `ftype` smallint(5) unsigned NOT NULL default '0', `match` int(10) unsigned NOT NULL default '0', `input` int(10) unsigned NOT NULL default '0', `check` int(10) unsigned NOT NULL default '0', `score` decimal(8,3) NOT NULL default '0.000', `dinfo` text NOT NULL, PRIMARY KEY (`key`) ) TYPE=MyISAM; CREATE TABLE `Safe` ( `key` varchar(255) NOT NULL default '', `basic` varchar(64) NOT NULL default '', `fname` varchar(160) NOT NULL default '', `ctype` varchar(64) NOT NULL default '', `ftype` smallint(5) unsigned NOT NULL default '0', `match` int(10) unsigned NOT NULL default '0', `input` int(10) unsigned NOT NULL default '0', `check` int(10) unsigned NOT NULL default '0', `score` decimal(8,3) NOT NULL default '0.000', `dinfo` text NOT NULL, PRIMARY KEY (`key`) ) TYPE=MyISAM; GRANT SELECT,UPDATE,INSERT,DELETE ON FuzzyOcr.* TO fuzzyocr@localhost IDENTIFIED BY 'fuzzyocr'; FuzzyOcr-3.6.0/FuzzyOcr.pm0000644000175000001440000012353511207337733015007 0ustar decoderusers# <@LICENSE> # Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to you under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at: # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # # FuzzyOcr plugin, version 3.6 # # written by Christian Holler (decoder_at_own-hero_dot_net) # and Jorge Valdes (jorge_at_joval_dot_info) package FuzzyOcr; use strict; use warnings; use POSIX; use Fcntl ':flock'; use Mail::SpamAssassin; use Mail::SpamAssassin::Logger; use Mail::SpamAssassin::Util; use Mail::SpamAssassin::Timeout; use Mail::SpamAssassin::Plugin; use Time::HiRes qw( gettimeofday tv_interval ); use String::Approx 'adistr'; use FileHandle; use lib qw(/etc/mail/spamassassin); # Allow placing of FuzzyOcr in siteconfigdir use FuzzyOcr::Logging qw(debuglog errorlog warnlog infolog); use FuzzyOcr::Config qw(kill_pid get_tmpdir set_tmpdir get_all_tmpdirs get_pms save_pms get_timeout get_mysql_ddb get_scansets get_wordlist set_config get_config parse_config finish_parsing_end read_words); use FuzzyOcr::Hashing qw(check_image_hash_db add_image_hash_db calc_image_hash); use FuzzyOcr::Deanimate qw(deanimate); use FuzzyOcr::Scoring qw(wrong_ctype wrong_extension corrupt_img known_img_hash); use FuzzyOcr::Misc qw(max removedir removedirs save_execute); our @ISA = qw(Mail::SpamAssassin::Plugin); # constructor: register the eval rule sub new { my ( $class, $mailsa ) = @_; $class = ref($class) || $class; my $self = $class->SUPER::new($mailsa); bless( $self, $class ); $self->register_eval_rule("fuzzyocr_check"); $self->register_eval_rule("dummy_check"); $self->set_config($mailsa->{conf}); return $self; } sub dummy_check { return 0; } sub fuzzyocr_check { my ( $self, $pms ) = @_; my $conf = get_config(); save_pms($pms); my $end; my $begin = [gettimeofday]; if ($conf->{focr_global_timeout}) { my $t = get_timeout(); debuglog("Global Timeout set at ".$conf->{focr_timeout}." sec."); $t->run(sub { $end = fuzzyocr_do( $self, $conf, $pms ); }); if ($t->timed_out()) { infolog("Scan timed out after $conf->{focr_timeout} seconds."); infolog("Killing possibly running pid..."); my ($ret, $pid) = kill_pid(); if ($ret > 0) { infolog("Successfully killed PID $pid"); } elsif ($ret < 0) { infolog("No processes left... exiting"); } else { infolog("Failed to kill PID $pid, stale process!"); } infolog("Removing possibly leftover tempdirs..."); removedirs(get_all_tmpdirs()); return 0; } } else { $end = fuzzyocr_do( $self, $conf, $pms ); } debuglog("Processed in ". sprintf("%.6f",tv_interval($begin, [gettimeofday])) ." sec."); return $end; } sub fuzzyocr_do { my ( $self, $conf, $pms ) = @_; my $internal_score = 0; my $current_score = $pms->get_score(); my $score = $conf->{focr_autodisable_score} || 100; if ( $current_score > $score ) { infolog("Scan canceled, message has already more than $score points ($current_score)."); return 0; } my $nscore = $conf->{focr_autodisable_negative_score} || -100; if ( $current_score < $nscore ) { infolog("Scan canceled, message has less than $nscore points ($current_score)."); return 0; } my $imgdir; my %imgfiles = (); my @found = (); my @hashes = (); my $cnt = 0; my $imgerr = 0; my $main = $self->{main}; debuglog("Starting FuzzyOcr..."); #Show PMS info if asked to if ($conf->{focr_log_pmsinfo}) { my $msgid = $pms->get('Message-Id') ? $pms->get('Message-Id') : ""; my $from = $pms->get('From') ? $pms->get('From') : ""; my $to = $pms->get('To') ? $pms->get('To') : ""; chomp($from, $to, $msgid); infolog("Processing Message with ID \"$msgid\" ($from -> $to)"); } foreach my $p ( $pms->{msg}->find_parts(qr(^image\b)i), $pms->{msg}->find_parts(qr(Application/Octet-Stream)i), $pms->{msg}->find_parts(qr(application/pdf)i) ) { my $ctype = $p->{'type'}; my $fname = $p->{'name'} || 'unknown'; if (($fname eq 'unknown') and (defined $p->{'headers'}->{'content-id'}) ){ $fname = join('',@{$p->{'headers'}->{'content-id'}}); $fname =~ s/[<>]//g; $fname =~ tr/\@\$\%\&/_/s; } my $filename = $fname; $filename =~ tr{a-zA-Z0-9\-.}{_}cs; debuglog("fname: \"$fname\" => \"$filename\""); my $pdata = $p->decode(); my $pdatalen = length($pdata); my $w = 0; my $h = 0; if ( substr($pdata,0,3) eq "\x47\x49\x46" ) { ## GIF File $imgfiles{$filename}{ftype} = 1; ($w,$h) = unpack("vv",substr($pdata,6,4)); infolog("GIF: [${h}x${w}] $filename ($pdatalen)"); $imgfiles{$filename}{width} = $w; $imgfiles{$filename}{height} = $h; } elsif ( substr($pdata,0,2) eq "\xff\xd8" ) { ## JPEG File my @Markers = (0xC0,0xC1,0xC2,0xC3,0xC5,0xC6,0xC7,0xC9,0xCA,0xCB,0xCD,0xCE,0xCF); my $pos = 2; while ($pos < $pdatalen) { my ($b,$m) = unpack("CC",substr($pdata,$pos,2)); $pos += 2; if ($b != 0xff) { infolog("Invalid JPEG image"); $pos = $pdatalen + 1; last; } my $skip = 0; foreach my $mm (@Markers) { if ($mm == $m) { $skip++; last; } } last if ($skip); $pos += unpack("n",substr($pdata,$pos,2)); } if ($pos > $pdatalen) { errorlog("Cannot find image dimensions"); } else { ($h,$w) = unpack("nn",substr($pdata,$pos+3,4)); infolog("JPEG: [${h}x${w}] $filename ($pdatalen)"); $imgfiles{$filename}{ftype} = 2; $imgfiles{$filename}{height} = $h; $imgfiles{$filename}{width} = $w; } } elsif ( substr($pdata,0,4) eq "\x89\x50\x4e\x47" ) { # PNG File ($w,$h) = unpack("NN",substr($pdata,16,8)); $imgfiles{$filename}{ftype} = 3; $imgfiles{$filename}{width} = $w; $imgfiles{$filename}{height} = $h; infolog("PNG: [${h}x${w}] $filename ($pdatalen)"); } elsif ( substr($pdata,0,2) eq "BM" ) { ## BMP File ($w,$h) = unpack("VV",substr($pdata,18,8)); $imgfiles{$filename}{ftype} = 4; $imgfiles{$filename}{width} = $w; $imgfiles{$filename}{height} = $h; infolog("BMP: [${h}x${w}] $filename ($pdatalen)"); } elsif ( ## TIFF File (substr($pdata,0,4) eq "\x4d\x4d\x00\x2a") or (substr($pdata,0,4) eq "\x49\x49\x2a\x00") ) { my $worder = (substr($pdata,0,2) eq "\x4d\x4d") ? 0 : 1; my $offset = unpack($worder?"V":"N",substr($pdata,4,4)); my $number = unpack($worder?"v":"n",substr($pdata,$offset,2)) - 1; foreach my $n (0 .. $number) { my $add = 2 + ($n * 12); my ($id,$tag,$cnt,$val) = unpack($worder?"vvVV":"nnNN",substr($pdata,$offset+$add,12)); $h = $val if ($id == 256); $w = $val if ($id == 257); last if ($h != 0 and $w != 0); } infolog("TIFF: [${h}x${w}] $filename ($pdatalen) ($worder)"); infolog("Cannot determine size of TIFF image, setting to '1x1'") if ($h == 0 and $w == 0); $imgfiles{$filename}{ftype} = 5; $imgfiles{$filename}{width} = $w ? $w : 1; $imgfiles{$filename}{height} = $h ? $h : 1; } elsif (substr($pdata,0,5) eq "\x25\x50\x44\x46\x2d") { my $version = substr($pdata,5,3); infolog("PDF: [version $version] $filename ($pdatalen)"); $imgfiles{$filename}{ftype} = 6; $imgfiles{$filename}{version} = $version; $imgfiles{$filename}{width} = 0; $imgfiles{$filename}{height} = 0; } #Skip unless we found the right header unless (defined $imgfiles{$filename}{ftype}) { infolog("Skipping file with content-type=\"$ctype\" name=\"$fname\""); delete $imgfiles{$filename}; next; } if ($imgfiles{$filename}{ftype} == 6) { unless ($conf->{focr_scan_pdfs}) { infolog("Skipping PDF file: PDF Scanning was disabled in config"); next; } } else { #Skip images that cannot contain text if ($imgfiles{$filename}{height} < $conf->{focr_min_height}) { infolog("Skipping image: height < $conf->{focr_min_height}"); delete $imgfiles{$filename}; next; } #Skip images that cannot contain text if ($imgfiles{$filename}{width} < $conf->{focr_min_width}) { infolog("Skipping image: width < $conf->{focr_min_width}"); delete $imgfiles{$filename}; next; } #Skip too big images, screenshots etc if ($imgfiles{$filename}{height} > $conf->{focr_max_height}) { infolog("Skipping image: height > $conf->{focr_max_height}"); delete $imgfiles{$filename}; next; } #Skip too big images, screenshots etc if ($imgfiles{$filename}{width} > $conf->{focr_max_width}) { infolog("Skipping image: width > $conf->{focr_max_width}"); delete $imgfiles{$filename}; next; } } #Found Image!! Get a temporary dir to save image $imgdir = Mail::SpamAssassin::Util::secure_tmpdir(); unless ($imgdir) { errorlog("Scan canceled, cannot create Image TMPDIR."); return 0; } set_tmpdir($imgdir); #Generete unique filename to store image my $imgfilename = Mail::SpamAssassin::Util::untaint_file_path( $imgdir . "/" . $filename ); my $unique = 0; while (-e $imgfilename) { $imgfilename = Mail::SpamAssassin::Util::untaint_file_path( $imgdir . "/" . chr(65+$unique) . "." . $filename ); $unique++; } #Save important constants $imgfiles{$filename}{fname} = $fname; $imgfiles{$filename}{ctype} = $ctype; $imgfiles{$filename}{fsize} = $pdatalen; $imgfiles{$filename}{fpath} = $imgfilename; #Save Image to disk. unless (open PICT, ">$imgfilename") { errorlog("Cannot write \"$imgfilename\", skipping..."); delete $imgfiles{$filename}; removedir($imgdir); next; } binmode PICT; print PICT $pdata; close PICT; debuglog("Saved: $imgfilename"); #Increment valid image file counter $cnt++; #keep raw email for debugging later my $rawfilename = $imgdir . "/raw.eml"; if (open RAW, ">$rawfilename") { print RAW $pms->{msg}->get_pristine(); close RAW; debuglog("Saved: $rawfilename"); } } if ($cnt == 0) { debuglog("Skipping OCR, no image files found..."); return 0; } infolog("Found: $cnt images"); $cnt = 0; if ($conf->{focr_enable_image_hashing} == 3) { $conf->{focr_mysql_ddb} = get_mysql_ddb(); } # Try to load personal wordlist unless ($conf->{focr_no_homedirs}) { if ($conf->{focr_personal_wordlist} =~ m/^\//) { read_words( $conf->{focr_personal_wordlist} ); } else { my $peruserlist = $main->sed_path($conf->{focr_personal_wordlist}); if ( -r $peruserlist ) { read_words( $peruserlist ); } else { # Only complain if the file exists if ( -e $peruserlist ) { errorlog("Cannot read personal_wordlist: $peruserlist, skipping..."); } } } } my $haserr; foreach my $filename (keys %imgfiles) { my $pic = $imgfiles{$filename}; #infolog("Analyzing file with content-type=\"$$pic{ctype}\""); my @used_scansets = (); my $corrupt = 0; my $suffix = 0; my $generic_ctype = 0; my $digest; my $file = $$pic{fpath}; my $tfile = $file; my $pfile = $file . ".pnm"; my $efile = $file . ".err"; debuglog("pfile => $pfile"); debuglog("efile => $efile"); #Open ERRORLOG $haserr = $Mail::SpamAssassin::Logger::LOG_SA{level} == 3; if ($haserr) { $haserr = open RAWERR, ">$imgdir/raw.err"; debuglog("Errors to: $imgdir/raw.err") if ($haserr>0); } my $mimetype = $$pic{ctype}; if($mimetype =~ m'application/octet-stream'i) { $generic_ctype = 1; } if($$pic{fname} =~ /\.([\w-]+)$/) { $suffix = $1; } if ($suffix) { debuglog("File has Content-Type \"$mimetype\" and File Extension \"$suffix\""); } else { debuglog("File has Content-Type \"$mimetype\" and no File Extension"); } if ( $$pic{ftype} == 1 ) { infolog("Found GIF header name=\"$$pic{fname}\""); if ($conf->{focr_skip_gif}) { infolog("Skipping image check"); next; } if (defined($conf->{focr_max_size_gif}) and ($$pic{fsize} > $conf->{focr_max_size_gif})) { infolog("GIF file size ($$pic{fsize}) exceeds maximum file size for this format, skipping..."); next; } if ( ($$pic{ctype} !~ /gif/i) and not $generic_ctype) { wrong_ctype( "GIF", $$pic{ctype} ); $internal_score += $conf->{'focr_wrongctype_score'}; } if ( $suffix and $suffix !~ /gif/i) { wrong_extension( "GIF", $suffix); $internal_score += $conf->{'focr_wrongext_score'}; } my $interlaced_gif = 0; my $image_count = 0; foreach my $a (qw/gifsicle giftext giffix gifinter giftopnm/) { unless (defined $conf->{"focr_bin_$a"}) { errorlog("Cannot exec $a, skipping image"); next; } } my @stderr_data; my ($retcode, @stdout_data) = save_execute( "$conf->{focr_bin_giftext} $file", undef, ">$imgdir/giftext.info", ">>$imgdir/giftext.err", 1); if ($retcode<0) { # only care if we timed out chomp $retcode; errorlog("$conf->{focr_bin_giftext} Timed out [$retcode], skipping..."); ++$imgerr if $conf->{focr_keep_bad_images}>0; next; } foreach (@stdout_data) { unless ($interlaced_gif) { if ( $_ =~ /Image is Interlaced/i ) { $interlaced_gif = 1; } } if ( $_ =~ /^Image #/ ) { $image_count++; } } if ($interlaced_gif or ($image_count > 1)) { infolog("Image is interlaced or animated..."); } else { infolog("Image is single non-interlaced..."); $tfile .= "-fixed.gif"; printf RAWERR "## $conf->{focr_bin_giffix} $file >$tfile 2>>$efile\n" if ($haserr>0); $retcode = save_execute("$conf->{focr_bin_giffix} $file", undef, ">$tfile", ">>$efile"); if ($retcode<0) { # only care if we timed out chomp $retcode; errorlog("$conf->{focr_bin_giffix}: Timed out [$retcode], skipping..."); printf RAWERR "?? Timed out > $retcode\n" if ($haserr>0); ++$imgerr if $conf->{focr_keep_bad_images}>0; next; } if (open ERR, $efile) { @stderr_data = ; close ERR; foreach (@stderr_data) { if ( $_ =~ /GIF-LIB error/i ) { $corrupt = $_; last; } } } } my $fixedsize = (stat($tfile))[7]; if (defined($conf->{focr_max_size_gif}) and ($fixedsize > $conf->{focr_max_size_gif})) { infolog("Fixed GIF file size ($fixedsize) exceeds maximum file size for this format, skipping..."); next; } if ($corrupt) { if ($interlaced_gif or ($image_count > 1)) { infolog("Skipping corrupted interlaced image..."); corrupt_img($conf->{focr_corrupt_unfixable_score}, $corrupt); $internal_score += $conf->{focr_corrupt_unfixable_score}; next; } if (-z $tfile) { infolog("Uncorrectable corruption detected, skipping non-interlaced image..."); corrupt_img($conf->{focr_corrupt_unfixable_score}, $corrupt); $internal_score += $conf->{focr_corrupt_unfixable_score}; next; } infolog("Image is corrupt, but seems fixable, continuing..."); corrupt_img($conf->{focr_corrupt_score}, $corrupt); $internal_score += $conf->{focr_corrupt_score}; } if ($image_count > 1) { infolog("File contains <$image_count> images, deanimating..."); $tfile = deanimate($tfile); } if ($interlaced_gif) { infolog("Processing interlaced_gif $tfile..."); my $cfile = $tfile; if ($tfile =~ m/\.gif$/i) { $tfile =~ s/\.gif$/-fixed.gif/i; } else { $tfile .= ".gif"; } printf RAWERR qq(## $conf->{focr_bin_gifinter} $cfile >$tfile 2>>$efile\n) if ($haserr>0); $retcode = save_execute("$conf->{focr_bin_gifinter} $cfile", undef, ">$tfile", ">>$efile"); if ($retcode<0) { chomp $retcode; printf RAWERR "?? Timed out > $retcode\n" if ($haserr>0); errorlog("$conf->{focr_bin_gifinter}: Timed out [$retcode], skipping..."); ++$imgerr if $conf->{focr_keep_bad_images}>0; next; } elsif ($retcode>0) { chomp $retcode; printf RAWERR "?? [$retcode] returned from $conf->{focr_bin_gifinter}\n" if ($haserr>0); errorlog("$conf->{focr_bin_gifinter}: Returned [$retcode], skipping..."); ++$imgerr if $conf->{focr_keep_bad_images}>0; next; } } printf RAWERR qq(## $conf->{focr_bin_giftopnm} $tfile >$pfile 2>>$efile\n) if ($haserr>0); $retcode = save_execute("$conf->{focr_bin_giftopnm} $tfile", undef, ">$pfile", ">>$efile"); if ($retcode<0) { chomp $retcode; printf RAWERR "?? Timed out > $retcode\n" if ($haserr>0); errorlog("$conf->{focr_bin_giftopnm}: Timed out [$retcode], skipping..."); ++$imgerr if $conf->{focr_keep_bad_images}>0; next; } elsif ($retcode>0) { chomp $retcode; printf RAWERR "?? [$retcode] returned from $conf->{focr_bin_giftopnm}\n" if ($haserr>0); errorlog("$conf->{focr_bin_giftopnm}: Returned [$retcode], skipping..."); ++$imgerr if $conf->{focr_keep_bad_images}>0; next; } } elsif ( $$pic{ftype} == 2 ) { infolog("Found JPEG header name=\"$$pic{fname}\""); if ($conf->{focr_skip_jpeg}) { infolog("Skipping image check"); next; } if (defined($conf->{focr_max_size_jpeg}) and ($$pic{fsize} > $conf->{focr_max_size_jpeg})) { infolog("JPEG file size ($$pic{fsize}) exceeds maximum file size for this format, skipping..."); next; } if ( ($$pic{ctype} !~ /(jpeg|jpg)/i) and not $generic_ctype) { wrong_ctype( "JPEG", $$pic{ctype} ); $internal_score += $conf->{'focr_wrongctype_score'}; } if ( $suffix and $suffix !~ /(jpeg|jpg|jfif)/i) { wrong_extension( "JPEG", $suffix); $internal_score += $conf->{'focr_wrongext_score'}; } foreach my $a (qw/jpegtopnm/) { unless (defined $conf->{"focr_bin_$a"}) { errorlog("Cannot exec $a, skipping image"); next; } } printf RAWERR qq(## $conf->{focr_bin_jpegtopnm} $file >$pfile 2>>$efile\n) if ($haserr>0); my $retcode = save_execute("$conf->{focr_bin_jpegtopnm} $file", undef, ">$pfile", ">>$efile"); if ($retcode<0) { chomp $retcode; printf RAWERR "?? Timed out > $retcode\n" if ($haserr>0); errorlog("$conf->{focr_bin_jpegtopnm}: Timed out [$retcode], skipping..."); ++$imgerr if $conf->{focr_keep_bad_images}>0; next; } elsif ($retcode>0) { chomp $retcode; printf RAWERR "?? [$retcode] returned from $conf->{focr_bin_jpegtopnm}\n" if ($haserr>0); errorlog("$conf->{focr_bin_jpegtopnm}: Returned [$retcode], skipping..."); ++$imgerr if $conf->{focr_keep_bad_images}>0; next; } } elsif ( $$pic{ftype} == 3 ) { infolog("Found PNG header name=\"$$pic{fname}\""); if ($conf->{focr_skip_png}) { infolog("Skipping image check"); next; } if (defined($conf->{focr_max_size_png}) and ($$pic{fsize} > $conf->{focr_max_size_png})) { infolog("PNG file size ($$pic{fsize}) exceeds maximum file size for this format, skipping..."); next; } if ( ($$pic{ctype} !~ /png/i) and not $generic_ctype) { wrong_ctype( "PNG", $$pic{ctype} ); $internal_score += $conf->{'focr_wrongctype_score'}; } if ( $suffix and $suffix !~ /(png)/i) { wrong_extension( "PNG", $suffix); $internal_score += $conf->{'focr_wrongext_score'}; } foreach my $a (qw/pngtopnm/) { unless (defined $conf->{"focr_bin_$a"}) { errorlog("Cannot exec $a, skipping image"); next; } } printf RAWERR qq(## $conf->{focr_bin_pngtopnm} $file >$pfile 2>>$efile\n) if ($haserr>0); my $retcode = save_execute("$conf->{focr_bin_pngtopnm} $file", undef, ">$pfile", ">>$efile"); if ($retcode<0) { chomp $retcode; printf RAWERR "?? Timed out > $retcode\n" if ($haserr>0); errorlog("$conf->{focr_bin_pngtopnm}: Timed out [$retcode], skipping..."); ++$imgerr if $conf->{focr_keep_bad_images}>0; next; } elsif ($retcode>0) { chomp $retcode; printf RAWERR "?? [$retcode] returned from $conf->{focr_bin_pngtopnm}\n" if ($haserr>0); errorlog("$conf->{focr_bin_pngtopnm}: Returned [$retcode], skipping..."); ++$imgerr if $conf->{focr_keep_bad_images}>0; next; } } elsif ( $$pic{ftype} == 4 ) { infolog("Found BMP header name=\"$$pic{fname}\""); if ($conf->{focr_skip_bmp}) { infolog("Skipping image check"); next; } if (defined($conf->{focr_max_size_bmp}) and ($$pic{fsize} > $conf->{focr_max_size_bmp})) { infolog("BMP file size ($$pic{fsize}) exceeds maximum file size for this format, skipping..."); next; } if ( ($$pic{ctype} !~ /bmp/i) and not $generic_ctype) { wrong_ctype( "BMP", $$pic{ctype} ); $internal_score += $conf->{'focr_wrongctype_score'}; } if ( $suffix and $suffix !~ /(bmp)/i) { wrong_extension( "BMP", $suffix); $internal_score += $conf->{'focr_wrongext_score'}; } foreach my $a (qw/bmptopnm/) { unless (defined $conf->{"focr_bin_$a"}) { errorlog("Cannot exec $a, skipping image"); next; } } printf RAWERR qq(## $conf->{focr_bin_bmptopnm} $file >$pfile 2>>$efile\n) if ($haserr>0); my $retcode = save_execute("$conf->{focr_bin_bmptopnm} $file", undef, ">$pfile", ">>$efile"); if ($retcode<0) { chomp $retcode; printf RAWERR "?? Timed out > $retcode\n" if ($haserr>0); errorlog("$conf->{focr_bin_bmptopnm}: Timed out [$retcode], skipping..."); ++$imgerr if $conf->{focr_keep_bad_images}>0; next; } elsif ($retcode>0) { chomp $retcode; printf RAWERR "?? [$retcode] returned from $conf->{focr_bin_bmptopnm}\n" if ($haserr>0); errorlog("$conf->{focr_bin_bmptopnm}: Returned [$retcode], skipping..."); ++$imgerr if $conf->{focr_keep_bad_images}>0; next; } } elsif ( $$pic{ftype} == 5 ) { infolog("Found TIFF header name=\"$$pic{fname}\""); if ($conf->{focr_skip_tiff}) { infolog("Skipping image check"); next; } if (defined($conf->{focr_max_size_tiff}) and ($$pic{fsize} > $conf->{focr_max_size_tiff})) { infolog("TIFF file size ($$pic{fsize}) exceeds maximum file size for this format, skipping..."); next; } if ( ($$pic{ctype} !~ /tif/i) and not $generic_ctype) { wrong_ctype( "TIFF", $$pic{ctype} ); $internal_score += $conf->{'focr_wrongctype_score'}; } if ( $suffix and $suffix !~ /tif/i) { wrong_extension( "TIFF", $suffix); $internal_score += $conf->{'focr_wrongext_score'}; } foreach my $a (qw/tifftopnm/) { unless (defined $conf->{"focr_bin_$a"}) { errorlog("Cannot exec $a, skipping image"); next; } } printf RAWERR qq(## $conf->{focr_bin_tifftopnm} $file >$pfile 2>>$efile\n) if ($haserr>0); my $retcode = save_execute("$conf->{focr_bin_tifftopnm} $file", undef, ">$pfile", ">>$efile"); if ($retcode<0) { chomp $retcode; printf RAWERR "?? Timed out > $retcode\n" if ($haserr>0); errorlog("$conf->{focr_bin_tifftopnm}: Timed out [$retcode], skipping..."); ++$imgerr if $conf->{focr_keep_bad_images}>0; next; } elsif ($retcode>0) { chomp $retcode; printf RAWERR "?? [$retcode] returned from $conf->{focr_bin_tifftopnm}\n" if ($haserr>0); errorlog("$conf->{focr_bin_tifftopnm}: Returned [$retcode], skipping..."); ++$imgerr if $conf->{focr_keep_bad_images}>0; next; } } elsif ($$pic{ftype} == 6) { infolog("Found PDF header name=\"$$pic{fname}\""); my $missing_bin = 0; foreach my $a (qw/pdftops pstopnm pdfinfo/) { unless (defined $conf->{"focr_bin_$a"}) { $missing_bin = 1; errorlog("Cannot exec $a, skipping image"); next; } } if ($missing_bin) { next; } my @stderr_data; my ($retcode, @stdout_data) = save_execute( "$conf->{focr_bin_pdfinfo} $file", undef, ">$imgdir/pdfinfo.info", ">>$imgdir/pdfinfo.err", 1); foreach (@stdout_data) { if ($_ =~ /^Pages:\s*([0-9]+)/) { $$pic{pages} = $1; } } unless ($$pic{pages}) { infolog("Can't determine page count of PDF Document\n"); } if ($$pic{pages} > $conf->{focr_pdf_maxpages}) { infolog("PDF has too many pages, skipping this file...\n"); next; } if ( ($$pic{ctype} !~ /pdf/i) and not $generic_ctype) { wrong_ctype( "Application/PDF", $$pic{ctype} ); $internal_score += $conf->{'focr_wrongctype_score'}; } $retcode = save_execute("$conf->{focr_bin_pdftops} $file -", undef, ">$file.ps", ">>$efile"); if ($retcode<0) { chomp $retcode; printf RAWERR "?? Timed out > $retcode\n" if ($haserr>0); errorlog("$conf->{focr_bin_pdftops}: Timed out [$retcode], skipping..."); ++$imgerr if $conf->{focr_keep_bad_images}>0; next; } elsif ($retcode>0) { chomp $retcode; printf RAWERR "?? [$retcode] returned from $conf->{focr_bin_pdftops}\n" if ($haserr>0); errorlog("$conf->{focr_bin_pdftops}: Returned [$retcode], skipping..."); ++$imgerr if $conf->{focr_keep_bad_images}>0; next; } $retcode = save_execute("$conf->{focr_bin_pstopnm} -stdout -xsize=1000 $file.ps", undef, ">$pfile", ">>$efile"); if ($retcode<0) { chomp $retcode; printf RAWERR "?? Timed out > $retcode\n" if ($haserr>0); errorlog("$conf->{focr_bin_pstopnm}: Timed out [$retcode], skipping..."); ++$imgerr if $conf->{focr_keep_bad_images}>0; next; } elsif ($retcode>0) { chomp $retcode; printf RAWERR "?? [$retcode] returned from $conf->{focr_bin_pstopnm}\n" if ($haserr>0); errorlog("$conf->{focr_bin_pstopnm}: Returned [$retcode], skipping..."); ++$imgerr if $conf->{focr_keep_bad_images}>0; next; } } else { errorlog("Image type not recognized, unknown format. Skipping this image..."); next; } if($conf->{focr_enable_image_hashing}) { infolog("Calculating image hash for: $pfile"); ($corrupt, $digest) = calc_image_hash($pfile,$pic); if ($corrupt) { infolog("Error calculating the image hash, skipping hash check..."); } else { my ($score, $dinfo, $whash); $whash = $conf->{focr_enable_image_hashing} == 3 ? $conf->{focr_mysql_hash} : $conf->{focr_db_hash}; ($score,$dinfo) = check_image_hash_db($digest, $whash, $$pic{fname}, $$pic{ctype}, $$pic{ftype}); if ($score > 0) { known_img_hash($score,$dinfo); infolog("Message is SPAM. $dinfo") if ($conf->{focr_enable_image_hashing} < 3); removedirs(get_all_tmpdirs()); return 0; } $whash = $conf->{focr_enable_image_hashing} == 3 ? $conf->{focr_mysql_safe} : $conf->{focr_db_safe}; ($score,$dinfo) = check_image_hash_db($digest, $whash, $$pic{fname}, $$pic{ctype}, $$pic{ftype}); if ($score > 0) { infolog("Image in KNOWN_GOOD. Skipping OCR checks..."); next; } } if ($digest eq '') { infolog("Empty Hash, skipping..."); next; } } else { infolog("Image hashing disabled in configuration, skipping..."); } # Note: $current_score is here the score that the message had at the beginning # and $score is the autodisable_score defined in the config # $internal_score describes the score that the message got by FuzzyOcr so far. if ($internal_score + $current_score > $score) { my $total = $internal_score + $current_score; warnlog("FuzzyOcr stopped, message got $internal_score points by other FuzzyOcr tests ($total>$score)."); #infolog("OCR canceled, message got already more than $score points ($total) by other FuzzyOcr tests."); return 0; } my @ocr_results = (); my $scansets = get_scansets(); my $newlist = ''; foreach my $s (@$scansets) { $newlist .= ' ' . $s->{label} . '(' . $s->{hit_counter} . ')'; } infolog("Scanset Order:$newlist"); my $mcnt = 0; my $modus = 0; my $modus_match = 0; my $wref = get_wordlist(); my %words = %$wref; foreach my $scanset (@$scansets) { my $scanlabel = $scanset->{label}; my $scancmd = $scanset->{command}; if ($scancmd =~ m/^\$/) { warnlog("Skipping $scanlabel, invalid command '$scancmd'"); next; } if (($$pic{ftype} != 6) and ($scancmd =~ m/ocrad/) and ($$pic{width} < 16 or $$pic{height} < 16)) { warnlog("Skipping $scanlabel, image too small"); next; } my $cmcnt = 0; my @cfound; if (defined $scanset->{args}) { $scancmd .= ' ' . $scanset->{args}; } printf RAWERR qq(## $scancmd\n) if ($haserr>0); my ($retcode, @result) = $scanset->run($pfile); if ($retcode<0) { if ($retcode == -1) { printf RAWERR qq(Timeout[$conf->{focr_timeout}]: $scancmd\n) if ($haserr>0); errorlog("Timeout[$scanlabel]: \"$scancmd\" took more than $conf->{focr_timeout} sec."); } elsif ($retcode == -2) { printf RAWERR qq(Cannot exec[$scanlabel]: $scancmd\n) if ($haserr>0); errorlog("Cannot execute($scanlabel): \"$scancmd\""); } else { printf RAWERR qq(Unknown error <$retcode>: $scancmd\n) if ($haserr>0); errorlog("Unknown error: [$retcode]..."); } infolog("Skipping scanset, trying next..."); next; } elsif ($retcode>0) { chomp $retcode; my $errstr = "Return code: $retcode, Error: "; $errstr .= join( '', @result ); warnlog("Errors in Scanset \"$scanlabel\""); warnlog($errstr); warnlog("Skipping scanset because of errors, trying next..."); printf RAWERR qq($errstr\n) if ($haserr>0); next; } debuglog("ocrdata=>>".join("",@result)."<<=end"); foreach $modus (0 .. 1) { $cmcnt = 0; @cfound = (); foreach my $ww (keys %words) { my $w = lc $ww; $w =~ s/[^a-z0-9 ]//g; if ($modus) { $w =~ s/ //g; } if ($conf->{focr_strip_numbers}) { $w =~ s/[0-9]//g; } my $wcnt = 0; foreach (@result) { $_ = lc; if ($modus) { s/ //g; } if ($conf->{focr_strip_numbers}) { tr/!;|(0815/iiicoals/; s/[0-9]//g; } else { tr/!;|(/iiic/; } s/[^a-z0-9 ]//g; my $matched = abs(adistr( $w, $_ )); if ( $matched < $words{$ww} ) { $wcnt++; infolog( "Scanset \"$scanlabel\" found word \"$w\" with fuzz of " . sprintf("%0.4f",$matched) . "\nline: \"$_\"" ); if ($conf->{focr_unique_matches}) { last; } } } $cmcnt += $wcnt; if ( ( $conf->{focr_verbose} > 0 ) and ($wcnt) ) { push( @cfound, "\"$w\" in $wcnt lines" ); } } $mcnt = max($mcnt, $cmcnt); if ($mcnt == $cmcnt) { @found = @cfound; } if ((not $modus) and ($cmcnt >= $conf->{focr_counts_required})) { if ($mcnt == $cmcnt) { $modus_match = 0; } debuglog("Enough OCR Hits without space stripping, skipping second matching pass..."); last; } elsif (not $modus) { debuglog("Not enough OCR Hits without space stripping, doing second matching pass..."); if ($mcnt == $cmcnt) { $modus_match = 1; } } } if ($mcnt >= $conf->{focr_counts_required} and $conf->{focr_minimal_scanset}) { infolog("Scanset \"$scanlabel\" generates enough hits ($mcnt), skipping further scansets..."); if ($conf->{focr_autosort_scanset}) { foreach my $s (@$scansets) { if ($s->{label} eq $scanlabel) { if ($s->{hit_counter} < $conf->{focr_autosort_buffer}) { $s->{hit_counter} = $s->{hit_counter} + 1; } } else { if ($s->{hit_counter} > 0) { $s->{hit_counter} = $s->{hit_counter} - 1; } } } } last; } } if ($conf->{focr_enable_image_hashing}) { my $info = join('::',$mcnt,$$pic{fname},$$pic{ctype},$$pic{ftype},$digest); push(@hashes, $info); } # Normal match or match without spaces? if ($modus_match) { $cnt += $mcnt; } else { $cnt += $conf->{focr_twopass_scoring_factor} * $mcnt; } } close RAWERR if ($haserr>0); if ($cnt == 0) { if ($conf->{focr_enable_image_hashing} > 1 and @hashes) { infolog("Message is ham, saving..."); foreach my $h (@hashes) { my ($mcnt,$fname,$ctype,$ftype,$digest) = split('::',$h,5); next if $mcnt; my $whash = $conf->{focr_enable_image_hashing} == 3 ? $conf->{focr_mysql_safe} : $conf->{focr_db_safe}; add_image_hash_db($digest,0,$whash,$fname,$ctype,$ftype); } } } else { my $score = '0.000'; my $debuginfo = ("Words found:\n".join( "\n", @found )."\n($cnt word occurrences found)" ); if ($cnt >= $conf->{focr_counts_required}) { $score = sprintf "%0.3f", $conf->{focr_base_score} + (( $cnt - $conf->{focr_counts_required} ) * $conf->{focr_add_score} ); infolog("Message is spam, score = $score"); } else { $score = sprintf("%0.3f", $conf->{focr_add_score} * $cnt) if $conf->{focr_score_ham}; infolog("Message is ham, score = $score"); } if ($conf->{focr_enable_image_hashing} and $conf->{focr_hashing_learn_scanned} and $score > 0) { foreach my $h (@hashes) { my ($mcnt,$fname,$ctype,$ftype,$digest) = split('::',$h,5); next unless $mcnt; my $whash = $conf->{focr_enable_image_hashing} == 3 ? $conf->{focr_mysql_hash} : $conf->{focr_db_hash}; add_image_hash_db($digest,$score,$whash,$fname,$ctype,$ftype,$debuginfo); } } if ( $conf->{focr_verbose} > 0 and $conf->{focr_verbose} < 3 ) { infolog($debuginfo) unless ($conf->{focr_enable_image_hashing} == 3); } for my $set ( 0 .. 3 ) { $pms->{conf}->{scoreset}->[$set]->{"FUZZY_OCR"} = $score; } #$pms->test_log("Words found:"); #foreach (@found) { # $pms->test_log($_); # } # $pms->test_log("($cnt word occurrences found)"); my @dinfo = split('\n', $debuginfo); foreach (@dinfo) { $pms->test_log($_); } $pms->_handle_hit( "FUZZY_OCR", $score, "BODY: ", "BODY", $pms->{conf}->get_description_for_rule("FUZZY_OCR")); } if ($imgerr == 0 and $conf->{focr_keep_bad_images}<2) { removedirs(get_all_tmpdirs()); } if ($conf->{focr_enable_image_hashing} == 3) { if (defined $conf->{focr_mysql_ddb}) { $conf->{focr_mysql_ddb}->disconnect; } } debuglog("FuzzyOcr ending successfully..."); return 0; } 1; #vim: et ts=4 sw=4 FuzzyOcr-3.6.0/FuzzyOcr.scansets0000644000175000001440000000273111207335640016203 0ustar decoderusers# This file contains the scansets # Do not modify this on your own unless you have read the manual and know what you're doing # Note: If the focr_minimal_scanset option is enabled (default), # not all of these scansets run for every picture. But be aware # that for ham images, all of them will always run. # Standard Ocrad Scanset scanset ocrad { command = $ocrad args = -s5 $input } # Inverted Ocrad scanset scanset ocrad-invert { command = $ocrad args = -s5 -i $input } # Inverted Ocrad scanset with decolorization scanset ocrad-decolorize-invert { preprocessors = ppmtopgm, pamthreshold, pamtopnm command = $ocrad args = -s5 -i $input } # Ocrad scanset with decolorization scanset ocrad-decolorize { preprocessors = ppmtopgm, pamthreshold, pamtopnm command = $ocrad args = -s5 $input } # Standard Gocr Scanset scanset gocr { command = $gocr args = -i $input } # Tweaked Gocr Scanset scanset gocr-180 { command = $gocr args = -l 180 -d 2 -i $input } # An example Scanset how to use tesseract (disabled by default) #scanset tesseract { # preprocessors = maketiff # command = $tesseract # args = $input $output # force_output_in = $output.txt #} # Another example, this basically does the same as the inverted Ocrad Scanset # Only listed here to serve as example, ocrad-invert does this already # #scanset gocr-invert { # preprocessors = normalize, invert, normalize # command = $gocr # args = -i $input #} FuzzyOcr-3.6.0/FuzzyOcr.cf0000644000175000001440000002643711207335640014761 0ustar decoderusers# Syntax: # loadplugin # path where Plugin resides. loadplugin FuzzyOcr FuzzyOcr.pm body FUZZY_OCR eval:fuzzyocr_check() body FUZZY_OCR_WRONG_CTYPE eval:dummy_check() body FUZZY_OCR_CORRUPT_IMG eval:dummy_check() body FUZZY_OCR_WRONG_EXTENSION eval:dummy_check() body FUZZY_OCR_KNOWN_HASH eval:dummy_check() describe FUZZY_OCR Mail contains an image with common spam text inside describe FUZZY_OCR_WRONG_CTYPE Mail contains an image with wrong content-type set describe FUZZY_OCR_WRONG_EXTENSION Mail contains an image with wrong file extension describe FUZZY_OCR_CORRUPT_IMG Mail contains a corrupted image describe FUZZY_OCR_KNOWN_HASH Mail contains an image with known hash priority FUZZY_OCR 900 ### ### Plugin Configuration ### ### ### Logging options ### # Verbosity level (see manual) # Level 0 - Errors only # Level 1 - Errors and Warnings # Level 2 - Errors, Warnings and Info Messages # Level 3 - Full debug output # Default value: 1 #focr_verbose 3 # Log Message-Id, From, To # Default: 1 #focr_log_pmsinfo 0 # Send logging output to stderr. # Default value: 1 #focr_log_stderr 0 # Logfile (make sure it is writable by the plugin) # Default value: none #focr_logfile /tmp/FuzzyOcr.log ### ### Wordlists ### # Here we defined the words to scan for # Default value: /etc/mail/spamassassin/FuzzyOcr.words #focr_global_wordlist /etc/mail/spamassassin/FuzzyOcr.words # # This is the path RELATIVE to the respective home directory # for the personalized list. This list is merged with the global # word list on execution. # Default value: ~/.spamassassin/fuzzyocr.words # If value begins with '/', it is treated as fixed path. #focr_personal_wordlist fuzzyocr.words # # This option allows you to disable the whole personalization stuff, # i.e. FuzzyOcr will not call functions in SA that require home # directories for your users. This is only required if you are running # an environment where the users don't have home directories at all. # Default value: 0 # #focr_no_homedirs 1 # ## Optionally, disable this option if you want to scan for numbers ## Setting this to 0 will cause FuzzyOcr not to strip numbers from ## both the wordlist and the OCR results # #focr_strip_numbers 1 ### ### Helper Applications ### # These parameters can be used to change other detection settings # If you leave these commented out, the defaults will be used. # Do not use " " around any parameters! ### ### Step 1: ### Inform the plugin which helper apps are required. ### # The following are already included by default: # #focr_bin_helper gifsicle, giffix, giftext, gifinter, giftopnm #focr_bin_helper jpegtopnm, pngtopnm, bmptopnm, tifftopnm, ppmhist #focr_bin_helper gocr, ocrad # Include additional scanner/preprocessor commands here: # focr_bin_helper pnmnorm, pnminvert, pamthreshold, ppmtopgm, pamtopnm focr_bin_helper tesseract # These helpers must be defined before enabling PDF scanning #focr_bin_helper pdfinfo, pdftops, pstopnm ### ### Step 2: ### Inform the plugin of the search path to find all helper apps. ### Only the first match will be considered, so the order is important. ### # Search path for locating helper applications #focr_path_bin /usr/local/netpbm/bin:/usr/local/bin:/usr/bin ### ### Step 3: ### You can optionally define a helper application location, bypassing ### the search path algorithm. Please note that if the helper app is not ### previously defined, it will generate an error: #focr_bin_gifsicle /usr/bin/gifsicle #focr_bin_giffix /usr/bin/giffix #focr_bin_giftext /usr/bin/giftext #focr_bin_gifinter /usr/bin/gifinter #focr_bin_giftopnm /usr/bin/giftopnm #focr_bin_jpegtopnm /usr/bin/jpegtopnm #focr_bin_pngtopnm /usr/bin/pngtopnm #focr_bin_bmptopnm /usr/bin/bmptopnm #focr_bin_tifftopnm /usr/bin/tifftopnm #focr_bin_ppmhist /usr/bin/ppmhist #focr_bin_gocr /usr/bin/gocr #focr_bin_ocrad /usr/bin/ocrad #focr_bin_pnmnorm /usr/bin/pnmnorm #focr_bin_pnminvert /usr/bin/pnminvert #focr_bin_pdfinfo /usr/bin/pdfinfo #focr_bin_pdftops /usr/bin/pdftops #focr_bin_pstopnm /usr/bin/pstopnm ### ### Scansets ### # Paths to the files containing Scansets and Preprocessors definitions # #focr_preprocessor_file /etc/mail/spamassassin/FuzzyOcr.preps #focr_scanset_file /etc/mail/spamassassin/FuzzyOcr.scansets # Setting this to 1 will cause FuzzyOcr to skip all other scansets, # if a scanset has reached the amount of hits specified in # focr_counts_required. (i.e. if the image is detected as spam). # This saves resources, but lowers the scores because not the best, # but the first best scanset is taken as result. # Default value: 1 #focr_minimal_scanset 0 # This option is only used when focr_minimal_scanset is enabled. # Basically, this counts the effectiveness of a scanset on the current # mail traffic and resorts the scansets with the most effective first. # This saves unnecessary scanner passes and saves resources. # Default value: 1. #focr_autosort_scanset 0 # This is a parameter for the focr_autosort_scanset function, and specifies # the maximum value of the effectiveness counter used in each scanset. If you # increase this, it will take longer until the autosort function adapts to new # types of spam, setting it too low will lower the effectiveness of the # function. # Default value: 10 #focr_autosort_buffer 10 ### ### Scan Settings ### # Timeout for the plugin, in seconds. (Maximum runtime of the plugin) # Default value: 10 #focr_timeout 15 # Use a global timeout value instead of per helper application. # Default value: 0 #focr_global_timeout 1 # Minimum image size to scan. Images with dimensions smaller than the # ones specified here will be skipped: # (This parameter does not apply to PDF files) # Default: Height:4 Width:4 # #focr_min_height 4 #focr_min_width 4 # Maximum image size to scan. Images with dimensions bigger than the # ones specified here will be skipped: # (This parameter does not apply to PDF files) # Default: Height:800 Width:800 # #focr_max_height 800 #focr_max_width 800 # Maximum file size for different formats in byte, bigger pictures # will not be scanned # Default values: Unlimited) #focr_max_size_gif 80000 #focr_max_size_jpeg 100000 #focr_max_size_png 80000 #focr_max_size_bmp 500000 #focr_max_size_tiff 500000 # Skip checking the following image types # Default value: 0 (check image type) #focr_skip_gif 1 #focr_skip_jpeg 1 #focr_skip_png 1 #focr_skip_bmp 1 #focr_skip_tiff 1 # # PDF specific options # WARNING: Enable this at your own risk, this might lead to false positives and classify # important documents as spam. YOU HAVE BEEN WARNED. #focr_scan_pdfs 0 # PDFs having more pages than this value will be skipped #focr_pdf_maxpages 1 # Default detection treshold (see manual) # Default value: 0.25 (Can be changed on a per word basis in the wordlist). #focr_threshold 0.20 # Number of minimum matches before the rule scores (Default value: 2) #focr_counts_required 3 # Setting this will cause every word to be matched only once per image (Default value: 0) #focr_unique_matches 1 # This is the score for a hit after focr_counts_required matches # Default value: 5 #focr_base_score 5 # This is the additional score for every additional match after # focr_counts_required matches # Default value: 1 #focr_add_score 0.375 # This option defines the factor, which is multiplied with the number # of matches, that were made without stripping spaces. FuzzyOcr does two # matching attempts on OCR results, one without space strippings and one with. # To weight the first match type more, this factor is applied. # Default value: 1.5 #focr_twopass_scoring_factor 1.5 # This is the score to give for a wrong content-type. # e.g. JPEG image but content type says GIF # Default value: 1.5 #focr_wrongctype_score 1.5 # This is the score to give for a wrong file extension. # e.g. JPEG image but file extension says GIF # Default value: 1.5 #focr_wrongext_score 1.5 # This is the score to give for a corrupted image. # This currently affects only GIF images # Default value: 2.5 #focr_corrupt_score 2.5 # This is the score to give for a corrupted unfixable image. # This currently affects only GIF images. # Default value: 5 #focr_corrupt_unfixable_score 5 # This is used to disable the OCR engine if the message has # already more points than this value # Default value: 10 #focr_autodisable_score 30 # This is used to disable the OCR engine if the message has # already less points than this value # Default value: -5 #focr_autodisable_negative_score -5 ### ### Hashing Options (Optional) ### # Select which type of image hashing to use: # Default value: 0 (disabled) # Allowed values: # 1 ... use digest_hash only (deprecated) # 2 ... use digest_db w/digest_hash import (see requirements, recommended) # 3 ... use mysql database (see requirements, experimental) #-- # The score is saved with the hash in the database, allowing the plugin to # skip the scans when the image is found in the database, using the score # from the previous scans. #-- #focr_enable_image_hashing 3 # Set this to skip updating the hashing database at startup # Default value: 0 (update at startup) #focr_skip_updates 1 # Automatically add hashes of spam images recognized by OCR to the Image # Hash database, to disable, set to 0 # Default value: 1 (learn) #focr_hashing_learn_scanned 1 # Score images who's global word count is below focr_counts_required using # the following formulae: (focr_add_score * word count) as score. # Default value: 0 (ignore images) #focr_score_ham 1 # If the image hash database feature is enabled (Type 1 Hashing), # specify the file to use as database # Default value: /etc/mail/spamassassin/FuzzyOcr.hashdb #focr_digest_db /etc/mail/spamassassin/FuzzyOcr.hashdb # If the image hash db feature is enabled (Type 2 Hashing), # specify the file to use as the SPAM database # Default value: /etc/mail/spamassassin/FuzzyOcr.db #focr_db_hash /etc/mail/spamassassin/FuzzyOcr.db # If the image hash db feature is enabled (Type 2 Hashing), # specify the file to use as the HAM database # Default value: /etc/mail/spamassassin/FuzzyOcr.safe.db #focr_db_safe /etc/mail/spamassassin/FuzzyOcr.safe.db # Auto-prune: Expire records from hasing databases after these many days # Default value: 35 #focr_db_max_days 15 ### ### MySQL options (Type 3 Hashing) ### #focr_mysql_db FuzzyOcr #focr_mysql_hash Hash #focr_mysql_safe Safe #focr_mysql_user fuzzyocr #focr_mysql_pass fuzzyocr #focr_mysql_host localhost #focr_mysql_port 3306 #focr_mysql_socket /tmp/mysql.sock # If set, the database table is updated with different data from one of # the following: # + filename, # + image-params, # + content-type, # + file-type, # + score, # + word-info # Default value: 0 #focr_mysql_update_hash 1 ### ### Miscellaneous Options ### # The pluging uses a temporary directory to store intermediate information. # In order to Keep these files for debugging purposes use any of these # values: # 0 = always cleanup (default value) # 1 = keep only if error # 2 = always keep #-- # Keeping these intermediate files could fill your HDD _very_ fast! # Make shure you periodically empty your temp dir (usually: /tmp) or # suffer the conscecuences. You've been warned!! #-- #focr_keep_bad_images 1 ################################################################# # DO NOT REMOVE THIS LINE, IT IS REQUIRED UNDER ALL CIRCUMSTANCES focr_end_config FuzzyOcr-3.6.0/LICENSE0000644000175000001440000000145311207335640013650 0ustar decoderusers# <@LICENSE> # Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to you under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at: # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. #