Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Rewrite of news.php.net:

* Fixes dozens of encoding errors and attachment viewing issues
* Entire site have been restructured
* Incoporates the following commits by Marco Schuster from PR #1:
  - b77495c
  - 75fe8ff
* Interface have preferences to make it easier to subscribe to lists
* Interface supports internationalization with the following languages included:
  - English
  - Danish
* For now the codebase uses a minized templating system which probably should be reverted, but lets keep it for now

Signed-off-by: Kalle Sommer Nielsen <kalle@php.net>
  • Loading branch information...
commit 354b0d0e354db82bf07c1696105ccacef261e4a4 1 parent d7f43ee
@KalleZ KalleZ authored
Showing with 2,879 additions and 1,101 deletions.
  1. +31 −0 .htaccess
  2. +0 −49 README
  3. +208 −279 article.php
  4. +145 −0 attachment.php
  5. +0 −165 common.inc
  6. +0 −141 getpart.php
  7. +75 −150 group.php
  8. BIN  i/g.gif
  9. BIN  i/l.gif
  10. BIN  i/udm.gif
  11. BIN  images/empty_flag.gif
  12. BIN  images/flag_ar.png
  13. BIN  images/flag_bg.png
  14. BIN  images/flag_ca.png
  15. BIN  images/flag_cs.png
  16. BIN  images/flag_da.png
  17. BIN  images/flag_de.png
  18. BIN  images/flag_el.png
  19. BIN  images/flag_en.png
  20. BIN  images/flag_es.png
  21. BIN  images/flag_fa.png
  22. BIN  images/flag_fi.png
  23. BIN  images/flag_fr.png
  24. BIN  images/flag_he.png
  25. BIN  images/flag_hk.png
  26. BIN  images/flag_hu.png
  27. BIN  images/flag_id.png
  28. BIN  images/flag_it.png
  29. BIN  images/flag_ja.png
  30. BIN  images/flag_kr.png
  31. BIN  images/flag_lt.png
  32. BIN  images/flag_nl.png
  33. BIN  images/flag_no.png
  34. BIN  images/flag_pl.png
  35. BIN  images/flag_pt-br.png
  36. BIN  images/flag_pt.png
  37. BIN  images/flag_ro.png
  38. BIN  images/flag_ru.png
  39. BIN  images/flag_se.png
  40. BIN  images/flag_sk.png
  41. BIN  images/flag_sl.png
  42. BIN  images/flag_sv.png
  43. BIN  images/flag_tr.png
  44. BIN  images/flag_tw.png
  45. BIN  images/flag_zh.png
  46. BIN  images/icon_rdf.png
  47. BIN  images/icon_rdf_big.png
  48. BIN  images/icon_rss.png
  49. BIN  images/icon_rss_big.png
  50. BIN  images/sprites.png
  51. +41 −0 include/common.inc
  52. +225 −0 include/functions.inc
  53. +51 −0 include/ip-to-country.inc
  54. +86 −0 include/language.inc
  55. +121 −0 include/languages/da.inc
  56. +121 −0 include/languages/en.inc
  57. +87 −0 include/nntp.inc
  58. +79 −0 include/posttohost.inc
  59. +87 −0 include/preferences.inc
  60. +66 −0 include/template.inc
  61. +38 −65 index.php
  62. +0 −23 nntp.inc
  63. +37 −0 preferences.php
  64. +1 −1  robots.txt
  65. +0 −108 search.php
  66. +0 −120 style.css
  67. +146 −0 styles/home.css
  68. +156 −0 styles/news.css
  69. +43 −0 styles/reset.css
  70. +500 −0 styles/theme.css
  71. +77 −0 subscribe.php
  72. +73 −0 templates/article.tpl
  73. +3 −0  templates/article_attachmentbit.tpl
  74. +6 −0 templates/error.tpl
  75. +14 −0 templates/footer.tpl
  76. +17 −0 templates/frontpage.tpl
  77. +20 −0 templates/frontpage_groupbit.tpl
  78. +47 −0 templates/groupview.tpl
  79. +7 −0 templates/groupview_bit.tpl
  80. +7 −0 templates/groupview_bit_rdf.tpl
  81. +7 −0 templates/groupview_bit_rss.tpl
  82. +19 −0 templates/groupview_navigation.tpl
  83. +11 −0 templates/groupview_rdf.tpl
  84. +12 −0 templates/groupview_rss.tpl
  85. +109 −0 templates/header.tpl
  86. +89 −0 templates/preferences.tpl
  87. +17 −0 templates/redirect.tpl
View
31 .htaccess
@@ -0,0 +1,31 @@
+# +----------------------------------------------------------------------+
+# | PHP.net Website Systems |
+# +----------------------------------------------------------------------+
+# | Copyright (c) 2011 The PHP Group |
+# +----------------------------------------------------------------------+
+# | This source file is subject to version 3.01 of the PHP license, |
+# | that is bundled with this package in the file LICENSE, and is |
+# | available through the world-wide-web at the following url: |
+# | http://www.php.net/license/3_01.txt |
+# | If you did not receive a copy of the PHP license and are unable to |
+# | obtain it through the world-wide-web, please send a note to |
+# | license@php.net so we can mail you a copy immediately. |
+# +----------------------------------------------------------------------+
+# | Author: |
+# | Jim Winstead <jimw@php.net> |
+# | Kalle Sommer Nielsen <kalle@php.net> |
+# | Felipe Pena <felipe@php.net> |
+# +----------------------------------------------------------------------+
+
+RewriteEngine on
+
+RewriteRule ^((?:php|ug|svn).+)/start/([0-9]+) group.php?group=$1&start=$2 [L]
+RewriteRule ^((?:php|ug|svn).+)/([0-9]+) article.php?group=$1&id=$2 [L]
+RewriteRule ^((?:php|ug|svn)[^/]+)(/)?$ group.php?group=$1 [L]
+RewriteRule ^subscribe/((?:php|ug|svn).+)(/)?$ subscribe.php?group=$1 [L]
+RewriteRule ^attachment/((?:php|ug|svn).+)/([0-9]+)/([0-9]+)(/)?$ attachment.php?group=$1&article=$2&id=$3 [L]
+RewriteRule ^preferences(/)?$ preferences.php [L]
+RewriteRule ^rss/((?:php|ug|svn)[^/]+)(/)?$ group.php?group=$1&format=rss [L]
+RewriteRule ^rss/((?:php|ug|svn).+)/start/([0-9]+) group.php?group=$1&start=$2&format=rss [L]
+RewriteRule ^rdf/((?:php|ug|svn)[^/]+)(/)?$ group.php?group=$1&format=rdf [L]
+RewriteRule ^rdf/((?:php|ug|svn).+)/start/([0-9]+) group.php?group=$1&start=$2&format=rdf [L]
View
49 README
@@ -1,49 +0,0 @@
-this is all very ugly. just proof-of-concept, really.
-
-the biggest thing to do would be to do something smart with
-mime-encoded messages. but keeping the current property of <b>not</b>
-slurping the whole damn message into memory just to do so.
-
-another thing to do would be to support posting. to avoid
-completely anonymous posting, this could require confirming the
-email address before allowing posts. to do this without actually
-having to maintain a database of users, we could send an email
-containing md5(md5("email:timestamp").$secret) (where $secret is
-some value that is kept secret. duh.) and then let the user "log
-in" by supplying their email address and this code, and storing
-that in a cookie. depends on a secret for 'security', but like i
-said, it avoids having to maintain any sort of state on the server
-side. blocking email addresses for posting will be easy enough
-if anyone ever abuses the system.
-
-should also probably protect email addresses from harvesters.
-then again, anyone who wanted to harvest email addresses could just
-crawl the nntp server directly. or they can crawl any of the other
-mail archives that don't protect the addresses.
-
-keeping track of a .newsrc-like state for users would be cool,
-too. too bad there's no Set::IntSpan for php.
-
-perhaps chasing up the references: chain to display the
-thread when displaying an article would be interesting. i
-have a feeling that building some sort of index is going
-to be desirable at some point. should use jwz's threading
-algorithm. http://www.jwz.org/doc/threading.html
-
-ftp://ftp.isi.edu/in-notes/rfc2047.txt explains how to decode encoded
-header fields. handling utf-8 and iso-8859-1 should be pretty easy.
-could use the gnu recode functions to do this in a general way,
-i think.
-
-oh, and this uses direct socket functions instead of the php imap
-extension because nntp is a drop-dead-easy protocol, and i'm allergic
-to the c-client code.
-
----
-SC.2004.09.03:
-Here are the appropriate Rewrite rules for apache:
- RewriteEngine on
- RewriteRule ^/(php.+)/start/([0-9]+) /group.php?group=$1&i=$2 [L]
- RewriteRule ^/(php.+)/([0-9]+) /article.php?group=$1&article=$2 [L]
- RewriteRule ^/(php[^/]+)(/)?$ /group.php?group=$1 [L]
-
View
487 article.php
@@ -1,294 +1,223 @@
<?php
+/*
+ +----------------------------------------------------------------------+
+ | PHP.net Website Systems |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 2011 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Author: |
+ | Kalle Sommer Nielsen <kalle@php.net> |
+ | Based on code by: |
+ | Jim Winstead <jimw@php.net> |
+ +----------------------------------------------------------------------+
+*/
+
+require 'include/common.inc';
+
+if (!isset($_GET['group'])) {
+ error($lang['groups_error']);
+}
-require 'common.inc';
-require 'nntp.inc';
+$group = preg_replace('@[^A-Za-z0-9.-]@', '', $_GET['group']);
-if (isset($_GET['article'])) {
- $article = (int)$_GET['article'];
-} else {
- error("No article specified");
+if (!$nntp->command('GROUP ' . $group, 211)) {
+ error($lang['groups_error']);
}
-if (isset($_GET['group'])) {
- $group = preg_replace('@[^A-Za-z0-9.-]@', '', $_GET['group']);
-} else {
- $group = false;
+if (!isset($_GET['id']) || !is_numeric($_GET['id']) || !$nntp->command('ARTICLE ' . (string) $_GET['id'], 220)) {
+ error($lang['article_error']);
}
-$s = nntp_connect(NNTP_HOST);
-if (!$s) {
- error("Failed to connect to news server");
+$article = new Template('article');
+$article['group'] = $group;
+$article['id'] = (string) $_GET['id'];
+$article['message'] = '';
+$article['signature'] = '';
+
+$parser_state = 1;
+
+$mimecount = $attachmentcount = 0;
+$boundary = $mimetype = $encoding = $charset = '';
+$boundaries = $headers = $masterheaders = $attachments = Array();
+
+foreach ($nntp->getRawResults() as $line) {
+ if ($line == ".\r\n") {
+ break;
+ } else if ($parser_state == 1 && ($line == "\n" || $line == "\r\n")) {
+ $parser_state = 2;
+
+ 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)) {
+ $boundary = $boundaries[] = trim($m[2]);
+ }
+
+ if (preg_match('/([^;]+)(;|\$)/', $headers['content-type'], $m)) {
+ $mimetype = trim(strtolower($m[1]));
+
+ ++$mimecount;
+ }
+ }
+
+ if (isset($headers['content-transfer-encoding'])) {
+ $encoding = strtolower(trim($headers['content-transfer-encoding']));
+ }
+
+ if ($mimetype && $mimetype != 'text/plain' && substr($mimetype, 0, 10) != 'multipart/') {
+ if (isset($headers['content-type']) && preg_match('/name=(["\']?)(.+)\1/s', $headers['content-type'], $m)) {
+ $name = trim($m[2]);
+ } else if (isset($headers['content-disposition']) && preg_match('/filename=(["\']?)(.+)\1/s', $headers['content-disposition'], $m)) {
+ $name = trim($m[2]);
+ } else {
+ $name = $lang->format('article_unnamed_attachment_x', ++$attachmentcount);
+ }
+
+ if (isset($headers['content-description'])) {
+ $name .= ' ' . trim($headers['content-description']);
+ }
+
+ $attachments[] = Array(
+ 'name' => $name,
+ 'id' => $mimecount,
+ 'type' => $mimetype
+ );
+ }
+
+ $headers = Array();
+
+ continue;
+ } else if (substr($line, 0, 2) == '..') {
+ $line = substr($line, 1);
+ }
+
+ if ($parser_state == 1) {
+ $hline = explode(': ', $line, 2);
+
+ if ($hline[0] && isset($hline[1])) {
+ $key = $last_key = strtolower($hline[0]);
+ $headers[$key] = $masterheaders[$key] = rtrim($hline[1]);
+ } elseif (isset($last_key)) {
+ $headers[$last_key] .= $line;
+ $masterheaders[$last_key] .= $line;
+
+ unset($last_key);
+ }
+ } else {
+ if ($boundary && substr($line, 0, 2) == '--' && in_array(substr($line, 2, strlen($boundary)), $boundaries)) {
+ $parser_state = 1;
+
+ if (substr($line, 2 + strlen($boundary)) == '--') {
+ array_pop($boundaries);
+
+ $boundary = end($boundaries);
+ } else {
+ $mimetype = '';
+ $headers = Array();
+ }
+
+ continue;
+ }
+
+ if ($mimetype && $mimetype != 'text/plain') {
+ continue;
+ }
+
+ switch ($encoding) {
+ case 'quoted-printable':
+ $line = quoted_printable_decode($line);
+ break;
+ case 'base64':
+ $line = base64_decode($line);
+ break;
+ }
+
+ if ($charset) {
+ $line = to_utf8($line, $charset);
+ }
+
+ if (isset($buffer)) {
+ $line = $buffer . $line;
+
+ unset($buffer);
+ } else if (substr($line, -2) != "\r\n") {
+ $buffer = $line;
+
+ continue;
+ }
+
+ $line = preg_replace('/((mailto|https?|ftp|nntp|news):.+?)(&gt;|\\s|\\)|\\.\\s|$)/', '<a href="\\1">\\1</a>\\3', htmlentities($line, ENT_NOQUOTES, 'UTF-8'));
+
+ if ($parser_state != 3 && $line == "-- \r\n") {
+ $old_parser_state = $parser_state;
+ $parser_state = 3;
+ } else if ($parser_state == 3 && $line == "\r\n") {
+ $parser_state = $old_parser_state;
+
+ unset($old_parser_state);
+ }
+
+ if ($parser_state == 3) {
+ $article['signature'] .= $line;
+ } else {
+ $article['message'] .= $line;
+ }
+ }
}
-if ($group) {
- $res = nntp_cmd($s,"GROUP $group",211);
- if (!$res) {
- error("Failed to select group");
- }
-}
+$attachment_list = '';
-$res = nntp_cmd($s, "ARTICLE $article",220);
-if (!$res) {
- error("Failed to get article ". $article);
-}
+if ($attachments) {
+ sort($attachments);
-$started = 0;
-$inheaders = 1; $headers = array();
-$masterheaders = null;
-$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")) {
- $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);
- }
-
- 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,$headers,$charset);
- $started = 1;
- }
-
- $encoding = strtolower(trim(@$headers['content-transfer-encoding']));
- if (strlen($mimetype)
- && $mimetype != "text/plain"
- && substr($mimetype,0,10) != "multipart/") {
- # Display a link to the attachment
- $name = '';
- if ($headers['content-type']
- && preg_match('/name=(["\']?)(.+)\1/s', $headers['content-type'], $m)) {
- $name = trim($m[2]);
- } else if ($headers['content-disposition']
- && preg_match('/filename=(["\']?)(.+)\1/s', $headers['content-type'], $m)) {
- $name = trim($m[2]);
- }
-
- if ($headers['content-description']) {
- $description = trim($headers['content-description']) . " ";
- } else {
- $description = '';
- }
-
- $description .= $name;
- $link_desc = "[$mimetype]";
- if (strlen($description)) {
- $link_desc .= " " . $description;
- }
-
- $dl_link = "/getpart.php?group=$group&amp;article=$article&amp;part=$mimecount";
- $link_desc = htmlspecialchars($link_desc,ENT_QUOTES,"UTF-8");
-
- echo "Attachment: <a href=\"$dl_link\">${link_desc}</a><br />\n";
- }
-
- if ($masterheaders == null) {
- $headers = $masterheaders;
- }
- continue;
- }
- # fix lines that started with a period and got escaped
- if (substr($line,0,2) == "..") {
- $line = substr($line,1);
- }
-
-
- if ($inheaders) {
- @list($k,$v) = explode(": ", $line, 2);
- if ($k && $v) {
- $headers[strtolower($k)] = $v;
- $lk = strtolower($k);
- } else {
- $headers[$lk] .= $line;
- }
- }
- else {
-
- if ($boundary
- && substr($line,0,2) == '--'
- && substr($line,2,strlen($boundary)) == $boundary) {
-
- $inheaders = 1;
-
- if (substr($line,2+strlen($boundary)) == '--') {
- # end of this container
- array_pop($boundaries);
- $boundary = end($boundaries);
- } else {
- # next section; start with an inherited set of headers
- $headers = $masterheaders;
- $mimetype = "";
- }
-
- continue;
- }
-
- if (strlen($mimetype) && $mimetype != "text/plain") {
- continue;
- }
-
- switch($encoding) {
- case "quoted-printable":
- $line = quoted_printable_decode($line);
- break;
- case "base64":
- $line = base64_decode($line);
- break;
- }
-
- // 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);
- }
-
- $line = $linebuf . $line;
-
- 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.
- $line = htmlentities($line,ENT_NOQUOTES,"utf-8");
- $line = preg_replace("/((mailto|https?|ftp|nntp|news):.+?)(&gt;|\\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) == "&gt;") {
- echo "<span class=\"quote\">$line</span>";
- } else {
- echo $line;
- }
- }
-}
-if ($inheaders && !$started) {
- head("$group: ". $headers[subject]);
- start_article($group,$headers,$charset);
-}
-if ($insig) {
- echo "</span>";
-}
-echo " </pre>\n";
-echo " </blockquote>\n";
-
-function start_article ($group,$headers,$charset) {
- 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";
- # date
- echo ' <td class="headerlabel">Date:</td>' . "\n";
- echo ' <td class="headervalue">' . format_date($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 " </tr>\n";
- echo " <tr>\n";
- # references
- if (!empty($headers['references']) || !empty($headers['in-reply-to'])) {
- $ref = $headers["references"] ? $headers["references"] : $headers["in-reply-to"];
- 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/".htmlspecialchars(urlencode($v), ENT_QUOTES, "UTF-8")."\">".($c++)."</a>&nbsp;";
- }
- echo "</td>\n";
- }
- # groups
- if ($headers["newsgroups"]) {
- echo ' <td class="headerlabel">Groups:</td>' . "\n";
- echo ' <td class="headervalue">';
- $r = explode(",", chop($headers["newsgroups"]));
- while (list($k,$v) = each($r)) {
- echo "<a href=\"/".htmlspecialchars(urlencode($v), ENT_QUOTES, "UTF-8")."\">".htmlspecialchars($v, ENT_QUOTES, "UTF-8")."</a>&nbsp;";
- }
- 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";
- echo " <pre>\n";
+ foreach ($attachments as $block) {
+ $item = new Template('article_attachmentbit');
+ $item['name'] = $block['name'];
+ $item['id'] = $block['id'];
+ $item['type'] = $block['type'];
+ $item['group'] = $group;
+ $item['article'] = $article['id'];
+
+ $attachment_list .= $item;
+ }
}
-// Does not check existence of next, so consider this the super duper fast [broken] version
-// Based off navbar() in group.php
-function navbar($group, $current) {
-
- $group = htmlspecialchars($group, ENT_QUOTES, "UTF-8");
-
- echo ' <table border="0" cellpadding="2" cellspacing="2" width="100%">' . "\n";
- echo ' <tr class="alisthead">' . "\n";
- echo ' <td class="nav">';
-
- if ($current > 1) {
- echo ' <a href="/' , $group , '/' , ($current-1) , '"><b>&laquo; previous</b></a>';
- } else {
- echo '&nbsp;';
- }
-
- echo ' </td>' . "\n";
- echo ' <td align="center" class="alisthead">' . "$group (#$current)</td>\n";
- echo ' <td align="right" class="nav">';
- echo ' <a href="/' , $group , '/' , ($current+1) , '"><b>next &raquo;</b></a>';
- echo ' </td>' . "\n";
- echo ' </tr>' . "\n";
- echo ' </table>' . "\n";
+$references = Array();
+
+if (!empty($masterheaders['references']) || !empty($masterheaders['in-reply-to'])) {
+ $refs = explode(' ', !empty($masterheaders['references']) ? $masterheaders['references'] : $headers['in-reply-to']);
+
+
+ foreach ($refs as $ref) {
+ $ref = trim($ref);
+
+ if (empty($ref) || !preg_match('/^<.+>$/', $ref) || !($res = $nntp->command('XPATH ' . $ref, 223, true)) || $res{0} == '/') {
+ continue;
+ }
+
+ $references[] = explode('/', $res);
+ }
}
-navbar($group, $article);
-foot();
+$article['attachment_list'] = $attachment_list;
+$article['headers'] = $masterheaders;
+$article['attachments'] = !empty($attachment_list);
+$article['references'] = $references;
+$article['next'] = $nntp->command('ARTICLE ' . ($article['id'] + 1), 220);
+$article['prev'] = ($article['id'] > 1);
+
+echo new Template('header');
+echo $article;
+echo new Template('footer');
+
+?>
View
145 attachment.php
@@ -0,0 +1,145 @@
+<?php
+/*
+ +----------------------------------------------------------------------+
+ | PHP.net Website Systems |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 2011 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Author: |
+ | Kalle Sommer Nielsen <kalle@php.net> |
+ | Based on code by: |
+ | Jim Winstead <jimw@php.net> |
+ +----------------------------------------------------------------------+
+*/
+
+require 'include/common.inc';
+
+if (!isset($_GET['group'])) {
+ error($lang['groups_error']);
+}
+
+$group = preg_replace('@[^A-Za-z0-9.-]@', '', $_GET['group']);
+
+if (!$nntp->command('GROUP ' . $group, 211)) {
+ error($lang['groups_error']);
+}
+
+if (!isset($_GET['article']) || !is_numeric($_GET['article']) || !$nntp->command('ARTICLE ' . (string) $_GET['article'], 220)) {
+ error($lang['article_error']);
+}
+
+if (!isset($_GET['id'])) {
+ error($lang['attachment_error']);
+}
+
+$part = (integer) $_GET['id'];
+$parser_state = 1;
+
+$emit = false;
+$mimecount = $attachmentcount = 0;
+$boundary = $encoding = $buffer = '';
+$boundaries = $headers = $masterheaders = $attachments = Array();
+
+foreach ($nntp->getRawResults() as $line) {
+ if ($line == ".\r\n") {
+ break;
+ } else if ($parser_state == 1 && ($line == "\n" || $line == "\r\n")) {
+ $parser_state = 2;
+
+ if (isset($headers['content-type'])) {
+ if (preg_match('/boundary=(["\']?)(.+)\1/is', $headers['content-type'], $m)) {
+ $boundary = $boundaries[] = trim($m[2]);
+ }
+
+ if (preg_match('/([^;]+)(;|\$)/', $headers['content-type'], $m)) {
+ ++$mimecount;
+ }
+
+ $emit = ($mimecount == $part);
+ }
+
+ if (isset($masterheaders['content-transfer-encoding'])) {
+ $encoding = strtolower(trim($masterheaders['content-transfer-encoding']));
+ }
+
+ $headers = Array();
+
+ continue;
+ } else if (substr($line, 0, 2) == '..') {
+ $line = substr($line, 1);
+ }
+
+ if ($parser_state == 1) {
+ $hline = explode(': ', $line, 2);
+
+ if ($hline[0] && isset($hline[1])) {
+ $key = $last_key = strtolower($hline[0]);
+
+ if ($emit && isset($masterheaders[$key])) {
+ continue;
+ }
+
+ $headers[$key] = $masterheaders[$key] = rtrim($hline[1]);
+ } elseif (isset($last_key)) {
+ $headers[$last_key] .= $line;
+ $masterheaders[$last_key] .= $line;
+
+ unset($last_key);
+ }
+ } else {
+ if ($boundary && substr($line, 0, 2) == '--' && in_array(substr($line, 2, strlen($boundary)), $boundaries)) {
+ $parser_state = 1;
+
+ if (substr($line, 2 + strlen($boundary)) == '--') {
+ array_pop($boundaries);
+
+ $boundary = end($boundaries);
+ } else {
+ $headers = Array();
+ }
+
+ $emit = false;
+
+ continue;
+ } else if (!$emit) {
+ continue;
+ }
+
+ switch ($encoding) {
+ case 'quoted-printable':
+ $buffer .= quoted_printable_decode($line);
+ break;
+ case 'base64':
+ $buffer .= base64_decode($line);
+ break;
+ default:
+ $buffer .= $line;
+ }
+ }
+}
+
+if (empty($buffer)) {
+ error($lang['attachment_error']);
+}
+
+$filename = $lang['attachment_filename'];
+
+if (preg_match('/name=(["\']?)(.+)\1/s', $masterheaders['content-type'], $m)) {
+ $filename = trim($m[2]);
+}
+
+header('Content-Type: ' . $headers['content-type']);
+header('Content-Disposition: attachment; filename="' . $filename . '"');
+header('Content-Length: ' . strlen($buffer));
+
+echo $buffer;
+
+?>
View
165 common.inc
@@ -1,165 +0,0 @@
-<?php
-
-define('NNTP_HOST', 'localhost');
-
-function error($str) {
- head("PHP news : error");
- echo "<blockquote><strong>Error:</strong> $str</blockquote>\n";
- foot();
- die();
-}
-
-function head($title="PHP news") {
- header("Content-type: text/html; charset=utf-8");
- echo '<?xml version="1.0"?>' . "\n";
-
-?>
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
- "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
- <head>
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
- <title><?php echo $title?></title>
- <link rel="stylesheet" href="/style.css" type="text/css" />
- </head>
- <body>
- <table width="100%" border="0" cellspacing="0" cellpadding="0">
- <tr class="header">
- <td>
- <a href="/index.php"><img src="/i/l.gif" width="120" height="67" alt="PHP" /></a>
- </td>
- <td align="right" valign="bottom">
- PHP.net <a href="news://<?php echo $_SERVER['HTTP_HOST']; ?>/" class="top">news server</a> web interface
- </td>
- </tr>
- <tr class="subheader">
- <td colspan="2">
- <img src="/i/g.gif" width="1" height="1" alt="" />
- </td>
- </tr>
- </table>
-<?php
-}
-
-function foot() {?>
- <hr />
- <div class="small">
- Written by Jim Winstead. no rights reserved. (<a href="https://git.php.net/?p=web/news.git">source code</a>)
- </div>
- </body>
-</html>
-<?php
-}
-
-function to_utf8($str, $charset)
-{
- $n = iconv($charset ? $charset : 'iso-8859-1', 'utf-8', $str);
- if ($n === false) {
- return $str;
- }
- return $n;
-}
-
-/*
-if (function_exists("mb_convert_encoding")) {
-function to_utf8($str, $charset)
-{
-return mb_convert_encoding($str, "utf-8", strlen($charset) ? $charset : "iso-8859-1");
-}
-} else if (function_exists("recode_string")) {
-function to_utf8($str, $charset)
-{
-if (strlen($charset) == 0)
-$charset = "iso-8859-1";
-return recode_string("$charset..utf-8", $str);
-}
-} else if (function_exists("iconv")) {
-function to_utf8($str, $charset)
-{
-return iconv(strlen($charset) ? $charset : "iso-8859-1", "utf-8", $str);
-}
-} else {
-function to_utf8($str, $charset)
-{
-return $str;
-}
-}
-*/
-
-function decode_header($charset,$encoding,$text) {
- if (strtolower($encoding) == "b") {
- $text = base64_decode($text);
- } else {
- $text = quoted_printable_decode($text);
- }
- return to_utf8($text, $charset);
-}
-
-function recode_header($header, $basecharset) {
- if (strpos($header, "=?") === false) {
- return to_utf8($header, $basecharset);
- }
- return preg_replace("/=\\?(.+?)\\?([qb])\\?(.+?)(\\?=|$)/ie", "decode_header('\\1','\\2','\\3')", $header);
-}
-
-/* Email spam protection (taken from php-bugs-web) */
-function spam_protect($txt) {
- $translate = array('@' => ' at ', '.' => ' dot ');
-
- /* php.net addresses are not protected! */
- if (preg_match('/^(.+)@php\.net/i', $txt)) {
- return $txt;
- } else {
- return strtr($txt, $translate);
- }
-}
-
-
-# this turns some common forms of email addresses into mailto: links
-function format_author($a, $charset) {
- $a = recode_header($a, $charset);
- if (preg_match("/^\s*(.+)\s+\\(\"?(.+?)\"?\\)\s*$/",$a,$ar)) {
- return "<a href=\"mailto:".htmlspecialchars(urlencode(spam_protect($ar[1])), ENT_QUOTES, "UTF-8")."\" class=\"email fn n\">".str_replace(" ", "&nbsp;", htmlspecialchars($ar[2], ENT_QUOTES, "UTF-8"))."</a>";
- }
- if (preg_match("/^\s*\"?(.+?)\"?\s*<(.+)>\s*$/",$a,$ar)) {
- return "<a href=\"mailto:".htmlspecialchars(urlencode(spam_protect($ar[2])), ENT_QUOTES, "UTF-8")."\" class=\"email fn n\">".str_replace(" ", "&nbsp;", htmlspecialchars($ar[1], ENT_QUOTES, "UTF-8"))."</a>";
- }
- if (ereg("@",$a)) {
- $a = spam_protect($a);
- return "<a href=\"mailto:".htmlspecialchars(urlencode($a), ENT_QUOTES, "UTF-8")."\" class=\"email fn n\">".htmlspecialchars($a, ENT_QUOTES, "UTF-8")."</a>";
- }
- return str_replace(" ", "&nbsp;", htmlspecialchars($a, ENT_QUOTES, "UTF-8"));
-}
-
-function format_subject($s, $charset) {
- global $article;
- $s = recode_header($s, $charset);
- $s = preg_replace("/^(Re: *)?\[(PHP|PEAR)(-.*)?\] /i", "\\1", $s);
- // make this look better on the preview page..
- if (strlen($s) > 150 && !isset($article)) {
- $s = substr($s, 0, 150) . "...";
- } else {
- $s = wordwrap($s, 150);
- }
- return nl2br(htmlspecialchars($s, ENT_QUOTES, "UTF-8"));
-}
-
-
-function format_title($s, $charset) {
- global $article;
- $s = recode_header($s, $charset);
- $s = preg_replace("/^(Re: *)?\[(PHP|PEAR)(-.*)?\] /i", "\\1", $s);
- // make this look better on the preview page..
- if (strlen($s) > 150 && !isset($article)) {
- $s = substr($s, 0, 150) . "...";
- } else {
- $s = wordwrap($s, 150);
- }
- return htmlspecialchars($s, ENT_QUOTES, "UTF-8");
-}
-
-function format_date($d) {
- $d = strtotime($d);
- $d = strftime("%c", $d);
- return str_replace(" ", "&nbsp;", $d);
-}
View
141 getpart.php
@@ -1,141 +0,0 @@
-<?php
-
-require 'common.inc';
-require 'nntp.inc';
-
-if (isset($_GET['group'])) {
- $group = preg_replace('@[^A-Za-z0-9.-]@', '', $_GET['group']);
-} else {
- $group = false;
-}
-
-if (isset($_GET['article'])) {
- $article = (int)$_GET['article'];
-} else {
- error("No article specified");
-}
-
-if (isset($_GET['part'])) {
- $part = $_GET['part'];
-} else {
- error("No part specified");
-}
-
-$s = nntp_connect(NNTP_HOST);
-if (!$s) {
- error("Failed to connect to news server");
-}
-
-if ($group) {
- $res = nntp_cmd($s,"GROUP $group",211);
- if (!$res) {
- error("Failed to select group");
- }
-}
-
-$res = nntp_cmd($s, "ARTICLE $article",220);
-if (!$res) {
- error("Failed to get article ". $article);
-}
-
-$emit = false;
-
-$inheaders = 1; $headers = array();
-$masterheaders = null;
-$mimetype = $boundary = $charset = $encoding = "";
-$mimecount = 0; // number of mime parts
-$boundaries = array();
-$lk = '';
-while (!feof($s)) {
- $line = fgets($s, 4096);
- if ($line == ".\r\n") {
- break;
- }
- if ($inheaders && ($line == "\n" || $line == "\r\n")) {
- $inheaders = 0;
- if ($headers['content-type']
- && preg_match("/charset=(\"|'|)(.+)\\1/is", $headers['content-type'], $m)) {
- $charset = trim($m[2]);
- }
- if ($headers['content-type']
- && preg_match("/boundary=(\"|'|)(.+)\\1/is", $headers['content-type'], $m)) {
- $boundaries[] = trim($m[2]);
- $boundary = end($boundaries);
- }
- if ($headers['content-type']
- && preg_match("/([^;]+)(;|\$)/", $headers['content-type'], $m)) {
- $mimetype = trim(strtolower($m[1]));
- ++$mimecount;
- }
-
- $emit = ($mimecount == $part);
-
- $encoding = strtolower(trim($headers['content-transfer-encoding']));
- if ($emit) {
- if (isset($headers['content-type'])) {
- header('Content-Type: ' . $headers['content-type']);
- }
- if (isset($headers['content-disposition'])) {
- header('Content-Disposition: ' . $headers['content-disposition']);
- }
- if (isset($headers['content-description'])) {
- header('Content-Description: ' . $headers['content-description']);
- }
- }
-
- if ($masterheaders == null) {
- $headers = $masterheaders;
- }
- continue;
- }
- # fix lines that started with a period and got escaped
- if (substr($line,0,2) == "..") {
- $line = substr($line,1);
- }
- if ($inheaders) {
- list($k,$v) = explode(": ", $line, 2);
- if ($k && $v) {
- $headers[strtolower($k)] = $v;
- $lk = strtolower($k);
- } else {
- $headers[$lk] .= $line;
- }
- } else {
-
- if ($boundary
- && substr($line,0,2) == '--'
- && substr($line,2,strlen($boundary)) == $boundary) {
-
- $inheaders = 1;
-
- if (substr($line,2+strlen($boundary)) == '--') {
- # end of this container
- array_pop($boundaries);
- $boundary = end($boundaries);
- } else {
- # next section; start with an inherited set of headers
- $headers = $masterheaders;
- $mimetype = "";
- }
-
- continue;
- }
-
- if (!$emit) {
- continue;
- }
-
- switch($encoding) {
- case "quoted-printable":
- $line = quoted_printable_decode($line);
- break;
- case "base64":
- $line = base64_decode($line);
- break;
- }
-
- echo $line;
-
- }
-}
-
View
225 group.php
@@ -1,171 +1,96 @@
<?php
+/*
+ +----------------------------------------------------------------------+
+ | PHP.net Website Systems |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 2011 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Author: |
+ | Kalle Sommer Nielsen <kalle@php.net> |
+ | Based on code by: |
+ | Jim Winstead <jimw@php.net> |
+ +----------------------------------------------------------------------+
+*/
-require 'common.inc';
-require 'nntp.inc';
+require 'include/common.inc';
-if (isset($_GET['group'])) {
- $group = preg_replace('@[^A-Za-z0-9.-]@', '', $_GET['group']);
-} else {
- error("Missing group");
+if (!isset($_GET['group'])) {
+ error($lang['groups_error']);
}
-if (isset($_GET['format'])) {
- $format = $_GET['format'];
-} else {
- // assume html
- $format = 'html';
-}
+$group = preg_replace('@[^A-Za-z0-9.-]@', '', $_GET['group']);
-if (isset($_GET['i'])) {
- $i = (int)$_GET['i'];
-} else {
- $i = 0;
+if (($data = $nntp->command('GROUP ' . $group, 211)) === false) {
+ error($lang['groups_error']);
}
-$s = nntp_connect(NNTP_HOST);
-if (!$s) {
- error("Failed to connect to news server");
-}
+$format = '';
-$res = nntp_cmd($s,"GROUP $group",211);
-if (!$res) {
- error("Failed to get info on group");
+if (isset($_GET['format']) && in_array(strtolower($_GET['format']), Array('rss', 'rdf'))) {
+ $format = '_' . strtolower($_GET['format']);
}
-list (, $f, $l, $g) = explode(" ", $res);
-if (!$i || $i > $l - 19 || $i < $f) {
- $i = $l - $f > 19 ? $l - 19 : $f;
-}
-$n = min($l, $i + 19);
+$start = (isset($_GET['start']) ? (integer) $_GET['start'] : 0);
+
+list(, $first, $last) = explode(' ', $data);
-$res = nntp_cmd($s,"XOVER $i-$n", 224);
-if (!$res) {
- error("Failed to get xover data");
+if (!$start || $start > ($last - 19) || $start < $first) {
+ $start = ($last - $first) > 19 ? $last - 19 : $first;
}
-$host = htmlspecialchars($_SERVER['HTTP_HOST'], ENT_QUOTES, "UTF-8");
-switch($format) {
- case 'rss':
- header("Content-type: text/xml");
- echo '<?xml version="1.0" encoding="utf-8"?>' . "\n";?>
-<rss version="0.93">
- <channel>
- <title><?php echo $host; ?>: <?php echo $group?></title>
- <link>http://<?php echo $host; ?>/group.php?group=<?php echo $group?></link>
- <description></description>
-<?php break;
-case 'rdf':
-header("Content-type: text/xml");
-echo '<?xml version="1.0" encoding="utf-8"?>' . "\n";
-?>
-<rdf:RDF
- xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
- xmlns="http://my.netscape.com/rdf/simple/0.9/">
- <channel>
- <title><?php echo $host; ?>: <?php echo $group?></title>
- <link>http://<?php echo $host; ?>/group.php?group=<?php echo $group?></link>
- <description><?php echo $group?> Newsgroup at <?php echo NNTP_HOST; ?></description>
- <language>en-US</language>
- </channel>
-<?php
-break;
-case 'html':
-default:
-head($group);
-navbar($group,$f,$l,$i);
-echo ' <table class="alist" width="100%">' . "\n";
-echo ' <tr>' . "\n";
-echo ' <td class="alisthead">#</td>' . "\n";
-echo ' <td class="alisthead">subject</td>' . "\n";
-echo ' <td class="alisthead">author</td>' . "\n";
-echo ' <td class="alisthead">date</td>' . "\n";
-echo ' <td class="alisthead">lines</td>' . "\n";
-echo ' </tr>' . "\n";
-break;
+$n = min($last, $start + 19);
+
+if (!$nntp->command('XOVER ' . $start . '-' . $n, 224)) {
+ error($lang['groups_error_xover']);
}
-# list of articles
-$class = "even";
-# TODO: somehow determine the correct charset
-$charset = "";
-
-while ($line = fgets($s, 16384)) {
- if ($line == ".\r\n") break;
- $line = chop($line);
- list($n,$subj,$author,$odate,$messageid,$references,$bytes,$lines,$extra)
- = explode("\t", $line, 9);
- /* $date = date("H:i:s M/d/y", strtotime($odate)); */
- $date822 = date("r", strtotime($odate));
-
- switch($format) {
- case 'rss':
- echo " <item>\n";
- echo " <link>http://$host/$group/$n</link>\n";
- echo " <title>", format_subject($subj, $charset), "</title>\n";
- echo " <description>", htmlspecialchars(format_author($author, $charset), ENT_QUOTES, "UTF-8"), "</description>\n";
- echo " <pubDate>$date822</pubDate>\n";
- echo " </item>\n";
- break;
- case 'rdf':
- echo " <item>\n";
- echo " <title>", format_subject($subj, $charset), "</title>\n";
- echo " <link>http://$host/$group/$n</link>\n";
- echo " <description>", htmlspecialchars(format_author($author, $charset), ENT_QUOTES, "UTF-8"), "</description>\n";
- echo " <pubDate>$date822</pubDate>\n";
- echo " </item>\n";
- break;
- case 'html':
- default:
- echo " <tr>\n";
- echo " <td class=\"$class\"><a href=\"/$group/$n\">$n</a></td>\n";
- echo " <td class=\"$class\"><a href=\"/$group/$n\">";
- echo format_subject($subj, $charset);
- echo "</a></td>\n";
- echo " <td class=\"$class vcard\">".format_author($author, $charset)."</td>\n";
- echo " <td align=\"center\" class=\"$class\"><tt>" . format_date($odate) . "</tt></td>\n";
- echo " <td align=\"right\" class=\"$class\">$lines</td>\n";
- echo " </tr>\n";
- }
- $class = ($class == "even") ? "odd" : "even";
+if (empty($format)) {
+ $navigation = new Template('groupview_navigation');
+ $navigation['group'] = $group;
+ $navigation['start'] = $start;
+ $navigation['first'] = $first;
+ $navigation['last'] = $last;
}
-switch ($format) {
- case 'rss':
- echo " </channel>\n</rss>\n";
- break;
- case 'rdf':
- echo "</rdf:RDF>\n";
- break;
- case 'html':
- default:
- echo " </table>\n";
- navbar($group, $f, $l, $i);
- foot();
+$groups = '';
+
+foreach($nntp->getResults(16384, "\t", 9) as $line) {
+ $bit = new Template('groupview_bit' . $format);
+ $bit['id'] = $line[0];
+ $bit['subject'] = $line[1];
+ $bit['author'] = $line[2];
+ $bit['date'] = $line[3];
+ $bit['lines'] = $line[7];
+ $bit['group'] = $group;
+
+ $last_date = $bit['date'];
+
+ $groups .= $bit;
}
-function navbar($g, $f, $l, $i) {
- echo ' <table border="0" cellpadding="2" cellspacing="2" width="100%">' . "\n";
- echo ' <tr class="alisthead">' . "\n";
- echo ' <td class="nav">';
- if ($i > $f) {
- $p = max($i-20,$f);
- echo "<a href=\"/" . htmlspecialchars($g, ENT_QUOTES, "UTF-8") . "/start/$p\"><b>&laquo; previous</b></a>";
- } else {
- echo "&nbsp;";
- }
- echo '</td>' . "\n";
- $j = min($i + 20, $l);
- $c = $l - $f + 1;
- echo ' <td align="center" class="alisthead">'.htmlspecialchars($g, ENT_QUOTES, "UTF-8")." ($i-$j of $c)</td>\n";
- echo ' <td align="right" class="nav">';
- if ($i+20 <= $l) {
- $n = min($i + 20, $l - 19);
- echo "<a href=\"/" . htmlspecialchars($g, ENT_QUOTES, "UTF-8") . "/start/$n\"><b>next &raquo;</b></a>";
- }
- else {
- echo "&nbsp;";
- }
- echo '</td>' . "\n";
- echo ' </tr>' . "\n";
- echo ' </table>' . "\n";
+$groupview = new Template('groupview' . $format);
+$groupview['group'] = $group;
+$groupview['groups'] = $groups;
+$groupview['date'] = $last_date;
+
+if (empty($format)) {
+ $groupview['navigation'] = $navigation;
+
+ echo new Template('header');
+ echo $groupview;
+ echo new Template('footer');
+} else {
+ header('Content-type: text/xml');
+
+ echo $groupview;
}
+
+?>
View
BIN  i/g.gif
Deleted file not rendered
View
BIN  i/l.gif
Deleted file not rendered
View
BIN  i/udm.gif
Deleted file not rendered
View
BIN  images/empty_flag.gif
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  images/flag_ar.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  images/flag_bg.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  images/flag_ca.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  images/flag_cs.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  images/flag_da.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  images/flag_de.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  images/flag_el.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  images/flag_en.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  images/flag_es.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  images/flag_fa.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  images/flag_fi.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  images/flag_fr.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  images/flag_he.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  images/flag_hk.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  images/flag_hu.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  images/flag_id.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  images/flag_it.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  images/flag_ja.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  images/flag_kr.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  images/flag_lt.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  images/flag_nl.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  images/flag_no.png
Diff not rendered
View
BIN  images/flag_pl.png
Diff not rendered
View
BIN  images/flag_pt-br.png
Diff not rendered
View
BIN  images/flag_pt.png
Diff not rendered
View
BIN  images/flag_ro.png
Diff not rendered
View
BIN  images/flag_ru.png
Diff not rendered
View
BIN  images/flag_se.png
Diff not rendered
View
BIN  images/flag_sk.png
Diff not rendered
View
BIN  images/flag_sl.png
Diff not rendered
View
BIN  images/flag_sv.png
Diff not rendered
View
BIN  images/flag_tr.png
Diff not rendered
View
BIN  images/flag_tw.png
Diff not rendered
View
BIN  images/flag_zh.png
Diff not rendered
View
BIN  images/icon_rdf.png
Diff not rendered
View
BIN  images/icon_rdf_big.png
Diff not rendered
View
BIN  images/icon_rss.png
Diff not rendered
View
BIN  images/icon_rss_big.png
Diff not rendered
View
BIN  images/sprites.png
Diff not rendered
View
41 include/common.inc
@@ -0,0 +1,41 @@
+<?php
+/*
+ +----------------------------------------------------------------------+
+ | PHP.net Website Systems |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 2011 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Author: |
+ | Kalle Sommer Nielsen <kalle@php.net> |
+ +----------------------------------------------------------------------+
+*/
+
+require 'include/nntp.inc';
+require 'include/functions.inc';
+require 'include/preferences.inc';
+require 'include/language.inc';
+require 'include/template.inc';
+
+define('SERVER_NAME', 'www.tuxxedo.net');
+define('SERVER_PATH', '/phpdotnet/news/');
+define('NNTP_SERVER', 'news.php.net');
+define('SCRIPT_NAME', end(explode('/', $_SERVER['SCRIPT_NAME'])));
+
+$langs = Array(
+ 'en',
+ 'da'
+ );
+
+$prefs = new Preferences;
+$lang = new Language($prefs->language);
+$nntp = new NNTP(NNTP_SERVER);
+
+?>
View
225 include/functions.inc
@@ -0,0 +1,225 @@
+<?php
+/*
+ +----------------------------------------------------------------------+
+ | PHP.net Website Systems |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 2011 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Author: |
+ | Kalle Sommer Nielsen <kalle@php.net> |
+ | Based on code by: |
+ | Jim Winstead <jimw@php.net> |
+ +----------------------------------------------------------------------+
+*/
+
+function message_wrapper($template, array $vars) {
+ ob_get_clean();
+ echo new Template('header');
+
+ $wrapper = new Template($template);
+
+ foreach ($vars as $var => $value) {
+ $wrapper[$var] = $value;
+ }
+
+ echo $wrapper;
+ echo new Template('footer');
+
+ exit;
+}
+
+function error($message) {
+ message_wrapper('error', Array(
+ 'error' => $message
+ ));
+}
+
+function redirect($title, $message, $location) {
+ message_wrapper('redirect', Array(
+ 'title' => $title,
+ 'message' => $message,
+ 'location' => $location
+ ));
+}
+
+function to_utf8($text, $charset = 'iso-8859-1') {
+ $charset = strtolower($charset);
+
+ if ($charset == 'utf8' || $charset == 'utf-8') {
+ return $text;
+ }
+
+ $converted = iconv($charset, 'utf-8', $text);
+
+ if ($converted === false) {
+ return $text;
+ }
+
+ return $converted;
+}
+
+function decode_header($charset, $encoding, $text) {
+ if (strtolower($encoding) == 'b') {
+ $text = base64_decode($text);
+ } else {
+ $text = quoted_printable_decode($text);
+ }
+
+ return to_utf8($text, $charset);
+}
+
+function recode_header($header, $basecharset) {
+ if (strpos($header, '=?') === false) {
+ return to_utf8($header, $basecharset);
+ }
+
+ return preg_replace('/=\\?(.+?)\\?([qb])\\?(.+?)(\\?=|$)/ie', 'decode_header("\\1", "\\2", "\\3")', $header);
+}
+
+function spam_protect($email) {
+ if (preg_match('/^(.+)@php\.net/i', $email)) {
+ return $email;
+ }
+
+ return strtr($email, Array('@' => ' at ', '.' => ' dot '));
+}
+
+function parse_newsgroup_list($authors) {
+ foreach (explode(',', $authors) as $author) {
+ $author = $email = recode_header(trim($author), 'ISO-8859-1');
+
+ if (preg_match('/^\s*(.+)\s+\\("?(.+?)"?\\)\s*$/', $author, $ar)) {
+ $email = $ar[1];
+ } else if (preg_match('/^\s*"?(.+?)"?\s*<(.+)>\s*$/', $author, $ar)) {
+ $email = $ar[2];
+ }
+
+ if (($pos = strpos($email, '@')) !== false && substr($email, $pos) == '@lists.php.net') {
+ return $email;
+ }
+ }
+
+ return false;
+}
+
+function format_author($author) {
+ $author = recode_header($author, 'ISO-8859-1');
+
+ if (preg_match('/^\s*(.+)\s+\\("?(.+?)"?\\)\s*$/', $author, $ar)) {
+ return '<a href="mailto:' . htmlspecialchars(urlencode(spam_protect($ar[1]))) . '">' . str_replace('_', ' ', htmlspecialchars($ar[2])) . '</a>';
+ } else if (preg_match('/^\s*"?(.+?)"?\s*<(.+)>\s*$/', $author, $ar)) {
+ return '<a href="mailto:' . htmlspecialchars(urlencode(spam_protect($ar[2]))) . '">' . str_replace('_', ' ', htmlspecialchars($ar[1])) . '</a>';
+ } else if (strpos($author, '@') !== false) {
+ $author = spam_protect($author);
+
+ return '<a href="mailto:' . htmlspecialchars(urlencode($author)) . '">' . htmlspecialchars($author) . '</a>';
+ }
+
+ return htmlspecialchars($author);
+}
+
+function format_date($date) {
+ return strftime('%c', strtotime($date));
+}
+
+function format_xml_date($date) {
+ return date('r', strtotime($date));
+}
+
+function format_subject($subject, &$is_svn = false) {
+ $is_svn = false;
+ $subject = recode_header($subject, 'iso-8859-1');
+
+ if ((($pos = strpos($subject, '[PHP')) !== false || ($pos = strpos($subject, '[PEAR')) !== false)) {
+ if (($end_pos = strpos($subject, ']', $pos)) !== false) {
+ $subject = ltrim(substr_replace($subject, '', $pos, $end_pos - $pos + 1));
+ }
+ }
+
+ if (strlen($subject) > 60) {
+ $subject = substr($subject, 0, 60) . '...';
+ } else {
+ $subject = wordwrap($subject, 60);
+ }
+
+ if (substr($subject, 0, 4) == 'svn:') {
+ $is_svn = true;
+ $subject = str_replace('_', ' ', $subject);
+ }
+
+ return nl2br(htmlspecialchars($subject));
+}
+
+function format_newsgroups($newsgroups) {
+ $groups = '';
+ $split = explode(',', $newsgroups);
+ $size = sizeof($split) - 1;
+
+ sort($split);
+
+ foreach ($split as $index => $group) {
+ $groups .= '<a href="' . SERVER_PATH . $group . '/">' . $group . '</a>' . ($index != $size ? '<br />' : '');
+ }
+
+ return $groups;
+}
+
+function format_references(array $references) {
+ global $lang;
+
+ $refs = '';
+ $ref = 0;
+ $size = sizeof($references) - 1;
+
+ foreach ($references as $index => $block) {
+ $refs .= '<a href="' . SERVER_PATH . $block[0] . '/' . $block[1] . '/">' . $lang->format('reference_x', ++$ref) . '</a>' . ($index != $size ? '<br />' : '');
+ }
+
+ return $refs;
+}
+
+function format_message($message, $depth = 1) {
+ $message = ($depth == 1 ? nl2br($message) : $message);
+
+ $quoted = $buffer = '';
+ $parsing = false;
+
+ foreach (explode('<br />', $message) as $line) {
+ if (empty($line)) {
+ continue;
+ } else if (substr(ltrim($line), 0, 4) == '&gt;') {
+ if (!$parsing) {
+ $parsing = true;
+ $quoted .= '<div class="quote-depth depth-' . $depth++ . '">' . "\r\n";
+ }
+
+ $buffer .= substr(ltrim($line), 4) . '<br />';
+ } else {
+ if ($parsing) {
+ $quoted .= format_message($buffer, $depth) . '</div>' . "\r\n";
+ $buffer = '';
+
+ --$depth;
+ }
+
+ $parsing = false;
+ $quoted .= $line . '<br />';
+ }
+ }
+
+ if ($parsing) {
+ $quoted .= format_message($buffer, $depth) . '</div>' . "\r\n";
+ }
+
+ return $quoted;
+}
+
+?>
View
51 include/ip-to-country.inc
@@ -0,0 +1,51 @@
+<?php
+/*
+ +----------------------------------------------------------------------+
+ | PHP.net Website Systems |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 2011 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Author: |
+ | Gabor Hojtsy <goba@php.net> |
+ +----------------------------------------------------------------------+
+*/
+
+function i2c_realip() {
+ $ip = false;
+
+ if (!empty($_SERVER['HTTP_CLIENT_IP'])) {
+ $ip = $_SERVER['HTTP_CLIENT_IP'];
+ }
+
+ if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
+ $ips = explode (', ', $_SERVER['HTTP_X_FORWARDED_FOR']);
+
+ if ($ip) {
+ array_unshift($ips, $ip);
+
+ $ip = false;
+ }
+
+ for ($i = 0; $i < count($ips); $i++) {
+ if (!preg_match('/^(?:10|172\.(?:1[6-9]|2\d|3[01])|192\.168)\./', $ips[$i])) {
+ if (ip2long($ips[$i]) != false) {
+ $ip = $ips[$i];
+
+ break;
+ }
+ }
+ }
+ }
+
+ return ($ip ? $ip : $_SERVER['REMOTE_ADDR']);
+}
+
+?>
View
86 include/language.inc
@@ -0,0 +1,86 @@
+<?php
+/*
+ +----------------------------------------------------------------------+
+ | PHP.net Website Systems |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 2011 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Author: |
+ | Kalle Sommer Nielsen <kalle@php.net> |
+ +----------------------------------------------------------------------+
+*/
+
+class Language implements ArrayAccess {
+ protected $languages = Array();
+ protected $translation = Array();
+
+ public function __construct($code) {
+ global $langs;
+
+ include 'include/languages/' . $code . '.inc';
+
+ $this->languages = $langs;
+ $this->translation = $translation;
+
+ if ($code != 'en') {
+ include 'include/languages/en.inc';
+
+ $this->translation = array_merge($translation, $this->translation);
+ }
+
+ }
+
+ public function format() {
+ $args = func_get_args();
+ $size = sizeof($args);
+ $args[0] = $this[$args[0]];
+
+ if ($args[0] === NULL || !$size) {
+ return '';
+ } else if ($size == 1) {
+ return $args[0];
+ }
+
+ $vars = Array();
+
+ for ($i = 1; $i < $size; ++$i) {
+ $vars['{' . ($i) . '}'] = $args[$i];
+ }
+
+ return str_replace(array_keys($vars), $vars, $args[0]);
+ }
+
+ public function getAvailableLanguages() {
+ return $this->languages;
+ }
+
+ public function offsetGet($offset) {
+ if (isset($this->translation[$offset])) {
+ return to_utf8($this->translation[$offset], $this->translation['encoding']);
+ }
+ }
+
+ public function offsetSet($offset, $value) {
+ $this->translation[$offset] = $value;
+ }
+
+ public function offsetUnset($offset) {
+ if (isset($this->translation[$offset])) {
+ unset($this->translation[$offset]);
+ }
+ }
+
+ public function offsetExists($offset) {
+ return isset($this->translation[$offset]);
+ }
+}
+
+?>
View
121 include/languages/da.inc
@@ -0,0 +1,121 @@
+<?php
+/*
+ +----------------------------------------------------------------------+
+ | PHP.net Website Systems |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 2011 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Author: |
+ | Kalle Sommer Nielsen <kalle@php.net> |
+ +----------------------------------------------------------------------+
+*/
+
+$translation = Array(
+
+/* Common */
+'title' => 'PHP Nyheder',
+'encoding' => 'iso-8859-1',
+
+'success' => 'Succes',
+'error' => 'Fejl',
+'subscribe' => 'Tilmeld',
+'unsubscribe' => 'Afmeld',
+'attachments' => 'Vedhæftede filer',
+'references' => 'Referencer',
+'reference_x' => 'Reference #{1}',
+'redirect' => 'Vidrestil',
+'home' => 'Hjem',
+'news_groups' => 'Nyhedsgrupper',
+'preferences' => 'Præferencer',
+'mailing_lists' => 'Postlister',
+'subject' => 'Emne',
+'author' => 'Forfatter',
+'date' => 'Dato',
+'lines' => 'Linjer',
+'by' => 'af',
+'email' => 'E-mail',
+'next' => 'Næste',
+'previous' => 'Forrige',
+'showing_x_y_of_z' => 'Viser {1} - {2} af {3}',
+'copyright_x' => 'Copyright &copy; 2001-{1} The PHP Group',
+'my_phpdotnet' => 'Min PHP.net',
+'contact' => 'Kontakt',
+'other_phpdotnet_sites' => 'Andre PHP.net sider',
+'mirror_sites' => 'Mirror sider',
+'privacy_policy' => 'Privatlivspolitik',
+
+/* Languages */
+'lang_en' => 'Engelsk / English',
+'lang_da' => 'Dansk',
+
+/* Popular (and quick) groups */
+'popular_group_core' => 'PHP i kernen',
+'popular_group_documentation' => 'PHP Dokumentationen',
+'popular_group_translations' => 'Dokumentations oversættelser',
+
+/* NNTP */
+'nntp_error_connect' => 'Kan ikke forbinde til nyhedsserver',
+'nntp_error_handshake' => 'Kan ikke modtage håndtryk fra nyhedsserver',
+'nntp_error_command' => 'Kan ikke sende kommando til server, kommandoen er for lang',
+
+/* posttohost() */
+'posttohost_error_parse' => 'Kan ikke forstå vært URL',
+'posttohost_error_connect_x' => 'Kan ikke forbinde til vært: {1}',