Mercurial > hg > pnewss
comparison common.php @ 13:cccd73f72bf6 draft
Added filtering support and several bugfixes
author | Ivo Smits <Ivo@UCIS.nl> |
---|---|
date | Thu, 10 Jul 2014 22:26:45 +0200 |
parents | 7917bd536187 |
children | 372f4e195986 |
comparison
equal
deleted
inserted
replaced
12:7917bd536187 | 13:cccd73f72bf6 |
---|---|
22 | 22 |
23 The views and conclusions contained in the software and documentation are those of the | 23 The views and conclusions contained in the software and documentation are those of the |
24 authors and should not be interpreted as representing official policies, either expressed | 24 authors and should not be interpreted as representing official policies, either expressed |
25 or implied, of Ivo Smits.*/ | 25 or implied, of Ivo Smits.*/ |
26 | 26 |
27 $pnewss_hooks = array('article_stored' => array()); | 27 $pnewss_hooks = array('article_stored' => array(), 'article_filter' => array()); |
28 | 28 |
29 require_once './pdo.php'; | 29 require_once './pdo.php'; |
30 require_once './config.php'; | 30 require_once './config.php'; |
31 | 31 |
32 function nntp_readline($socket) { | 32 function nntp_readline($socket) { |
33 $line = fgets($socket, 512); | 33 $line = fgets($socket); |
34 if ($line === FALSE || $line === NULL) return $line; | 34 if ($line === FALSE || $line === NULL) return $line; |
35 $line = rtrim($line, "\r\n"); | 35 $line = rtrim($line, "\r\n"); |
36 writelog('R: '.$line); | 36 writelog('R: '.$line); |
37 return $line; | 37 return $line; |
38 } | 38 } |
62 } | 62 } |
63 | 63 |
64 function pnewss_call_hooks($hooks, $args) { | 64 function pnewss_call_hooks($hooks, $args) { |
65 foreach ($hooks as $hook) call_user_func_array($hook, $args); | 65 foreach ($hooks as $hook) call_user_func_array($hook, $args); |
66 } | 66 } |
67 function pnewss_call_filter_hooks($hooks, $args) { | |
68 foreach ($hooks as $hook) if (!call_user_func_array($hook, $args)) return FALSE; | |
69 return TRUE; | |
70 } | |
71 | |
72 function nntp_article_wanted($messageid) { | |
73 global $db, $pnewss_hooks; | |
74 if ($db->evalRow('SELECT `id` FROM `messages` WHERE `messageid` = ?', $messageid) !== FALSE) return FALSE; | |
75 if (!pnewss_call_filter_hooks($pnewss_hooks['article_filter'], array(array('messageid' => $messageid)))) return FALSE; | |
76 return TRUE; | |
77 } | |
67 | 78 |
68 function nntp_article_store($lines, $header = array()) { | 79 function nntp_article_store($lines, $header = array()) { |
69 global $db, $pnewss_hooks; | 80 global $db, $pnewss_hooks; |
70 $headers = array(); | 81 $headers = array(); |
71 if (!count($header)) { | 82 if (!count($header)) { |
75 $header[] = $line; | 86 $header[] = $line; |
76 } | 87 } |
77 } | 88 } |
78 $headername = NULL; | 89 $headername = NULL; |
79 foreach ($header as $headerid => $line) { | 90 foreach ($header as $headerid => $line) { |
80 if (!strlen($line) || $line == '.') throw new Exception('Empty or terminating header line'); | 91 if (!strlen($line)) throw new Exception('Empty header line'); |
81 if (strpos($line, "\r") !== FALSE || strpos($line, "\n") !== FALSE || strpos($line, "\0")) throw new Exception('Invalid newline or NUL character in header line'); | 92 if (strpos($line, "\r") !== FALSE || strpos($line, "\n") !== FALSE || strpos($line, "\0")) throw new Exception('Invalid newline or NUL character in header line'); |
82 if (strlen($line) && strlen($headername) && ($line[0] == ' ' || $line[0] == "\t") && isset($headers[$headername])) { | 93 if (strlen($line) && strlen($headername) && ($line[0] == ' ' || $line[0] == "\t") && isset($headers[$headername])) { |
83 $headers[$headername] .= ' '.trim($line, " \t"); | 94 $headers[$headername] .= ' '.trim($line, " \t"); |
84 unset($header[$headerid]); | 95 unset($header[$headerid]); |
85 continue; | 96 continue; |
87 $parts = explode(': ', $line, 2); | 98 $parts = explode(': ', $line, 2); |
88 $headername = strtoupper($parts[0]); | 99 $headername = strtoupper($parts[0]); |
89 switch ($headername) { | 100 switch ($headername) { |
90 case 'PATH': case 'FROM': case 'NEWSGROUPS': case 'SUBJECT': case 'DATE': case 'MESSAGE-ID': case 'SENDER': | 101 case 'PATH': case 'FROM': case 'NEWSGROUPS': case 'SUBJECT': case 'DATE': case 'MESSAGE-ID': case 'SENDER': |
91 if (isset($headers[$headername])) throw new Exception('Duplicate header: '.$headername); | 102 if (isset($headers[$headername])) throw new Exception('Duplicate header: '.$headername); |
92 $headers[strtoupper($parts[0])] = $parts[1]; | 103 $headers[$headername] = $parts[1]; |
93 unset($header[$headerid]); | 104 unset($header[$headerid]); |
94 break; | 105 break; |
95 case 'ORGANIZATION': case 'LINES': | 106 case 'ORGANIZATION': case 'LINES': |
96 case 'MIME-VERSION': case 'CONTENT-TYPE': case 'CONTENT-TRANSFER-ENCODING': case 'USER-AGENT': | 107 case 'MIME-VERSION': case 'CONTENT-TYPE': case 'CONTENT-TRANSFER-ENCODING': case 'USER-AGENT': |
97 case 'REFERENCES': case 'REPLY-TO': case 'SENDER': case 'FOLLOWUP-TO': case 'IN-REPLY-TO': | 108 case 'REFERENCES': case 'REPLY-TO': case 'FOLLOWUP-TO': case 'IN-REPLY-TO': |
98 case 'EXPIRES': case 'CONTROL': case 'DISTRIBUTION': case 'KEYWORDS': case 'SUMMARY': | 109 case 'EXPIRES': case 'CONTROL': case 'DISTRIBUTION': case 'KEYWORDS': case 'SUMMARY': |
99 break; | 110 break; |
100 case 'NNTP-POSTING-HOST': case 'X-TRACE': case 'XREF': case 'X-COMPLAINTS-TO': | 111 case 'NNTP-POSTING-HOST': case 'X-TRACE': case 'XREF': case 'X-COMPLAINTS-TO': |
101 case 'NNTP-POSTING-DATE': | 112 case 'NNTP-POSTING-DATE': |
102 unset($header[$headerid]); | 113 unset($header[$headerid]); |
106 if ($headername[0] == 'X' && $headername[1] == '-') break; | 117 if ($headername[0] == 'X' && $headername[1] == '-') break; |
107 writelog("Received unknown header $headername"); | 118 writelog("Received unknown header $headername"); |
108 } | 119 } |
109 } | 120 } |
110 foreach ($lines as $line) { | 121 foreach ($lines as $line) { |
111 if ($line == '.') throw new Exception('Terminating body line'); | 122 if (strpos($line, "\r") !== FALSE || strpos($line, "\n") !== FALSE || strpos($line, "\0")) throw new Exception('Invalid newline or NUL character in body line'); |
112 if (strpos($line, "\r") !== FALSE || strpos($line, "\n") !== FALSE || strpos($line, "\0")) throw new Exception('Invalid newline or NUL character in header line'); | |
113 } | 123 } |
114 if (!isset($headers['NEWSGROUPS'])) throw new Exception('Missing required Newsgroups: header'); | 124 if (!isset($headers['NEWSGROUPS'])) throw new Exception('Missing required Newsgroups header'); |
115 $newsgroups = array(); | 125 $newsgroups = array(); |
116 foreach (explode(',', $headers['NEWSGROUPS']) as $groupname) { | 126 foreach (explode(',', $headers['NEWSGROUPS']) as $groupname) { |
117 $group = $db->evalRowAssoc('SELECT * FROM `groups` WHERE `name` = ?', $groupname); | 127 $group = $db->evalRowAssoc('SELECT * FROM `groups` WHERE `name` = ?', $groupname); |
118 if ($group === FALSE) continue; | 128 if ($group === FALSE) continue; |
119 $newsgroups[] = $group['id']; | 129 $newsgroups[] = $group['id']; |
128 if ($article !== FALSE) throw new Exception('Duplicate'); | 138 if ($article !== FALSE) throw new Exception('Duplicate'); |
129 $headers['PATH'] = 'pNewss.Core.UCIS.nl'.(isset($headers['PATH'])?'!'.$headers['PATH']:''); | 139 $headers['PATH'] = 'pNewss.Core.UCIS.nl'.(isset($headers['PATH'])?'!'.$headers['PATH']:''); |
130 foreach (array('Path', 'From', 'Newsgroups', 'Subject', 'Date', 'Message-ID', 'Sender') as $headername) { | 140 foreach (array('Path', 'From', 'Newsgroups', 'Subject', 'Date', 'Message-ID', 'Sender') as $headername) { |
131 if (isset($headers[strtoupper($headername)])) $header[] = $headername.': '.$headers[strtoupper($headername)]; | 141 if (isset($headers[strtoupper($headername)])) $header[] = $headername.': '.$headers[strtoupper($headername)]; |
132 } | 142 } |
133 $id = $db->insert('INSERT INTO `messages` (`messageid`, `header`, `body`) VALUES (?, ?, ?)', array($messageid, implode("\r\n", $header), implode("\r\n", $lines))); | 143 if (!pnewss_call_filter_hooks($pnewss_hooks['article_filter'], array(array('messageid' => $messageid, 'headers' => $headers, 'body' => $lines)))) throw new Exception('Filtered'); |
144 $headertext = implode("\r\n", $header); | |
145 $bodytext = implode("\r\n", $lines); | |
146 if (strlen($headertext) > 65535 || strlen($bodytext) > 16777215) throw new Exception('Message too big'); | |
147 $id = $db->insert('INSERT INTO `messages` (`messageid`, `header`, `body`) VALUES (?, ?, ?)', array($messageid, $headertext, $bodytext)); | |
134 foreach ($newsgroups as $groupid) $db->insert('INSERT INTO `groupmessages` (`group`, `message`) VALUES (?, ?)', array($groupid, $id)); | 148 foreach ($newsgroups as $groupid) $db->insert('INSERT INTO `groupmessages` (`group`, `message`) VALUES (?, ?)', array($groupid, $id)); |
135 pnewss_call_hooks($pnewss_hooks['article_stored'], array(array('messageid' => $messageid, 'headers' => $headers, 'body' => $lines, 'dbid' => $id))); | 149 pnewss_call_hooks($pnewss_hooks['article_stored'], array(array('messageid' => $messageid, 'headers' => $headers, 'body' => $lines, 'dbid' => $id))); |
136 return $messageid; | 150 return $messageid; |
137 } | 151 } |