1<?php
2
3require_once dirname(__FILE__).'/accesscheck.php';
4flush();
5
6//$limit = '';
7$numperrun = 10000;
8ob_end_flush();
9$count = 0;
10$notmatched = 0;
11$existmatch = 0;
12$rules = array();
13
14function output($message)
15{
16    echo $message."<br/>\n";
17    flush();
18}
19
20// lets not do this unless we do some locking first
21$abort = ignore_user_abort(1);
22$process_id = getPageLock();
23if (empty($process_id)) {
24    return;
25}
26$req = Sql_Fetch_Row_query(sprintf('select count(*) from %s ', $GLOBALS['tables']['bounce']));
27$total = $req[0];
28if (isset($_GET['s'])) {
29    $s = sprintf('%d', $_GET['s']);
30    $e = $s + $numperrun;
31} else {
32    $s = 0;
33    $e = $numperrun;
34}
35$limit = ' limit '.$s.', '.$numperrun;
36
37if ($total > $numperrun && $e < $total) {
38    $next = '<p class="button">'.PageLink2('generatebouncerules&s='.$e,
39            $GLOBALS['I18N']->get('Process Next Batch')).'</p>';
40} else {
41    $next = '';
42}
43
44$req = Sql_query(sprintf('select * from %s %s ', $GLOBALS['tables']['bounce'], $limit));
45while ($row = sql_Fetch_array($req)) {
46    $alive = checkLock($process_id);
47    if ($alive) {
48        keepLock($process_id);
49    } else {
50        echo $GLOBALS['I18N']->get('Process Killed by other process');
51        exit;
52    }
53    ++$count;
54    if ($count % 10 == 0) {
55        echo '. '."\n";
56        flush();
57        if ($count > 1000000) {
58            return;
59        }
60    }
61    $regexid = matchedBounceRule($row['data']);
62    if ($regexid) {
63        Sql_Query(sprintf('insert into %s (regex,bounce) values(%d,%d)',
64            $GLOBALS['tables']['bounceregex_bounce'], $regexid, $row['id']), 1);
65        $bouncematched = 1;
66        ++$existmatch;
67    } else {
68        $lines = explode("\n", $row['data']);
69        //  print '<br/>'.sizeof($lines).' lines';
70        $bouncematched = 0;
71        set_time_limit(100);
72        foreach ($lines as $line) {
73            if (preg_match('/ (55\d) (.*)/', $line, $regs)) {
74                $bouncematched = 1;
75                $code = $regs[1];
76                $info = $regs[2];
77                //if ($code != 550) {
78                //  print "<br/>$line";
79                //  print "<br/><b>$code</b>";
80                //  print htmlspecialchars(" $info");
81                $rule = preg_replace('/[^\s\<]+@[^\s\>]+/', '.*', $info);
82                $rule = preg_replace('/\{.*\}/U', '.*', $rule);
83                $rule = preg_replace('/\(.*\)/U', '.*', $rule);
84                $rule = preg_replace('/\<.*\>/U', '.*', $rule);
85                $rule = preg_replace('/\[.*\]/U', '.*', $rule);
86                $rule = preg_replace('/\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/', '\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/',
87                    $rule); //# replace IPs with their regex
88                $rule = str_replace('?', '.', $rule);
89                $rule = str_replace('/', '.', $rule);
90                $rule = str_replace('"', '.', $rule);
91                $rule = str_replace('(', '.', $rule);
92                $rule = str_replace(')', '.', $rule);
93
94                if (stripos($rule, 'Unknown local user') !== false) {
95                    $rule = 'Unknown local user';
96                } elseif (preg_match('/Unknown local part (.*) in/iU', $rule, $regs)) {
97                    $rule = preg_replace('/'.preg_quote($regs[1]).'/', '.*', $rule);
98                } elseif (preg_match('/mta(.*)\.mail\.yahoo\.com/iU', $rule)) {
99                    $rule = preg_replace('/mta[\d]+/i', 'mta[\\d]+', $rule);
100                }
101
102                $rule = trim($rule);
103                if (!in_array($rule, $rules) && strlen($rule) > 25) {
104                    // && $code != 554 && $code != 552) {
105                    if (VERBOSE) {
106                        echo '<br/>'.htmlspecialchars($rule);
107                    }
108                    array_push($rules, $rule);
109
110                    //}
111                    switch ($code) {
112                        case 554:
113                        case 552:
114                            $action = 'unconfirmuseranddeletebounce';
115                            break;
116                        case 550:
117                            $action = 'blacklistuseranddeletebounce';
118                            break;
119                        default:
120                            $action = 'unconfirmuseranddeletebounce';
121                            break;
122                    }
123                    Sql_Query(sprintf('insert into %s (regex,action,comment,status) values("%s","%s","%s","candidate")',
124                        $GLOBALS['tables']['bounceregex'], addslashes(trim($rule)), $action,
125                        'Auto Created from bounce '.$row['id']."\n".' line: '.addslashes($line)), 1);
126                    $regexid = sql_insert_id();
127                    if ($regexid) { // most likely duplicate entry if no value
128                        Sql_Query(sprintf('insert into %s (regex,bounce) values(%d,%d)',
129                            $GLOBALS['tables']['bounceregex_bounce'], $regexid, $row['id']), 1);
130                    } else {
131                        //            print matchedBounceRule($row['data']);
132                        echo $GLOBALS['I18N']->get('Hmm, duplicate entry, ').' '.$row['id']." $code $rule<br/>";
133                    }
134                }
135            }
136        }
137    }
138    if (!$bouncematched) {
139        ++$notmatched;
140    }
141}
142
143echo '<ul>';
144echo '<li>'.count($rules).' '.$GLOBALS['I18N']->get('new rules found').'</li>';
145echo '<li>'.$notmatched.' '.$GLOBALS['I18N']->get('bounces not matched').'</li>';
146echo '<li>'.$existmatch.' '.$GLOBALS['I18N']->get('bounces matched to existing rules').'</li>';
147if ($next) {
148    echo '<li>'.$next.'</li>';
149}
150echo '</ul>';
151
152releaseLock($process_id);
153
154return;
155