Location: PHPKode > projects > PHP SiteBuilder > include/dynamisk.php
<?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'] .= '&amp;cfg[sideNr]='.($cfg['sideNr'] - 1);
		$links['prevPage'] .= '&amp;cfg[count]='.$cfg['count'].'"';
#		$links['prevPage'] .= ' '.$txt['css'];
		$links['prevPage'] .= (!empty($class)) ? ' class="'.$class.'"' : '';
		$links['prevPage'] .= '>&lt;- '.$txt['prevLabel'].'</a>';
	} else {
		$links['prevPage'] = '&lt;- '.$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'].'&amp;';
			$quickPageLink[$j] .= 'cfg[sideNr]='.$j.'&amp;';
			$quickPageLink[$j] .= 'cfg[count]='.$cfg['count'].'">'.$j.'</a>';
		}
	}
	$links['quick'] = '|&nbsp;'.implode('&nbsp;|&nbsp;', $quickPageLink).'&nbsp|';

	// Link to next page -- if necessary
	if ($cfg['sideNr'] < $cfg['maxSider']) {
		$links['nextPage'] = '<a href="'.$cfg['baseLink'];
		$links['nextPage'] .= '&amp;cfg[sideNr]='.($cfg['sideNr'] + 1);
		$links['nextPage'] .= '&amp;cfg[count]='.$cfg['count'].'"';
#		$links['nextPage'] .= ' '.$txt['css'];
		$links['nextPage'] .= (!empty($class)) ? ' class="'.$class.'"' : '';
		$links['nextPage'] .= '>'.$txt['nextLabel'].' -&gt;</a>';
	} else {
		$links['nextPage'] = $txt['nextLabel'].' -&gt;';
	}

	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 />&nbsp;
-->
<?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 .= '&nbsp;'.$links['quick'].'&nbsp;';
	$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: */
?>
Return current item: PHP SiteBuilder