Commit: 151949772442ed3b9a1b5202a000ae88de1bc468
Author: Ben Ramsey <[email protected]> Sat, 23 Jan 2016 00:37:56
-0500
Parents: 7cbd35c71a8e5c5c76178e19c23af2176f373d80
Branches: master
Link:
http://git.php.net/?p=web/news.git;a=commitdiff;h=151949772442ed3b9a1b5202a000ae88de1bc468
Log:
Use the Nntp and fMailbox classes to display messages and attachments
Changed paths:
M article.php
diff --git a/article.php b/article.php
index 7e40ce7..1f6921c 100644
--- a/article.php
+++ b/article.php
@@ -2,6 +2,10 @@
require 'common.php';
+/* Prevents the poor mail server from suffering if it receives a message with
many references */
+/* (References: <xxx> or In-Reply-To: <xxx>) */
+define('REFERENCES_LIMIT', 20);
+
if (isset($_GET['article'])) {
$article = (int)$_GET['article'];
} else {
@@ -14,273 +18,159 @@ if (isset($_GET['group'])) {
$group = false;
}
-$s = nntp_connect(NNTP_HOST);
-if (!$s) {
- error("Failed to connect to news server");
-}
+try {
+ $nntpClient = new \Web\News\Nntp(NNTP_HOST);
+ $message = $nntpClient->readArticle($article, $group);
-if ($group) {
- $res = nntp_cmd($s,"GROUP $group",211);
- if (!$res) {
- error("Failed to select group");
+ if ($message === null) {
+ error('No article found');
}
-}
-$res = nntp_cmd($s, "ARTICLE $article",220);
-if (!$res) {
- error("Failed to get article ". $article);
-}
+ $mail = fMailbox::parseMessage($message);
-/* Prevents the poor mail server from suffering if it receives a message with
many references */
-/* (References: <xxx> or In-Reply-To: <xxx>) */
-define( 'REFERENCES_LIMIT', 20 );
+ $rawReferences = [];
+ if (!empty($mail['headers']['references'])) {
+ $rawReferences = $mail['headers']['references'];
+ } elseif (!empty($mail['headers']['in-reply-to'])) {
+ $rawReferences = $mail['headers']['in-reply-to'];
+ }
-$started = 0;
-$inheaders = 1; $headers = array();
-$masterheaders = array();
-$mimetype = $boundary = $charset = $encoding = "";
-$mimecount = 0; // number of mime parts
-$boundaries = array();
-$lk = '';
-$linebuf = '';
-$insig = false;
-while (!feof($s)) {
- $line = fgets($s);
- if ($line == ".\r\n") break;
- if ($inheaders && ($line == "\n" || $line == "\r\n")) {
- if (empty($masterheaders)) {
- /* $masterheaders should contain the first headers with
From, Subject, */
- /* etc., not the ones from multiparts */
- $masterheaders = $headers;
+ $references = [];
+ foreach ($rawReferences as $ref) {
+ $matches = [];
+ if (preg_match_all('/\<(.*?)\>/', $ref, $matches)) {
+ foreach ($matches[0] as $match) {
+ $references[] = $match;
+ }
}
+ }
- $inheaders = 0;
- if (isset($headers['content-type'])) {
- if (preg_match('/charset=(["\']?)([\w-]+)\1/i',
$headers['content-type'], $m)) {
- $charset = trim($m[2]);
- }
-
- if(preg_match('/boundary=(["\']?)(.+)\1/is',
$headers['content-type'], $m)) {
- $boundaries[] = trim($m[2]);
- $boundary = end($boundaries);
- }
+ $refsResolved = [];
- if (preg_match("/([^;]+)(;|\$)/",
$headers['content-type'], $m)) {
- $mimetype = trim(strtolower($m[1]));
- ++$mimecount;
- }
- }
- if (!$started) {
- head("$group: ".format_title($headers['subject'],
$charset));
- start_article($group, $masterheaders, $charset);
- $started = 1;
+ $refCount = 0;
+ foreach ($references as $messageId) {
+ if (!$messageId) {
+ continue;
}
-
- if (!empty($headers['content-transfer-encoding'])) {
- $encoding =
strtolower(trim($headers['content-transfer-encoding']));
+ if ($refCount >= REFERENCES_LIMIT) {
+ break;
}
- if (strlen($mimetype)
- && $mimetype != "text/plain"
- && substr($mimetype,0,10) != "multipart/") {
- # Display a link to the attachment
- $name = '';
- if (!empty($headers['content-type'])
- && preg_match('/name=(["\']?)(.+)\1/s',
$headers['content-type'], $m)) {
- $name = trim($m[2]);
- } else if (!empty($headers['content-disposition'])
- && preg_match('/filename=(["\']?)(.+)\1/s',
$headers['content-disposition'], $m)) {
- $name = trim($m[2]);
- }
+ $refsResolved[] = $nntpClient->xpath($messageId);
+ $refCount++;
+ }
+} catch (Exception $e) {
+ error($e->getMessage());
+}
- if (!empty($headers['content-description'])) {
- $description =
trim($headers['content-description']) . " ";
- } else {
- $description = '';
- }
+head("{$group}: " . format_title($mail['headers']['subject'], 'utf-8'));
+start_article($mail, $refsResolved);
- $description .= $name;
- $link_desc = "[$mimetype]";
- if (strlen($description)) {
- $link_desc .= " " . $description;
- }
+$lines = preg_split("@(?<=\r\n|\n)@", $mail['text']);
+$insig = 0;
- $dl_link =
"/getpart.php?group=$group&article=$article&part=$mimecount";
- $link_desc =
htmlspecialchars($link_desc,ENT_QUOTES,"UTF-8");
-
- /* Attachment filename and mimetype might contain
malicious characters */
- printf('Attachment: <a href="%s">%s</a><br />'."\n",
- $dl_link,
- htmlspecialchars($link_desc)
- );
- }
-
- continue;
- }
+foreach ($lines as $line) {
# fix lines that started with a period and got escaped
if (substr($line,0,2) == "..") {
$line = substr($line,1);
}
- if ($inheaders) {
- /* header fields can be split across lines: CRLF WSP where WSP
*/
- /* is a space (ASCII 32) or tab (ASCII 9) */
- if ($lk && ($line[0] == ' ' || $line[0] == "\t")) {
- $headers[$lk] .= $line;
- } else {
- @list($k,$v) = explode(": ", $line, 2);
- if ($k && $v) {
- $headers[strtolower($k)] = $v;
- $lk = strtolower($k);
- } // else not a header field
- }
+ # this is some amazingly simplistic code to color quotes/signatures
+ # differently, and turn links into real links. it actually appears
+ # to work fairly well, but could easily be made more sophistimicated.
+ /* NOQUOTES? Why? It creates invalid HTML: http:"x */
+ $line = htmlentities($line,ENT_QUOTES,"utf-8");
+ $line =
preg_replace("/((mailto|https?|ftp|nntp|news):.+?)(>|\\s|\\)|\\.\\s|$)/","<a
href=\"\\1\">\\1</a>\\3",$line);
+ if (!$insig && ($line == "-- \r\n" || $line == "--\r\n")) {
+ echo "<span class=\"signature\">";
+ $insig = 1;
}
- else {
-
- if ($boundary
- && substr($line,0,2) == '--'
- && substr($line,2,strlen($boundary)) == $boundary) {
+ if (!$insig && substr($line,0,4) == ">") {
+ echo "<span class=\"quote\">$line</span>";
+ } else {
+ echo $line;
+ }
+}
- $inheaders = 1;
+if ($insig) {
+ echo "</span>";
+ $insig = 0;
+}
- if (substr($line,2+strlen($boundary)) == '--') {
- # end of this container
- array_pop($boundaries);
- $boundary = end($boundaries);
- } else {
- /* Next section: start with no headers, default
content type should be
- /* text/plain, but for now ignore that (see rfc
2046 5.1.3) */
- $headers = array();
- $mimetype = "";
- }
+echo "<br><br>";
- continue;
- }
+if (!empty($mail['attachment'])) {
+ foreach ($mail['attachment'] as $mimecount => $attachment) {
+ $mimetype = $attachment['mimetype'];
+ $name = $attachment['filename'];
- if (strlen($mimetype) && $mimetype != "text/plain") {
+ if ($mimetype == 'text/plain') {
+ echo htmlspecialchars($attachment['data']);
continue;
}
- switch($encoding) {
- case "quoted-printable":
- $line = quoted_printable_decode($line);
- break;
- case "base64":
- $line = base64_decode($line);
- break;
+ if (!empty($attachment['description'])) {
+ $description = trim($attachment['description']) . " ";
+ } else {
+ $description = '';
}
- // we can't convert it to UTF, because cvs commits don't have
charset info
- // so its preferable to leave it as-is, and let users choose
the correct charset
- // in their browser. this is specially important for php.doc.*
groups
- if ($charset && strpos(strtolower($charset), 'utf-8') ===
false) {
- $line = to_utf8($line, $charset);
+ $description .= $name;
+ $link_desc = "[$mimetype]";
+ if (strlen($description)) {
+ $link_desc .= " " . $description;
}
- $line = $linebuf . $line;
+ $dl_link =
"/getpart.php?group=$group&article=$article&part=$mimecount";
+ $link_desc = htmlspecialchars($link_desc,ENT_QUOTES,'UTF-8');
- if (in_array(substr($line, -1), array("\n", "\r"))) {
- $linebuf = '';
- } else {
- $linebuf = $line;
- continue;
- }
-
- # this is some amazingly simplistic code to color
quotes/signatures
- # differently, and turn links into real links. it actually
appears
- # to work fairly well, but could easily be made more
sophistimicated.
- /* NOQUOTES? Why? It creates invalid HTML: http:"x */
- $line = htmlentities($line,ENT_QUOTES,"utf-8");
- $line =
preg_replace("/((mailto|https?|ftp|nntp|news):.+?)(>|\\s|\\)|\\.\\s|$)/","<a
href=\"\\1\">\\1</a>\\3",$line);
- if (!$insig && $line == "-- \r\n") {
- echo "<span class=\"signature\">";
- $insig = 1;
- }
- if ($insig && $line == "\r\n") {
- echo "</span>";
- $insig = 0;
- }
- if (!$insig && substr($line,0,4) == ">") {
- echo "<span class=\"quote\">$line</span>";
- } else {
- echo $line;
- }
+ /* Attachment filename and mimetype might contain malicious
characters */
+ printf('Attachment: <a href="%s">%s</a><br />'."\n",
+ $dl_link,
+ htmlspecialchars($link_desc)
+ );
}
}
-if ($inheaders && !$started) {
- head("$group: ". $headers['subject']);
- start_article($group, $masterheaders, $charset);
-}
-if ($insig) {
- echo "</span>";
-}
+
echo " </pre>\n";
echo " </blockquote>\n";
-function start_article($group, $headers, $charset) {
+function start_article($mail, $refsResolved) {
echo " <blockquote>\n";
echo ' <table border="0" cellpadding="2" cellspacing="2"
width="100%">' . "\n";
# from
echo ' <tr class="vcard">' . "\n";
echo ' <td class="headerlabel">From:</td>' . "\n";
- echo ' <td class="headervalue">' . format_author($headers['from'],
$charset)."</td>\n";
+ echo ' <td class="headervalue">' .
format_author($mail['headers']['from']['raw'], 'utf-8')."</td>\n";
# date
echo ' <td class="headerlabel">Date:</td>' . "\n";
- echo ' <td class="headervalue">' .
format_date($headers["date"])."</td>\n";
+ echo ' <td class="headervalue">' .
format_date($mail['headers']['date'])."</td>\n";
echo " </tr>\n";
# subject
echo ' <tr>' . "\n";
echo ' <td class="headerlabel">Subject:</td>' . "\n";
- echo ' <td class="headervalue"
colspan="3">'.format_subject($headers["subject"], $charset)."</td>\n";
+ echo ' <td class="headervalue"
colspan="3">'.format_subject($mail['headers']['subject'], 'utf-8')."</td>\n";
echo " </tr>\n";
echo " <tr>\n";
# references
- if (!empty($headers['references']) || !empty($headers['in-reply-to'])) {
- $ref = $headers["references"] ? $headers["references"] :
$headers["in-reply-to"];
+ if (!empty($refsResolved)) {
echo ' <td class="headerlabel">References:</td>' . "\n";
echo ' <td class="headervalue">';
- $r = explode(" ", $ref);
- $c = 1;
- $s = nntp_connect(NNTP_HOST)
- or die("failed to connect to news server");
- while (list($k,$v) = each($r)) {
- if (!$v) continue;
- $v = trim($v);
- if (!preg_match("/^<.+>\$/", $v)) {
- continue;
- }
- if (strlen($v) > 504) {
- // 512 chars including CRLF
- continue;
- }
- $res2 = nntp_cmd($s, "XPATH $v",223)
- or print("<!-- failed to get reference article id
".htmlspecialchars($v, ENT_QUOTES, "UTF-8")." -->");
- list(,$v) = split("/", trim($res2));
- if (empty($v)) {
- continue;
- }
-
- echo "<a href=\"/$group/". urlencode($v)
."\">".($c++)."</a> ";
- if ($c > REFERENCES_LIMIT) {
- printf('More than %d references',
REFERENCES_LIMIT);
- break;
- }
+ foreach ($refsResolved as $k => $ref) {
+ echo "<a href=\"/". urlencode($ref['group']) . '/' .
urlencode($ref['articleId']) ."\">".($k + 1)."</a> ";
}
echo "</td>\n";
}
# groups
- if (!empty($headers["newsgroups"])) {
+ if (!empty($mail['headers']['newsgroups'])) {
echo ' <td class="headerlabel">Groups:</td>' . "\n";
echo ' <td class="headervalue">';
- $r = explode(",", chop($headers["newsgroups"]));
+ $r = explode(",", rtrim($mail['headers']['newsgroups']));
while (list($k,$v) = each($r)) {
echo "<a
href=\"/".urlencode($v)."\">".htmlspecialchars($v)."</a> ";
}
echo "</td>\n";
}
echo " </tr>\n";
- //while (list($k,$v) = each($headers)) {
- // echo "<!-- ", htmlspecialchars($k),": ",preg_replace("/-+/", "-",
htmlspecialchars($v))," -->\n";
- //}
echo " </table>\n";
echo " </blockquote>\n";
echo " <blockquote>\n";--
PHP Webmaster List Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php