changeset 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
files common.php fetchnews.php reloadarticle.php server.php
diffstat 4 files changed, 40 insertions(+), 21 deletions(-) [+]
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;
--- a/fetchnews.php	Wed Jun 12 22:22:07 2013 +0200
+++ b/fetchnews.php	Thu Jul 10 22:26:45 2014 +0200
@@ -61,7 +61,6 @@
 				$line = nntp_readline($socket);
 				$code = strtok($line, " \t");
 				if ($code != 240 && $code != 235) print("Article $article[messageid] was not accepted ($code)\n");
-				if ($article['id'] > $peer['lastposted']) $peer['lastposted'] = $article['id'];
 			} else {
 				print("IHAVE rejected by remote server, falling back to POST\n");
 				$peer['post'] = 1;
@@ -104,6 +103,8 @@
 					if (!$groupmessage) {
 						$db->insert('INSERT INTO `groupmessages` (`group`, `message`) VALUES (?, ?)', array($group['id'], $message['id']));
 					}
+				} else if (!nntp_article_wanted($messageid)) {
+					print("Ignoring filtered article $messageid\n");
 				} else {
 					nntp_writeline($socket, 'ARTICLE '.$i);
 					$line = nntp_readline($socket);
--- a/reloadarticle.php	Wed Jun 12 22:22:07 2013 +0200
+++ b/reloadarticle.php	Thu Jul 10 22:26:45 2014 +0200
@@ -45,6 +45,9 @@
 strtok(" \t"); //article number
 $lines = nntp_readlines($socket);
 nntp_article_store($lines);
+nntp_writeline($socket, 'QUIT');
+nntp_readline($socket);
+fclose($socket);
 
 function writelog($line) {
 	print($line."\n");
--- a/server.php	Wed Jun 12 22:22:07 2013 +0200
+++ b/server.php	Thu Jul 10 22:26:45 2014 +0200
@@ -95,9 +95,9 @@
 			if ($groupname === FALSE) {
 				$group = $currentgroup;
 			} else {
-				$group = $db->evalRowAssoc('SELECT * FROM `groups` WHERE `name` = ?', $groupname);
+				$group = $db->evalRowAssoc('SELECT * FROM `groups` WHERE `name` = ?', array($groupname));
 			}
-			if ($group === FALSE) {
+			if (!$group) {
 				nntp_writeline(STDOUT, '411 No such group '.$groupname);
 			} else {
 				$currentgroup = $group;
@@ -173,10 +173,10 @@
 				$articlea = $db->evalRowAssoc('SELECT * FROM `messages` WHERE `id` = ?', $article['message']);
 				if ($articlea === FALSE) {
 					nntp_writeline(STDOUT, '430 no such article found');
-					return NULL;
+				} else {
+					$currentarticle = $article;
+					nntp_writeline(STDOUT, '223 '.$article['number'].' <'.$articlea['messageid'].'> ok');
 				}
-				$currentarticle = $article;
-				nntp_writeline(STDOUT, '223 '.$article['number'].' <'.$articlea['messageid'].'> ok');
 			}
 			break;
 		case 'POST':
@@ -196,8 +196,8 @@
 				break;
 			}
 			$messageid = substr($messageid, 1, -1);
-			if ($db->evalRow('SELECT `id` FROM `messages` WHERE `messageid` = ?', $messageid) !== FALSE) {
-				nntp_writeline(STDOUT, '435 Duplicate');
+			if (!nntp_article_wanted($messageid)) {
+				nntp_writeline(STDOUT, '435 Duplicate or filtered');
 				break;
 			}
 			nntp_writeline(STDOUT, '335 Send article to be transferred');
@@ -216,8 +216,8 @@
 				break;
 			}
 			$messageid = substr($messageid, 1, -1);
-			if ($db->evalRow('SELECT `id` FROM `messages` WHERE `messageid` = ?', $messageid) !== FALSE) {
-				nntp_writeline(STDOUT, '438 <'.$messageid.'> Duplicate');
+			if (!nntp_article_wanted($messageid)) {
+				nntp_writeline(STDOUT, '438 <'.$messageid.'> Duplicate or filtered');
 				break;
 			}
 			nntp_writeline(STDOUT, '238 <'.$messageid.'> Send article to be transferred');
@@ -230,8 +230,8 @@
 				break;
 			}
 			$messageid = substr($messageid, 1, -1);
-			if ($db->evalRow('SELECT `id` FROM `messages` WHERE `messageid` = ?', $messageid) !== FALSE) {
-				nntp_writeline(STDOUT, '439 <'.$messageid.'> Duplicate');
+			if (!nntp_article_wanted($messageid)) {
+				nntp_writeline(STDOUT, '439 <'.$messageid.'> Duplicate or filtered');
 				break;
 			}
 			try {
@@ -290,6 +290,7 @@
 		}
 	} else {
 		nntp_writeline(STDOUT, '500 Error in arguments');
+		return NULL;
 	}
 	$article['messagenumber'] = $messagenumber;
 	return $article;