Mercurial > hg > pnewss
diff server.php @ 0:d7ab68b71c74
Initial commit
author | Ivo Smits <Ivo@UCIS.nl> |
---|---|
date | Mon, 11 Apr 2011 22:44:47 +0200 |
parents | |
children | 40e545510a57 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/server.php Mon Apr 11 22:44:47 2011 +0200 @@ -0,0 +1,204 @@ +#!/usr/bin/php +<?php +chdir('/home/ivo/projects/pnewss'); +require_once './pdo.php'; +require_once './config.php'; + +$logfile = fopen('./server.log', 'w'); +$currentgroup = NULL; +$currentarticle = NULL; + +function exception_handler($exception) { + nntp_writeline(STDOUT, ''); + nntp_writeline(STDOUT, '590 Exception: '.$exception->getMessage()); + die(); +} +function error_handler($errno, $errstr, $errfile, $errline) { + nntp_writeline(STDOUT, ''); + nntp_writeline(STDOUT, '590 Error in file '.$errfile.' line '.$errline.' error '.$errno.' '.$errstr); + die(); +} +set_exception_handler('exception_handler'); +set_error_handler("error_handler"); + +nntp_writeline(STDOUT, '200 pNewss ready'); +while (TRUE) { + $line = nntp_readline(STDIN); + if ($line === FALSE || $line === NULL) break; + $cmd = strtok($line, " \t"); + switch (strtoupper($cmd)) { + case 'LIST': + nntp_writeline(STDOUT, '215 List of groups follows'); + foreach ($db->evalAllAssoc('SELECT * FROM `groups`') as $group) { + $groupmessages = $db->evalRow('SELECT MIN(`number`), MAX(`number`) FROM `groupmessages` WHERE `group` = ?', $group['id']); + nntp_writeline(STDOUT, $group['name'].' '.intval($groupmessages[1]).' '.intval($groupmessages[0]).' n'); + } + nntp_writeline(STDOUT, '.'); + break; + case 'GROUP': + $groupname = strtok(" \t"); + $group = $db->evalRowAssoc('SELECT * FROM `groups` WHERE `name` = ?', $groupname); + if ($group === FALSE) { + nntp_writeline(STDOUT, '411 No such group '.$groupname); + } else { + $currentgroup = $group; + $groupmessages = $db->evalRow('SELECT MIN(`number`), MAX(`number`), COUNT(`number`) FROM `groupmessages` WHERE `group` = ?', $group['id']); + nntp_writeline(STDOUT, '211 '.intval($groupmessages[2]).' '.intval($groupmessages[0]).' '.intval($groupmessages[1]).' '.$group['name']); + if ($groupmessages[0] === NULL) { + $currentarticle = NULL; + } else { + $currentarticle = $db->evalRowAssoc('SELECT * FROM `groupmessages` WHERE `group` = ? AND `number` = ?', array($group['id'], $groupmessages[0])); + if ($currentarticle === FALSE) $currentarticle = NULL; + } + } + break; + case 'STAT': + $article = nntp_get_article(strtok(" \t")); + if ($article === NULL) break; + nntp_writeline(STDOUT, '223 '.$article['messagenumber'].' <'.$article['messageid'].'> stat'); + break; + case 'HEAD': + $article = nntp_get_article(strtok(" \t")); + if ($article === NULL) break; + nntp_writeline(STDOUT, '221 '.$article['messagenumber'].' <'.$article['messageid'].'> head'); + foreach (explode("\r\n", $article['header']) as $line) nntp_writeline(STDOUT, $line); + nntp_writeline(STDOUT, '.'); + break; + case 'BODY': + $article = nntp_get_article(strtok(" \t")); + if ($article === NULL) break; + nntp_writeline(STDOUT, '222 '.$article['messagenumber'].' <'.$article['messageid'].'> body'); + foreach (explode("\r\n", $article['body']) as $line) nntp_writeline(STDOUT, $line); + nntp_writeline(STDOUT, '.'); + break; + case 'ARTICLE': + $article = nntp_get_article(strtok(" \t")); + if ($article === NULL) break; + nntp_writeline(STDOUT, '220 '.$article['messagenumber'].' <'.$article['messageid'].'> article'); + foreach (explode("\r\n", $article['header']) as $line) nntp_writeline(STDOUT, $line); + nntp_writeline(STDOUT, ''); + foreach (explode("\r\n", $article['body']) as $line) nntp_writeline(STDOUT, $line); + nntp_writeline(STDOUT, '.'); + break; + case 'LAST': + if ($currentarticle === NULL) { + nntp_writeline(STDOUT, '420 no current article has been selected'); + break; + } + $article = $db->evalRowAssoc('SELECT * FROM `groupmessages` WHERE `group` = ? AND `number` < ? ORDER BY `number` DESC LIMIT 1', array($currentarticle['group'], $currentarticle['number'])); + if ($article === FALSE) { + nntp_writeline(STDOUT, '422 no previous article in this group'); + } else { + $articlea = $db->evalRowAssoc('SELECT * FROM `messages` WHERE `id` = ?', $article['message']); + if ($articlea === FALSE) { + nntp_writeline(STDOUT, '430 no such article found'); + return NULL; + } + $currentarticle = $article; + nntp_writeline(STDOUT, '223 '.$article['number'].' <'.$articlea['messageid'].'> ok'); + } + break; + case 'NEXT': + if ($currentarticle === NULL) { + nntp_writeline(STDOUT, '420 no current article has been selected'); + break; + } + $article = $db->evalRowAssoc('SELECT * FROM `groupmessages` WHERE `group` = ? AND `number` > ? ORDER BY `number` ASC LIMIT 1', array($currentarticle['group'], $currentarticle['number'])); + if ($article === FALSE) { + nntp_writeline(STDOUT, '422 no previous article in this group'); + } else { + $articlea = $db->evalRowAssoc('SELECT * FROM `messages` WHERE `id` = ?', $article['message']); + if ($articlea === FALSE) { + nntp_writeline(STDOUT, '430 no such article found'); + return NULL; + } + $currentarticle = $article; + nntp_writeline(STDOUT, '223 '.$article['number'].' <'.$articlea['messageid'].'> ok'); + } + break; + case 'QUIT': + nntp_writeline(STDOUT, '205 .'); + return; + case 'XOVER': + case 'MODE': + case 'CAPABILITIES': + nntp_writeline(STDOUT, '500 Command not implemented'); + break; + default: + nntp_writeline(STDOUT, '500 Command not understood'); + break; + } +} + +function nntp_get_article($article) { + global $currentgroup, $currentarticle, $db; + if ($article === FALSE) { + if ($currentarticle === NULL) { + nntp_writeline(STDOUT, '420 no current article has been selected'); + return NULL; + } + $messagenumber = $currentarticle['number']; + $article = $db->evalRowAssoc('SELECT * FROM `messages` WHERE `id` = ?', $currentarticle['message']); + if ($article === FALSE) { + nntp_writeline(STDOUT, '430 no such article found'); + return NULL; + } + } elseif (strlen($article) > 2 && $article[0] == '<' && $article[strlen($article)-1] == '>') { + $messagenumber = 0; + $article = substr($article, 1, -1); + $article = $db->evalRowAssoc('SELECT * FROM `messages` WHERE `messageid` = ?', $article); + if ($article === FALSE) { + nntp_writeline(STDOUT, '430 no such article found'); + return NULL; + } + } elseif (is_numeric($article)) { + if ($currentgroup === NULL) { + nntp_writeline(STDOUT, '412 no newsgroup has been selected'); + return NULL; + } + $article = $db->evalRowAssoc('SELECT * FROM `groupmessages` WHERE `group` = ? AND `number` = ?', array($currentgroup['id'], $article)); + if ($article === FALSE) { + nntp_writeline(STDOUT, '423 no such article number in this group'); + return NULL; + } + $currentarticle = $article; + $messagenumber = $article['number']; + $article = $db->evalRowAssoc('SELECT * FROM `messages` WHERE `id` = ?', $article['message']); + if ($article === FALSE) { + nntp_writeline(STDOUT, '430 no such article found'); + return NULL; + } + } else { + nntp_writeline(STDOUT, '500 Error in arguments'); + } + $article['messagenumber'] = $messagenumber; + return $article; +} + +function writelog($line) { + global $logfile; + fwrite($logfile, $line."\n"); +} +function nntp_readline($socket) { + global $logfile; + $line = fgets($socket, 512); + if ($line === FALSE || $line === NULL) return $line; + $line = rtrim($line, "\r\n"); + fwrite($logfile, 'R: '.$line."\n"); + return $line; +} +function nntp_writeline($socket, $line) { + global $logfile; + fwrite($logfile, 'W: '.$line."\n"); + fwrite($socket, $line."\r\n"); +} +function nntp_readlines($socket) { + $line = nntp_readline($socket); + $lines = array(); + while ($line != '.' && $line !== FALSE && $line !== FALSE) { + $lines[] = $line; + $line = nntp_readline($socket); + } + if ($line != '.') die("Unexpected end of message header\n"); + return $lines; +}