<?php
// Show source if requested.
if (isset($_GET['source']) || isset($source))
{
echo '<html><head><meta name="robots" content="noindex,nofollow"></head><body>';
highlight_file(__FILE__);
die();
}
require_once("MyCSV.class.php");
if (isset($_SERVER['PHP_SELF'])) $PHP_SELF = $_SERVER['PHP_SELF'];
$PHP_SELF = preg_replace('/index\.\w+$/', '', $PHP_SELF);
if (isset($_REQUEST['action'])) $action = $_REQUEST['action'];
if (isset($_REQUEST['title'])) $title = $_REQUEST['title'];
if (empty($title)) $title = "Main Page";
else $title = stripslashes($title);
$db = new MyCSV("pages");
$relationships = new MyCSV("relationships");
$record = @$db->data[$title];
if (empty($record))
{
header("HTTP/1.0 404 Not Found");
}
if (! empty($HTTP_POST_VARS['content']) && strlen($HTTP_POST_VARS['content']) < 10000)
{
$record['content'] = trim(stripslashes($HTTP_POST_VARS['content']));
// Transform Windows/Mac/whatever line breaks to simple "\n".
$record['content'] = preg_replace('{\s*?\n\r*|\s*?\r}', "\n", $record['content']);
if (empty($record['created'])) $record['created'] = date("Y-m-d H:i:s");
$record['modified'] = date("Y-m-d H:i:s");
if (empty($record['id']))
{
$record['id'] = $title;
$db->insert($record);
}
else $db->update($record);
$db->write();
$relationships->reset();
while ($rel = $relationships->each())
{
if ($rel['subject'] == $title) $relationships->delete($rel['id']);
}
foreach ($HTTP_POST_VARS['predicate'] as $i => $predicate)
{
$object = $HTTP_POST_VARS['object'][$i];
if (empty($predicate) || empty($object)) continue;
$relationships->insert(array(
'subject' => $title,
'predicate' => $predicate,
'object' => $object));
}
$relationships->write();
}
if (empty($record['content'])) $action = "edit";
function callback($matches)
{
if (empty($matches[1])) return $matches[0];
else
{
return '<a class="auto" href="./?title=' . $matches[0] . '">' . $matches[0] . '</a>';
}
}
function echoPage($content, $more = false)
{
global $PHP_SELF, $db, $title;
$content = preg_replace('{<a>([^<]*)}is', '<a href=\1>\1', $content);
$content = preg_replace('{<img>([^<]*)</img>}is', '<img src="\1">', $content);
$content = preg_replace('{<a=}is', '<a href=', $content);
$content = preg_replace('{<img=}is', '<img src=', $content);
$content = preg_replace_callback('{<a\s+href\s*=\s*([^\s"][^>]*)}is', function ($matches) {
return '<a href="' . htmlspecialchars($matches[1]) . '"';
}, $content);
$content = preg_replace('{<a href="([^:"]*")}is', "<a href=\"$PHP_SELF?title=\\1", $content);
// Detect links/anchors even if they are not in <a href>.
$content = preg_replace_callback('{
<a\b.*?</a>|<img[^>]*>
|
\b(http://|(www\.))([^\s"\'<>\[\]\\\]{4,}[\w/=])
}isx',
function ($matches) {
return stripslashes($matches[1] ? '<a href="http://' . $matches[2] . $matches[3] . '">' . $matches[0] . '</a>' : $matches[0]);
},
$content);
// Generate unordered and ordered lists, two nested levels maximum.
for ($i = 0; $i < 3; $i++)
$content = preg_replace_callback(
'/\n( *)(?:[*-]|\d\.) [^\n]+(\n\1(?: |[*-]|\d\.) [^\n]+)+/is',
'list_callback',
$content);
if (strpos($content, '<pageindex>') !== false)
{
$ids = $db->ids();
usort($ids, 'strnatcasecmp');
$replacement = "";
foreach ($ids as $id)
{
$replacement .= htmlspecialchars($id) . " <small>(created " . $db->data[$id]['created'] . ", modified " . $db->data[$id]['modified'] . ")</small><br>";
}
$content = str_replace('<pageindex>', $replacement, $content);
}
if (strpos($content, '<recentchanges>') !== false)
{
$db->sort("modified DESC");
$replacement = "";
while ($row = $db->each())
{
$replacement .= $row['modified'] . " " . htmlspecialchars($row['id']) . " <small>(created " . $row['created'] . ")</small><br>";
}
$content = str_replace('<recentchanges>', $replacement, $content);
}
unset($db->data[$title]);
$pattern = '{<a\b.*?</a>|<[^>]*|(' . implode('|', array_map('preg_quote', array_map('htmlspecialchars', $db->ids()))) . ')}sS';
$content = preg_replace_callback($pattern, 'callback', $content);
// Replace double quotes with »...« (German style).
// See http://maettig.com/1058945580
$content = preg_replace_callback(
'{<(code|head|pre|script)\b.+?</\1>|<[^>]*>|(?<!\w)"(([^"<]|<[^>]*>)+)"(?!\w)}sS',
function ($matches) {
return stripslashes($matches[2] ? '„' . $matches[2] . '“' : $matches[0]);
},
$content
);
// Replace remaining double quotes with their HTML entities.
//- $content = str_replace('"', '"', $content);
// Replace " - " and " -- " with the n-dash (German style).
// See http://maettig.com/1058945580
$content = preg_replace_callback(
'!<(code|head|pre|script)\b.+?</\1>|<[^>]*>|(?<= )(-{1,2})(?= )!sS',
function ($matches) {
return stripslashes($matches[2] ? '–' : $matches[0]);
},
$content);
// Preserve multiple vertical white spaces.
//- $content = preg_replace('/(^|\s)[ \t]/mS', '\1 ', $content);
if ($more)
{
$content = preg_replace('{<more>.*$}is',
'<div>[<a href="' . $PHP_SELF . '?title=' . htmlspecialchars($more) . '">read on...</a>]</div>', $content);
}
echo $content;
}
function list_callback($matches)
{
$listUO = preg_match('/^\s*[*-]/s', $matches[0]) ? "ul" : "ol";
$matches[0] = preg_replace(
'/\n' . $matches[1] . '(?:[*-]|\d\.) ([^\n]+(\n' . $matches[1] . ' [^\n]+)*)/s',
"<li>\\1\n</li>\n",
$matches[0]);
return "\n<$listUO>\n" . $matches[0] . "</$listUO>";
}
?><html>
<head>
<meta name="robots" content="noindex,nofollow">
<title>TM::Wiki-><?=htmlspecialchars($title)?></title>
<style type="text/css">
body{background-color:#EEE;}
#menu{
background-color:white;
border:1px solid #999;
float:right;
list-style-position:inside;
margin:0;
overflow:hidden;
padding:0 1ex 1ex 1ex;
width:27ex;
}
#menu ul{
list-style-position:inside;
margin:0;
padding:0 0 0 3ex;
}
#menu li{
margin:1ex 0 0 0;
padding:0;
white-space:nowrap;
}
#page{
margin-right:31ex;
}
.rdfType{
border:1px solid #999;
margin:0 0 2ex 0;
padding:1ex;
}
.rdfTypeA{
background-color:#DDD;
border-color:white;
border-style:inset;
border-width:1px 1px 0 1px;
display:block;
margin:2ex 0 0 0;
padding:0 1ex;
}
h1{font-size:150%;}
h2{font-size:125%;font-style:italic;}
#title small{font-size:smaller;font-weight:normal;}
#content{
background-color:white;
border:1px solid #999;
margin:0;
padding:1ex;
}
p,ul,ol,dl,blockquote{margin-bottom:0.75em;margin-top:0.75em;}
li,dd{
margin-bottom:0.25em;
}
blockquote,q{
background-color:#F7F7DD;
font-style:italic;
quotes:'' '' '' '';
}
pre,code{
background-color:#E6E6F7;
}
blockquote{
border-left-color:#CC9;
padding:0.2ex;
}
pre{
border-left-color:#99C;
padding:0.2ex;
}
dd{
border-left-color:#DED;
padding:0;
}
blockquote,pre,dd{
border-left-width:3px;
border-left-style:solid;
padding-left:1ex;
}
.edit{
margin:0;
padding:0;
text-align:right;
margin-top:-1px;
}
.edit a{
background-color:#DDD;
border-color:white;
border-style:outset;
border-width:0 1px 1px 1px;
margin:0 2ex;
padding:0 2ex;
text-align:right;
}
textarea{
margin-right:31ex;
/*width:100%;*/
}
textarea,input{
border-width:1px;
margin:1px 0;
}
textarea,input[type=text]{
padding:2px;
}
input[type=submit]{
background-color:#CCC;
border-width:2px;
padding:0 1ex;
}
a:link{color:#06C;font-weight:bold;text-decoration:none;}
a:visited{color:#039;font-weight:bold;text-decoration:none;}
a:active,a:hover,input:hover{background-color:#DEF;color:black;}
a:link.auto,a:visited.auto{font-weight:normal;}
a[href^="http://"]{font-weight:normal;text-decoration:underline;}
</style>
</head>
<body>
<h1 id="title"><a href="http://maettig.com/">TM</a>::<a href="<?=$PHP_SELF?>">Wiki</a>-><a href="<?=$PHP_SELF?>?title=<?=htmlspecialchars($title)?>" rel="bookmark" title="Permalink"><?=htmlspecialchars($title)?></a>
<small>(created <?=date("Y-m-d G:i", @strtotime($db->data[$title]['created']))?>,
modified <?=date("Y-m-d G:i", @strtotime($db->data[$title]['modified']))?>)</small></h1>
<ul id="menu">
<?php
$menu = "";
$parents = array();
$relationships->sort('subject');
while ($rel = $relationships->each())
{
if ($rel['subject'] == $title && $rel['predicate'] == 'rdfs:subClassOf')
{
$menu .= "<li><a href=\"" . $PHP_SELF . "?title=" . htmlspecialchars($rel['object']) . "\">" . htmlspecialchars($rel['object']) . "</a></li>";
$parents[$rel['object']] = true;
}
}
if ($title == "Main Page")
{
$menu .= "<li>Main Page</li>{subMenu}";
}
else
{
$menu .= "<ul>";
$relationships->reset();
while ($rel = $relationships->each())
{
if ($rel['predicate'] != 'rdfs:subClassOf') continue;
foreach ($parents as $parent => $bool)
{
if ($rel['object'] == $parent)
{
if ($rel['subject'] != $title)
{
$menu .= "<li><a href=\"" . $PHP_SELF . "?title=" . htmlspecialchars($rel['subject']) . "\">" . htmlspecialchars($rel['subject']) . "</a></li>";
}
else
{
$menu .= "<li>" . htmlspecialchars($rel['subject']) . "</li>{subMenu}";
}
break;
}
}
}
}
$subMenu = "<ul>";
$relationships->reset();
while ($rel = $relationships->each())
{
if ($rel['predicate'] == 'rdfs:subClassOf' && $rel['object'] == $title)
{
$subMenu .= "<li><a href=\"" . $PHP_SELF . "?title=" . htmlspecialchars($rel['subject']) . "\">" . htmlspecialchars($rel['subject']) . "</a></li>";
}
}
$subMenu .= "</ul>";
echo str_replace("{subMenu}", $subMenu, $menu);
?>
</ul></ul>
<? if (! empty($action)) { ?>
<form action="<?=$PHP_SELF?>" method="post">
<input name="title" type="hidden" value="<?=htmlspecialchars($title)?>">
<textarea cols="90" name="content" rows="25"><?=htmlspecialchars($record['content'])?></textarea><br>
<fieldset>
<legend>Relationships</legend>
<?php
$ids = $db->ids();
natcasesort($ids);
$options = "<option value=\"\">-</option>";
foreach ($ids as $id)
{
$options .= "<option>" . $id . "</option>";
}
$relationships->sort("predicate, object");
while ($rel = $relationships->each())
{
if ($rel['subject'] != $title) continue;
echo htmlspecialchars($title) . " ";
echo "<select name=\"predicate[]\" size=\"1\">" . str_replace(">" . $rel['predicate'] . "<", " selected>" . $rel['predicate'] . "<", $options) . "</select>";
echo " ";
echo "<select name=\"object[]\" size=\"1\">" . str_replace(">" . $rel['object'] . "<", " selected>" . $rel['object'] . "<", $options) . "</select><br>";
}
echo htmlspecialchars($title) . " ";
echo "<select name=\"predicate[]\" size=\"1\">" . $options . "</select>";
echo " ";
echo "<select name=\"object[]\" size=\"1\">" . $options . "</select>";
?>
</fieldset>
<input type="submit" value="Save page">
<input name="action" type="submit" value="Save page and continue editing">
</form>
<? } ?>
<div id="page">
<? if (! empty($record['content'])) { ?>
<div id="content"><?
echoPage($record['content']);
echo "<div style=\"border:1px dotted black;margin:2ex 0;padding:1ex\">";
$relationships->reset();
while ($rel = $relationships->each())
{
if ($rel['subject'] != $title) continue;
$relH = htmlspecialchars($title) . " ";
$relH .= htmlspecialchars($rel['predicate']) . " ";
$relH .= htmlspecialchars($rel['object']) . "<br>";
if ($rel['predicate'] == 'rdf:type' || $rel['predicate'] == 'rdfs:subClassOf')
echo "<span style=\"color:#999\">" . $relH . "</span>";
else echo $relH;
}
echo "</div>";
$parents = array();
$relationships->sort("object");
while ($rel = $relationships->each())
{
if ($rel['subject'] == $title && $rel['predicate'] == 'rdf:type')
{
$parents[] = "<a href=\"" . $PHP_SELF . "?title=" . htmlspecialchars($rel['object']) . "\">< Back to " . htmlspecialchars($rel['object']) . "</a>";
}
}
if (! empty($parents)) echo "<p>[ " . implode(" | ", $parents) . " ]</p>";
function getChilds($title, &$childs)
{
global $relationships;
$relA = $relationships->data;
foreach ($relA as $rel)
{
if ($rel['predicate'] == 'rdfs:subClassOf' && $rel['object'] == $title)
{
if (empty($childs[$rel['subject']]))
getChilds($rel['subject'], $childs);
$childs[$rel['subject']] = true;
}
}
$childs[$title] = true;
}
$childs = array();
getChilds($title, $childs);
$db->sort("created DESC");
while ($page = $db->each())
{
$relationships->reset();
while ($rel = $relationships->each())
{
if ($rel['subject'] != $page['id'] || $rel['predicate'] != 'rdf:type' ||
empty($childs[$rel['object']]))
{
continue;
}
echo "<a class=\"rdfTypeA\" href=\"" . $PHP_SELF . "?title=" . htmlspecialchars($db->data[$rel['subject']]['id']) . "\">" . htmlspecialchars($db->data[$rel['subject']]['id']);
echo " (created " . date("Y-m-d G:i", strtotime($db->data[$rel['subject']]['created']));
echo ", modified " . date("Y-m-d G:i", strtotime($db->data[$rel['subject']]['modified'])) . ")";
echo "</a>";
echo "<div class=\"rdfType\">";
echo echoPage($db->data[$rel['subject']]['content'], $db->data[$rel['subject']]['id']);
echo "</div>";
break;
}
}
?>
<p><a href="feed.php?title=<?=htmlspecialchars($title)?>"
style="background-color:#F60;border:1px solid;border-color:#FCA #730 #420 #F95;color:white;font:bold 10px Verdana,sans-serif;padding:0 4px;text-decoration:none">RSS 1.0</a></p>
</div>
<? } ?>
<? if (empty($action)) { ?>
<p class="edit"><a href="<?=$PHP_SELF?>?title=<?=htmlspecialchars($title)?>&action=edit">Edit this page</a></p>
<? } ?>
</div>
<p>
<a href="<?=$PHP_SELF?>?source=1">Show PHP source</a>
</p>
</body>
</html>