Mercurial > hg > pnewss
comparison common.php @ 11:e0807e0b1a67
Added common.php, updated server synchronization to continue after a connection failure
author | Ivo Smits <Ivo@UCIS.nl> |
---|---|
date | Sat, 18 Jun 2011 15:59:11 +0200 |
parents | |
children | 7917bd536187 |
comparison
equal
deleted
inserted
replaced
10:ca88deec5352 | 11:e0807e0b1a67 |
---|---|
1 <?php | |
2 /* Copyright 2010 Ivo Smits <Ivo@UCIS.nl>. All rights reserved. | |
3 Redistribution and use in source and binary forms, with or without modification, are | |
4 permitted provided that the following conditions are met: | |
5 | |
6 1. Redistributions of source code must retain the above copyright notice, this list of | |
7 conditions and the following disclaimer. | |
8 | |
9 2. Redistributions in binary form must reproduce the above copyright notice, this list | |
10 of conditions and the following disclaimer in the documentation and/or other materials | |
11 provided with the distribution. | |
12 | |
13 THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED | |
14 WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND | |
15 FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR | |
16 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
17 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR | |
18 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON | |
19 ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | |
20 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF | |
21 ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
22 | |
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 | |
25 or implied, of Ivo Smits.*/ | |
26 | |
27 require_once './pdo.php'; | |
28 require_once './config.php'; | |
29 | |
30 function nntp_readline($socket) { | |
31 $line = fgets($socket, 512); | |
32 if ($line === FALSE || $line === NULL) return $line; | |
33 $line = rtrim($line, "\r\n"); | |
34 writelog('R: '.$line); | |
35 return $line; | |
36 } | |
37 function nntp_writeline_data($socket, $line) { | |
38 if (strlen($line) && $line[0] == '.') $line = '.'.$line; | |
39 nntp_writeline($socket, $line); | |
40 } | |
41 function nntp_writeline($socket, $line) { | |
42 writelog('W: '.$line); | |
43 fwrite($socket, $line."\r\n"); | |
44 } | |
45 function nntp_readlines($socket) { | |
46 $line = nntp_readline($socket); | |
47 $lines = array(); | |
48 while ($line != '.' && $line !== FALSE && $line !== FALSE) { | |
49 if (strlen($line) && $line[0] == '.') $line = substr($line, 1); | |
50 $lines[] = $line; | |
51 $line = nntp_readline($socket); | |
52 } | |
53 if ($line != '.') throw new Exception('Unexpected end of message'); | |
54 return $lines; | |
55 } | |
56 | |
57 function nntp_article_store($lines, $header = array()) { | |
58 global $db; | |
59 $headers = array(); | |
60 if (!count($header)) { | |
61 while (count($lines)) { | |
62 $line = array_shift($lines); | |
63 if (!strlen($line)) break; | |
64 $header[] = $line; | |
65 } | |
66 } | |
67 foreach ($header as $headerid => $line) { | |
68 if (!strlen($line) || $line == '.') throw new Exception('Empty or terminating header line'); | |
69 if (strpos($line, "\r") !== FALSE || strpos($line, "\n") !== FALSE || strpos($line, "\0")) throw new Exception('Invalid newline or NUL character in header line'); | |
70 $parts = explode(': ', $line, 2); | |
71 $headername = strtoupper($parts[0]); | |
72 switch ($headername) { | |
73 case 'PATH': case 'FROM': case 'NEWSGROUPS': case 'SUBJECT': case 'DATE': case 'MESSAGE-ID': case 'SENDER': | |
74 if (isset($headers[$headername])) throw new Exception('Duplicate header: '.$headername); | |
75 $headers[strtoupper($parts[0])] = $parts[1]; | |
76 unset($header[$headerid]); | |
77 break; | |
78 case 'ORGANIZATION': case 'LINES': | |
79 case 'MIME-VERSION': case 'CONTENT-TYPE': case 'CONTENT-TRANSFER-ENCODING': case 'USER-AGENT': | |
80 case 'REFERENCES': case 'REPLY-TO': case 'SENDER': case 'FOLLOWUP-TO': case 'IN-REPLY-TO': | |
81 case 'EXPIRES': case 'CONTROL': case 'DISTRIBUTION': case 'KEYWORDS': case 'SUMMARY': | |
82 break; | |
83 case 'NNTP-POSTING-HOST': case 'X-TRACE': case 'XREF': case 'X-COMPLAINTS-TO': | |
84 case 'NNTP-POSTING-DATE': | |
85 unset($header[$headerid]); | |
86 $line = NULL; | |
87 break; | |
88 default: | |
89 writelog("Received unknown header $headername"); | |
90 } | |
91 } | |
92 foreach ($lines as $line) { | |
93 if ($line == '.') throw new Exception('Terminating body line'); | |
94 if (strpos($line, "\r") !== FALSE || strpos($line, "\n") !== FALSE || strpos($line, "\0")) throw new Exception('Invalid newline or NUL character in header line'); | |
95 } | |
96 if (!isset($headers['NEWSGROUPS'])) throw new Exception('Missing required Newsgroups: header'); | |
97 $newsgroups = array(); | |
98 foreach (explode(',', $headers['NEWSGROUPS']) as $groupname) { | |
99 $group = $db->evalRowAssoc('SELECT * FROM `groups` WHERE `name` = ?', $groupname); | |
100 if ($group === FALSE) continue; | |
101 $newsgroups[] = $group['id']; | |
102 } | |
103 if (!count($newsgroups)) throw new Exception('No known newsgroups listed'); | |
104 if (!isset($headers['MESSAGE-ID'])) $headers['MESSAGE-ID'] = '<'.md5(time().rand()).'@pNewss.Core.UCIS.nl>'; | |
105 $messageid = $headers['MESSAGE-ID']; | |
106 if (strlen($messageid) < 3 || strlen($messageid) > 250 || $messageid[0] != '<' || strpos($messageid, '>') !== strlen($messageid) - 1) throw new Exception('Bad Message-ID'); | |
107 $messageid = substr($messageid, 1, -1); | |
108 $article = $db->evalRowAssoc('SELECT * FROM `messages` WHERE `messageid` = ?', $messageid); | |
109 if ($article !== FALSE) throw new Exception('Duplicate'); | |
110 $headers['PATH'] = 'pNewss.Core.UCIS.nl'.(isset($headers['PATH'])?'!'.$headers['PATH']:''); | |
111 foreach (array('Path', 'From', 'Newsgroups', 'Subject', 'Date', 'Message-ID', 'Sender') as $headername) { | |
112 if (isset($headers[strtoupper($headername)])) $header[] = $headername.': '.$headers[strtoupper($headername)]; | |
113 } | |
114 $id = $db->insert('INSERT INTO `messages` (`messageid`, `header`, `body`) VALUES (?, ?, ?)', array($messageid, implode("\r\n", $header), implode("\r\n", $lines))); | |
115 foreach ($newsgroups as $groupid) $db->insert('INSERT INTO `groupmessages` (`group`, `message`) VALUES (?, ?)', array($groupid, $id)); | |
116 return $messageid; | |
117 } |