THIS source compiler<?php
/* DISPLAY.PHP - Functions to display data. Most functions here are called by
a process we call RULES and more information can be found in RULES.PHP.
This code is the heart of THIS as it does all the data input handling
and all the HTML display -- hence the name. Everything goes through this
file (so to speak).
*/
/* displayhtml - display content/HTML mixed with PHP variables */
// Variable number of arguments; basically:
//
// $templ template name (index in assoc. array of templates)
// $name name (PHP variable for the data, include the '$')
// $data data referenced in the HTML template
//
// Example: displayhtml('comment','$record',$record);
//
// This way $record can be referenced by the HTML directly: {$record['title']}
//
// Inside the function the variable name is '$val' and the data is '$$val'
function displayhtml() {
$args = func_get_args();
$templ = $args[0];
// set variable variable if there is one
if (isset($args[1])) { // assumes if 1 then 2
$val = str_replace('$','',$args[1]);
$$val = $args[2];
}
html('template',$templ);
$html = html(); // data that can be referenced
$config = config(); // by the HTML
$arg = getvar('arg');
$text = htmltempl($templ); // the HTML; can silently
if (!$text) { // fail if not found
debug("'$templ' not found");
if (config('shownotfounds') && !config('nodisplaymessages'))
$text = geterror('TEMPLATE');
// falls though
else
return;
}
else
debug("'$templ'");
// if data passed was a string it may reference variables
if (isset($val) && is_string($$val))
if (eval(_textset($val,$$val)) === FALSE)
displayerror();
// if no data passed assume the HTML might reference variables
if (!isset($val))
if (eval(_textset('text',$text)) === FALSE)
$err = displayerror();
// and now the HTML and all it's variables are displayed
if (!isset($err))
if (eval(_printset($text)) === FALSE)
displayerror();
// and that is our web template "engine" - pretty advanced and powerful, ay?
}
/* displayerror - display the PHP error message */
// this is new and experimental and might be moved...
function displayerror() {
if (config('showerrors')) {
$message = php_error($file,$line);
html('error',$message);
html('file',$file);
html('line',$line);
displaymessage(geterror('TEMPLERR'));
}
debug(php_error());
return 1;
}
/* displaymessage - display a message in place of a post */
function displaymessage($message, $class = 'entry') {
if (config('nodisplaymessages'))
return;
$html = html(); // data that can be referenced
$config = config(); // by $message
$arg = getvar('arg');
eval(_textset('message',$message));
print "<div class='$class'>$message</div>";
}
/* displayentries - display posts */
function displayentries() {
$ids = dblistrecords(); // array if IDs
if ($ids === FALSE) {
if (debug()) html('error',dberror());
displaymessage(geterror('NOTREAD'));
return;
}
sortrecords($ids); // config('sortfunc')
$arg = getvar('arg');
$start = (int)getvar('start');
if ($start < 0 || $start >= count($ids))
$start = 0;
$end = config('postsperpage');
$i = 0; $c = 0;
foreach ($ids as $id) {
if ($i++ < $start) continue;
$record = readrecord($id);
if (!$record) // should never happen but
continue; // never say never...
if (isset($record['draft'])) {
debug('draft skipped');
continue;
}
$titles[$record['id']] = substr($record['title'],0,60);
// record goes "out to User Agent" through this:
displayrecord($record,$id);
if (++$c == $end)
break;
}
html('posts',$c);
if ($c)
html('titles',html_elements($titles,'<option value="$1">$2</option>'));
if ($c == 0)
displaymessage('No posts.');
// "more" and/or "prev" links
if ($c > 1 && !config('allowbasecomments') && htmltempl('moreprev')) {
$start = $start - config('postsperpage');
html('count',$i);
html('start',$start);
html('more_vis',($i < count($ids)) ? 'visible' : 'hidden');
html('prev_vis',($start >= 0) ? 'visible' : 'hidden');
displayhtml('moreprev');
}
if (config('allowbasecomments'))
displaycomments();
}
/* displayentry - display a single entry (called when 'grok'ing) */
// see RULES.PHP for input validation
function displayentry() {
$id = getvar('id');
if (!html('record')) {
if ($id === '' || !dblistrecords($id)) {
displaymessage('Post not found');
return;
}
$record = readrecord($id);
html('record',$record);
}
displayrecord(html('record'),$id);
if (config('allowcomments') && !isset($record['nocomments']))
displaycomments();
}
/* displaycomments - display comments if there are any */
// comments are associated with an entry; just display them all, we do not
// expect to be a site with thousands of comments! see config('maxmsgs')
// NOTE this used to be a "rule" (in RULES.INI) but then we "internalized"
// it by conditionally calling it here -- and 'id' is validated previously
function displaycomments() {
$entryid = (int)getvar('id'); // ('' becomes 0)
debug("'$entryid'");
$ids = dblistcomments($entryid);
if ($ids === FALSE) // db query error
return;
if (!$ids && config('nocommentadd'))
return;
displayhtml('commentintro');
$msgcount = count($ids);
if ($msgcount) {
if (config('rsortcomments'))
$ids = array_reverse($ids);
foreach ($ids as $id) {
$record = dbreadcomment($id);
displayhtml('comment','$record',$record);
}
}
else
displayhtml('nocomment');
if (config('nocommentadd'))
return;
if ($msgcount >= config('maxmsgs'))
displayhtml('commentmax');
else
displaycommentform();
}
/* displaycommentform - displays 'commentadd' template */
function displaycommentform() {
$html = html();
$arg = getvar('arg');
$entryid = getvar('id');
$url = "?arg=$arg&id=$entryid&op=submit";
$code = 0; // used to be a user function
$from = cookie_get('from'); // until we found out it's
if ($from !== '') { // simpler here
$code = cookie_get('visitor');
$_POST['from'] = $from;
}
$form['fromlink'] = $html['fromlink']; // copy template string
if (!config('visitorcode'))
$form['hidecode'] = 'hide';
if ($code) { // logged in if true
$form['hidecode'] = 'hide';
$form['hidefrom'] = 'hide';
$form['fromlink'] = str_replace('$1',$from,$html['frominlink']);
}
$form['url'] = $url;
$form['cancel'] = isset($_POST['button']) ? '' : 'disabled';
$form['submit'] = '';
if (config('mustpreview')) {
$form['submit'] = isset($_POST['button']) ? '' : 'disabled';
if (htmlgeterror('comment_message'))
$form['submit'] = 'disabled'; // reset if error
if (!isset($_POST['data']) || is_empty($_POST['data']))
$form['submit'] = 'disabled';
}
foreach ($_POST as $n => $v)
$_POST[$n] = htmlspecialchars($v);
displayhtml('commentadd','$form',$form);
}
/* displaysubmit - result of form to submit user comment */
// NOTE this function knows the following POST inputs:
//
// 'from', 'code', 'subj', 'body', 'button'
//
// and these GET inputs:
//
// 'arg, 'id'
//
// $arg and $id are validated elsewhere, the others are validated here
//
// (as long as $code is empty, as it should be if 'visitorcode' is undefined
// or zero, all of the "visitor" functions do nothing; see file VISITORS)
function displaysubmit() {
$arg = getvar('arg');
$entryid = (int)getvar('id'); // make sure "" is 0
$button = postvar('button');
if (!dblistrecords($entryid)) { // check ID
$entryid = 0;
$button = 'cancel';
}
if ($entryid == 0)
$url = "?arg=$arg";
else
$url = "?arg=$arg&op=grok&id=$entryid";
if ($button == 'cancel')
redirect($url);
// now the basic inputs are verified need to get and parse/verify the POST
// data - this part is too confusing and will be redesigned as it's done here
// and in CONVERT.PHP (function convert_user()), plus it'd be nice to make this
// configurable... what to do is on the tip of our tongue...
// this is the data/filter definition array
$filter = array( // the strip funcs
'from' => array(32,'my_strip_tags'), // are in INC/BASE.PHP
'subj' => array(32,'my_strip_tags'),
'code' => 64,
'data' => array(config('postlimit'),'if_strip_tags'),
);
// this gets and fiters the data from the POST variables and it
// may modify the $_POST data
list($from,$subj,$code,$data) = postvars($filter);
checkbadinput($data); // in ERROR.PHP
$vcode = visitor_validate($from,$code); // ignored if disabled
// now we offer up some feedback if any inputs are stupid inputs
if ($data == '') // since no elses
$error = htmlseterror('SUBMIT'); // these are order
// dependent
if ($vcode === FALSE)
$error = htmlseterror('FROM'); // and don't put elses
// because they're not
if ($vcode === NULL) // mutually exclusive
$error = htmlseterror('CODE');
if ($button == 'preview' || isset($error)) {
do_rules('preview'); // call another rule
exit; // (it's okay)
}
if ($button == 'submit' && !isset($error)) {
visitor_store($from,$code);
$record = createcomment();
// note that comments, unlike posts, are stored in their converted form,
// which is weird... but posts are editable and comments are not
$r = dbwritecomment($entryid,$record);
// what can go wrong here? need to test...
$url .= "#$r";
}
redirect($url);
}
/* displaypreview - preview a comment */
function displaypreview() {
$record = createcomment(); // POST data
displayhtml('commentpreview');
displayhtml('comment','$record',$record);
}
/* displayrecord - display record data */
// $record entry to display
// ($id) for grok url
function displayrecord($record, $id = '') {
$op = getvar('op');
$arg = getvar('arg');
$single = ($op == 'grok');
if ($op == 'page')
$record['grok'] = "?arg=$arg&op=page&id=$id";
else
$record['grok'] = "?arg=$arg&op=grok&id=$id";
if (($start = getvar('start')) && $start > 0)
$record['grok'] .= "&start=$start";
// use of extract reduces complexity at the expense of a little obfuscation
// its use here is more of a test to see how much code it reduces (not much)
// (May 28, I've decided I don't like it.)
extract($record,EXTR_OVERWRITE|EXTR_PREFIX_ALL|EXTR_REFS,'r');
$record['murl'] = '';
if (!$single && isset($r_more)) { // 'more' a truncated
$r_body = $r_more; // copy of 'body'
$record['murl'] = _morelink($r_grok);
}
unset($record['more']);
debug($record,config('debugtruncate'));
if ($single) {
$htfile = 'entry';
}
else {
$htfile = 'entries';
if (isset($r_nogrok))
$htfile = 'entries_n';
if (config('allowcomments'))
$record['curl'] = _commentlink($r_grok,$record);
if (isset($r_more)) { // 'more' a truncated
$r_body = $r_more; // copy of 'body'
$record['murl'] = _morelink($r_grok);
unset($record['more']);
}
}
// usercode stuff; might modify record (see file USERCODE)
if (!config('nousercode') && function_exists('usercode'))
usercode($record);
// goes out to UA here:
if (isset($r_notop))
html('top','');
displayhtml($htfile,'$record',$record);
}
/* displaypage - display a "page" */
function displaypage($id = '') {
if (empty($id))
$id = getvar('id');
$arg = getvar('arg');
if (preg_match('/[^a-zA-Z0-9]+/',$id))
$id = '';
if ($id === '' || !dblistpages($id)) {
displaymessage('<b>Page not found.</b>');
return;
}
$record = readfilerecord($id);
$record['grok'] = "?arg=$arg&op=page&id=$id";
displayhtml('page','$record',$record);
}
/* displayhelp - display site help page */
// this is a "first draft"
function displayhelp() {
if (debug()) errorlog(0);
$arg = getvar('arg');
$topic = ($topic = getvar('h')) ? $topic : "index";
$help = config('helpdir')."$topic.html";
if (is_file($help))
eval(_htmlshow($help));
else {
echo "<div class='helptext'>";
echo "hmm... the help file for '$topic' is missing";
echo "</div>";
}
}
/* displayfile - display a text file */
function displayfile() {
$srcdir = config('srcdir');
$file = getvar('file');
// first, just stop on a '/' in the name and, obviously, not found
if (strpos($file,'/') !== FALSE || !is_file($srcdir.$file)) {
notfound();
return;
}
preg_match('/\.([^.]+)$/',$file,$res);
$typ = (isset($res[1])) ? $res[1] : 'txt';
switch ($typ) {
case 'txt':
case 'xml':
case 'php':
$type = 'text/plain';
break;
case 'zip':
$type = 'application/zip';
break;
case 'jpeg':
case 'jpg':
$type = 'image/jpeg';
break;
case 'png':
$type = 'image/png';
break;
default:
echo 'file type unsupported, sorry';
return;
}
$size = filesize($srcdir.$file);
if (debug()) errorlog(0);
header('Content-Type: '.$type);
header('Content-Length: '.$size);
header('Content-Disposition: attachment; filename="'.$file.'"');
readfile($srcdir.$file);
}
function displaynotfound() {
header('HTTP/1.1 404 Not Found');
readfile(html('notfound.html'));
exit;
}
/* displaysetup - reads the post record and puts it in the $html array */
// this "caches" the post data before any HTML gets displayed
// actually not a rule but called by do_rule() so it's kinda sorta a rule
function displaysetup() {
$id = getvar('id');
if ($id === '' || !dblistrecords($id))
return;
$record = readrecord($id);
html('record',$record);
}
/* login - login form handler */
function login() {
$name = postvar('name');
$code = postvar('code');
$redirect = postvar('redirect');
$visit = visitor_login($name,$code);
// 'It is recommended that you avoid "stacking" ternary expressions.'
// -- PHP.NET
$r = ($visit === FALSE) ? "not found" : (($visit === NULL) ? "bad code" : (($visit === "") ? "missing" : "okay!"));
debug("visitor: '$name','$code' = $r");
if ($visit)
cookie_set('from',$name);
redirect('?'.$redirect);
// NOTE when there is a redirect like here, any debug output is lost; that's
// why there is the "noredirect" configuration setting
// NOTE ALSO that any output prevents the cookie from being set and possibly
// even the redirect!
}
/* logout - forget visitor information */
// we actually do not need this as it can now be done directly as a rule;
// see [logout] in RULES.INI
function logout() {
$redirect =& $_GET['redirect'];
cookie_unset('from');
redirect('?'.$redirect);
}
/* _htmlshow - read a template file or buffer */
function _htmlshow($file, $html = NULL) {
if (!$html)
if (!($html = file_get_contents($file)))
$html = "$file notfound";
return _printset($html);
}
function _addslashes($text) {
if (config('escslash'))
$text = addcslashes($text,'\"');
else {
$text = addcslashes($text,'"');
if (preg_match('/([\\\\]+)$/',$text,$res)) {
$l = strlen($res[1]);
if (($l & 1) == 1)
$text .= '\\';
}
}
return $text;
}
function _printset($html) {
$html = _addslashes($html);
return "print \"$html\";";
}
function _textset($name, $text) {
$text = _addslashes($text,'"');
return "\$$name = \"$text\";";
}
/* _commentlink - form the "comments" link (curl) */
function _commentlink($url, $record) {
$n = 0;
if ($record['id'])
$n = dbcountcomments($record['id']);
$link = ($t = html('commentstext')) ? $t : "comments ($n)";
$link = str_replace('$N',$n,$link);
$link = "<a href='$url#comments'>$link</a>";
if (($linkwrap = html('commentslink')) != "")
$link = str_replace('$1',$link,$linkwrap);
return $link;
}
function _morelink($url) {
$more = ($m = html('moretext')) ? $m : "there is more";
$link = "<a href='$url#more'>$more</a>";
return $link;
}
/* _displaydebug - print_r all the arrays and stuff */
// this is a registered function so gets called last
// this can dump EVERYTHING, that is all data generated and used by this code
// no sensitive data is stored
//
// see file DEBUGGING
// see file CONFIG
function _displaydebug() {
if (defined('CONFIGNODUMP')) return;
if (($d = debug()) == 0 || $d < 0) return;
// if debug set to display in HTML comments don't do two things:
// do not wrap output in the "<pre></pre>" tags
// do not htmlentitie-ize them -- but must eat '-->' and '--' !
if ($d < 100)
print "\n<div style='font-size:13px; background:white; color:black;'><pre>";
else
print "<!--\n";
ob_start(($d < 100) ? 'obentities' : 'obcomments');
$ad = ($d > 100) ? $d - 100 : $d;
if ($ad == 2) {
dump($_GET,"_GET: ",1);
dump($_POST,"_POST: ",1);
}
if ($ad == 3)
dump(get_defined_constants(true),"CONSTANTS ",1);
if ($ad == 4)
dump($GLOBALS,"GLOBALS ",1);
if ($ad == 9) {
dump($_GET,"_GET: ",1,0);
dump($_POST,"_POST: ",1,0);
dump(config(),"CONFIG: ",1,0);
dump(html(),"HTML: ",1,0);
if (function_exists('rules'))
dump(do_rules(NULL),"RULES: ",1,0);
}
ob_end_flush();
print ($d < 100) ? "</pre></div>" : THIS_EOL."-->";
}
/* module initialization function */
function _config_display() {
$data = load_php_file('translate.ini');
gmlp_open($data);
if (!defined('CONFIGNODUMP') && debug())
register_shutdown_function('_displaydebug');
}
?>
Source Code Index