<?php
	/*
	 * blog.php :	This file provides the meta data parser for the CMS. It generates the temporary
	 *        		file containing the sorted posts. It also handles pre-parsing of embedded content
	 *           	such as images.
	 */
	
	if (!isset($CMS_ACTIVE)) exit();
	require_once "shared.php";

	if (isset($_GET['b'])) { // Blog post selector
		$postUrl = $_GET['b'];
		preg_match("/^[a-z0-9\\-" . POSTS_DIR_SEP . "]*$/", $postUrl, $matches); // SECURITY: Only lowercase a-z + numbers
		if (!$matches)
			unset($postUrl);
		else {
			$postUrl=substr($postUrl, 0, POSTS_MAX_FILENAME);
			$postUrl=POSTS_ROOT . str_replace(POSTS_DIR_SEP, "/", $postUrl) . ".php";
			if (!file_exists($postUrl)) {
				unset($postUrl);
			}
		}
	}

	$postsPage = 0;
	$postsSkip = 0;
	if (isset($_GET['s'])) { // Page selector for post listing
		if (is_numeric($_GET['s']) && $_GET['s'] < 100) { // SECURITY: MAX 100 pages
			$postsPage = (int)$_GET['s'];
			$postsSkip = $postsPage * POSTS_PAGE_SIZE;
		}
	}

	$tagSearchUrl = "";
	if (isset($_GET['t'])) { // Tag search
		$tagSearch = $_GET['t'];
		preg_match("/^[a-z0-9]*$/", $tagSearch, $matches); // SECURITY: Only lowercase a-z + numbers
		if (!$matches)
			unset($tagSearch);
		else {
			$tagSearch=substr($tagSearch, 0, POSTS_TAG_SEARCH); // SECURITY: Max search length POSTS_TAG_SEARCH
			$tagSearchUrl="&t=$tagSearch";
		}
	}

	$userPassword = "";
	if (isset($_POST['password'])) { // Protected sections
		$userPassword = $_POST['password'];
		preg_match("/^[a-z0-9]*$/", $userPassword, $matches); // SECURITY: Only lowercase a-z + numbers
		if (!$matches)
			$userPassword = "";
		else {
			$userPassword=substr($userPassword, 0, 32); // SECURITY: Max PW len = 32
		}
	}

	// --- $postUrl is now safe to use! (Full FS path)
	// --- $postsPage is now safe to use!
	// --- $tagSearch is now safe to use!
	// --- $userPassword is now safe to use!

	// Function called by the individual post headers to determin whether to display it and
	// to configure / complete the metadata.
	function renderPost() {
		global $CMS_INDEXING;
		global $blogentry;
		global $counters;
		global $meta;
		global $pageTitle;
		global $postUrl;
		global $htmlHead;
		global $CMS_RSS;
		
		$counters['figure'] = 1;
		$counters['video'] = 1;
		$counters['sources'] = 1;
		$meta['sources'] = array();

		$blogentry->file = substr($blogentry->file, strlen(POSTS_ROOT), -4);
		if (!(($posts = apcu_fetch('posts')) && isset($posts[$blogentry->file]) && $blogentry=$posts[$blogentry->file])) {
			//echo "[DBG] Regenerate meta info block...";
			if (!isset($blogentry->file))
				$blogentry->file = "";
			if (!isset($blogentry->title))
				$blogentry->title = "Untitled";
			if (!isset($blogentry->description))
				$blogentry->description = $blogentry->title;
			if (!isset($blogentry->author))
				$blogentry->author = "Anonymous";
			if (!isset($blogentry->status))
				$blogentry->status = "private";
			if (!isset($blogentry->ctime))
				$blogentry->ctime = time();
			if (!isset($blogentry->tags))
				$blogentry->tags = "untagged";

			$blogentry->tags = explode(',', $blogentry->tags);
			sort($blogentry->tags);
			$blogentry->permalink = getServerUrl() . "/?p=blog&b=" . str_replace("/", POSTS_DIR_SEP, $blogentry->file);
			$blogentry->isPublic = ($blogentry->status == "released");
		}
		$renderIt = $CMS_INDEXING || ($blogentry->status == "released") || ($blogentry->status == "unlisted");

		if ($renderIt && !isset($CMS_RSS)) {
			if (isset($postUrl) && !$CMS_INDEXING) { // Set meta information
				$pageTitle = $blogentry->title;
				$htmlHead .= '<meta name="description" content="' . $blogentry->description . '">
							  <meta name="keywords" content="' . join(",", $blogentry->tags) . '">
							  <meta name="author" content="' . $blogentry->author . '">';
			}
			echo "<blogheading><table><tr><td><h1><a href=\"$blogentry->permalink\">$blogentry->title</a></h1></td>";
			//echo '<td class="date">' . date("l, F jS Y, H:i", $blogentry->ctime) . "</td></tr></table></blogheading>";
			echo '<td class="head"><span class="author">' . $blogentry->author . '</span> | <span title="Original release: ' . date("l, F jS Y, H:i", $blogentry->ctime) . '" class="date">';
			if (isset($blogentry->utime)) {
				echo "Updated " . date("l, F jS Y, H:i", $blogentry->utime);
			} else {
				echo date("l, F jS Y, H:i", $blogentry->ctime);
			}
			echo "</span></td></tr></table></blogheading>";

		}

		return $renderIt;
	}	

	function renderFooter() {
		global $CMS_SINGLE_POST;
		global $counters;
		global $meta;
		$i = 1;
		$renderExt = isset($CMS_SINGLE_POST) && $CMS_SINGLE_POST;
		if ($renderExt && $counters['sources'] > 1) {
			echo '<hr class="sourceSeparator"><p class="sources">Sources:<br>';
			foreach ($meta['sources'] as $v) {
				echo '<span id="src' . $i . '">&nbsp;&nbsp;&nbsp;&nbsp;[' . $i++ . ']: <a href="' . $v . '">' . $v . '</a></span><br>';
			}
			echo '</p><hr class="sourceSeparator">';
		}

		global $blogentry;
		echo '<p class="tags">Tags: ';
		foreach ($blogentry->tags as $v) {
			echo '<a href="/?p=blog&t=' . $v . '">' . $v . '</a> ';
		}
		echo "</p>";

		
	}

	function extended() {
		global $CMS_SINGLE_POST;
		global $blogentry;
		$renderExt = isset($CMS_SINGLE_POST) && $CMS_SINGLE_POST;
		if ($renderExt) {
			echo '<span id="more"></span>';
		}
		else {
			echo '<p><a href="' . $blogentry->permalink . '#more">&rarr; Click here to continue reading &larr;</a></p>';
		}
		return $renderExt;
	}

	function password($pw) {
		global $userPassword;
		if ("$userPassword" == "$pw") {
			echo '<span id="prot"></span>';
			return true;
		}
		else {
			echo "<p>";
			if ($userPassword == "")
				echo "This section is protected. To view it, enter the correct password.";
			else
				echo "The password you entered is incorrect! Please try again.";
?>
		<form action="#prot" method="post">
			<input type="password" name="password"> <input type="submit" value="Unlock section">
		</form>
	</p>
<?php
		}
	}
	
	//apcu_clear_cache();	
	if (!($posts = apcu_fetch('posts'))) {
		$CMS_INDEXING = true;
		//echo "[DBG] Regenerate post index";
		
		$posts = array();
		foreach ($blogDirs as $dirName) {
			// Find all posts
			$Directory = new RecursiveDirectoryIterator('b/' . $dirName . '/');
			$Iterator  = new RecursiveIteratorIterator($Directory);
			$objects   = new RegexIterator($Iterator, '/^.+\.php$/i', RecursiveRegexIterator::GET_MATCH);

			// Load Meta data and put it into one big archive
			//$posts = array();
			foreach($objects as $file => $object){
				ob_start(); // These ob_lines will prevent output of actual HTML (the function already does this?!)
				require "$file";
				$blogentry->includeFile = $file;
				//echo "<hr>";
				ob_end_clean(); // Enable output, drop cached
				//array_push($posts, $blogentry);
				$posts[$blogentry->file] = $blogentry;
			}

			# Create list of columns relevant for sorting
			$sort = array();
			foreach($posts as $k=>$v) {
				$sort['ctime'][$k] = $v->ctime;;
				// $sort['author'][$k] = $v->author;
			}

			// Now sort the entries
			// Multiple keys: array_multisort($sort['author'], SORT_ASC, $sort['title'], SORT_ASC,$posts);
			array_multisort($sort['ctime'], SORT_DESC, $posts);
		}
		// Store to cache
		apcu_store('posts', $posts, CACHE_POSTS_TTL);
		$CMS_INDEXING = false;
	}
	

	if (!isset($CMS_RSS))
		echo "<blog>";
	if (isset($postUrl)) { // Display post
		$CMS_SINGLE_POST = true;
		echo '<div class="post">';
		// Header is rendered in renderPost()
		require $postUrl; // This will render the body
		//if ($blogentry->isPublic) { // Render the blog footer		
			//echo "<p class=\"author\">Written by $blogentry->author</p>";
			renderFooter();
		//}
		echo '</div>';
	}
	else {
		//echo "<h1>Blog posts</h1>";
		if (isset($tagSearch)) {
			echo "<h1 class=\"bloginfoheader\"><table border=0 style='width: 100%;'><tr><td>Archive for '$tagSearch'</td>";
			if (RSS_ENABLED) {
				echo '<td style="text-align:right;padding:6px; padding-bottom: 0px; "><a href="/rss.php?t=' . $tagSearch . '" title="RSS Feed for \'' . $tagSearch . '\'"><img src="img/rss.svg" style="width: 32px;"></a></td>';
			}
			echo '</tr></table></h1>';
			$pageTitle = "Archive for '$tagSearch'";
		}
		if (isset($CMS_RSS) && RSS_SHOW_FULL) {
			$CMS_SINGLE_POST = true;
		}
		$i = 0;
		$morePosts = false;
		foreach($posts as $k=>$v) {			
			if ($v->isPublic) {
				if (!isset($tagSearch) || in_array($tagSearch, $v->tags)) {
					if ($i++ >= $postsSkip) {
						if (isset($CMS_RSS)) {
							if (!isset($latestDisplayedPost)) {
								$latestDisplayedPost = $v->ctime;
							}
							echo '<item>
	<title>' . $v->title . '</title>
	<description><![CDATA[';
  							require $v->includeFile;
							renderFooter();
 							echo ']]></description>
	<link><![CDATA[' . $v->permalink . ']]></link>
	<guid isPermaLink="true"><![CDATA[' . $v->permalink . ']]></guid>
	<pubDate>' . date(RSS_DATE_FORMAT, $v->ctime) . '</pubDate>
	<dc:creator>' . $v->author . '</dc:creator>
</item>';
						} else {
							echo '<div class="post">';
							require $v->includeFile;
							renderFooter();
							echo "</div>";
							echo '<hr class="postSeparator">';
						}
						if (($i % POSTS_PAGE_SIZE) == 0) {
							$morePosts = true;
							break;
						}
					}
				}
			}
		}
		if ($morePosts || $postsSkip > 0)
			echo "<p><table class=\"blognav\"><tr>";
		if ($morePosts)
			echo '<td><a href="' . "?p=blog$tagSearchUrl&s=" . ($postsPage+1) . '">&lt;&lt; Older posts</a></td>';
		if ($postsSkip > 0)
			echo '<td style="text-align:right;"><a href="' . "?p=blog$tagSearchUrl&s=" . ($postsPage-1) . '">Newer posts &gt;&gt;</a></td>';
		if ($morePosts || $postsSkip > 0)
			echo "</tr></table></p>";
	}
	if (!isset($CMS_RSS))
		echo "</blog>";
?>