THIS source compiler<?php
/* RECORD.PHP - manipulate 'records' and write/read them to/from database *
This module "processes" posts as a step between the display code and the
database: DISPLAY > RECORD > MYSQL. For example:
displayrecord() calls readrecord() which calls dbreadrecord()
dbreadrecord() returns a $record and readrecord() validatesand converts the
record data suitible for displayrecord() to display it via displayhtml()
The following functions are defined:
readrecord() // called by DISPLAY and Admin
writerecord() // called by Admin
createrecord() // creates a $record with dummy data
createcomment() // creates comment $record from POST
stringtorecord() // converts raw post to $record
// dbreadrecord() calls this
recordtostring() // converts $record to string
sortrecords() // sorts list of record ids
readfilerecord()
*/
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 = stringtorecord($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;
// create date and time strings if needed; what's weird here is that
// date is optional (though shouldn't be) and time is created
if (!isset($record['date'])) {
$record['time'] = time();
$record['date'] = date(config('datestr'),$record['time']);
}
if (!isset($record['time']))
$record['time'] = strtotime($record['date']);
$record['datetime'] = date(DATE_RFC3339,$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 (config('headers'))
_defaultheaders($record);
_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 */
// the pages API is in the PAGES module
function readfilerecord($id) {
$record = dbreadpage($id);
if ($record == FALSE)
return createrecord("Error #21 ($id)",htmlgeterror('NOTFOUND'));
if (!isset($record['date'])) {
$record['time'] = time();
$record['date'] = date(config('datestr'),$record['time']);
}
if (!isset($record['time']))
$record['time'] = strtotime($record['date']);
$record['datetime'] = date(DATE_RFC3339,$record['time']);
$record['body'] = convert($record['body'],$record);
return $record;
}
/* writerecord - write a new record (previously non-existent) */
// assumes properly formated data from admin form but it adds the basics
// if they are missing; if $id assumes already validated that it exists
function writerecord($record, $headers = array(), $id = 0) {
debug("");
if (!is_array($record))
$record = stringtorecord($record);
// do some basic validation
if (!isset($record['title']))
$record['title'] = 'Title';
if (!isset($record['time']) && !isset($record['date']))
$record['time'] = time();
if ($headers)
foreach ($headers as $k => $v) {
if (is_numeric($k))
$record[$v] = '';
else
$record[$k] = $v;
}
if ($id)
return dbputrecord($id,$record);
return dbnewrecord($record);
}
/* stringtorecord - convert record string to associative array */
// assumes properly formated data; it sort of handles missing headers
function stringtorecord($data) {
$data = explode(THIS_EOL,$data);
// PREG_SPLIT__DELIM_CAPTURE is wanted here, but this:
// $data = preg_split('/(\n)/',$data,-1,PREG_SPLIT_DELIM_CAPTURE);
// puts the "\n" as a separate array member which is not right
foreach ($data as &$d)
$d .= THIS_EOL;
reset($data);
unset($d);
while (list( ,$_) = each($data)) {
if ($_ == THIS_EOL) {
$_ = '';
break;
}
$h = explode(':',$_);
if (count($h) == 1)
break;
$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);
}
/* 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;
}
/* createcomment - create a comment from POST data */
function createcomment() {
$date = datestrcmt();
$from = postvar('from');
$subj = postvar('subj');
$data = postvar('data');
$record['title'] = $subj;
$record['from'] = $from;
$record['date'] = $date;
$record['body'] = convert_user($data);
recorduserdata($record); // modifies $record
if ($record['from'] == '') $record['from'] = 'nobody';
if ($record['title'] == '') $record['title'] = 'nothing';
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'];
}
/* _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;
}
/* _defaultheaders - check for and/or create additional headers */
function _defaultheaders(&$record) {
$headers = config('headers');
if (!is_array($headers))
return;
foreach ($headers as $key => $val)
if (!isset($record[$key]))
$record[$key] = $val;
}
/* _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 < 0 || $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
}
?>
Source Code Index