index





















































































































































































































































































































































































































































































































































































































































































































































<?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 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'))
            
$text geterror('TEMPLATE');
            
// falls though
        
else
            return;
    }
    else
        
debug("'$templ'");


    if (!
config('shownotices'))
        
$e error_reporting(E_ALL E_NOTICE);

    
// if data passed was a string it may reference variables

    
if (isset($val) && is_string($$val))
        if (eval(
_textset($val,$$val)) === FALSE)
            
displayerror($templ);

    
// if no data passed assume the HTML might reference variables

    
if (!isset($val))
        if (eval(
_textset('text',$text)) === FALSE)
            
displayerror($templ);

    
// and now the HTML and all it's variables are displayed

    
$text addcslashes($text,'"');
    if (eval(
"print \"$text\";") === FALSE)
        
displayerror($templ);

// and that is our web template "engine" - pretty advanced and powerful, ay?

    
if (isset($e))
        
error_reporting($e);
}


/* displayerror - display the PHP error message */

// this is new and experimental and might be moved...

function displayerror($template) {

    if (
config('showerrors')) {
        
$theme config('themedir');
        if (
$theme$theme ", theme <b>$theme</b>";
        
$message php_error($file,$line);
        print 
"<p><tt>Error in template <b>$template</b>$theme$message, near line: $line.</tt></p>";
    }

    
debug(php_error());
}


/* 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');

    if (!
config('shownotices'))
        
$e error_reporting(E_ALL E_NOTICE);

    
$data "<div class='$class'>$message</div>";
    eval(
_htmlshow('',$data));

    if (isset(
$e))
        
error_reporting($e);
}


/* displayentries - display posts */

function displayentries() {

    
$ids dblistrecords();            // array if IDs
    
if ($ids === FALSE) {
        
$e 'Could not read from database. ';
        if (
debug()) $e .= dberror();
        
displaymessage($e);
        return;
    }

    
sortrecords($ids);            // config('sortfunc')

    
$arg getvar('arg');
    
$start = (int)getvar('start');
    if (
$start || $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;
    }

    if (
$c == 0)
        
displaymessage('No posts.');

// I wish there was a better way to do this:

    
if ($c && htmltempl('quickies')) {
        
$html html_elements($titles,'<option value="$1">$2</option>');
        
displayhtml('quickies','$OPTIONS',$html);
    }

// and this:

    // "previous" and/or "more" links

    
if (!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 (
$id === '' || !dblistrecords($id)) {
        
displaymessage('Post not found');
        return;
    }

    
$record readrecord($id);
    
displayrecord($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&amp;id=$entryid&amp;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 _commentcreat($from,$subj,$data);

// 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() {

    
$from postvar('from');
    
$subj postvar('subj');
    
$data postvar('data');

    
$record _commentcreat($from,$subj,$data);    // 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&amp;op=page&amp;id=$id";
    else
        
$record['grok'] = "?arg=$arg&amp;op=grok&amp;id=$id";

    if ((
$start getvar('start')) && $start 0)
        
$record['grok'] .= "&amp;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');

    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';
        
html('record',$record);
    }
    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:

    
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&amp;op=page&amp;id=$id";
    
displayhtml('page','$record',$record);
}


/* displayhelp - display site help page */

// this is a "first draft"

function displayhelp() {

    
$arg getvar('arg');

    
$topic = ($topic getvar('h')) ? $topic "index";
    
$help "doc/help/$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 */

// right now we expect only to be used for plain text files no matter the 
// extension; should we do images and stuff?

function displayfile() {

    
$srcdir config('srcdir');
    
$file getvar('file');

    if (
strpos($file,'/') !== FALSE || !is_file($srcdir.$file)) {
        echo(
"file '$file' not found");
        return;
    }

    
header('Content-type: text/plain');
    
readfile($srcdir.$file);
}


/* 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";

    
$html addcslashes($html,'"');
    return 
"print \"$html\";";
}

function 
_textset($name$text) {

    
$text addcslashes($text,'"');
    return 
"\$$name = \"$text\";";
}


/* _commentcreat - convert (POST) data to comment "record" */

function _commentcreat($from$title$body) {

    
$date datestrcmt();

    
$record['title'] = $title;
    
$record['from'] = $from;
    
$record['date'] = $date;
    
$record['body'] = convert_user($body);

// this is a little odd here in that the 'body' ($data actually) is filtered 
// here as it would when displayed - the other data has been filtered in the 
// submit processing code - the result is that the from and subj inputs will 
// be filtered in a manner that the commenter sees in the inputs, but will 
// only see the textarea filtered in the preview area - I mention this only 
// because that can be a little confusing...

    
if (config('loguserdata'))
        
recorduserdata($record);                // modifies $record

    
if ($record['from'] == ''$record['from'] = "nobody";
    if (
$record['title'] == ''$record['title'] = "nothing";

    return 
$record;
}


/* _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()) == || $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);
        
dump($_POST,"_POST: ",1);
        
dump(config(),"CONFIG: ",1);
        
dump(html(),"HTML: ",1);
        if (
function_exists('rules'))
            
dump(do_rules(NULL),"RULES: ",1);
    }

    
ob_end_flush();
    print (
$d 100) ? "</pre></div>" THIS_EOL."-->";
}


/* module initialization function */

function _display() {

    
gmlp_open(load_php_file('translate.ini'));

    if (!
defined('CONFIGNODUMP') && debug())
        
register_shutdown_function('_displaydebug');
}

?>