index




















































































































































































































































































































































































<?php

// RECORD.PHP - manipulate 'records' and write/read them to/from database
//
// This code was written in like 1982 but will only occasionally get tweaked.
//
// The following functions are defined:
//
// readrecord()
// readfilerecord()
// writerecord()
// createrecord()
// arraytorecord()
// recordtostring()
// sortrecords()
// recorduserdata()

if (!defined('THIS_EOL'))
    
define('THIS_EOL',"\n");


/* readrecord - read an entry (post) by ID and process it into a "record" */

// $data is a way for admin to preview (only ADMIN and DISPLAY call this
// function)

function readrecord($id$data NULL) {

    
debug("'$id'");

    
// first, read file into a "record"

    
if ($data)
        
$record arraytorecord($data);
    else
        
$record dbreadrecord($id);

    
// $record will be FALSE if record not found - the code actually
    // checks for existence with if (!dblistrecords($id)) so it should
    // never be FALSE

    
if ($record == FALSE) {
        
$record createrecord("Error #49",htmlgeterror('NOTFOUND'));
        
$record['nocomments'] = 1;
    }

    
$record['id'] = $id;

// look at all these things here - this is a perfect example of code that
// should be "data code" so that all of these defaults and things are
// set/determined by an external, editible data file so we do not have to
// keep updating this code to support new features! and in providing for that
// each installation -- and theme -- can do their own thing! and *THAT* is the
// meaning of "customizable"

    // if date string use it else use time string

    
if (!isset($record['date']) && isset($record['time']))
        
$record['date'] = date(config('datestr'),$record['time']);

    if (!isset(
$record['time']) && isset($record['date']))
        
$record['time'] = strtotime($record['date']);

    if (!isset(
$record['time']))
        
$record['time'] = time();

    if (!isset(
$record['date']))
        
$record['date'] = date(config('datestr'),$record['time']);

    if (isset(
$record['from']))
        
$record['from'] = convertchars($record['from']);

    if (isset(
$record['title']))
        
$record['title'] = convertchars($record['title']);
    else
        
$record['title'] = "";          // have to have a title

    
if (!isset($record['linktitle']))
        
$record['linktitle'] = $record['title'];

    
_recordrefs($record,$record['body']);        // modifies body

    
if ($record['body'])
        
$record['body'] = convert($record['body'],$record);

    if (isset(
$record['more']))
        
_morefunc($record);

    return 
$record;
}


/* readfilerecord - read a file in the format of an internal record */

function readfilerecord($id) {

    
// $record will be FALSE if page not found - an alternative is to
    // check for existence with if (!dblistpages($id)) ... which is
    // what we now do (only ADMIN and DISPLAY call this function)

// although the function name to read a page begins with 'db' that is a
// misnomer as the page is actually a file - but we like the consistency!
// (the page API is INC/PAGES.PHP)

    
$record dbreadpage($id);
    if (
$record == FALSE)
        return 
createrecord("Error #21 ($id)",htmlgeterror('NOTFOUND'));

    
$record['body'] = convert($record['body'],$record);

    return 
$record;
}


/* writerecord - write a new record (previously non-existent) */

function writerecord($record$logdata true) {

    
debug("");

    if (!
is_array($record))
        
$record arraytorecord($record);

    if (!isset(
$record['time']) && !isset($record['date']))
        
$record['time'] = time();

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

    
return dbnewrecord($record);
}


/* arraytorecord - convert record string/array to associative array */

function arraytorecord(/*mixed*/ $data) {

    if (!
is_array($data))
        
$data explode(THIS_EOL,$data);

    
// PREG_SPLIT__DELIM_CAPTURE is wanted here, but this puts the "\n"
    // not at the end of the string but as a separate array member:
    // $data = preg_split('/(\n)/',$data,-1,PREG_SPLIT_DELIM_CAPTURE);

    
foreach ($data as $a => $b)
        
$data[$a] = $b.THIS_EOL;
    
reset($data);

    while (list( ,
$_) = each($data)) {
        if (
$_ == THIS_EOL) break;
        
$h explode(':',$_);            // this odd code is for
        
$name array_shift($h);        //  tag: text
        
$name strtolower($name);        //  tag:
        
$value implode(':',$h);        //  tag: Title:Foobar
        
$record[$name] = trim($value);
    }

    
$record['body'] = '';
    while (list( ,
$_) = each($data))
        
$record['body'] .= $_;

    return 
$record;
}


/* recordtostring - convert record array into a string */

function recordtostring($record) {

    
$data =  '';
    foreach (
$record as $key => $value)
        if (
$key != 'body')
            
$data .= $key.':'.$value.THIS_EOL;

    return 
$data THIS_EOL $record['body'];
}


/* sortentries - sort the entries (natural sort is the default) */

function _cmptitle($a$b) { return strcmp($a['title'],$b['title']); }
function 
_cmptime($a$b)  { return strcmp($a['time'],$b['time']);   }

function 
sortrecords(&$ids$sort NULL) {

    if (
$sort === NULL)
        
$sort config('sortfunc');

    if (
$sort == "date") {
        
$i 0;
        foreach (
$ids as $id) {
            
$headers[$i] = _getrecordheaders($id);
            
$headers[$i]['file'] = $id;
            
$i++;
        }
        
usort($headers,"_cmptime");
        
$i 0;
        foreach (
$headers as $h) {
            
$ids[$i] = $h['file'];
            
$i++;
        }
    }
    else
    if (
$sort == "name") {
        
$i 0;
        foreach (
$ids as $id) {
            
$headers[$i] = _getrecordheaders($id);
            
$headers[$i]['file'] = $id;
            
$i++;
        }
        
usort($headers,"_cmptitle");
        
$i 0;
        foreach (
$headers as $h) {
            
$ids[$i] = $h['file'];
            
$i++;
        }
    }

    if (
config('reversesort') || $sort == "rsort")
        
$ids array_reverse($ids);
}


/* _internal functions */


/* _getrecordheaders - read a record header into an associative array */

function _getrecordheaders($id) {

    
debug("'$id'");

    
// no error checking as we have a valid ID at this point

    
$record dbreadrecord($id);
    unset(
$record['body']);

    
$record['id'] = $id;

    
// if no date create it (convert time from number to people string)

    
if (!isset($record['date']))
        
$record['date'] = date(config('datestr'),$record['time']);

    return 
$record;
}


/* createrecord - create an empty record */

function createrecord($title NULL$body "") {

    if (
$title == NULL)
        return 
"date: " date(config('datestr')) .
            
"\ntitle: Title\n\nPlace content here.";

    
$record['title'] = $title;
    
$record['body'] = $body;
    
$record['date'] =  date(config('datestr'));
    
$record['id'] = 0;
    return 
$record;
}


/* recorduserdata - add some server data to a record */

function recorduserdata(&$record) {

    if (isset(
$_SERVER['REMOTE_ADDR']))
        
$record['REMOTE_ADDR'] = $_SERVER['REMOTE_ADDR'];
    if (isset(
$_SERVER['HTTP_USER_AGENT']))
        
$record['HTTP_USER_AGENT'] = $_SERVER['HTTP_USER_AGENT'];
    if (isset(
$_SERVER['HTTP_REFERER']))
        
$record['HTTP_REFERER'] = $_SERVER['HTTP_REFERER'];
}


/* _recordrefs - replace record vars (marked by "[]") in a string */

// This substitutes a [word] in body with a record header value, ie.
// with a record header of "title: Foobar", the string "Hey there, [title]!"
// would result in "Hey there, Foobar!".

function _recordrefs($record,&$body) {

    
$re '/\[([a-zA-Z]+)\]/';
    if (
preg_match_all($re,$body,$res))
        foreach (
$res[0] as $k => $v) {
            
$h $res[1][$k];
            if (isset(
$record[$h]))
                
$body str_replace($v,$record[$h],$body);
        }
}


/* "more" functions */

// these functions try to locate the "more" string in a post and truncate
// the post at that point - they are not too clear and not too efficient...

/* _morefunc - process "more" function */

function _morefunc(&$record) {

    
$bodydata explode(THIS_EOL,$record['body']);

    if ((
$t $record['more']))
        if (!
is_numeric($t) || ($t || $t >= count($bodydata)))
            
$t 0;    // force _morecheck()

    
$c = ($t) ? $t _morecheck($bodydata);

    if (
$c) {
        
$bodydata _moretruncate($bodydata,$c);
        
$record['more'] = implode(THIS_EOL,$bodydata);
    }
}


/* _morecheck - return index to "more" marker (or Nth blank line) */

function _morecheck($data) {

// many settings do not have defaults, but if this one not set there are
// way too many errors... we actually do not like wasting the code's time
// with such defaults (and too many comments! - but we put this one here in
// hope that people are actually reading this code)

    
$moremark = ($t config('moremark')) ? $t '<!--more-->';

    
// this would be nice:
    //$count = array_search('moremark',$data);
    // but we need a substring search, i.e. array_strstr()...

// a side effect of the conversion code (CONVERT.PHP) leaves the more mark
// within '<p></p>' but that is okay as this is a strstr(); the translate.ini
// file now skips that so we should rewrite this...

    
for ($count 0$n count($data); $count $n$count++)
        if (
strstr($data[$count],$moremark))
            break;

    if (
$count == $n)            // hit end
        
return $count;

    if (!
$count) {
        
$p = ($p config('morepara')) ? $p 6;
        
$para 0;

        while (list( ,
$_) = each($data)) {
            if (
$para++ == $p)
                break;
            
$count++;
        }
    }

    return 
$count;
}


/* _moretruncate - truncate body array at more marker index */

function _moretruncate($data$count) {

    return 
array_slice($data,0,$count);
// the arbitrariness of the slice can possibly result in the removal of a
// needed closing tag so the <!--more--> marker must not be placed before
// an ending tag
}

?>