Changeset 995

Show
Ignore:
Timestamp:
04/06/2006 03:36:48 AM (3 years ago)
Author:
rjl
Message:

Added more granularity to expiry options

Location:
trunk
Files:
2 modified

Legend:

Unmodified
Added
Removed
  • trunk/maia.conf.dist

    r987 r995  
    7676 
    7777 
     78### expire-quarantine-cache.pl 
     79 
     80# Mail types to expire (add values together as desired): 
     81#    0 = none (don't expire anything) 
     82#    1 = expire Suspected Non-Spam 
     83#    2 = expire Suspected Spam 
     84#    4 = expire Viruses/Malware 
     85#    8 = expire items with Invalid Mail Headers 
     86#   16 = expire items with Banned File Attachments 
     87#   32 = expire Confirmed Non-Spam 
     88#   64 = expire Confirmed Spam 
     89$mail_types = 1 + 2 + 4 + 8 + 16; 
     90 
     91 
    7892### send-quarantine-digests.pl 
    7993 
  • trunk/scripts/expire-quarantine-cache.pl

    r994 r995  
    7676 
    7777    use DBI; 
     78    use Getopt::Long; 
     79 
     80    # constants 
     81    use constant SECS_PER_HOUR => 60 * 60; 
     82    use constant SECS_PER_DAY => SECS_PER_HOUR * 24; 
     83    use constant SUSPECTED_NONSPAM =>   1; # Type H 
     84    use constant SUSPECTED_SPAM =>      2; # Type S 
     85    use constant VIRUSES =>             4; # Type V 
     86    use constant BAD_HEADERS =>         8; # Type B 
     87    use constant BANNED_ATTACHMENTS => 16; # Type F 
     88    use constant CONFIRMED_NONSPAM =>  32; # Type G 
     89    use constant CONFIRMED_SPAM =>     64; # Type C 
     90    use constant ALL => (SUSPECTED_NONSPAM + 
     91                         SUSPECTED_SPAM +  
     92                         VIRUSES + 
     93                         BAD_HEADERS + 
     94                         BANNED_ATTACHMENTS + 
     95                         CONFIRMED_NONSPAM + 
     96                         CONFIRMED_SPAM); 
     97 
     98    my %types = ( 
     99                  "S" => "Suspected Spam", 
     100                  "H" => "Suspected Non-Spam", 
     101                  "V" => "Virus/Malware", 
     102                  "B" => "Invalid Mail Header", 
     103                  "F" => "Banned File Attachment", 
     104                  "G" => "Confirmed Non-Spam", 
     105                  "C" => "Confirmed Spam" 
     106    ); 
    78107 
    79108    # prototypes 
     
    84113    sub delete_mail_item($$); 
    85114    sub delete_mail_references($$$); 
    86     sub expire_quarantine($); 
    87     sub expire_ham_cache($); 
     115    sub run_expiry_query($$$); 
     116    sub expire_quarantine($$); 
     117    sub expire_ham_cache($$); 
    88118    sub expire_orphans($); 
    89119    sub expire_strays($); 
     120    sub run_count_query($$); 
    90121    sub count_ham_cache($); 
    91122    sub count_q_cache($); 
     
    104135    }; 
    105136 
     137    # defaults (overridden by settings in /etc/maia.conf) 
     138    $mail_types = (ALL - CONFIRMED_NONSPAM - CONFIRMED_SPAM)  
     139        if !defined($mail_types); 
     140 
     141    my $suspected_nonspam = ($mail_types & SUSPECTED_NONSPAM) != 0; 
     142    my $suspected_spam = ($mail_types & SUSPECTED_SPAM) != 0; 
     143    my $viruses = ($mail_types & VIRUSES) != 0; 
     144    my $bad_headers = ($mail_types & BAD_HEADERS) != 0; 
     145    my $banned_files = ($mail_types & BANNED_ATTACHMENTS) != 0; 
     146    my $confirmed_nonspam = ($mail_types & CONFIRMED_NONSPAM) != 0; 
     147    my $confirmed_spam = ($mail_types & CONFIRMED_SPAM) != 0; 
     148    my $debug = 0; 
     149    my $quiet = 0; 
     150 
     151    GetOptions("suspected-nonspam|suspected-ham!" => \$suspected_nonspam, 
     152               "suspected-spam!" => \$suspected_spam, 
     153               "viruses!" => \$viruses, 
     154               "bad-headers!" => \$bad_headers, 
     155               "banned-files|banned-attachments!" => \$banned_files, 
     156               "confirmed-nonspam|confirmed-ham!" => \$confirmed_nonspam, 
     157               "confirmed-spam!" => \$confirmed_spam, 
     158               "debug" => \$debug, 
     159               "quiet" => \$quiet); 
     160 
     161    # Sanity-check any supplied arguments 
     162    if ($debug && $quiet) { 
     163        $debug = 0; 
     164        $quiet = 0; 
     165        output("Warning: --debug and --quiet negate each other."); 
     166    } 
     167    if (!$suspected_nonspam && ($mail_types & SUSPECTED_NONSPAM)) { 
     168        $mail_types -= SUSPECTED_NONSPAM; 
     169    } elsif ($suspected_nonspam && !($mail_types & SUSPECTED_NONSPAM)) { 
     170        $mail_types += SUSPECTED_NONSPAM; 
     171    }  
     172    if (!$suspected_spam && ($mail_types & SUSPECTED_SPAM)) { 
     173        $mail_types -= SUSPECTED_SPAM; 
     174    } elsif ($suspected_spam && !($mail_types & SUSPECTED_SPAM)) { 
     175        $mail_types += SUSPECTED_SPAM; 
     176    }  
     177    if (!$viruses && ($mail_types & VIRUSES)) { 
     178        $mail_types -= VIRUSES; 
     179    } elsif ($viruses && !($mail_types & VIRUSES)) { 
     180        $mail_types += VIRUSES; 
     181    }  
     182    if (!$bad_headers && ($mail_types & BAD_HEADERS)) { 
     183        $mail_types -= BAD_HEADERS; 
     184    } elsif ($bad_headers && !($mail_types & BAD_HEADERS)) { 
     185        $mail_types += BAD_HEADERS; 
     186    }  
     187    if (!$banned_files && ($mail_types & BANNED_ATTACHMENTS)) { 
     188        $mail_types -= BANNED_ATTACHMENTS; 
     189    } elsif ($banned_files && !($mail_types & BANNED_ATTACHMENTS)) { 
     190        $mail_types += BANNED_ATTACHMENTS; 
     191    }  
     192    if (!$confirmed_nonspam && ($mail_types & CONFIRMED_NONSPAM)) { 
     193        $mail_types -= CONFIRMED_NONSPAM; 
     194    } elsif ($confirmed_nonspam && !($mail_types & CONFIRMED_NONSPAM)) { 
     195        $mail_types += CONFIRMED_NONSPAM; 
     196    }  
     197    if (!$confirmed_spam && ($mail_types & CONFIRMED_SPAM)) { 
     198        $mail_types -= CONFIRMED_SPAM; 
     199    } elsif ($confirmed_spam && !($mail_types & CONFIRMED_SPAM)) { 
     200        $mail_types += CONFIRMED_SPAM; 
     201    }  
     202 
     203    if ($debug) { 
     204        output("Starting"); 
     205        output(sprintf("Expire Suspected Non-Spam:                 %s",  
     206               ($mail_types & SUSPECTED_NONSPAM) ? "Yes" : "No")); 
     207        output(sprintf("Expire Suspected Spam:                     %s",  
     208               ($mail_types & SUSPECTED_SPAM) ? "Yes" : "No")); 
     209        output(sprintf("Expire Viruses/Malware:                    %s",  
     210               ($mail_types & VIRUSES) ? "Yes" : "No")); 
     211        output(sprintf("Expire items with Invalid Mail Headers:    %s",  
     212               ($mail_types & BAD_HEADERS) ? "Yes" : "No")); 
     213        output(sprintf("Expire items with Banned File Attachments: %s",  
     214               ($mail_types & BANNED_ATTACHMENTS) ? "Yes" : "No")); 
     215        output(sprintf("Expire Confirmed Non-Spam:                 %s",  
     216               ($mail_types & CONFIRMED_NONSPAM) ? "Yes" : "No")); 
     217        output(sprintf("Expire Confirmed Spam:                     %s",  
     218               ($mail_types & CONFIRMED_SPAM) ? "Yes" : "No")); 
     219    } 
     220 
    106221    my $dbh; 
    107222 
     
    114229    } 
    115230 
    116     my $qcount = expire_quarantine($dbh); 
    117     my $hcount = expire_ham_cache($dbh); 
     231    my ($s_count, $v_count, $b_count, $f_count, $c_count) = expire_quarantine($dbh, $mail_types); 
     232    my ($h_count, $g_count) = expire_ham_cache($dbh, $mail_types); 
     233    my $qcount = $s_count + $v_count + $b_count + $f_count + $c_count; 
     234    my $hcount = $h_count + $g_count; 
    118235    my $cleanup = expire_orphans($dbh); 
    119236    my $strayclean = expire_strays($dbh); 
    120237    recalc_stats($dbh) if ($qcount + $hcount + $cleanup + $strayclean > 0); 
    121238 
    122     my $curhamcount = count_ham_cache($dbh); 
    123     my $curqcount = count_q_cache($dbh); 
     239    my $cur_h_count = count_ham_cache($dbh); 
     240    my ($cur_s_count, $cur_v_count, $cur_b_count, $cur_f_count) = count_q_cache($dbh); 
    124241    expire_tokens($dbh); 
    125242 
    126     output(sprintf("%d quarantined items expired", $qcount)); 
    127     output(sprintf("%d cached non-spam items expired", $hcount)); 
    128     if ($cleanup > 0) { 
    129         output(sprintf("%d orphaned items expired - please investigate!", $cleanup)); 
    130     } 
    131     if ($strayclean > 0) { 
    132         output(sprintf("%d stray items expired - please investigate!", $strayclean)); 
    133     }  
    134     output("Current Cache After Expiration:"); 
    135     output(sprintf("Quarantined Items: %d", $curqcount)); 
    136     output(sprintf("Non-spam Items: %d", $curhamcount)); 
     243    if (!$quiet) { 
     244        output(sprintf("%d Suspected Spam items expired", $s_count)); 
     245        output(sprintf("%d Virus/Malware items expired", $v_count)); 
     246        output(sprintf("%d items with Invalid Mail Headers expired", $b_count)); 
     247        output(sprintf("%d items with Banned File Attachments expired", $f_count)); 
     248        output(sprintf("%d Confirmed Spam items expired", $c_count)); 
     249        output(sprintf("%d Suspected Non-Spam items expired", $h_count)); 
     250        output(sprintf("%d Confirmed Non-Spam items expired", $g_count)); 
     251        if ($cleanup > 0) { 
     252            output(sprintf("%d orphaned items expired", $cleanup)); 
     253        } 
     254        if ($strayclean > 0) { 
     255            output(sprintf("%d stray references expired", $strayclean)); 
     256        } 
     257        output("Current Cache After Expiration:"); 
     258        output(sprintf("Suspected Spam items: %d", $cur_s_count)); 
     259        output(sprintf("Virus/Malware items: %d", $cur_v_count)); 
     260        output(sprintf("Items with Invalid Mail Headers: %d", $cur_b_count)); 
     261        output(sprintf("Items with Banned File Attachments: %d", $cur_f_count)); 
     262        output(sprintf("Suspected Non-Spam items: %d", $cur_h_count)); 
     263    } 
    137264 
    138265    # Disconnect from the database 
     
    199326        $mail_id = $1 if $mail_id =~ /^([0-9]*)$/si; # untaint 
    200327 
     328        output(sprintf("Deleting mail item %d", $mail_id)) if $debug; 
     329 
    201330        # Delete the mail item itself 
    202331        $delete = "DELETE FROM maia_mail WHERE id = ?"; 
     
    238367 
    239368    # Delete mail references for all recipients who see this mail item 
    240     # as Suspected (S)pam, (V)irus, (B)ad Header, or Banned (F)iles. 
     369    # as mail of a specific type [SVBFCHG]. 
    241370    # Delete the mail item itself if there are no other recipients. 
    242371    sub delete_mail_references($$$) { 
    243         my($dbh, $mail_id, $op) = @_; 
     372        my($dbh, $mail_id, $type) = @_; 
    244373        my($sth, $delete, $select); 
    245374 
    246375        $mail_id = $1 if $mail_id =~ /^([0-9]*)$/si; # untaint 
    247376 
    248         if ($op eq "spam") { 
    249  
    250             # Delete mail references for all recipients 
    251             # who see this mail item as suspected spam, 
    252             # virus-infected, a banned attachment, or an 
    253             # invalid mail header. 
    254             $delete = "DELETE FROM maia_mail_recipients " . 
    255                       "WHERE (type = 'S' OR type = 'B' OR type = 'F' OR type = 'V') " . 
    256                       "AND mail_id = ?"; 
    257         } else { 
    258  
    259             # Delete mail references for all recipients 
    260             # who see this mail item as suspected ham. 
    261             $delete = "DELETE FROM maia_mail_recipients " . 
    262                       "WHERE type = 'H' " . 
    263                       "AND mail_id = ?"; 
    264         } 
     377        # Delete mail references for all recipients 
     378        # who see this mail item as suspected spam, 
     379        # virus-infected, a banned attachment, or an 
     380        # invalid mail header. 
     381        $delete = "DELETE FROM maia_mail_recipients " . 
     382                  "WHERE type = ? " . 
     383                  "AND mail_id = ?"; 
    265384 
    266385        $sth = $dbh->prepare($delete) 
    267386                   or fatal(sprintf("Couldn't prepare query: %s", $dbh->errstr)); 
    268         $sth->execute($mail_id) 
     387        $sth->execute($type, $mail_id) 
    269388            or fatal(sprintf("Couldn't execute query: %s", $dbh->errstr)); 
    270389 
     
    287406 
    288407 
    289     # Expire quarantined items [SVBF] older than the specified 
    290     # expiration period. 
    291     sub expire_quarantine($) { 
    292         my($dbh) = @_; 
    293         my($select, $sth, @row); 
    294         my($days, $expiry_count); 
    295         my $secsperday = 24 * 60 * 60; 
     408    # Expire items of the specified type [SVBFCHG] that are older than 
     409    # the specified number of days. 
     410    sub run_expiry_query($$$) { 
     411        my($dbh, $type, $days) = @_; 
    296412        my $dbtype = get_db_type($dbh); 
    297  
    298         $days = get_config_value($dbh, "expiry_period"); 
    299         $days = $1 if $days =~ /^([1-9]+[0-9]*)$/si; # untaint 
    300         my $secs = $days * $secsperday; 
    301         output(sprintf("Expiring quarantined items [SVBF] older than %d days", $days)); 
    302         $select = "SELECT DISTINCT maia_mail.id, maia_mail.received_date " . 
    303                   "FROM maia_mail, maia_mail_recipients " . 
    304                   "WHERE maia_mail.id = maia_mail_recipients.mail_id " . 
    305                   "AND (maia_mail_recipients.type = 'S' OR " . 
    306                        "maia_mail_recipients.type = 'B' OR " . 
    307                        "maia_mail_recipients.type = 'F' OR " . 
    308                        "maia_mail_recipients.type = 'V') "; 
    309         if ($dbtype =~ /^mysqli?$/si) { 
     413        my $secs = $days * SECS_PER_DAY; 
     414        my $count = 0; 
     415         
     416        output(sprintf("Expiring %s items [%s] older than %d days", $types{$type}, $type, $days)) 
     417            if (!$quiet); 
     418        my $select = "SELECT DISTINCT maia_mail.id, maia_mail.received_date " . 
     419                     "FROM maia_mail, maia_mail_recipients " . 
     420                     "WHERE maia_mail.id = maia_mail_recipients.mail_id " . 
     421                     "AND (maia_mail_recipients.type = ?) "; 
     422        if ($dbtype =~ /^mysql$/si) { 
    310423            $select .= "AND maia_mail.received_date < DATE_SUB(CURRENT_TIMESTAMP, INTERVAL " . $secs . " SECOND)"; 
    311424        } elsif ($dbtype =~ /^pg$/si) { 
    312425            $select .= "AND maia_mail.received_date < NOW() - INTERVAL '" . $secs . " SECOND'"; 
    313426        } 
    314         $sth = $dbh->prepare($select) 
    315                    or fatal(sprintf("Couldn't prepare query: %s", $dbh->errstr)); 
    316         $sth->execute() 
    317             or fatal(sprintf("Couldn't execute query: %s", $dbh->errstr)); 
    318         $expiry_count = 0; 
    319         while (@row = $sth->fetchrow_array()) { 
    320             delete_mail_references($dbh, $row[0], "spam"); 
    321             $expiry_count++; 
     427        my $sth = $dbh->prepare($select) 
     428            or fatal(sprintf("Couldn't prepare query: %s", $dbh->errstr)); 
     429        $sth->execute($type) 
     430            or fatal(sprintf("Couldn't execute query: %s", $dbh->errstr)); 
     431        while (my @row = $sth->fetchrow_array()) { 
     432            output(sprintf("Deleting %s references to mail item %d", $types{$type}, $row[0])) 
     433                if $debug; 
     434            delete_mail_references($dbh, $row[0], $type); 
     435            $count++; 
    322436        } 
    323437        $sth->finish; 
    324438 
    325         return $expiry_count; 
    326     } 
    327  
    328  
    329     # Expire cached ham items [H] older than the specified 
     439        return $count; 
     440    } 
     441 
     442 
     443    # Expire quarantined items [SVBFC] older than the specified 
    330444    # expiration period. 
    331     sub expire_ham_cache($) { 
    332         my($dbh) = @_; 
    333         my($select, $sth, @row); 
    334         my($days, $expiry_count); 
    335         my $secsperday = 24 * 60 * 60; 
    336         my $dbtype = get_db_type($dbh); 
    337  
    338         $days = get_config_value($dbh, "ham_cache_expiry_period"); 
     445    sub expire_quarantine($$) { 
     446        my($dbh, $mail_types) = @_; 
     447        my $s_count = 0; 
     448        my $v_count = 0; 
     449        my $b_count = 0; 
     450        my $f_count = 0; 
     451        my $c_count = 0; 
     452 
     453        my $days = get_config_value($dbh, "expiry_period"); 
    339454        $days = $1 if $days =~ /^([1-9]+[0-9]*)$/si; # untaint 
    340         my $secs = $days * $secsperday; 
    341         output(sprintf("Expiring cached ham items [H] older than %d days", $days)); 
    342         $select = "SELECT DISTINCT maia_mail.id, maia_mail.received_date " . 
    343                   "FROM maia_mail, maia_mail_recipients " . 
    344                   "WHERE maia_mail.id = maia_mail_recipients.mail_id " . 
    345                   "AND maia_mail_recipients.type = 'H' "; 
    346         if ($dbtype =~ /^mysqli?$/si) { 
    347             $select .= "AND maia_mail.received_date < DATE_SUB(CURRENT_TIMESTAMP, INTERVAL " . $secs . " SECOND)"; 
    348         } elsif ($dbtype =~ /^pg$/si) { 
    349             $select .= "AND maia_mail.received_date < NOW() - INTERVAL '" . $secs . " SECOND'"; 
    350         } 
    351         $sth = $dbh->prepare($select) 
    352                    or fatal(sprintf("Couldn't prepare query: %s", $dbh->errstr)); 
    353         $sth->execute() 
    354             or fatal(sprintf("Couldn't execute query: %s", $dbh->errstr)); 
    355         $expiry_count = 0; 
    356         while (@row = $sth->fetchrow_array()) { 
    357             delete_mail_references($dbh, $row[0], "ham"); 
    358             $expiry_count++; 
    359         } 
    360         $sth->finish; 
    361  
    362         return $expiry_count; 
    363     } 
    364  
    365  
     455 
     456        $s_count = run_expiry_query($dbh, "S", $days) if ($mail_types & SUSPECTED_SPAM); 
     457        $v_count = run_expiry_query($dbh, "V", $days) if ($mail_types & VIRUSES); 
     458        $b_count = run_expiry_query($dbh, "B", $days) if ($mail_types & BAD_HEADERS); 
     459        $f_count = run_expiry_query($dbh, "F", $days) if ($mail_types & BANNED_ATTACHMENTS); 
     460        $c_count = run_expiry_query($dbh, "C", $days) if ($mail_types & CONFIRMED_SPAM); 
     461 
     462        return ($s_count, $v_count, $b_count, $f_count, $c_count); 
     463    } 
     464 
     465 
     466    # Expire cached ham items [HG] older than the specified 
     467    # expiration period. 
     468    sub expire_ham_cache($$) { 
     469        my($dbh, $mail_types) = @_; 
     470        my $h_count = 0; 
     471        my $g_count = 0; 
     472 
     473        my $days = get_config_value($dbh, "ham_cache_expiry_period"); 
     474        $days = $1 if $days =~ /^([1-9]+[0-9]*)$/si; # untaint 
     475 
     476        $h_count = run_expiry_query($dbh, "H", $days) if ($mail_types & SUSPECTED_NONSPAM); 
     477        $g_count = run_expiry_query($dbh, "G", $days) if ($mail_types & CONFIRMED_NONSPAM); 
     478 
     479        return ($h_count, $g_count); 
     480    } 
     481 
     482 
     483    # Expire orphaned items older than one hour.  Orphans are mail items 
     484    # that exist in spite of the fact that no recipient references are 
     485    # left pointing to it.  Orphans should not exist--they suggest that 
     486    # a bug or some other database inconsistency is to blame--but we do 
     487    # basic housecleaning here just in case. 
    366488    sub expire_orphans($) { 
    367489        my($dbh) = @_; 
    368490        my($select, $sth, @row); 
    369491        my($expiry_count); 
    370         my $secsperhour = 60 * 60; 
    371492        my $dbtype = get_db_type($dbh); 
    372493 
    373         output("Expiring orphaned items older than one hour"); 
     494        output("Expiring Orphaned items (mail with no recipients) older than one hour") 
     495            if (!$quiet); 
    374496        $select = "SELECT DISTINCT maia_mail.id, maia_mail_recipients.mail_id " . 
    375497                  "FROM maia_mail " . 
     
    377499                  "ON maia_mail.id = maia_mail_recipients.mail_id " . 
    378500                  "WHERE maia_mail_recipients.type IS NULL "; 
    379         if ($dbtype =~ /^mysqli?$/si) { 
    380             $select .= "AND maia_mail.received_date < DATE_SUB(CURRENT_TIMESTAMP, INTERVAL " . 1 * $secsperhour . " SECOND)"; 
     501        if ($dbtype =~ /^mysql$/si) { 
     502            $select .= "AND maia_mail.received_date < DATE_SUB(CURRENT_TIMESTAMP, INTERVAL " . 1 * SECS_PER_HOUR . " SECOND)"; 
    381503        } elsif ($dbtype =~ /^pg$/si) { 
    382             $select .= "AND maia_mail.received_date < NOW() - INTERVAL '" . 1 * $secsperhour . " SECOND'"; 
     504            $select .= "AND maia_mail.received_date < NOW() - INTERVAL '" . 1 * SECS_PER_HOUR . " SECOND'"; 
    383505        } 
    384506        $sth = $dbh->prepare($select) 
     
    388510        $expiry_count = 0; 
    389511        while (@row = $sth->fetchrow_array()) { 
    390             output(sprintf("Deleting ORPHAN %d", $row[0])); 
     512            output(sprintf("Deleting ORPHAN %d", $row[0])) if $debug; 
    391513            delete_mail_item($dbh, $row[0]); 
    392514            $expiry_count++; 
     
    398520 
    399521 
     522    # Expire stray references.  Strays are references to mail items that 
     523    # no longer exist.  Like orphans, these should not exist, and indicate 
     524    # a bug or a database inconsistency.  We clean these up here for good 
     525    # measure. 
    400526    sub expire_strays($) { 
    401527        my($dbh) = @_; 
     
    403529        my($expiry_count); 
    404530       
    405         output("Expiring Stray Mail Recipient references with no Mail Item"); 
     531        output("Expiring Stray References (recipients references with no mail items)") 
     532            if (!$quiet); 
    406533        $select = "SELECT maia_mail_recipients.mail_id " . 
    407534                  "FROM maia_mail_recipients " . 
     
    416543        $expiry_count = 0; 
    417544        while (@row = $sth->fetchrow_array()) { 
    418             output(sprintf("Deleting STRAY RECIPIENT %d", $row[0])); 
     545            output(sprintf("Deleting STRAY RECIPIENT %d", $row[0])) if $debug; 
    419546            # calling delete_mail_item to delete the reference in case there are entries in other tables too. 
    420547            delete_mail_item($dbh, $row[0]); 
     
    427554 
    428555 
     556    # Return a count of the current number of items of the 
     557    # specified type [SVBFCHG]. 
     558    sub run_count_query($$) { 
     559        my($dbh, $type) = @_; 
     560        my $count = 0; 
     561 
     562        my $select = "SELECT COUNT(DISTINCT maia_mail_recipients.mail_id) " . 
     563                     "FROM maia_mail_recipients " . 
     564                     "WHERE maia_mail_recipients.type = ?"; 
     565         
     566        my $sth= $dbh->prepare($select) 
     567            or fatal(sprintf("Couldn't prepare query: %s", $dbh->errstr)); 
     568        $sth->execute($type) 
     569            or fatal(sprintf("Couldn't execute query: %s", $dbh->errstr)); 
     570        my @row = $sth->fetchrow_array(); 
     571        $count = $row[0]; 
     572         
     573        $sth->finish; 
     574 
     575        return $count; 
     576    } 
     577 
     578 
    429579    # Returns the total number of unconfirmed items in the ham cache. 
    430580    sub count_ham_cache($) { 
    431         my($dbh) = @_; 
    432         my($select, $sth, @row); 
    433         my($ham_count); 
    434  
    435         $select = "SELECT COUNT(DISTINCT maia_mail_recipients.mail_id) " . 
    436                   "FROM maia_mail_recipients " . 
    437                   "WHERE maia_mail_recipients.type = 'H' "; 
    438          
    439         $sth= $dbh->prepare($select) 
    440             or fatal(sprintf("Couldn't prepare query: %s", $dbh->errstr)); 
    441         $sth->execute() 
    442             or fatal(sprintf("Couldn't execute query: %s", $dbh->errstr)); 
    443         @row = $sth->fetchrow_array(); 
    444         $ham_count = $row[0]; 
    445          
    446         $sth->finish; 
    447  
    448         return $ham_count; 
    449              
     581        my($dbh) = @_; 
     582 
     583        my $cur_h_count = run_count_query($dbh, "H"); 
     584 
     585        return ($cur_h_count); 
    450586    } 
    451587 
     
    454590    sub count_q_cache($) { 
    455591        my($dbh) = @_; 
    456         my($select, $sth, @row); 
    457         my($q_count); 
    458  
    459         $select = "SELECT COUNT(DISTINCT maia_mail_recipients.mail_id) " . 
    460                   "FROM maia_mail_recipients " . 
    461                   "WHERE (maia_mail_recipients.type = 'S' OR " . 
    462                        "maia_mail_recipients.type = 'B' OR " . 
    463                        "maia_mail_recipients.type = 'F' OR " . 
    464                        "maia_mail_recipients.type = 'V') "; 
    465  
    466         $sth= $dbh->prepare($select) 
    467             or fatal(sprintf("Couldn't prepare query: %s", $dbh->errstr)); 
    468         $sth->execute() 
    469             or fatal(sprintf("Couldn't execute query: %s", $dbh->errstr)); 
    470         @row = $sth->fetchrow_array(); 
    471         $q_count = $row[0]; 
    472  
    473         $sth->finish; 
    474  
    475         return $q_count; 
    476  
     592 
     593        my $cur_s_count = run_count_query($dbh, "S"); 
     594        my $cur_v_count = run_count_query($dbh, "V"); 
     595        my $cur_b_count = run_count_query($dbh, "B"); 
     596        my $cur_f_count = run_count_query($dbh, "F"); 
     597 
     598        return ($cur_s_count, $cur_v_count, $cur_b_count, $cur_f_count); 
    477599    } 
    478600 
     
    484606        my($delete, $sth, @row); 
    485607 
    486         output("Expiring tokens due to expire now"); 
     608        output("Expiring Tokens due to expire now") if (!$quiet); 
    487609        $delete = "DELETE FROM maia_tokens where expires < NOW()"; 
    488610        $sth = $dbh->prepare($delete) 
     
    506628            $token = "H"; 
    507629        } else { 
    508             $token = ""; 
     630            return; 
    509631        } 
    510632 
     
    603725        my($sth, @row, $select, $user_id); 
    604726 
    605         output("Recalculating statistics"); 
     727        output("Recalculating statistics") if (!$quiet); 
    606728        $select = "SELECT maia_users.id FROM maia_users"; 
    607729        $sth = $dbh->prepare($select)