409 lines
11 KiB
PHP
Executable file
409 lines
11 KiB
PHP
Executable file
<?php
|
|
define('W2APP', true);
|
|
/*
|
|
* W2
|
|
*
|
|
* Copyright (C) 2007-2011 Steven Frank <http://stevenf.com/>
|
|
*
|
|
* Code may be re-used as long as the above copyright notice is retained.
|
|
* See README.txt for full details.
|
|
*
|
|
* Written with Coda: <http://panic.com/coda/>
|
|
*
|
|
*/
|
|
|
|
// Install PSR-4-compatible class autoloader
|
|
spl_autoload_register(function($class){
|
|
require str_replace('\\', DIRECTORY_SEPARATOR, ltrim($class, '\\')).'.php';
|
|
});
|
|
|
|
// Get Markdown class
|
|
use md\MarkdownExtra;
|
|
|
|
|
|
// User configurable options:
|
|
require_once "config.php";
|
|
|
|
function __( $label, $alt_word = null )
|
|
{
|
|
return is_null($alt_word) ? $label : $alt_word;
|
|
}
|
|
|
|
function truncate($text, $chars) {
|
|
if (strlen($text) <= $chars) {
|
|
return $text;
|
|
}
|
|
$text = $text." ";
|
|
$text = substr($text,0,$chars);
|
|
$text = substr($text,0,strrpos($text,' '));
|
|
$text = $text."...";
|
|
return $text;
|
|
}
|
|
|
|
function printHeader($title, $action, $html, $bodyclass="")
|
|
{
|
|
// TODO: Improve this garbage, I suck at PHP and this is just stuff I found on the internet.
|
|
$nhtml = $html;
|
|
$nhtml = preg_replace( '@<p\b[^>]*>(?=.*?<a\b[^>]*>).*?<\@p>@si', '', $nhtml);
|
|
$nhtml = preg_replace( '@<(li)[^>]*?>.*?</\\1>@si', '', $nhtml);
|
|
$nhtml = preg_replace( '@<(ul)[^>]*?>.*?</\\1>@si', '', $nhtml);
|
|
$nhtml = strip_tags($nhtml);
|
|
$nhtml = preg_replace('/\s*$^\s*/m', "\n", $nhtml);
|
|
$nhtml = truncate($nhtml, 512);
|
|
|
|
print "<!doctype html>\n";
|
|
print "<html lang=\"en\">\n";
|
|
print " <head>\n";
|
|
print " <meta charset=\"UTF-8\">\n";
|
|
print " <meta name=\"description\" content=\"$nhtml\">\n";
|
|
print " <link rel=\"icon\" href=\"/icons/fav.svg\"/>\n";
|
|
print " <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n";
|
|
print " <link type=\"text/css\" rel=\"stylesheet\" href=\"" . BASE_URI . "/" . CSS_FILE ."\" />\n";
|
|
print " <title>".PAGE_TITLE."$title</title>\n";
|
|
print " </head>\n";
|
|
print " <body".($bodyclass != "" ? " class=\"$bodyclass\"":"").">\n";
|
|
}
|
|
|
|
function printFooter()
|
|
{
|
|
print " </body>\n";
|
|
print "<p class=\"footer\">Wiki licensed under the <a href=\"https://git.speedie.site/speedie/spmenu-wiki/raw/branch/master/LICENSE\">MIT</a> license. Articles and images licensed under the CC-BY-SA 4.0 license. <a href=\"https://git.speedie.site/speedie/spmenu-wiki\">Source code</a></p>";
|
|
print "</html>";
|
|
}
|
|
|
|
// Support functions
|
|
|
|
function descLengthSort($val_1, $val_2)
|
|
{
|
|
$firstVal = strlen($val_1);
|
|
$secondVal = strlen($val_2);
|
|
return ( $firstVal > $secondVal ) ?
|
|
-1 : ( ( $firstVal < $secondVal ) ? 1 : 0);
|
|
}
|
|
|
|
function getAllPageNames($path = "")
|
|
{
|
|
$filenames = array();
|
|
$dir = opendir(PAGES_PATH . "/$path" );
|
|
while ( $filename = readdir($dir) )
|
|
{
|
|
if ( $filename[0] == "." )
|
|
{
|
|
continue;
|
|
}
|
|
if ( is_dir( PAGES_PATH . "/$path/$filename" ) )
|
|
{
|
|
array_push($filenames, ...getAllPageNames( "$path/$filename" ) );
|
|
continue;
|
|
}
|
|
if ( preg_match("/".PAGES_EXT."$/", $filename) != 1)
|
|
{
|
|
continue;
|
|
}
|
|
$filename = substr($filename, 0, -(strlen(PAGES_EXT)+1) );
|
|
$filenames[] = substr("$path/$filename", 1);
|
|
}
|
|
closedir($dir);
|
|
return $filenames;
|
|
}
|
|
|
|
function fileNameForPage($page)
|
|
{
|
|
return PAGES_PATH . "/$page." . PAGES_EXT;
|
|
}
|
|
|
|
function imageLinkText($imgName)
|
|
{
|
|
return "![".__("Image Description")."](/pages/".UPLOAD_FOLDER."/$imgName)";
|
|
}
|
|
|
|
function sanitizeFilename($inFileName)
|
|
{
|
|
return str_replace(array('~', '..', '\\', ':', '|', '&'), '-', $inFileName);
|
|
}
|
|
|
|
function pageURL($page)
|
|
{
|
|
return SELF . VIEW . "/".str_replace("%2F", "/", str_replace("%23", "#", urlencode(sanitizeFilename($page))));
|
|
}
|
|
|
|
function pageLink($page, $title, $attributes="")
|
|
{
|
|
return "<a href=\"" . pageURL($page) ."\"$attributes>$title</a>";
|
|
}
|
|
|
|
function redirectWithMessage($page, $msg)
|
|
{
|
|
$_SESSION["msg"] = $msg;
|
|
header("HTTP/1.1 303 See Other");
|
|
header("Location: " . pageURL($page) );
|
|
exit;
|
|
}
|
|
|
|
function checkedExecute(&$msg, $cmd)
|
|
{
|
|
$returnValue = 0;
|
|
$output = '';
|
|
exec($cmd, $output, $returnValue);
|
|
if ($returnValue != 0)
|
|
{
|
|
$msg .= "<br/>Error executing command ".$cmd." (return value: ".$returnValue."): ".implode(" ", $output);
|
|
}
|
|
return ($returnValue == 0);
|
|
}
|
|
|
|
function gitChangeHandler($commitmsg, &$msg)
|
|
{
|
|
if (!GIT_COMMIT_ENABLED)
|
|
{
|
|
return;
|
|
}
|
|
if (checkedExecute($msg, "cd ".PAGES_PATH." && git add -A && git commit -m ".escapeshellarg($commitmsg)))
|
|
{
|
|
if (!GIT_PUSH_ENABLED)
|
|
{
|
|
return;
|
|
}
|
|
checkedExecute($msg, "cd ".PAGES_PATH." && git push");
|
|
}
|
|
}
|
|
|
|
function toHTMLID($noid)
|
|
{ // in HTML5, only spaces aren't allowed
|
|
return str_replace(" ", "-", $noid);
|
|
}
|
|
|
|
function toHTML($inText)
|
|
{
|
|
$parser = new MarkdownExtra;
|
|
$parser->no_markup = true;
|
|
$outHTML = $parser->transform($inText);
|
|
|
|
preg_match_all(
|
|
"/\[\[(.*?)\]\]/",
|
|
$outHTML,
|
|
$matches,
|
|
PREG_PATTERN_ORDER
|
|
);
|
|
for ($i = 0; $i < count($matches[0]); $i++)
|
|
{
|
|
$fullLinkText = $matches[1][$i];
|
|
$linkTitleSplit = explode('|', $fullLinkText);
|
|
$linkedPage = $linkTitleSplit[0]; // split away an eventual link text
|
|
$linkText = (count($linkTitleSplit) > 1) ? $linkTitleSplit[1] : $linkedPage;
|
|
$pagePart = explode('#', $linkedPage)[0]; // split away an eventual anchor part
|
|
$linkedFilename = fileNameForPage(sanitizeFilename($pagePart));
|
|
$exists = file_exists($linkedFilename);
|
|
$outHTML = str_replace("[[$fullLinkText]]",
|
|
pageLink($linkedPage, $linkText, ($exists? "" : " class=\"noexist\"")), $outHTML);
|
|
}
|
|
$outHTML = preg_replace("/\{\{(.*?)\}\}/", "<img src=\"" . BASE_URI . "/images/\\1\" alt=\"\\1\" />", $outHTML);
|
|
|
|
// add an anchor in all title tags (h1/2/3/4):
|
|
preg_match_all(
|
|
"/<h([1-4])>(.*?)<\/h\\1>/",
|
|
$outHTML,
|
|
$matches,
|
|
PREG_PATTERN_ORDER
|
|
);
|
|
for ($i = 0; $i < count($matches[0]); $i++)
|
|
{
|
|
$prefix = "<h".$matches[1][$i].">";
|
|
$caption = $matches[2][$i];
|
|
$suffix = substr_replace($prefix, "/", 1, 0);
|
|
$outHTML = str_replace("$prefix$caption$suffix",
|
|
"$prefix<a id=\"".toHTMLID($caption)."\">$caption</a>$suffix", $outHTML);
|
|
}
|
|
return $outHTML;
|
|
}
|
|
|
|
// Main code
|
|
|
|
$action = isset($_REQUEST['action']) ? $_REQUEST['action'] : 'view';
|
|
$newPage = "";
|
|
$text = "";
|
|
$html = "";
|
|
if ($action === 'view')
|
|
{
|
|
// Look for page name following the script name in the URL, like this:
|
|
// http://stevenf.com/w2demo/index.php/Markdown%20Syntax
|
|
//
|
|
// Otherwise, get page name from 'page' request variable.
|
|
|
|
$page = preg_match('@^/@', @$_SERVER["PATH_INFO"]) ?
|
|
urldecode(substr($_SERVER["PATH_INFO"], 1)) : urldecode(@$_REQUEST['page']);
|
|
$page = sanitizeFilename($page);
|
|
if ( $page == "" )
|
|
{
|
|
$page = DEFAULT_PAGE;
|
|
}
|
|
$filename = fileNameForPage($page);
|
|
|
|
if ( file_exists($filename) )
|
|
{
|
|
$text = file_get_contents($filename);
|
|
}
|
|
else
|
|
{
|
|
$newPage = NULL;
|
|
include('404.php');
|
|
die();
|
|
}
|
|
}
|
|
|
|
$oldgitmsg = "";
|
|
$triedSave = false;
|
|
|
|
if ( $action === 'all' )
|
|
{
|
|
$pageNames = getAllPageNames();
|
|
$filelist = array();
|
|
$sortBy = isset($_REQUEST['sortBy']) ? $_REQUEST['sortBy'] : 'name';
|
|
if (!in_array($sortBy, array('name', 'recent')))
|
|
{
|
|
$sortBy = 'name';
|
|
}
|
|
if ($sortBy === 'name')
|
|
{
|
|
natcasesort($pageNames);
|
|
foreach($pageNames as $page)
|
|
{
|
|
$filelist[$page] = filemtime(fileNameForPage($page));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
foreach($pageNames as $page)
|
|
{
|
|
$filelist[$page] = filemtime(fileNameForPage($page));
|
|
}
|
|
arsort($filelist, SORT_NUMERIC);
|
|
}
|
|
$html .= "<p>".__('Total').": ".count($pageNames)." ".__("pages")."</p>";
|
|
$html .= "<table><thead>";
|
|
$html .= "<tr>".
|
|
"<td>".(($sortBy!='name')?("<a href=\"".SELF."?action=all&sortBy=name\">Name</a>"):"<span class=\"sortBy\">".__('Name')."</span>")."</td>".
|
|
"<td>".(($sortBy!='recent')?("<a href=\"".SELF."?action=all&sortBy=recent\">".__('Modified')."</a>"):"<span class=\"sortBy\">".__('Modified')."</span>")."</td>".
|
|
"</tr></thead><tbody>";
|
|
$date_format = __('date_format', TITLE_DATE);
|
|
|
|
foreach ($filelist as $pageName => $pageDate)
|
|
{
|
|
$html .= "<tr>".
|
|
"<td>".pageLink($pageName, $pageName)."</td>".
|
|
"<td valign=\"top\"><nobr>".date( $date_format, $pageDate)."</nobr></td>".
|
|
"</tr>\n";
|
|
}
|
|
$html .= "</tbody></table>\n";
|
|
}
|
|
else if ( $action === 'search' )
|
|
{
|
|
$matches = 0;
|
|
$q = $_REQUEST['q'];
|
|
$html .= " <h1>Search: $q</h1>\n";
|
|
|
|
if ( trim($q) != "" )
|
|
{
|
|
$html .= " <ul>\n";
|
|
$pagenames = getAllPageNames();
|
|
$found = FALSE;
|
|
$matchingPages = array();
|
|
foreach ($pagenames as $searchPage)
|
|
{
|
|
if ($searchPage === $q)
|
|
{
|
|
$found = TRUE;
|
|
}
|
|
if (preg_match("/{$q}/i", $searchPage))
|
|
{
|
|
array_unshift($matchingPages, $searchPage);
|
|
++$matches;
|
|
}
|
|
else
|
|
{
|
|
$text = file_get_contents(fileNameForPage($searchPage));
|
|
if ( preg_match("/{$q}/i", $text) )
|
|
{
|
|
$matchingPages[] = $searchPage;
|
|
++$matches;
|
|
}
|
|
}
|
|
}
|
|
foreach ($matchingPages as $page)
|
|
{
|
|
$link = pageLink($page, $page, ($page === $q)? " class=\"literalMatch\"": "");
|
|
$html .= " <li>$link</li>\n";
|
|
}
|
|
if (!$found)
|
|
{
|
|
$html .= " <li>".pageLink($q, __('Create page')." '$q'", " class=\"noexist\"")."</li>";
|
|
}
|
|
$html .= " </ul>\n";
|
|
}
|
|
$html .= " <p>$matches ".__('matches')."</p>\n";
|
|
}
|
|
else
|
|
{
|
|
$html .= empty($text) ? '' : toHTML($text);
|
|
}
|
|
|
|
$datetime = '';
|
|
|
|
if ( ($action === 'all'))
|
|
{
|
|
$title = __("All");
|
|
}
|
|
else if ( $action === 'search' )
|
|
{
|
|
$title = __("Search");
|
|
}
|
|
else if ($filename != '')
|
|
{
|
|
$title = $page;
|
|
$date_format = __('date_format', TITLE_DATE);
|
|
if ( $date_format )
|
|
{
|
|
$datetime = "<span class=\"titledate\">" . date($date_format, @filemtime($filename)) . "</span>";
|
|
}
|
|
}
|
|
else
|
|
{
|
|
$title = __($action);
|
|
}
|
|
|
|
header("Cache-Control: no-cache, must-revalidate"); // HTTP/1.1
|
|
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); // Date in the past
|
|
printHeader($title, $action, $html);
|
|
print " <div class=\"titlebar\"><span class=\"title\">$title</span>$datetime";
|
|
print " </div>\n";
|
|
print " <div class=\"toolbar\">\n";
|
|
print " <a href=\"" . SELF . "\"><img src=\"/icons/home.svg\" alt=\"". __(DEFAULT_PAGE) . "\" title=\"". __(DEFAULT_PAGE) . "\" class=\"icon\"></a>\n";
|
|
print " <a href=\"" . SELF . "?action=all\"><img src=\"/icons/list.svg\" alt=\"". __('All') . "\" title=\"". __('All') . "\" class=\"icon\"></a>\n";
|
|
print " <form method=\"post\" action=\"" . SELF . "?action=search\">\n";
|
|
print " <input class=\"search\" placeholder=\"". __('Search') ."\" size=\"20\" id=\"search\" type=\"text\" name=\"q\" />\n </form>\n";
|
|
print " </div>\n";
|
|
if (SIDEBAR_PAGE != '')
|
|
{
|
|
print " <div class=\"sidebar\">\n\n";
|
|
$sidebarFile = fileNameForPage(SIDEBAR_PAGE);
|
|
if (file_exists($sidebarFile))
|
|
{
|
|
$text = file_get_contents($sidebarFile);
|
|
}
|
|
else
|
|
{
|
|
$text = __('Sidebar file could not be found')." ($sidebarFile)";
|
|
}
|
|
print toHTML($text);
|
|
print " </div>\n";
|
|
}
|
|
print " <div class=\"main\">\n\n";
|
|
if(isset($_SESSION['msg']) && $_SESSION['msg'] != '')
|
|
{
|
|
print " <div class=\"note\">".$_SESSION['msg']."</div>";
|
|
unset($_SESSION['msg']);
|
|
}
|
|
print "$html\n";
|
|
print " </div>\n";
|
|
printFooter();
|