<?php //display the index of threads in a folder
/* ====================================================================================================================== */
/* NoNonsense Forum v7 © Copyright (CC-BY) Kroc Camen 2011
licenced under Creative Commons Attribution 3.0 <creativecommons.org/licenses/by/3.0/deed.en_GB>
you may do whatever you want to this code as long as you give credit to Kroc Camen, <camendesign.com>
*/
require_once './shared.php';
//get page number
define ('PAGE', preg_match ('/^[1-9][0-9]*$/', @$_GET['page']) ? (int) $_GET['page'] : 1);
//submitted info for making a new thread
//(name / password already handled in 'shared.php')
define ('TITLE', safeGet (@$_POST['title'], SIZE_TITLE));
define ('TEXT', safeGet (@$_POST['text'], SIZE_TEXT ));
/* ====================================================================================================================== */
//has the user submitted a new thread? (and is the info valid?)
if (FORUM_ENABLED && NAME && PASS && AUTH && TITLE && TEXT && @$_POST['email'] == 'hide@address.com') {
//the file on disk is a simplified version of the title:
$translit = preg_replace (
//replace non alphanumerics with underscores and donât use more than 2 in a row
array ('/[^_a-z0-9-]/i', '/_{2,}/'), '_',
//remove the additional characters added by transliteration, e.g. "ñ" = "~n",
//has the added benefit of converting âmicrosoft'sâ to âmicrosoftsâ instead of âmicrosoft_sâ
str_replace (array ("'", "`", "^", "~", "'", '"'), '', strtolower (
//unaccent: <php.net/manual/en/function.iconv.php>
iconv ('UTF-8', 'US-ASCII//IGNORE//TRANSLIT', TITLE)
))
);
//old iconv versions and certain inputs may cause a nullstring. don't allow a blank filename
if (!$translit) $translit = '_';
//if a thread already exsits with that name, append a number until an available filename is found
$c = 0;
do $file = $translit.($c++ ? '_'.($c-1) : '');
while (file_exists ("$file.rss"));
//write out the new thread as an RSS file
file_put_contents ("$file.rss", template_tags (<<<XML
<?xml version="1.0" encoding="utf-8" ?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<atom:link href="http://${_SERVER['HTTP_HOST']}&__URL__;.rss" rel="self" type="application/rss+xml" />
<title>&__TITLE__;</title>
<link>http://${_SERVER['HTTP_HOST']}&__URL__;</link>
<item>
<title>&__TITLE__;</title>
<link>http://${_SERVER['HTTP_HOST']}&__URL__;#&__ID__;</link>
<author>&__NAME__;</author>
<pubDate>&__DATE__;</pubDate>
<description>&__TEXT__;</description>
</item>
</channel>
</rss>
XML
, array (
'TITLE' => safeHTML (TITLE),
'URL' => PATH_URL.$file,
'NAME' => safeHTML (NAME),
'DATE' => gmdate ('r'),
'TEXT' => safeHTML (formatText (TEXT)), //process markup
'ID' => base_convert (microtime (), 10, 36) //generate a unique ID for the post A-Z/0-9
)));
//regenerate the folder's RSS file
indexRSS ();
//redirect to newley created thread
header ('Location: '.FORUM_URL.PATH_URL.$file, true, 303);
exit;
}
/* ====================================================================================================================== */
/* sub-forums
---------------------------------------------------------------------------------------------------------------------- */
//donât all sub-sub-forums
if (!PATH) foreach (array_filter (
//get a list of folders:
//include only directories, but ignore directories starting with â.â and the users / themes folders
preg_grep ('/^(\.|users$|themes$)/', scandir ('.'), PREG_GREP_INVERT), 'is_dir'
) as $FOLDER) {
//the sorting (below) requires we be in the directory at hand to use `filemtime`
chdir ($FOLDER);
//get a list of files in the folder to determine which one is newest
$threads = preg_grep ('/\.rss$/', scandir ('.'));
//order by last modified date
array_multisort (array_map ('filemtime', $threads), SORT_DESC, $threads);
//read the newest thread (folder could be empty though)
$last = ($xml = @simplexml_load_file ($threads[0])) ? $xml->channel->item[0] : '';
$FOLDERS[] = array (
'URL' => safeURL (FORUM_PATH."$FOLDER/"),
'NAME' => safeHTML ($FOLDER),
//canât include these details if the folder was empty (no threads)
'DATETIME' => !$last ? '' : date ('c', strtotime ($last->pubDate)),
'TIME' => !$last ? '' : date (DATE_FORMAT, strtotime ($last->pubDate)),
'AUTHOR' => !$last ? '' : safeHTML ($last->author),
'MOD' => !$last ? '' : isMod ($last->author),
'POSTLINK' => !$last ? '' : substr ($last->link, strpos ($last->link, '/', 9))
);
chdir ('..');
}
/* threads
---------------------------------------------------------------------------------------------------------------------- */
//get list of threads (if any--could be an empty folder)
if ($threads = preg_grep ('/\.rss$/', scandir ('.'))) {
//order by last modified date
array_multisort (array_map ('filemtime', $threads), SORT_DESC, $threads);
//does this folder have a sticky list?
$stickies = array ();
if (file_exists ('sticky.txt')) {
//get sticky list, trimming any files that no longer exist
$stickies = array_intersect (file ('sticky.txt', FILE_IGNORE_NEW_LINES + FILE_SKIP_EMPTY_LINES), $threads);
//order the stickies by reverse date order
array_multisort (array_map ('filemtime', $stickies), SORT_DESC, $stickies);
//remove the stickies from the thread list
$threads = array_diff ($threads, $stickies);
}
//paging (stickies are not included in the count as they appear on all pages)
$PAGES = pageList (PAGE, ceil (count ($threads) / FORUM_THREADS));
//slice the full list into the current page
$threads = array_merge ($stickies, array_slice ($threads, (PAGE-1) * FORUM_THREADS, FORUM_THREADS));
//generate the list of threads with data, for the template
foreach ($threads as $file) if (
//read the file, and refer to the last post made (the first item in RSS feed as newest is first)
$xml = @simplexml_load_file ($file)
) {
$last = &$xml->channel->item[0];
$THREADS[] = array (
'STICKY' => in_array ($file, $stickies),
'LOCKED' => (bool) $xml->channel->xpath ("category[text()='locked']"),
//link to the thread--go to the last page of replies
'URL' => pathinfo ($file, PATHINFO_FILENAME).'?page=last',
'TITLE' => safeHTML ($xml->channel->title),
'COUNT' => count ($xml->channel->item) - 1,
//info of last post made to thread
'DATETIME' => date ('c', strtotime ($last->pubDate)), //HTML5 datetime attr
'TIME' => date (DATE_FORMAT, strtotime ($last->pubDate)), //human readable
'AUTHOR' => safeHTML ($last->author),
'MOD' => isMod ($last->author),
'POSTLINK' => substr ($last->link, strpos ($last->link, '/', 9)) //link to the last post
);
}
}
/* new thread form
---------------------------------------------------------------------------------------------------------------------- */
//(exclude if posting has been disabled)
if (FORUM_ENABLED) $FORM = array (
'NAME' => safeString (NAME),
'PASS' => safeString (PASS),
'TITLE' => safeString (TITLE),
'TEXT' => safeHTML (TEXT),
'ERROR' => empty ($_POST) ? ERROR_NONE //no problem? show default help text
: (!NAME ? ERROR_NAME //the name is missing
: (!PASS ? ERROR_PASS //the password is missing
: (!TITLE ? ERROR_TITLE //the title is missing
: (!TEXT ? ERROR_TEXT //the message text is missing
: ERROR_AUTH)))) //the name / password pair didnât match
);
//all the data prepared, now output the HTML
include FORUM_ROOT.'/themes/'.FORUM_THEME.'/index.inc.php';
?>