Location: PHPKode > projects > Blite > blite-0.1-beta6/blite/index.php
<?php
/*
 *      Copyright 2012 Douglas Robbins <hide@address.com>
 *      
 *      This file is part of Blite, a blogging application, available at
 *      <http://blite.ca/>.
 * 
 *      Blite is free software; you can redistribute it and/or modify
 *      it under the terms of the GNU General Public License as published by
 *      the Free Software Foundation; either version 3 of the License, or
 *      (at your option) any later version.
 *      
 *      This program is distributed in the hope that it will be useful,
 *      but WITHOUT ANY WARRANTY; without even the implied warranty of
 *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *      GNU General Public License for more details.
 *      
 *      You should have received a copy of the GNU General Public License
 *      along with this program. If not, see <http://www.gnu.org/licenses/>.
 */

$tstart = microtime(true);
$browse = 1;

if (!file_exists('configure.php')) {
	echo "Configuration file not found.";
	exit;
}

require('configure.php');
require('themes/' . $cfg['theme'] . '/templates/items.php');

$_SESSION['lastpage'] = $protocol . '://' . $_SERVER['SERVER_NAME'] . $_SERVER['REQUEST_URI'];

if (!empty($_GET['p']) && is_numeric($_GET['p']) && $_GET['p'] > 0) {
	$p = $_GET['p'];
}
else {
	$p = 1;
}
if (!empty($_GET['t']) && is_numeric($_GET['t']) && $_GET['t'] > 0) {
	$t = $_GET['t'];
	if ($p) {
		unset($p);
	}
}
if (!empty($_GET['c']) && is_numeric($_GET['c']) && $_GET['c'] > 0) {
	$c = $_GET['c'];
}
elseif (!empty($_GET['a'])) {
	list ($x, $y) = explode('-', $_GET['a'], 2);
	if ($x && is_numeric($x) && $x > 0) {
		$archyear = $x;
	}
	if ($y && is_numeric($y) && $y > 0 && $y < 13) {
		$archmonth = $y;
	}
	if ($archyear && $archmonth) {
		$a = $archyear . '-' . $archmonth;
	}
}

// Build a nonce.

if ( ($cfg['enablecomments'] == 1 && !empty($_GET['t'])) || $authuser ) {
	$noncestamp = time();
	$nonce = sha1( $noncestamp . $_SERVER['REMOTE_ADDR'] . $cfg['noncesalt'] );
}

$q = 1;

// Build the category array and list.

$query_params = '';
$results = db_query("SELECT id, catname, postcount FROM categories ORDER BY catname");

$categories = '';
while ($row = db_getdata($results)) {
	$postcount = $row['postcount'];
	if (empty($postcount)) {
		$postcount = 0;
	}
	$catid = $row['id'];
	$catname = $row['catname'];
	$catarray[$catid] = $catname;
	$countsbycat[$catid] = $postcount;
	if ($cfg['showcategories'] == 1 && $postcount > 0) {
		$categories .= "<li><a href='?c=$catid'>" . htmlspecialchars($catname) . "</a> ($postcount)</li>\n";
	}
}

$sb_objects['categories'] = '';
if ($cfg['showcategories'] == 1) {
	if (empty($categories)) {
		$categories = "<li>" . $lang['nocategories'] . "</li>";
	}
	$sb_objects['categories'] = "\n<div class='sbtitle'>" . $lang['categories'] . "</div>\n\n<ul class='sbitems'>\n$categories</ul>\n";
}

// A page of posts.

if (!empty($p)) {
	$limit = 10;
	$offset = 0;
	if (!empty($cfg['threadsperpage']) && is_int($cfg['threadsperpage'])) {
		$limit = $cfg['threadsperpage'];
	}
	if ($p > 1) {
		$offset = ($p - 1) * $limit;
	}
	$threadstyle = 'first';
	
	// From a category.
	if (!empty($c)) {
		$query_params = array ( 'c' => 'int' );
		$totalthreads = $countsbycat[$c];
		$results = db_query("SELECT categorized.postid as id, posts.stamp, posts.status, posts.title, posts.categories, posts.body, posts.comcount FROM categorized LEFT JOIN posts ON categorized.postid=posts.id  WHERE categorized.catid=? AND posts.status='1' ORDER BY posts.stamp DESC LIMIT $offset,$limit");
	}
	
	// Or from archive.
	elseif (!empty($a)) {
		$query_params = array ( 'archyear' => 'int', 'archmonth' => 'int' );
		$rowcount = db_query("SELECT postcount FROM archives WHERE year=? AND month=?");
		$row = db_getdata($rowcount);
		$totalthreads = $row['postcount'];
		$query_params = array ( 'a' => 'txt' );
		$results = db_query("SELECT id,status,stamp,title,categories,body,comcount FROM posts WHERE arch=? AND status='1' ORDER BY stamp DESC LIMIT $offset,$limit");
	}
	
	// Or default.
	else {
		$query_params = '';
		$rowcount = db_query("SELECT COUNT(*) as count FROM posts WHERE status='1'");
		$row = db_getdata($rowcount);
		$totalthreads = $row['count'];
		$results = db_query("SELECT id,status,stamp,title,categories,body,comcount FROM posts WHERE status='1' ORDER BY stamp DESC LIMIT $offset,$limit");
	}
	
	// If we land in a category or an archive with no posts, redirect to main page.
	if ( (!empty($c) || !empty($a)) && empty($totalthreads)) {
		header("Location: " . $cfg['home']);
		exit;
	}
	
	$numberposts = $totalthreads . ' ' . $lang['posts'];
	if ($totalthreads == '1') {
		$numberposts = '1 ' . $lang['post'];
	}
	
	$thiscatname = '';
	$thisarchname = '';
	if (!empty($c)) {
		$thiscatname = htmlspecialchars($catarray[$c]);
	}
	elseif (!empty($a)) {
		$thisarchname = $months[$archmonth] . ' ' . $archyear;
	}
	
	while ($row = db_getdata($results)) {
		$page['maincontent'] .= format_post($row, '');
		if ($threadstyle == 'first') {
			$threadstyle = '';
		}
		// Note if this is the only post in a category/archive.
		if ($totalthreads == 1) {
			$poststatus = $row['status'];
			$postid = $row['id'];
			$comcount = $row['comcount'];
		}
		unset($row);
	}
	
	// Add the comments if the only post in a category/archive.
	if ( $totalthreads == 1 && $cfg['enablecomments'] == 1 && $comcount > 0 &&  ($poststatus == 1 || $poststatus == 3 & $authuser) ) {
		$query_params = array ( 'postid' => 'int' );
		$results = db_query("SELECT id, stamp, name, email, ip, comment, web FROM comments WHERE postid=? ORDER BY stamp ASC");
		$page['maincontent'] .= build_comments($postid, $comcount);
	}
	
	if (empty($page['maincontent'])) {
		$page['maincontent'] = "<div class='noresult'>" . $lang['nocontent'] . "</div>";
	}
}

// A single post with comments.

elseif (!empty($t)) {
	$query_params = array ( 't' => 'int' );
	$results = db_query("SELECT id, stamp, status, title, categories, body, comcount FROM posts WHERE id=?");
	$row = db_getdata($results);
	$threadstyle = 'first';
	$postid = $row['id'];
	$poststatus = $row['status'];
	$pagination = '';
	
	// Function format_post() will alter $pagetitle and $pagedesc for a single post.
	$pagetitle = $page['pagetitle'];;
	$pagedesc  = $page['description'];;
	$page['maincontent'] = format_post($row, $t);
	$page['pagetitle'] = $pagetitle;
	$page['description'] = $pagedesc;
	
	// Comments.
	if ( $cfg['enablecomments'] == 1 && $row['comcount'] > 0 &&  ($poststatus == 1 || $poststatus == 3 & $authuser) ) {
		$query_params = array ( 't' => 'int' );
		$results = db_query("SELECT id, stamp, name, email, ip, comment, web FROM comments WHERE postid=? ORDER BY stamp ASC");
		$page['maincontent'] .= build_comments($t, $row['comcount']);
	}
	
}
if (!empty($t) || $totalthreads == 1) {	
	
	// Comment form.
	$form_submit_label = $lang['postcomment'];
	$form_title = $lang['addcomment'];
	$form_notes = '';
	if (!$authuser) {
		$form_notes .= "<li>" . str_replace("#editduration#", $cfg['editfor'], $lang['commentnote2']) . "</li>\n";
	}
	if ($cfg['blogspam'] == 1) {
		$form_notes .= "<li>" . $lang['commentnote3'] . " </li>\n";
	}
	
	// Quote a comment in the comment form.
	if (empty($SESSION['com_comment']) && !empty($_GET['q']) && is_numeric($_GET['q']) && $_GET['q'] > 0) {
		$q =$_GET['q'];
		
		$query_params = array ( 'q' => 'int' );
		$results = db_query("SELECT id, name, comment FROM comments WHERE id=?");
		
		$row = db_getdata($results);
		$qname = $row['name'];
		$qcomment = $row['comment'];
		$qcitation = str_replace("#name#", $qname, $lang['citation']);
		$comquote = "<blockquote>\n$qcitation\n$qcomment\n</blockquote>\n";
	}
	
	// Edit a comment in the form.
	elseif (!empty($_GET['e']) && is_numeric($_GET['e']) && $_GET['e'] > 0) {
	
		if ( isset($_COOKIE[$cookiename]) || $authuser ) {
			$e = $_GET['e'];
			$query_params = array ( 'e' => 'int' );
			$results = db_query("SELECT id, stamp, name, email, ip, comment, web FROM comments WHERE id=?");
			$row = db_getdata($results);
			
			// Reconstruct & check the cookie.
			$good_val = sha1 ($row['email'] . $row['ip'] . $_SERVER['HTTP_USER_AGENT']);
			$expired = false;
			if ( $row['stamp'] < time() - ($cfg['editfor'] * 60) ) {
					$expired = true;
			}
			if ( ($_COOKIE[$cookiename] == $good_val && $_SERVER['REMOTE_ADDR'] == $row['ip'] && !$expired) || $authuser ) {
				$form_name = htmlspecialchars($row['name']);
				$form_email = htmlspecialchars($row['email']);
				$form_web = htmlspecialchars($row['web']);
				$form_comment = $row['comment'];
				
				// Decode any <code> blocks.
				if ( stristr($form_comment, '<code>') ) {
					$form_comment = decode_code($form_comment);
				}
				$form_comment = htmlspecialchars($form_comment);
				
				$form_submit_label = $lang['savechanges'];
				$form_title = $lang['editcomment'];
				$form_notes = "<li>" . $lang['editreminder'] . "</li>\n";
				if ($authuser) {
					$form_notes = '';
				}
			}
		}
	
	}
	
	// If there are session vars for a user's name, email and comment, load them
	// into the local vars for the form, but not if we're editing a comment 
	// (as the form vars are loaded above).
	
	if (empty($e)) {
		$form_name = '';
		$form_email = '';
		$form_web = '';
		$form_comment = '';
		if ( !empty($_SESSION['com_name']) ) {
			$form_name = $_SESSION['com_name'];
		}
		if ( !empty($_SESSION['com_email']) ) {
			$form_email = $_SESSION['com_email'];
		}
		if ( !empty($_SESSION['com_web']) ) {
			$form_web = $_SESSION['com_web'];
		}
		if ( empty($e) && !empty($_SESSION['com_comment']) ) {
			$form_comment = $_SESSION['com_comment'];
		}
	}

	// Comment form.

	$com_error = '';
	if (!empty($_SESSION['com_error'])) {
		$com_error = $_SESSION['com_error'];
	}
	if (empty($comquote)) {
		$comquote = '';
	}
	if (empty($form_notes)) {
		$form_notes = '';
	}
	if (empty($e)) {
		$e = '';
	}
	if (!empty($postid) && $cfg['enablecomments'] == 1 && $poststatus == 1) {
		$page['maincontent'] .= "<div class='commentformshadow'></div>\n<form method='post' action='comment.php' id='commentform'>
		<div class='addcomment'>$form_title</div>" .
		$com_error . "
		<div class='label'>" . $lang['name'] . " *</div>
		<div class='in'><input type='text' name='name' value=\"" . $form_name . "\"></div>
		<div class='label'>" . $lang['email'] . " *</div>
		<div class='in'><input type='text' name='email' value=\"" . $form_email . "\"></div>
		<div class='label'>" . $lang['website'] . "</div>
		<div class='in'><input type='text' name='web' value=\"" . $form_web . "\"></div>
		<div class='label'>" . $lang['comment'] . " *</div>
		<div class='in'><textarea name='comment' cols='80' rows='10'>" . $comquote . $form_comment . "</textarea></div>
		<ul class='com_notes'>
		<li>" . $lang['usetags'] . $showtags . "</li>
		$usecode
		$form_notes
		</ul>
		<div class='buttons'><input type='submit' name='submit' value='$form_submit_label'></div>
		<input type='hidden' name='postid' value='$postid'>
		<input type='hidden' name='comid' value='$e'>
		<input type='hidden' name='nonce' value='$nonce'>
		<input type='hidden' name='stamp' value='$noncestamp'>
		</form>\n";
		
		if (!empty($_SESSION['com_error'])) {
			unset ($_SESSION['com_error']);
		}
		if (!empty($_SESSION['com_comment'])) {
			unset ($_SESSION['com_comment']);
		}
	}
}


// Create page navigation

if (empty($t)) {

	$numpages = ceil($totalthreads / $cfg['threadsperpage']);

	// Pagination links
	if ($p && ($numpages > 1)) {
		if ($numpages > 10) {
			if ($p > ($numpages-8) ) {
				$b_array = array("1", "...", $numpages-8, $numpages-7, $numpages-6, $numpages-5, $numpages-4, $numpages-3, $numpages-2, $numpages-1, $numpages);
			}
			elseif ($p > 7) {
				$b_array = array("1", "...", $p-3, $p-2, $p-1, $p, $p+1, $p+2, $p+3, "...", $numpages);
			}
			elseif ($p <= '7') {
				$b_array = array("1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "...", $numpages);
			}
		}
		else {
			$pagecount = 1;
			while ($pagecount < $numpages+1) {
				$b_array[] = $pagecount;
				$pagecount++;
			}
		}
		$pagination = '';
		foreach ($b_array as $bnum) {
			if ($bnum == '...') {
				$pagination .= "<span class='pg'>...</span>\n";
			}
			elseif ($bnum == $p) {
				$pagination .= "<span class='pg'>$bnum</span>\n";
			}
			elseif ($bnum <= $numpages) {
				if (!empty($c)) {
					$args = "c=$c&p=$bnum";
				}
				elseif (!empty($a)) {
					$args = "a=$a&p=$bnum";
				}
				else {
					$args = "p=$bnum";
				}
				$pagination .= "<a href='?$args' class='pg'>$bnum</a>\n";
			}
		}
		$pagination = "<div class='pages'><b>" . $lang['pages'] . "</b>: $pagination</div>";
	}
	if (empty($pagination)) {
		$pagination = "<div class='pages'><b>" . $lang['page'] . "</b>: 1 / 1</div>";
	}

}

// Build the archive list.

$sb_objects['archives'] = '';
if ($cfg['showarchives'] == 1) {

	if (file_exists($cfg['datadir'] . '/cache/archives')) {
		$sb_objects['archives'] = file_get_contents($cfg['datadir'] . '/cache/archives');
	}
	else {
	
		$query_params = '';
		$results = db_query("SELECT id,year,month,postcount FROM archives WHERE postcount > '0' ORDER BY year DESC,month");
		
		$year = '';
		while ($row = db_getdata($results)) {
			$postcount = $row['postcount'];
			$arg = "a=" . $row['year'] . '-' . $row['month'];
			if (!$postcount) {
				$postcount = '0';
			}
			if ($year > 1 && ($row['year'] !== $year)) {
				$sb_objects['archives'] = substr($sb_objects['archives'], 0, -2);
				$sb_objects['archives'] .= "</li>\n<li><b>" . $row['year'] . ":</b> ";
				$year = $row['year'];
			}
			elseif ($row['year'] !== $year) {
				$sb_objects['archives'] .= "<li><b>" . $row['year'] . ":</b> ";
				$year = $row['year'];
			}
			$month = $row['month'];
			$sb_objects['archives'] .= "<a href='?$arg'>" . $months_abbr[$month] . "&nbsp;($postcount)</a>, ";
			unset($row);
		}
		if ($sb_objects['archives']) {
			$sb_objects['archives'] = substr($sb_objects['archives'], 0, -2);
			$sb_objects['archives'] = "\n<div class='sbtitle'>" . $lang['archives'] . "</div>\n\n<ul class='sbitems'>" . $sb_objects['archives'] . "</li>\n</ul>\n";
		}
		else {
			$sb_objects['archives'] = "\n<div class='sbtitle'>" . $lang['archives'] . "</div>\n\n<ul class='sbitems'><li>" . $lang['noarchives'] . "</li></ul>\n";
		}
		write_file($cfg['datadir'] . '/cache/archives', $sb_objects['archives']);
		
	}
}


// Build the recent posts list.

$sb_objects['recentposts'] = '';
if ($cfg['numrecentposts'] > 0) {
	if (file_exists($cfg['datadir'] . '/cache/recent-posts')) {
		$sb_objects['recentposts'] = file_get_contents($cfg['datadir'] . '/cache/recent-posts');
	}
	else {
		$query_params = '';
		$results = db_query("SELECT id, stamp, title FROM posts WHERE status='1' ORDER BY stamp DESC LIMIT $cfg[numrecentposts]");
		
		while ($row = db_getdata($results)) {
			$postdate = date("d M Y", $row['stamp']+$timeoffset);
			$arg = "t=" . $row['id'];
			$sb_objects['recentposts'] .= "<li><a href='?$arg'>" . htmlspecialchars($row['title']) . "</a> " . $lang['poston'] . " $postdate</li>\n";
			unset($row);
		}
		if (!$sb_objects['recentposts']) {
			$sb_objects['recentposts'] = '<li>' . $lang['noposts'] . '</li>';
		}
		$sb_objects['recentposts'] = "\n<div class='sbtitle'>" . $lang['recentposts'] . "</div>\n\n<ul class='sbitems'>\n" . $sb_objects['recentposts'] . "</ul>\n";
		write_file($cfg['datadir'] . '/cache/recent-posts', $sb_objects['recentposts']);
		
	}
}


// Build the recent comments list.

$sb_objects['recentcomments'] = '';
if ($cfg['enablecomments'] == 1 && $cfg['numrecentcomments'] > 0) {
	if (file_exists($cfg['datadir'] . '/cache/recent-comments')) {
		$sb_objects['recentcomments'] = file_get_contents($cfg['datadir'] . '/cache/recent-comments');
	}
	else {
		$query_params = '';
		$results = db_query("SELECT comments.postid as postid, comments.id, comments.name, comments.comment, posts.title FROM comments, posts WHERE posts.status='1' AND comments.postid=posts.id ORDER BY comments.stamp DESC LIMIT $cfg[numrecentcomments]");
		
		while ($row = db_getdata($results)) {
			$truncomment = str_replace("\n", " ", $row['comment']);
			if (stristr($truncomment, '<blockquote>')) {
				$truncomment = preg_replace("/\<blockquote\>(.*)\<\/blockquote\>/", '', $truncomment);
			}
			$truncomment = trim(strip_tags($truncomment));
			$len = strlen($truncomment);
			if ($len > 50) {
				$truncomment = substr($truncomment, 0, 50) . '...';
			}
			if ( stristr($truncomment, '&lt;') ) {
				$truncomment = htmlspecialchars_decode($truncomment);
			}
			$truncomment = htmlspecialchars($truncomment);
			$arg = 't=' . $row['postid'] . '#comment-' . $row['id'];
			$sb_objects['recentcomments'] .= '<li><b>' . $row['name'] . '</b> ' . $lang['commenton'] . ' <i>' . htmlspecialchars($row['title']) . "</i>: <a href='?$arg'>" . $truncomment . "</a></li>\n";
			unset($row);
		}
		if (!$sb_objects['recentcomments']) {
			$sb_objects['recentcomments'] = "<li>" . $lang['nocomments'] . "</li>";
		}
		$sb_objects['recentcomments'] = "\n<div class='sbtitle'>" . $lang['recentcomments'] . "</div>\n\n<ul class='sbitems'>\n" . $sb_objects['recentcomments'] . "</ul>\n";
		write_file($cfg['datadir'] . '/cache/recent-comments', $sb_objects['recentcomments']);
	}
}


// Build the Admin sidebar panel.

$sb_objects['adminlinks'] = "\n<div class='sbtitle'>Administration</div>\n<ul class='sbitems sbadmin'>$adminnav</ul>\n";


// Timezone selector.

$offsetdisplay = "+0";
if (!empty($_COOKIE['timeoffset'])) {
	$offsetdisplay = $_COOKIE['timeoffset'];
}
$localtime = date('g:i a', (time() + $timeoffset));
$timezone = "\n<form method='post' action='time.php' class='timezone'><b>" . $lang['alltimesGMT'] . "</b> <input type='text' name='offset' value='" . $offsetdisplay . "' size=10> <b>" . $lang['hours'] . "</b></form>\n<div class='localtime'>" . $lang['localtime'] . ": $localtime</div>";


// Build the page array.

if (!empty($c)) {
	$page['infobar'] = str_replace("#numberposts#", $numberposts, $lang['categoryinfo']);
	$page['infobar'] = "<div class='infobar'>" . str_replace("#name#", $thiscatname, $page['infobar']) . "</div>\n";
	$page['pagetitle'] = $thiscatname . ' : ' . $page['pagetitle'];
}
elseif (!empty($a)) {
	$page['infobar'] = str_replace("#numberposts#", $numberposts, $lang['archiveinfo']);
	$page['infobar'] = "<div class='infobar'>" . str_replace("#month#", $thisarchname, $page['infobar']) . "</div>\n";
	$page['pagetitle'] = $thisarchname . ' : ' . $page['pagetitle'];
}

$page['sidebar'] = stripslashes($cfg['sidebar']);
foreach ($sb_objects as $key => $val) {
	$page['sidebar'] = str_replace("#${key}#",$val,$page['sidebar']);
}

if ($cfg['rssposts'] == 1) {
	$page['rss'] = "<link rel='alternate' type='application/rss+xml' href='" . $cfg['home'] . "rss.php' title='" . $lang['artrsstitle'] . "'>";
	$page['rssicon'] = "<div class='rssicon'><a href='rss.php' title='" . $lang['artrsstitle'] . "'><img src='themes/" .$cfg['theme'] . "/rss.png' width=32 height=32 border=0 alt='RSS'></a></div>";
	$page['rsstext'] = "<div class='rsstext'><a href='rss.php'>" . $lang['artrsstitle'] . "</a></div>";
}

if ($cfg['rsscomments'] == 1 && !empty($t)) {
	$page['rss'] .= "\n<link rel='alternate' type='application/rss+xml' href='" . $cfg['home'] . "rss.php?t=$t' title='" . $lang['comrsstitle'] . "'>";
}

$page['navbottom'] = "\n<div class='navleft'>\n$pagination\n<ul class='adminnav'>$adminnav</ul>\n</div>\n\n<div class='navright'>${timezone}#stats#</div>\n";

// Do nonce pruning?

if ( time() - ($cfg['noncespruneinterval'] * 3600) > $cfg['nonceslastpruned'] ) {
	prune_nonces();
}

// Load elements into the template.

$template = file_get_contents('themes/' . $cfg['theme'] . '/templates/main.tpl');
$template = str_replace("#maincontent#", $sub_template, $template);
foreach ($page as $key => $val) {
	$template = str_replace("#${key}#",$val,$template);
}

// SQL, memory and gen time stats.

$tend = microtime(true);
$proc_time = round(($tend - $tstart),4);
$memory_usage = number_format(round(memory_get_peak_usage() / 1024));
$stats = "\n<div class='phptime'>$queries SQLite queries, $memory_usage kb peak memory usage, generated in " . round(($tend - $tstart),4) . " sec.</div>\n";

$template = str_replace("#stats#",$stats,$template);

header("Content-Type: text/html; charset=" . $cfg['charset']);
echo $template;
exit;


// Functions used above. ======================================================

function prune_nonces() {
	global $cfg;
	global $db;
	global $queries;
	$queries = $queries+2;
	$now = time();
	$stamp = $now - ($cfg['nonceslifetime'] * 3600);
	$db->exec("DELETE FROM nonces WHERE stamp < '$stamp'");
	$db->exec("UPDATE settings set value='$now' WHERE name='nonceslastpruned'");
}

function format_post($row, $t) {
	global $lang;
	global $catarray;
	global $threadstyle;
	global $authuser;
	global $pagetitle;
	global $pagedesc;
	global $timeoffset;
	global $cfg;
	global $p;
	global $post_template;
	global $nonce;
	global $noncestamp;
	global $totalthreads;
	
	$post = $post_template;
	$items['threadstyle'] = $threadstyle;
	$id = $row['id'];

	// If this is the only post in a category or archive, treat it as a full post.
	if ($totalthreads == 1 & !empty($id)) {
		$t = $id;
	}
	
	if (empty($id)) {
		$items = array (
			"threadstyle" => 'first',
			"posttitle"   => $lang['notfound'],
			"dateline"    => '',
			"body"        => '<p>' . $lang['notfoundtext'] . '</p>',
			"comcnt"      => '',
			"post_admin"  => ''
		);
	}
	elseif ($row['status'] > 1 && !$authuser) {
		$items = array (
			"threadstyle" => 'first',
			"posttitle"   => $lang['notavail'],
			"dateline"    => '',
			"body"        => '<p>' . $lang['notavailtext'] . '</p>',
			"comcnt"      => '',
			"post_admin"  => ''
		);
	}
	
	else {	
		$items['posttitle'] = htmlspecialchars($row['title']);
		if (empty($t)) { 
			$items['posttitle'] = "<a href='?t=$id'>" . $items['posttitle'] . "</a>";
		}
		else {
			$pagetitle = $items['posttitle'] . ' : ' . $pagetitle;
		}
		$items['body'] = $row['body'];
		
		// Load excerpt from cache.
		if ($cfg['excerpts'] == '1' && file_exists($cfg['datadir'] . '/cache/excerpt-' . $id)) {
			$body_excerpt = file_get_contents($cfg['datadir'] . '/cache/excerpt-' . $id);
			if (!empty($t)) {
				$pagedesc = htmlspecialchars(strip_tags($body_excerpt));
				$pagedesc = trim(preg_replace("/\r\n|\r|\n/", " ", $pagedesc));
			}
			else {
				$items['body'] = $body_excerpt . "\n<p class='readmore'><a href='?t=$id' class='readmore'>" . $lang['readmore'] . "</a>...</p>\n";
			}
		}
		
		// Or build the excerpt.
		elseif ($cfg['excerpts'] == '1') {
		
			// Make an excerpt if the text contains an excerpt marker.
			if ( preg_match ("/\n<!-- -mark- -->\n/", $items['body'], $matches) ) {
				$excerpt_mark = $matches[0];
				list($body_excerpt) = explode($excerpt_mark, $items['body'], 2);
			}
			
			// If this is a full post, assign the excerpt to the meta description field.
			if ( !empty($body_excerpt) && !empty($t) ) {
				$pagedesc = htmlspecialchars(strip_tags($body_excerpt));
				$pagedesc = preg_replace("/\r\n|\r|\n/", " ", $pagedesc);
				$body_excerpt = '';
			}
			
			// If it isn't a full post, use the excerpt along with a 'read more' link.
			elseif ( !empty($body_excerpt) && $totalthreads > 1) {
				// Ensure the excerpt is valid.
				$body_excerpt = dom_it($body_excerpt);
				$items['body'] = $body_excerpt;
				write_file($cfg['datadir'] . '/cache/excerpt-' . $id, $body_excerpt);
				$items['body'] .= "\n<p class='readmore'><a href='?t=$id' class='readmore'>" . $lang['readmore'] . "</a>...</p>\n";
			}
		}
		
		// If this is a full post and we don't have an excerpt to use as the page meta
		// description, use the first ~200 characters of the post.
		
		if ( !empty($t) && empty($body_excerpt) ) {
			$pagedesc = htmlspecialchars(substr(strip_tags($items['body']), 0, 200 ));
			$pagedesc = preg_replace("/\r\n|\r|\n/", " ", $pagedesc) . '...';
		}

		$commentcount = $row['comcount'];
		if (empty($commentcount)) {
			$commentcount = '0';
		}
		$p_date = date("d M Y, g:i a", $row['stamp']+$timeoffset);
		
		if (stristr($row['categories'], ' ')) {
			$cats = explode(' ', $row['categories']);
			$p_cats = '';
			foreach ($cats as $catid) {
				$p_cats .= "<i><a href='?c=$catid'>" . $catarray[$catid] . '</a></i>, ';
			}
			$p_cats = substr($p_cats, 0, -2);
		}
		else {
			$catid = $row['categories'];
			$p_cats = "<i><a href='?c=$catid'>" . $catarray[$catid] . '</a></i>';
		}
		
		if ($row['status'] == 2) {
			$dateline_template = $lang['draftsavedin'];
			$items['dateline'] = str_replace("#categories#", '<i>'.strip_tags($p_cats).'</i>', $dateline_template);
			$items['dateline'] = "<span class='draft'>" . $lang['draft'] . "</span> " . $items['dateline'];
		}
		elseif ($row['status'] == 3) {
			$dateline_template = $lang['postedin'];
			$items['dateline'] = str_replace("#categories#", '<i>'.strip_tags($p_cats).'</i>', $dateline_template);
			$items['dateline'] = "<span class='retracted'>" . $lang['retracted'] . "</span> " . $items['dateline'];
		}
		else {
			$dateline_template = $lang['postedin'];
			$items['dateline'] = str_replace("#categories#", $p_cats, $dateline_template);
		}
		$items['dateline'] = str_replace("#date#", $p_date, $items['dateline']);
		
		$items['comcnt'] = '';
		if ($cfg['enablecomments'] == 1 && !$t && $commentcount == 1) {
			$items['comcnt'] = "<a href='?t=${id}#comments'>" . $commentcount . ' ' . $lang['comment'] . "</a>";
		}
		elseif ($cfg['enablecomments'] == 1 && !$t && $commentcount > 1) {
			$items['comcnt'] = "<a href='?t=${id}#comments'>" . $commentcount . ' ' . $lang['comments'] . "</a>";
		}
		elseif ($cfg['enablecomments'] == 1 && !$t) {
			$items['comcnt'] = "<a href='?t=${id}#commentform'>" . $lang['nocomments'] . "</a>";
		}
		if (!empty($items['comcnt'])) {
			$items['comcnt'] = "<div class='p_comcnt'>" . $items['comcnt'] . "</div>\n";
		}
		
		$items['post_admin'] = '';
		if ($authuser) {
			$items['post_admin'] = "<div class='p_admin'>\n<form method='post' action='post.php' class='inline'>\n";
			$items['post_admin'] .= "<input type='submit' name='edit' value='" . $lang['admineditpost'] . "' class='blink'>\n";
			if ($row['status'] == 2 || $row['status'] == 3) {
				$items['post_admin'] .= " &nbsp;&middot;&nbsp; <input type='submit' name='publish' value='" . $lang['adminpubpost'] . "' class='blink' onClick=\"return confirm('" . $lang['pubpostcfrm'] . "')\">\n";
			}
			elseif ($row['status'] == 1) {
				$items['post_admin'] .= " &nbsp;&middot;&nbsp; <input type='submit' name='retract' value='" . $lang['admindelpost'] . "' class='blink' onClick=\"return confirm('" . $lang['delpostcfrm'] . "')\">\n";
			}
			$items['post_admin'] .= "<input type='hidden' name='postid' value='${id}'>\n";
			$items['post_admin'] .= "<input type='hidden' name='nonce' value='${nonce}'>\n";
			$items['post_admin'] .= "<input type='hidden' name='stamp' value='${noncestamp}'>\n";
			$items['post_admin'] .= "</form>\n</div>\n";
		}
		
		$items['postid'] = $row['id']; 
	
	}
	
	foreach ($items as $key => $val) {
		$post = str_replace("#${key}#", $val, $post);
	}
	unset($items);
	return $post;
}

// Build all comments for a post.
function build_comments($postid, $comcount) {
	global $results;
	global $cfg;
	global $timeoffset;
	global $poststatus;
	global $authuser;
	global $nonce;
	global $noncestamp;
	global $lang;
	global $comment_template;
	global $comments_all;
	global $cookiename;
	
	$allcoms['comments'] = '';
	while ($comrow = db_getdata($results)) {
		$commentdate = date('d M Y, g:i a', $comrow['stamp']+$timeoffset);
		$items['commentid'] = $comrow['id'];
		$commentname = htmlspecialchars($comrow['name']);
		$commentweb = htmlspecialchars($comrow['web']);
		$webrel = '';
		$webtarget = '';
		if (!empty($commentweb)) {
			if ($cfg['linksnofollow'] == 1) {
				$webrel = "rel='nofollow'";
			}
			if ($cfg['linksnewwindow'] == 1) {
				$webtarget = "target='_blank'";
			}
			$commentname = "<a href='$commentweb' $webrel $webtarget>$commentname</a>";
		}
		$items['commentname'] = $commentname;
		$items['commentbody'] = fix_newlines($comrow['comment']);
		$items['comment_admin'] = '';
		if ($authuser) {
			$items['comment_admin'] = "<a href='?t=" . $postid . "&amp;e=" . $items['commentid'] . "#commentform' class='blink'>".$lang['edit']."</a>";
			$items['comment_admin'] .= "<form method='post' action='comment.php' class='inline'>\n";
			$items['comment_admin'] .= " &nbsp;&middot;&nbsp; <input type='submit' name='delete' value='" . $lang['admindelcom'] . "' class='blink' onClick=\"return confirm('" . $lang['delcomcfrm'] . "')\">";
			if ($cfg['blogspam'] == 1) {
				$items['comment_admin'] .= " &nbsp;&middot;&nbsp; <input type='submit' name='spam' value='" . $lang['adminspam'] . "' class='blink' onClick=\"return confirm('" . $lang['trainspamcfrm'] . "')\">";
				$items['comment_admin'] .= " &nbsp;&middot;&nbsp; <input type='submit' name='ham' value='" . $lang['adminham'] . "' class='blink' onClick=\"return confirm('" . $lang['trainhamcfrm'] . "')\">";
			}
			$items['comment_admin'] .= "<input type='hidden' name='threadid' value='" . $postid . "'>";
			$items['comment_admin'] .= "<input type='hidden' name='commentid' value='" . $comrow['id'] . "'>";
			$items['comment_admin'] .= "<input type='hidden' name='nonce' value='$nonce'>";
			$items['comment_admin'] .= "<input type='hidden' name='stamp' value='$noncestamp'>";
			$items['comment_admin'] .= "</form>\n";
			$items['comment_admin'] = "<div class='adminitems'>" . $items['comment_admin'] . "</div>\n";
		}
		
		$items['dateline'] = $commentdate;
		if ($poststatus == 1) {
			$items['dateline'] .= " &nbsp;&middot;&nbsp; <a href='?t=" . $postid . "&amp;q=" . $comrow['id'] . "#commentform' rel='nofollow'>" . $lang['quote'] . "</a>";
		}
		
		$cookiename = 'comment-' . $comrow['id'];
		
		if ( isset($_COOKIE[$cookiename]) && !$authuser ) {
			$items['dateline'] .= "&nbsp;&middot;&nbsp; <a href='?t=" . $postid . "&amp;e=" . $comrow['id'] . "#commentform' class='admin'>".$lang['edit']."</a>";
		}
		
		$comment = $comment_template;
		foreach ($items as $key => $val) {
			$comment = str_replace("#${key}#", $val, $comment);
		}
		$allcoms['comments'] .= $comment;
		unset($comment);
		unset($items);
		unset($comrow);
	}
	
	$allcoms['commentstitle'] = $comcount . " " . $lang['comments'];
	if ($comcount == 1) {
		$allcoms['commentstitle'] = $comcount . " " . $lang['comment'];
	}
	$allcoms['commentsrssicon'] = '';
	$allcoms['commentsrsstext'] = '';
	if ($cfg['rsscomments'] == 1 && $poststatus == 1) {
		$allcoms['commentsrssicon'] = "<div class='c_rss'><a href='rss.php?t=" . $postid . "' title='" . $lang['comrsstitle'] . "'><img src='themes/" . $cfg['theme'] . "/rss24.png' width=24 height=24 border=0 alt='RSS'></a></div>\n";
		$allcoms['commentsrsstext'] = "<div class='c_rss'><a href='rss.php?t=" . $postid . "' title='" . $lang['comrsstitle'] . "'>" . $lang['comrsstitle'] . "</a></div>\n";
	}

	if (!empty($allcoms['comments'])) {
		foreach ($allcoms as $key => $val) {
			$comments_all = str_replace("#${key}#", $val, $comments_all);
		}
		unset($allcoms);
	}

	return $comments_all;
}


function fix_newlines($comment) {
	// Strip extra newlines within block tags....
	if (stristr($comment,'<')) {
		$wstags = array('code', 'pre', 'ol', 'ul', 'li', 'blockquote');
		foreach ($wstags as $wstag) {
			if (stristr($comment,"<$wstag")){
				$comment = str_replace("<$wstag>\n", "<$wstag>", $comment);
				$comment = str_replace("\n</$wstag>", "</$wstag>", $comment);
				$comment = str_replace("</$wstag>\n", "</$wstag>", $comment);
			}
		}
	}
	// Replace newlines with br tag.
	if (stristr($comment,"\n")) {
		$comment = str_replace("\n", "<br>\n", $comment);
	}
	return $comment;
}

?>
Return current item: Blite