2017-01-27 20:29:27 +01:00
< ? 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 ;
2017-05-27 11:45:08 +02:00
global $CMS_RSS ;
2017-01-27 20:29:27 +01:00
$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 );
2017-05-27 11:45:08 +02:00
$blogentry -> permalink = getServerUrl () . " /?p=blog&b= " . str_replace ( " / " , POSTS_DIR_SEP , $blogentry -> file );
2017-01-27 20:29:27 +01:00
$blogentry -> isPublic = ( $blogentry -> status == " released " );
}
$renderIt = $CMS_INDEXING || ( $blogentry -> status == " released " ) || ( $blogentry -> status == " unlisted " );
2017-05-27 11:45:08 +02:00
if ( $renderIt && ! isset ( $CMS_RSS )) {
2017-01-27 20:29:27 +01:00
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 class="date">' . date ( " l, F jS Y, H:i " , $blogentry -> ctime ) . " </span></td></tr></table></blogheading> " ;
}
return $renderIt ;
}
function renderFooter () {
2017-06-18 16:15:07 +02:00
global $CMS_SINGLE_POST ;
2017-01-27 20:29:27 +01:00
global $counters ;
global $meta ;
$i = 1 ;
2017-06-18 16:15:07 +02:00
$renderExt = isset ( $CMS_SINGLE_POST ) && $CMS_SINGLE_POST ;
if ( $renderExt && $counters [ 'sources' ] > 1 ) {
2017-01-27 20:29:27 +01:00
echo '<hr class="sourceSeparator"><p class="sources">Sources:<br>' ;
foreach ( $meta [ 'sources' ] as $v ) {
echo '<span id="src' . $i . '"> [' . $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">→ Click here to continue reading ←</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 ;
}
2017-05-27 11:45:08 +02:00
if ( ! isset ( $CMS_RSS ))
echo " <blog> " ;
2017-01-27 20:29:27 +01:00
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 )) {
2017-05-27 11:45:08 +02:00
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>' ;
2017-01-27 20:29:27 +01:00
$pageTitle = " Archive for ' $tagSearch ' " ;
}
2017-05-27 11:45:08 +02:00
if ( isset ( $CMS_RSS ) && RSS_SHOW_FULL ) {
$CMS_SINGLE_POST = true ;
}
2017-01-27 20:29:27 +01:00
$i = 0 ;
$morePosts = false ;
foreach ( $posts as $k => $v ) {
if ( $v -> isPublic ) {
if ( ! isset ( $tagSearch ) || in_array ( $tagSearch , $v -> tags )) {
if ( $i ++ >= $postsSkip ) {
2017-05-27 11:45:08 +02:00
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">' ;
}
2017-01-27 20:29:27 +01:00
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 ) . '"><< Older posts</a></td>' ;
if ( $postsSkip > 0 )
echo '<td style="text-align:right;"><a href="' . " ?p=blog $tagSearchUrl &s= " . ( $postsPage - 1 ) . '">Newer posts >></a></td>' ;
if ( $morePosts || $postsSkip > 0 )
echo " </tr></table></p> " ;
2017-05-27 11:45:08 +02:00
}
if ( ! isset ( $CMS_RSS ))
echo " </blog> " ;
2017-01-27 20:29:27 +01:00
?>