comparison server.php @ 7:01dc7eeaf5df

Added some more checks to article data, added some commands, added 'dot stuffing' for block transfers
author Ivo Smits <Ivo@UCIS.nl>
date Tue, 12 Apr 2011 14:10:41 +0200
parents 5d62af5270dd
children 005339a1b2ce
comparison
equal deleted inserted replaced
6:bc6045ed0b2e 7:01dc7eeaf5df
24 while (TRUE) { 24 while (TRUE) {
25 $line = nntp_readline(STDIN); 25 $line = nntp_readline(STDIN);
26 if ($line === FALSE || $line === NULL) break; 26 if ($line === FALSE || $line === NULL) break;
27 $cmd = strtoupper(strtok($line, " \t")); 27 $cmd = strtoupper(strtok($line, " \t"));
28 switch ($cmd) { 28 switch ($cmd) {
29 case 'CAPABILITIES':
30 nntp_writeline(STDOUT, '101 Capability list:');
31 nntp_writeline_data(STDOUT, 'VERSION 2');
32 nntp_writeline_data(STDOUT, 'IMPLEMENTATION pNewss [http://wiki.ucis.nl/pNewss]');
33 nntp_writeline_data(STDOUT, 'POST');
34 nntp_writeline_data(STDOUT, 'READER');
35 nntp_writeline_data(STDOUT, 'IHAVE');
36 nntp_writeline_data(STDOUT, 'LIST ACTIVE');
37 nntp_writeline(STDOUT, '.');
38 //HDR, LIST, OVER, STARTTLS, STREAMING,
39 break;
40 case 'DATE':
41 nntp_writeline(STDOUT, '111 '.gmdate('YmdHis'));
42 break;
43 case 'HELP':
44 nntp_writeline(STDOUT, '100 Help text follows:');
45 nntp_writeline_data(STDOUT, 'Supported commands: CAPABILITIES,DATE,HELP,LIST,GROUP,LISTGROUP,STAT,HEAD,BODY,ARTICLE,LAST,NEXT,POST,IHAVE,QUIT');
46 nntp_writeline(STDOUT, '.');
47 break;
29 case 'LIST': 48 case 'LIST':
30 nntp_writeline(STDOUT, '215 list of groups follows'); 49 nntp_writeline(STDOUT, '215 list of groups follows');
31 foreach ($db->evalAllAssoc('SELECT * FROM `groups`') as $group) { 50 foreach ($db->evalAllAssoc('SELECT * FROM `groups`') as $group) {
32 $groupmessages = $db->evalRow('SELECT MIN(`number`), MAX(`number`) FROM `groupmessages` WHERE `group` = ?', $group['id']); 51 $groupmessages = $db->evalRow('SELECT MIN(`number`), MAX(`number`) FROM `groupmessages` WHERE `group` = ?', $group['id']);
33 nntp_writeline(STDOUT, $group['name'].' '.intval($groupmessages[1]).' '.intval($groupmessages[0]).' n'); 52 nntp_writeline_data(STDOUT, $group['name'].' '.intval($groupmessages[1]).' '.intval($groupmessages[0]).' n');
34 } 53 }
35 nntp_writeline(STDOUT, '.'); 54 nntp_writeline(STDOUT, '.');
36 break; 55 break;
37 case 'GROUP': 56 case 'GROUP':
57 case 'LISTGROUP':
38 $groupname = strtok(" \t"); 58 $groupname = strtok(" \t");
39 $group = $db->evalRowAssoc('SELECT * FROM `groups` WHERE `name` = ?', $groupname); 59 if ($groupname === FALSE) {
60 $group = $currentgroup;
61 } else {
62 $group = $db->evalRowAssoc('SELECT * FROM `groups` WHERE `name` = ?', $groupname);
63 }
40 if ($group === FALSE) { 64 if ($group === FALSE) {
41 nntp_writeline(STDOUT, '411 No such group '.$groupname); 65 nntp_writeline(STDOUT, '411 No such group '.$groupname);
42 } else { 66 } else {
43 $currentgroup = $group; 67 $currentgroup = $group;
44 $groupmessages = $db->evalRow('SELECT MIN(`number`), MAX(`number`), COUNT(`number`) FROM `groupmessages` WHERE `group` = ?', $group['id']); 68 $groupmessages = $db->evalRow('SELECT MIN(`number`), MAX(`number`), COUNT(`number`) FROM `groupmessages` WHERE `group` = ?', $group['id']);
47 $currentarticle = NULL; 71 $currentarticle = NULL;
48 } else { 72 } else {
49 $currentarticle = $db->evalRowAssoc('SELECT * FROM `groupmessages` WHERE `group` = ? AND `number` = ?', array($group['id'], $groupmessages[0])); 73 $currentarticle = $db->evalRowAssoc('SELECT * FROM `groupmessages` WHERE `group` = ? AND `number` = ?', array($group['id'], $groupmessages[0]));
50 if ($currentarticle === FALSE) $currentarticle = NULL; 74 if ($currentarticle === FALSE) $currentarticle = NULL;
51 } 75 }
76 if ($cmd == 'LISTGROUP') {
77 $range = strtok(" \t");
78 if ($range !== FALSE) {
79 $parts = explode('-', $range);
80 if (count($parts) == 1 || !strlen($parts[1])) {
81 $query = 'SELECT `number` FROM `groupmessages` WHERE `group` = ? AND `number` >= ?';
82 $queryargs = array($group['id'], $parts[0]);
83 } else {
84 $query = 'SELECT `number` FROM `groupmessages` WHERE `group` = ? AND `number` BETWEEN ? AND ?';
85 $queryargs = array($group['id'], $parts[0], $parts[1]);
86 }
87 } else {
88 $query = 'SELECT `number` FROM `groupmessages` WHERE `group` = ?';
89 $queryargs = array($group['id']);
90 }
91 foreach ($db->evalColumn($query, $queryargs) as $number) nntp_writeline_data(STDOUT, $number);
92 nntp_writeline(STDOUT, '.');
93 }
52 } 94 }
53 break; 95 break;
54 case 'STAT': 96 case 'STAT':
55 case 'HEAD': 97 case 'HEAD':
56 case 'BODY': 98 case 'BODY':
62 case 'HEAD': nntp_writeline(STDOUT, '221 '.$article['messagenumber'].' <'.$article['messageid'].'> head'); break; 104 case 'HEAD': nntp_writeline(STDOUT, '221 '.$article['messagenumber'].' <'.$article['messageid'].'> head'); break;
63 case 'BODY': nntp_writeline(STDOUT, '222 '.$article['messagenumber'].' <'.$article['messageid'].'> body'); break; 105 case 'BODY': nntp_writeline(STDOUT, '222 '.$article['messagenumber'].' <'.$article['messageid'].'> body'); break;
64 case 'STAT': nntp_writeline(STDOUT, '223 '.$article['messagenumber'].' <'.$article['messageid'].'> stat'); break; 106 case 'STAT': nntp_writeline(STDOUT, '223 '.$article['messagenumber'].' <'.$article['messageid'].'> stat'); break;
65 default: throw new Exception('Internal error'); 107 default: throw new Exception('Internal error');
66 } 108 }
67 if ($cmd == 'HEAD' || $cmd == 'ARTICLE') foreach (explode("\r\n", $article['header']) as $line) nntp_writeline(STDOUT, $line); 109 if ($cmd == 'HEAD' || $cmd == 'ARTICLE') foreach (explode("\r\n", $article['header']) as $line) nntp_writeline_data(STDOUT, $line);
68 if ($cmd == 'ARTICLE') nntp_writeline(STDOUT, ''); 110 if ($cmd == 'ARTICLE') nntp_writeline(STDOUT, '');
69 if ($cmd == 'BODY' || $cmd == 'ARTICLE') foreach (explode("\r\n", $article['body']) as $line) nntp_writeline(STDOUT, $line); 111 if ($cmd == 'BODY' || $cmd == 'ARTICLE') foreach (explode("\r\n", $article['body']) as $line) nntp_writeline_data(STDOUT, $line);
70 if ($cmd != 'STAT') nntp_writeline(STDOUT, '.'); 112 if ($cmd != 'STAT') nntp_writeline(STDOUT, '.');
71 break; 113 break;
72 case 'LAST': 114 case 'LAST':
73 case 'NEXT': 115 case 'NEXT':
74 if ($currentarticle === NULL) { 116 if ($currentarticle === NULL) {
95 break; 137 break;
96 case 'POST': 138 case 'POST':
97 nntp_writeline(STDOUT, '340 Ok, recommended message-ID <'.md5(time().rand()).'@pNews.Core.UCIS.nl>'); 139 nntp_writeline(STDOUT, '340 Ok, recommended message-ID <'.md5(time().rand()).'@pNews.Core.UCIS.nl>');
98 $lines = nntp_readlines(STDIN); 140 $lines = nntp_readlines(STDIN);
99 try { 141 try {
100 $msgid = nntp_article_store($lines); 142 $messageid = nntp_article_store($lines);
101 nntp_writeline(STDOUT, '240 Article received <'.$msgid.'>'); 143 nntp_writeline(STDOUT, '240 Article received <'.$messageid.'>');
102 } catch (Exception $ex) { 144 } catch (Exception $ex) {
103 nntp_writeline(STDOUT, '441 '.$ex->getMessage()); 145 nntp_writeline(STDOUT, '441 '.$ex->getMessage());
104 } 146 }
105 break; 147 break;
148 case 'IHAVE':
149 $messageid = strtok(" \t");
150 if ($messageid === FALSE || strlen($messageid) <= 2 || $messageid[0] != '<' || $messageid[strlen($messageid)-1] == '>') {
151 nntp_writeline(STDOUT, '435 Argument error');
152 break;
153 }
154 $messageid = substr($messageid, 1, -1);
155 if ($db->evalRow('SELECT `id` FROM `messages` WHERE `messageid` = ?', $messageid) !== FALSE) {
156 nntp_writeline(STDOUT, '435 Duplicate');
157 break;
158 }
159 nntp_writeline(STDOUT, '335 Send article to be transferred');
160 $lines = nntp_readlines(STDIN);
161 try {
162 $messageid = nntp_article_store($lines);
163 nntp_writeline(STDOUT, '235 Article received <'.$messageid.'>');
164 } catch (Exception $ex) {
165 nntp_writeline(STDOUT, '437 '.$ex->getMessage());
166 }
167 break;
106 case 'QUIT': 168 case 'QUIT':
107 nntp_writeline(STDOUT, '205 .'); 169 nntp_writeline(STDOUT, '205 Bye.');
108 return; 170 return;
109 default: 171 default:
110 nntp_writeline(STDOUT, '500 Command not understood'); 172 nntp_writeline(STDOUT, '500 Command not understood');
111 break; 173 break;
112 } 174 }