<?php
/**
* All functions that are used in general by the PHP SiteBuilder application
*
* @file dynamisk.php
* @author Tobias H. Michaelsen {mailto:hide@address.com}
* @author Jesper Rønn {mailto:hide@address.com}
* @date 1980-01-01
*
* $Id: dynamisk.php,v 1.20 2001/10/16 02:45:16 zaiborg Exp $
*/
if (defined('__dynamisk')) return;
else define('__dynamisk', 1);
if (DEBUG) { echo "<!-- Start of file: dynamisk -->\n"; }
/**
* Return the PHP Sitebuilder version
*
* @return string The PHP Sitebuilder version number
*/
function apiVersion() {
// this should be in sync with the VERSION file
// $ver is calculated in config.text.php
global $site;
$ver_file = $site['docroot'].'VERSION';
if ($ver_str = @file($ver_file)) {
$ver = implode("", $ver_str);
$ver = str_replace("PHP SiteBuilder ", "", $ver);
$ver = str_replace("release ", "", $ver);
} else {
$ver = 'n/a';
}
return $ver; // example "0.99-10"
}
/**
* Find the most recent frontpage that is not newer than today
*
* @return string Path and filename of the latest frontpage or an error message.
*/
function latestFrontpage()
{
global $cfg, $site, $txt;
$path = $site['docroot'].$cfg['frontPageDir'];
if ($d = @dir($path)) {
if (DEBUG) {
echo "Directory handle: ".$d->handle."<br />\n";
echo "Path: ".$d->path."<br />\n";
echo "Pattern: ".$cfg['frontpagePattern']."<br />\n";
echo "Files:<br>\n";
}
// read matching filenames into an array
// with timestamp for sorting
$frontpages = array();
while ($filename = $d->read()) {
if (eregi($cfg['frontpagePattern'], $filename, $date)) {
$ts = mktime(0, 0, 0, $date[2], $date[3], $date[1]);
$frontpages[] = Array(
'filename' => $filename,
'timestamp' => $ts
);
if (DEBUG) { echo "|$filename| - |$ts|<br />\n"; }
} elseif (DEBUG) {
echo "|$filename| - could not be used<br />\n";
}
}
$d->close();
}
if (isset($frontpages)) {
$latestFrontpage = $path."/".findLatest($frontpages);
} else {
$latestFrontpage = $txt['frontpageMissing'];
}
return $latestFrontpage;
}
/**
* Find latest frontpage, that is not newer than today, in an array.
*
* @date 1999-11-12
* @param array Array of arrays containing 'filename' and 'timestamp'.
* @return string The newest 'filename'.
*/
function findLatest($frontpages)
{
$frontpageCount = count($frontpages);
$now = time();
$latest = 0;
for ($i = 0; $i < $frontpageCount; $i++) {
if ($frontpages[$i]['timestamp'] < $now and $latest < $frontpages[$i]['timestamp']) {
$latest = $frontpages[$i]['timestamp'];
$latestIndex = $i;
}
}
return $frontpages[$latestIndex]['filename'];
}
// get all old frontpages and sort them for output a list
function getOldFrontpages()
{
global $cfg;
$d = dir($cfg['articlePath']);
if (DEBUG) {
echo "Directory handle: ".$d->handle."<br>\n";
echo "Path: ".$d->path."<br>\n";
echo "Files:<br>\n";
}
$nu = time();
while ($fn = $d->read())
{
echo (DEBUG) ? "|$fn| - " : "";
if (eregi($cfg['frontpagePattern'], $fn, $dato))
{
// check if page is newer than today, otherwise don't show
$ts = mktime(0,0,0,$dato[2],$dato[3],$dato[1]);
if ($nu > $ts)
{
$pages[] = $fn;
echo (DEBUG) ? "read:<br>\n" :"";
} else
echo (DEBUG) ? "is too recent...<br>\n" : "";
} else
echo (DEBUG) ? "could not be used...<br>\n" : "";
}
$d->close();
if ($pages) {
rsort($pages); // is cronological.
}
$numPages = count($pages);
echo (DEBUG) ? "num pages: ".$numPages."<br>\n" : "";
echo "<ul>\n";
# create link to current fronpage. It is the last one in the array
echo "\t<li>Current: <b>";
$linkNavn = createFrontpageLink($pages[0]);
echo "</b></li>\n";
for( $j = 1 ; $j < $numPages ; $j++ )
{
echo (DEBUG) ? " Old frontpage: $pages[$j] " : "";
echo "\t<li><b>";
createFrontpageLink($pages[$j]);
echo "</b></li>\n";
}
echo "</ul>\n<br>\n";
}
// create link for linking to old frontpages
function createFrontpageLink($fn)
{
global $cfg, $path;
$linkName = eregi_replace($cfg['frontpagePattern'] , "\\1-\\2-\\3" , $fn);
if (DEBUG) { echo " linkname is now nu: $linkName \n\n<br>"; }
echo "<a href=\"index.php?a=".$cfg['articlePath']."/$fn\">$linkName</a>";
echo "<br>\n";
}
/**
* Date and time formating.
*
* @param string $format Formating text string with locale formating from lang.xx.php.
* Ex. getDateTime($txt['longdate']);
* @param integer $uxtime Unix time (seconds since 1980). Now, if nothing is specified.
* @return string Formated string containing date and time.
*/
function getDateTime($format, $uxtime = '')
{
settype($uxtime, "integer");
if (empty($uxtime)) {
$uxtime = time(); // Now!
}
$str = strftime($format, $uxtime);
return $str;
}
/**
* Prepare a string, possibly containing newlines and HTML tags and special
* chars, for debug output.
*
* @param string $str Input string with HTML tags and newlines.
* @return string Input string with special chars and HTML tags
* replaced with HTML entities and newlines replaced
* with litteral \r and \n.
*/
function fixup($str)
{
$trans = get_html_translation_table(HTML_SPECIALCHARS);
$trans = array_merge($trans, array("\n" => "\\n", "\r", "\\r"));
$str = strtr($str, $trans);
return $str;
}
/**
* Compute Links.
*
* Comment:
* Pages and positions are calculated from:
* $cfg['sideNr'] og $cfg['count'] (number per page).
*
* Additional parameters used for previous/next page link:
* $txt['css'] -- pt. 'class="footer"'
*
* Input:
* $cfg['sideNr'], $cfg['maxSider'],
* $txt['css'], $txt['nextLabel'], $txt['prevLabel']
* These should be given as arguments for the function, instead of taken from
* global variables.
*
* @return array Three text strings:
* 'prevPage': Link to previous page. (If any. Otherwise "dead" link)
* 'nextPage': Link to next page. (If any. Otherwise "dead" link)
* 'quick': Quick-navigation links. (Eg. |1|2|3|4| etc.)
*/
function computeLinks($baseLink='', $pageNr='', $totalPages='', $class='')
{
global $txt, $show, $cfg;
if (DEBUG) { echo "<b>\$cfg['sideNr']:\t".$cfg['sideNr']."</b><br />\n"; }
// Links to previous page -- if necessary
if ($cfg['sideNr'] > 1) {
$links['prevPage'] = '<a href="'.$cfg['baseLink'];
$links['prevPage'] .= '&cfg[sideNr]='.($cfg['sideNr'] - 1);
$links['prevPage'] .= '&cfg[count]='.$cfg['count'].'"';
# $links['prevPage'] .= ' '.$txt['css'];
$links['prevPage'] .= (!empty($class)) ? ' class="'.$class.'"' : '';
$links['prevPage'] .= '><- '.$txt['prevLabel'].'</a>';
} else {
$links['prevPage'] = '<- '.$txt['prevLabel'];
}
// Quick-link for all pages
for ($j = 1; $j <= $cfg['maxSider']; $j++) {
if ($j == $cfg['sideNr']) {
$quickPageLink[$j] = "<b>$j</b>";
} else {
$quickPageLink[$j] = '<a href="'.$cfg['baseLink'].'&';
$quickPageLink[$j] .= 'cfg[sideNr]='.$j.'&';
$quickPageLink[$j] .= 'cfg[count]='.$cfg['count'].'">'.$j.'</a>';
}
}
$links['quick'] = '| '.implode(' | ', $quickPageLink).' |';
// Link to next page -- if necessary
if ($cfg['sideNr'] < $cfg['maxSider']) {
$links['nextPage'] = '<a href="'.$cfg['baseLink'];
$links['nextPage'] .= '&cfg[sideNr]='.($cfg['sideNr'] + 1);
$links['nextPage'] .= '&cfg[count]='.$cfg['count'].'"';
# $links['nextPage'] .= ' '.$txt['css'];
$links['nextPage'] .= (!empty($class)) ? ' class="'.$class.'"' : '';
$links['nextPage'] .= '>'.$txt['nextLabel'].' -></a>';
} else {
$links['nextPage'] = $txt['nextLabel'].' ->';
}
return $links;
}
/**
* outputLinks($links)
* outputs links in a Formatted HTML table:
* this function only contains formatting info!
*
* @param array $links to output.
*/
function outputLinks($links, $class = '')
{
// TODO:
// Use <div> for the whole "navigation" and drop $txt['css']!
global $txt;
/* Start HTML output */
/*?>
<table width="100%" border="0" align="right">
<tr>
<td width="30%" align="left" <?php echo $txt['css']; ?>><?php echo $links['prevPage']; ?></td>
<td width="40%" align="center" <?php echo $txt['css']; ?>><?php echo $links['quick']; ?></td>
<td width="30%" align="right" <?php echo $txt['css']; ?>><?php echo $links['nextPage']; ?></td>
</tr>
</table>
<!--
<br />
-->
<?php
*/
// Alternative output format:
$link = '<div'.(!empty($class) ? ' class="'.$class.'"' : '');
$link .= ' style="text-align:center">';
$link .= '<span style="width:6.5em;text-align:right;">'.$links['prevPage'].'</span>';
$link .= ' '.$links['quick'].' ';
$link .= '<span style="width:6.5em;text-align:left;">'.$links['nextPage'].'</span>';
$link .= '</div>';
echo $link."\n";
return true;
}
/**
* Add a new news to news-file.
*
* @param string $filename Filename of news-file.
* @param string $date Date.
* @param string $description News text.
* @param string $link Link to relevant page.
* @param string $verbose Output additional debug information.
* @return boolean
*/
/* THIS FUNCTION HAS BEEN REPLACED!!! SE NEXT FUNCTION...
function addToNews($filename, $date, $description, $link, $verbose = false)
{
if ($verbose) echo "\n<br />Date before error-check: $date (line:".__LINE__.")\n";
// Error-check date format
if (!ereg("^[0-9]{1,2}/[0-9]{1,2}-[0-9]{2}$", $date)) {
if ($verbose) echo "Error: wrong date format!<br />\nReceived:\t$date<br />\nExpected:\t13/4-00\n";
$pat1 = "^[0-9]{2}?([0-9]{2})-?([0-9]{1,2})-?([0-9]{1,2})$"; // [yy]yy-[m]m-[d]d
$pat2 = "^[([0-9]{1,2})/([0-9]{1,2})/([0-9]{2})$"; // [m]m/[d]d/yy
if (ereg($pat1, $date)) {
$date = ereg_replace($pat1, "\\3/\\2-\\1", $date);
if ($verbose) echo "\n<br />\nDate converted to: $date (line:".__LINE__.")\n";
} elseif (ereg($pat2, $date)) {
$date = ereg_replace($pat2, "\\2/\\1-\\3", $date);
if ($verbose) echo "\n<br />\nDate converted to: $date (line:".__LINE__.")\n";
} else {
if ($verbose) echo "\n<br />\nWas unable to convert date format!<br />\nNews not written.";
return false;
}
}
// Try to make a back-up of the news-file
if (!@copy($filname, $filname.'.bak')) {
if ($verbose) echo "<br />\nUnable to copy $filname...<br />\n";
}
// Get old news as an array:
if (file_exists($filename)) {
$oldNews = file($filename);
} else {
$oldNews = array();
}
// Reset news-file
if ($fp = @fopen($filename, "w")) {
// Write new news to the top of the news-file
$news = "|".$date."|".$description."|".$link."|\n";
fputs($fp, $news);
if ($verbose) echo "<br />\nNew news: ".$news."<br />\n";
// Add the old news to the new news-file
foreach ($oldNews as $news) {
fputs($fp, $news);
if ($verbose) echo "Old news: ".$news."<br />\n";
}
fclose($fp);
// {{{ 'Clear cache' by deleting xml-file if it exists.
$xmlNewsFile = substr($filename, 0, -3).'xml';
if (file_exists($xmlNewsFile)) unlink($xmlNewsFile);
// }}}
return true;
} else {
// Failed to write new news-file
return false;
}
}
*/
/**
* Add a new news to news-file.
* Now handles xml-file.
*
* @param string $filename Filename of news-file.
* @param string $date Date.
* @param string $description News text.
* @param string $link Link to relevant page.
* @return boolean
*/
function addToNews($filename, $date, $description, $link)
{
include_once 'XML/Tree.php';
$xt = new XML_Tree($filename, '1.0', 'iso-8859-1');
$err = $xt->getTreeFromFile();
if (PEAR::isError($err)) {
echo $err->getMessage()."<br />\n";
}
$attributes = array(
'date' => $date,
'text' => $description,
'href' => $link
);
$node = new XML_Tree_Node('item', '', $attributes);
$xt->root->insertChild('', 1, $node);
$err = $xt->writeFile();
if (PEAR::isError($err)) {
echo $err->getMessage()."<br />\n";
}
}
/**
* Use to test "Which dir am I in?"
*
* @name listDirContents()
*/
function listDirContents()
{
echo '<div style="border: 1px solid black; padding 0.5em;">';
$d = dir("./");
echo "Handle: ".$d->handle."<br />\n";
echo "Path: ".$d->path."<br />\n";
while($entry=$d->read()) {
echo $entry."<br />\n";
}
$d->close();
echo "</div>";
return true;
}
/**
* Builde HTTP headers.
*
* Example:
* $headers =& buildHttpHeader();
* [...]
* sendHttpHeaders($headers);
*
* NEEDED:
* cookies must be supported in the PHP SiteBuilder
* model. Idea: Through a separate "setcookie" function
* When called,
* - save ALL variables
* - redirect to new page
* - send cookie
* - redirect to referring page. All variables must be preserved
*
* NOTICE:
* The header() function must be called before any other output is sent.
*
* @name buildHttpHeader
* @return array Standard HTTP headers for PHP Sitebuilder.
*/
function &buildHttpHeader()
{
global $cfg;
$e = isset($cfg['expiresTime']) ? $cfg['expiresTime'] : 60;
$r = isset($cfg['refreshTime']) ? $cfg['refreshTime'] : 1200;
$expires = gmdate('D, d M Y H:i:s', time()+$e);
$lastMod = gmdate('D, d M Y H:i:s'); // always modified
$headers[] = 'Expires: '.$expires.' GMT';
$headers[] = 'Last-Modified: '.$lastMod.' GMT';
$headers[] = 'Cache-Control: no-cache, must-revalidate';// HTTP/1.1
$headers[] = 'Pragma: no-cache'; // HTTP/1.0
$headers[] = 'Refresh: '.$r;
return $headers;
}
/**
* Send the HTTP headers.
*
* @param array $headers HTTP headers, passed by reference (speed).
*/
function sendHttpHeader(&$headers)
{
foreach ($headers as $val) header($val);
}
/**
* Get the body of a html document.
*
* Example:
* $htmlBody =& getBody('myHtmlFile.html');
* print $htmlBody;
*
* @param string $a Article file name.
* @return string $c Content of the (body of the) article.
*/
function &getBody($a)
{
if (!file_exists($a)) return null;
$c = file($a); // read $a into an array as $c
$c = join("", $c); // join all lines in $c with a space between them
// check wether a <body...> tag is pressent
if (preg_match("|<body[^>]*?>(.*?)</body>|si", $c, $out)) {
$c = $out[1];
}
return $c;
}
/**
* Check if a given file name is a HTML file.
*
* @param string $fileName Name of the file to check.
* @param boolean $thorough Test if file contains a HTML-tag.
* @return boolean True if HTML file, false otherwise.
*/
function isHTMLFile($filename, $thorough = false)
{
if ($thorough) {
$contents = join('', file($filename));
$result = preg_match("|<html[^>]*?>|si", $contents);
} else {
$result = eregi("\.htm(l)?$", basename($filename));
}
return $result;
}
/**
* Check if the wanted article is 'valid'.
* I.e. check if it exists, is in a folder that is allowed to be read
* and if it is a HTML document or a PHP script (or unknown).
*
* @param string $article Relative filename of the article.
* @return string Status of the article.
*/
function validateArticle($article)
{
global $cfg, $design, $site, $txt;
if (strstr($article, $site['docroot'])) {
// Remove $site['docroot'] from $article
$start = strlen($site['docroot']);
$len = strlen($article) - $start;
$article = substr($article, $start,$len);
}
$tmp = explode('/', $article);
$folder = ($tmp[0] == $article) ? '' : $tmp[0];
if (!file_exists($site['docroot'].$article)) {
$cfg['articleStatus'] = 'HTTP/1.1 404 Not Found';
$cfg['headers'][] = $cfg['articleStatus'];
}
elseif (!in_array($folder, $cfg['allowArticleFromFolders']) or
in_array ($folder, $cfg['denyArticleFromFolders']) or
is_dir($article) ) {
$cfg['articleStatus'] = 'HTTP/1.1 403 Forbidden';
$cfg['headers'][] = $cfg['articleStatus'];
}
elseif (eregi("\.htm(l)?$", basename($article)))
$cfg['articleStatus'] = 'HTML';
elseif (eregi("\.php(3|4)?$", basename($article)))
$cfg['articleStatus'] = 'PHP';
else
$cfg['articleStatus'] = 'Unknown';
return $cfg['articleStatus'];
}
/**
* Return global handle to databse connection.
* Create one if it does not exist.
*
* Example:
* $db =& getGlobalDB($cfg['dsn']);
*
* @param mixed $dsn PEAR style Data Source Name; string or array.
* @return object Reference to database connection object.
*/
function &getGlobalDB($dsn)
{
if (!isset($GLOBALS['globalDatabaseHandle'])) {
include_once('DB.php');
$GLOBALS['globalDatabaseHandle'] = DB::connect($dsn);
}
return $GLOBALS['globalDatabaseHandle'];
}
/**
* Randomly pick an element in an array.
*
* @param array Input array.
* @return mixed Whetever is contained in the randomly picked element
* of the input array.
*/
function randomPick($arr)
{
if (is_array($arr)) {
$j = count($arr);
srand((double)microtime()*1000000);
$tmp = rand(1, $j);
return $arr[$tmp];
} else {
return $arr;
}
}
if (DEBUG) { echo "<!-- End of file: dynamisk -->\n"; }
/* vim: set tabstop=4: */
?>