diff 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
line wrap: on
line diff
--- a/common.php	Wed Jun 12 22:22:07 2013 +0200
+++ b/common.php	Thu Jul 10 22:26:45 2014 +0200
@@ -24,13 +24,13 @@
    authors and should not be interpreted as representing official policies, either expressed
    or implied, of Ivo Smits.*/
 
-$pnewss_hooks = array('article_stored' => array());
+$pnewss_hooks = array('article_stored' => array(), 'article_filter' => array());
 
 require_once './pdo.php';
 require_once './config.php';
 
 function nntp_readline($socket) {
-	$line = fgets($socket, 512);
+	$line = fgets($socket);
 	if ($line === FALSE || $line === NULL) return $line;
 	$line = rtrim($line, "\r\n");
 	writelog('R: '.$line);
@@ -64,6 +64,17 @@
 function pnewss_call_hooks($hooks, $args) {
 	foreach ($hooks as $hook) call_user_func_array($hook, $args);
 }
+function pnewss_call_filter_hooks($hooks, $args) {
+	foreach ($hooks as $hook) if (!call_user_func_array($hook, $args)) return FALSE;
+	return TRUE;
+}
+
+function nntp_article_wanted($messageid) {
+	global $db, $pnewss_hooks;
+	if ($db->evalRow('SELECT `id` FROM `messages` WHERE `messageid` = ?', $messageid) !== FALSE) return FALSE;
+	if (!pnewss_call_filter_hooks($pnewss_hooks['article_filter'], array(array('messageid' => $messageid)))) return FALSE;
+	return TRUE;
+}
 
 function nntp_article_store($lines, $header = array()) {
 	global $db, $pnewss_hooks;
@@ -77,7 +88,7 @@
 	}
 	$headername = NULL;
 	foreach ($header as $headerid => $line) {
-		if (!strlen($line) || $line == '.') throw new Exception('Empty or terminating header line');
+		if (!strlen($line)) throw new Exception('Empty header line');
 		if (strpos($line, "\r") !== FALSE || strpos($line, "\n") !== FALSE || strpos($line, "\0")) throw new Exception('Invalid newline or NUL character in header line');
 		if (strlen($line) && strlen($headername) && ($line[0] == ' ' || $line[0] == "\t") && isset($headers[$headername])) {
 			$headers[$headername] .= ' '.trim($line, " \t");
@@ -89,12 +100,12 @@
 		switch ($headername) {
 			case 'PATH': case 'FROM': case 'NEWSGROUPS': case 'SUBJECT': case 'DATE': case 'MESSAGE-ID': case 'SENDER':
 				if (isset($headers[$headername])) throw new Exception('Duplicate header: '.$headername);
-				$headers[strtoupper($parts[0])] = $parts[1];
+				$headers[$headername] = $parts[1];
 				unset($header[$headerid]);
 				break;
 			case 'ORGANIZATION': case 'LINES':
 			case 'MIME-VERSION': case 'CONTENT-TYPE': case 'CONTENT-TRANSFER-ENCODING': case 'USER-AGENT':
-			case 'REFERENCES': case 'REPLY-TO': case 'SENDER': case 'FOLLOWUP-TO': case 'IN-REPLY-TO':
+			case 'REFERENCES': case 'REPLY-TO': case 'FOLLOWUP-TO': case 'IN-REPLY-TO':
 			case 'EXPIRES': case 'CONTROL': case 'DISTRIBUTION': case 'KEYWORDS': case 'SUMMARY':
 				break;
 			case 'NNTP-POSTING-HOST': case 'X-TRACE': case 'XREF': case 'X-COMPLAINTS-TO':
@@ -108,10 +119,9 @@
 		}
 	}
 	foreach ($lines as $line) {
-		if ($line == '.') throw new Exception('Terminating body line');
-		if (strpos($line, "\r") !== FALSE || strpos($line, "\n") !== FALSE || strpos($line, "\0")) throw new Exception('Invalid newline or NUL character in header line');
+		if (strpos($line, "\r") !== FALSE || strpos($line, "\n") !== FALSE || strpos($line, "\0")) throw new Exception('Invalid newline or NUL character in body line');
 	}
-	if (!isset($headers['NEWSGROUPS'])) throw new Exception('Missing required Newsgroups: header');
+	if (!isset($headers['NEWSGROUPS'])) throw new Exception('Missing required Newsgroups header');
 	$newsgroups = array();
 	foreach (explode(',', $headers['NEWSGROUPS']) as $groupname) {
 		$group = $db->evalRowAssoc('SELECT * FROM `groups` WHERE `name` = ?', $groupname);
@@ -130,7 +140,11 @@
 	foreach (array('Path', 'From', 'Newsgroups', 'Subject', 'Date', 'Message-ID', 'Sender') as $headername) {
 		if (isset($headers[strtoupper($headername)])) $header[] = $headername.': '.$headers[strtoupper($headername)];
 	}
-	$id = $db->insert('INSERT INTO `messages` (`messageid`, `header`, `body`) VALUES (?, ?, ?)', array($messageid, implode("\r\n", $header), implode("\r\n", $lines)));
+	if (!pnewss_call_filter_hooks($pnewss_hooks['article_filter'], array(array('messageid' => $messageid, 'headers' => $headers, 'body' => $lines)))) throw new Exception('Filtered');
+	$headertext = implode("\r\n", $header);
+	$bodytext = implode("\r\n", $lines);
+	if (strlen($headertext) > 65535 || strlen($bodytext) > 16777215) throw new Exception('Message too big');
+	$id = $db->insert('INSERT INTO `messages` (`messageid`, `header`, `body`) VALUES (?, ?, ?)', array($messageid, $headertext, $bodytext));
 	foreach ($newsgroups as $groupid) $db->insert('INSERT INTO `groupmessages` (`group`, `message`) VALUES (?, ?)', array($groupid, $id));
 	pnewss_call_hooks($pnewss_hooks['article_stored'], array(array('messageid' => $messageid, 'headers' => $headers, 'body' => $lines, 'dbid' => $id)));
 	return $messageid;