<?php

/*
 *	W-AGORA 4.2
 *	-----------
 *	$Id: misc_func.php,v 1.141 2005/04/19 14:18:58 mdruilhe Exp $
 *	Usage:		Include file for common usage functions
 *	Author:		Marc Druilhe <mdruilhe@w-agora.net> and OTHERS
 */

if (defined("_MISC_FUNC")) return;
define('_MISC_FUNC', 1);

// $html_entities_match = array('/&([^#])/', '/</', '/>/', '/"/', "/'/");
$html_entities_match = array('/&(?![A-Za-z]{0,4}\w{2,3};|#[0-9]{2,5};)/', '/</', '/>/', '/"/', "/'/");
$html_entities_replace = array("&amp;\\1", '&lt;', '&gt;', '&quot;', '&#39;');

$unkill_html_match = array('/&(nbsp|#160);/i', '/&(lt|#60);/i', '/&(gt|#62);/i', '/&(amp|#38);/i', '/&(quot|#34);/i', '/&#39;/');
$unkill_html_replace = array(' ', '<', '>', '&', '"', "'");

// tags always allowed
$allowed_tags = ' pre br b i u em ul ol li br p hr h1 h2 h3 h4 h5 h6 sup strike font div span strong blockquote tt code'; 

// sensitive tags always stripped
$banned_tags = 'script html body iframe frame frameset';

#	This function allows us to read the configuration file w/o overwriting
#	global config. variables
# ----------------------------------------------------------------------
function getDBaccess($site) {
	global $cfg_dir, $ext;

	require "${cfg_dir}/site_${site}.$ext";
	$access["dbname"] = $dbname;
	$access["dbhost"] = $dbhost;
	$access["dbport"] = $dbport;
	$access["dbuser"] = $dbuser;
	$access["dbpassword"] = $dbpassword;
	$access["dbadmuser"] = (empty($dbadmuser) ) ? $dbuser : $dbadmuser;
	$access["dbadmpassword"] = (empty($dbadmuser) ) ? $dbpassword : $dbadmpassword;
	$access["bn_access"] = $bn_access;
	$access["usersource"] = (empty($bn_usersource) )  ? "agora_user" : $bn_usersource;
	return $access;
}

function msg ($number, $default="") {
	global $site, $bn, $icon_dir, $img_dir, $ext;
	global $msg, $key, $thread, $pattern, $label_new, $alt_state_label;
	global $newestNote,	$label_latest;

	$mess = str_replace('"','\"', (isset($msg[$number])) ? $msg[$number] : $default);
	eval ("\$m=stripSlashes(\"$mess\");");
	return $m;
};

function dspMsg ($number, $default="") {
	print msg($number, $default);
};

function msgWarning ($message) {
	echo "<div align=\"center\"><div class=\"msgwarning\">$message</div></div>";
};

function msgForm ($message, $url, $action="", $target="", $method="get") {
	global $HTTP_POST_VARS, $bn, $site;
	global $frameset, $bn_frames, $bn_popup, $lynx, $popup;

	if ($lynx==1) $bn_frames=0;

	if (strpos($url, '?')) {
		list ($base_url, $qs) = explode('?', $url);    
	} else {
	    $base_url = $url;
	}
	
	echo "<form method=\"$method\" action=\"$base_url\" ";

	if (($action =="close") && $popup && $bn_popup) {
		if ($bn_frames) {
			echo " target=\"main\">\n";
			$frame= "opener.parent.main";
		} else {
			echo " target=\"_parent\">\n";
			$frame= "opener";
		}
	} elseif (!empty($target)) {
		echo " target=\"$target\">\n";
	} else  {
		echo ">\n";
	}

# Propagate all posted vars from the FORM
# ---------------------------------------
	if (is_array($HTTP_POST_VARS) && ($action=="back") ) {
		foreach ($HTTP_POST_VARS as $k => $v) {
			if (isset($$k)) {
				continue;
			} elseif (is_array($v)) {
				foreach ($HTTP_POST_VARS[$k] as $ak => $av) {
					$$k[$ak] = strip_magic_quotes($av);
					hiddenField("$k"."[$ak]", $$k[$ak]);
				}
			} elseif (!empty($v)) {
				$$k = strip_magic_quotes($v);
				hiddenField($k, $$k);
			}
		}
	}

# process Query string
# --------------------
	$a = split ('&', $qs);
	$i = 0;
	while ($i < count ($a)) {
		$b = split ('=', $a [$i]);
		$name=urldecode ($b[0]);
		$value = isset($b[1]) ? urldecode ($b[1]) : "";
		if ($name=="bn")
			$bn=$value;
		elseif ($name=="site")
			$site=$value;
		elseif ($name != "")
			hiddenField ($name, $value);
		$i++;
	}
	hiddenField ("bn", $bn);
	if (!empty($site)) {
		hiddenField ("site", $site);
	}
	if ($lynx==1) {
		hiddenField ("lynx", "1");
	}

	echo "<div align=\"center\"><div class=\"msgbox\">$message<br/>";
	$exit=0;
	switch ($action):
		case "back":
			if ($method=="post") {
				submitButton ('back',BUTTON_BACK);
			} else {
				submitButton ('back', BUTTON_BACK, 'history.back(); return false;');
			}
		break;
		case "close":
			if ($bn_popup && $popup) {
				$onclick = "if ($frame!=null) {" .			"$frame.location=\"$base_url?bn=$bn&$qs\";window.close()} else {window.close()}";
				echo getButton ('ok', BUTTON_OK, $onclick);
			}
			else {
				submitButton('',BUTTON_OK);
			}
		break;
		case "exit":
			$exit=1;
		break;
		default:
			submitButton('',BUTTON_OK);
		break;
	endswitch;
	
	echo "</div></div>";
	endForm();
	if ($frameset) {
		?></noframes></frameset><?php
	}
}

function formated_date ($unixdate, $format='', $tz_offset=0) {
	$offset = (empty ($tz_offset) ) ? $GLOBALS['bn_tz_offset'] : $tz_offset;
	return date( (empty($format)) ? $GLOBALS['bn_date_format'] : $format, $unixdate+($offset*3600) );
}


function getNavBar($base_url, $total_items, $first_item=0, $per_page=20, $nb_nums=5, $add_prevnext = true, $arg_first='first') {

	settype($per_page, 'integer');

	if($per_page<=0) {
		return '';
	}

	$nb_pages = ceil($total_items/$per_page);
	if ($nb_pages <= 1) {
		return '';
	}

	$page_num = floor($first_item/$per_page) + 1;

	$start_num = max($page_num-2, 1);
	$end_num = min($start_num+4, $nb_pages);

	$navbar = '<div class="navbar">';

	if ($add_prevnext) {
		$navbar .= '<span class="navbar_page">'. sprintf(PAGE_NUM_OF, $page_num, $nb_pages) . '</span>&nbsp;';
		if ($start_num > 1) {
			$navbar .= '<span class="navbar_first">'. anchor ("$base_url&$arg_first=0", "", "&laquo;", ALT_FIRST_PAGE, 'navbar_link'). '</span>&nbsp;';
		}

		if ($page_num > $start_num) {
			$prev = max(($page_num-2) * $per_page, 0);	// prevent for negative value
			$navbar .= '<span class="navbar_prev">'. anchor ("$base_url&$arg_first=$prev", "", "&lt;", ALT_PREV_PAGE, 'navbar_link'). '</span>&nbsp;';
		}
	}

	for ($pg=$start_num; $pg <=	$end_num; $pg++) {
		if ($pg == $page_num) {
			$navbar .= '<span class="navbar_current">'. $pg. '</span>&nbsp;';
		} else {
			$first = ($pg-1) * $per_page;
			$navbar .= ('<span class="navbar_page">'. anchor ("$base_url&$arg_first=$first", "", $pg, sprintf(ALT_GOTO_PAGE, $pg), 'navbar_link'). '</span>&nbsp;');
		}
	}

	if ($add_prevnext) {
		if ($page_num < $end_num) {
			$next = $page_num * $per_page;
			$navbar .= '<span class="navbar_next">'. anchor ("$base_url&$arg_first=$next", "", "&gt;", ALT_NEXT_PAGE, 'navbar_link'). '</span>&nbsp;';
		}

		if ($end_num < $nb_pages) {
			$last = ($nb_pages-1) * $per_page;
			$navbar .= '<span class="navbar_last">'. anchor ("$base_url&$arg_first=$last", "", "&raquo;", ALT_LAST_PAGE, 'navbar_link'). '</span>&nbsp;';
		}
	}

	$navbar .= '</div>';
	return $navbar;
}


function expandUrl ($url) {
	global $site, $bn;

	// extract fragment part
	list ($ret_url, $fragment) = explode('#', $url, 2);    
	if (empty($ret_url) ) return $url;

	// Extract query string
	list ($ret_url, $query) = explode('?', $ret_url, 2);    

	$query = '&'. str_replace('&amp;', '&', $query);

	if (!empty($bn) && !ereg ('&bn=', $query) ) {
		$query .= "&bn=$bn";
	}
	if (!empty($site) && !ereg ('&site=', $query) && !ereg ('&bn=', $query) ) {
		$query .= "&site=$site";
	}

	$search = array('/^&/', '/&/', '/ /'); 
	$replace = array('?', '&amp;', '+');
	$query = preg_replace($search, $replace, $query);

	if (strlen($query)>1) {
		$ret_url .= $query;
	}
	if (!empty($fragment)) {
		$ret_url .= "#$fragment";
	}

	return $ret_url;
}

function anchor ($url, $target="", $text="", $status="", $class="wa_link") {
	$class = (empty($class) ) ? '' : " class=\"$class\"";
	$target = (empty($target) ) ? '' : " target=\"$target\"";
	$text = empty($text) ? htmlSpecialChars($url) : $text;
	if (!empty($status)) {
		$status = strip_tags($status);
		$jsstatus = ' onmouseover="window.status=\'' . str_replace ("'", '`', $status) . '\';return true" onMouseout="window.status=\'\';return true"';
		$title = " title=\"$status\"";
	}
	return ('<a href="'.expandUrl($url)."\"$title$target$jsstatus$class>$text</a>");
}

function displayUrl ($url, $target="", $text="", $status="", $class="wa_link") {
	print  anchor($url, $target, $text, $status, $class);
}

function anchorWindow ($url, $text="", $status="", $width, $height, $class="wa_link") {
	global $site, $bn, $lynx, $bn_popup, $bn_frames;

	$url = expandUrl($url);
	if ($bn_popup) {
		$frame = "${bn}_post";
		$target = " target=\"$frame\"";
		$jswindow = " onClick=\"OpenWindow('$url','$frame',$width,$height); return false;\" ";
	} elseif ($bn_frames) {
		$target = " target=\"main\"";
		$jswindow = "";
	} else {
		$target ="";
		$jswindow = "";
	}

	$class = (empty($class) ) ? "" : " class=\"$class\"";
	$text = empty($text) ? htmlSpecialChars($url) : $text;
	if (!empty($status)) {
		$status = strip_tags($status);
		$jsstatus = ' onmouseover="window.status=\'' . str_replace ("'", '`', $status) . '\';return true" onMouseout="window.status=\'\';return true"';
		$title = " title=\"$status\"";
	}
	return ("<a href=\"$url\"$title$target$jsstatus$jswindow$class>$text</a>");

}

function openWindow ($url, $text="", $status="", $width, $height, $class="wa_link") {
	print anchorWindow ($url, $text, $status, $width, $height, $class);
}

/**
 * email validator (initial code found at zend.com)
 *
 * Beware that setting the second argument to true is quite time consuming.
 * The regexp is taken from Formmail by Matt Wright. Formmail can be found at;
 * http://www.worldwidemart.com/scripts/
 */
function validate_email ($email, $check_dns=false) {
	if (preg_match ('/^.+\@(\[?)[a-zA-Z0-9\-\.]+\.([a-zA-Z]{2,6}|[0-9]{1,3})(\]?)$/', $email) ) {
		if ($check_dns && function_exists("checkdnsrr") && !$GLOBALS["winbox"]) {
			$host = explode('@', $email);
			// Check for MX record
			if( checkdnsrr($host[1], 'MX') ) return true;
			// Check for A record
			if( checkdnsrr($host[1], 'A') ) return true;
			// Check for CNAME record
			if( checkdnsrr($host[1], 'CNAME') ) return true;
			if ($GLOBALS["debug"]) {
				printf ("<br /><b>unresolved dns address:</b><tt>%s<br /></tt>", nl2br($host[1]) );
			}
		} else {
			return true;
		}
	}
	return false;
}


function get_summary (&$text, $nchars=255) {
	settype($nchars, "integer");
	$search = array("/(\r|\n)/", "/\"/", "/'/"); 
	$replace = array("", "&quot;", "&#39;");

	$summary = my_br2nl($text);
	$summary = addslashes(preg_replace($search, $replace, nl2br(strip_tags($summary))));
	if (strlen($summary)>$nchars) {
		$summary = substr($summary, 0, $nchars-4);
		$summary = preg_replace("/( [^ ]+|[ ]*<[^>]+)$/", "", $summary) . " ...";
	}
	return $summary;
}

/* word_wrap($string, $cols, $prefix)
 *
 * Takes $string, and wraps it on a per-word boundary (does not clip
 * words UNLESS the word is more than $cols long), no more than $cols per
 * line. Allows for optional prefix string for each line. (Was written to
 * easily format replies to e-mails, prefixing each line with "> ".
 *
 * Copyright 1999 Dominic J. Eidson, use as you wish, but give credit
 * where credit due.
 */
function word_wrap ($string, $cols = 80, $prefix = "") {

	$t_lines = split( "\n", $string);
	$outlines = "";

	while(list(, $thisline) = each($t_lines)) {
		if(strlen($thisline) > $cols) {

			$newline = "";
			$t_l_lines = split(" ", $thisline);

			while(list(, $thisword) = each($t_l_lines)) {
				while((strlen($thisword) + strlen($prefix)) > $cols) {
					$cur_pos = 0;
					$outlines .= $prefix;

					for($num=0; $num < $cols-1; $num++) {
						$outlines .= $thisword[$num];
						$cur_pos++;
					}

					$outlines .= "\n";
					$thisword = substr($thisword, $cur_pos, (strlen($thisword)-$cur_pos));
				}

				if((strlen($newline) + strlen($thisword)) > $cols) {
					$outlines .= $prefix.$newline."\n";
					$newline = $thisword." ";
				} else {
					$newline .= $thisword." ";
				}
			}

			$outlines .= $prefix.$newline."\n";
		} else {
			$outlines .= $prefix.$thisline."\n";
		}
	}
	return $outlines;
}

function my_br2nl (&$text) {

	$match = array("'<br[^>]*[/]?>[\n]?'i", "'<p[^>]*/?>[\n]?'i");
	$replace = array("\n", "\n\n");
	return preg_replace($match, $replace, $text);
}

function my_nl2br (&$text) {
	return preg_replace ("/(\n|\r)*/", '', nl2br($text));
}

function kill_html (&$text) {
	global $html_entities_match, $html_entities_replace;

	return preg_replace($html_entities_match, $html_entities_replace, $text);
}

function unkill_html (&$text) {
	global $unkill_html_match, $unkill_html_replace;

	return preg_replace($unkill_html_match, $unkill_html_replace, $text);
}

function html2plaintext (&$text) {
	return unkill_html(strip_tags(stripSlashes(my_br2nl(strip_url(strip_smileys($text))))));	
}

/**
 * If magic_quotes_gpc is in use, run stripslashes() on $var.
 *
 * @param  string $var  The string to un-quote, if necessary.
 * @return string       $var, minus any magic quotes.
 */
function strip_magic_quotes (&$var) {

	static $magic_quotes;

	if (!isset($magic_quotes)) {
		$magic_quotes = get_magic_quotes_gpc();
	}

	if ($magic_quotes) {
		if (is_array($var)) {
			array_walk($var, 'strip_magic_quotes');
		} else {
			return stripslashes($var);
		}
	}
	return $var;
}

/**
 * Get a form variable from GET or POST data, stripped of magic
 * quotes if necessary. If the variable is somehow set in both the
 * GET data and the POST data, the value from the POST data will
 * be returned and the GET value will be ignored.
 *
 * @param string $var       The name of the form variable to look for.
 * @param string $default   (optional) The value to return if the
 *                          variable is not there.
 *
 * @return string     The cleaned form variable, or $default.
 */
function getFormVar($var, $default = null) {
	return ($val = getPostVar($var)) !== null ? $val : getGetVar($var, $default);
}

/**
 * Get a form variable from GET data, stripped of magic quotes if
 * necessary. This function will NOT return a POST variable.
 *
 * @param string $var       The name of the form variable to look for.
 * @param string $default   (optional) The value to return if the
 *                          variable is not there.
 *
 * @return string     The cleaned form variable, or $default.
 *
 */
function getGetVar($var, $default = null) {
	return (array_key_exists($var, $_GET)) ? strip_magic_quotes($_GET[$var]) : $default;
}

/**
 * Get a form variable from POST data, stripped of magic quotes if
 * necessary. This function will NOT return a GET variable.
 *
 * @param string $var       The name of the form variable to look for.
 * @param string $default   (optional) The value to return if the
 *                          variable is not there.
 *
 * @return string     The cleaned form variable, or $default.
 */
function getPostVar($var, $default = null) {
	return (array_key_exists($var, $_POST))	? strip_magic_quotes($_POST[$var]) : $default;
}

function kill_quotes (&$text) {
	return kill_html(my_br2nl($text));
//	return my_br2nl(str_replace("'", '&#39;', htmlspecialchars($text)));
}


function quote_text (&$text) {
//	$match = array('/</', '/>/', '/"/');
//	$replace = array('&lt;', '&gt;', '&quot;');
//	$_text = preg_replace ("/^(.*)$/mi", "> \\1", strip_tags(my_br2nl($text)) );
//	return preg_replace($match, $replace, $_text);
	return preg_replace ("/^(.*)$/mi", "> \\1", my_br2nl($text) );

}

function emphasize (&$text) {
	$begin_em =  '<em>&gt;';
	$end_em =  '</em>';
	$_text = preg_replace ("#<br */*>(\r|\n)*#i", "\n", $text);
	return  preg_replace ("/^(&gt;|>)(.*)$/mi", "{$begin_em}\\2{$end_em}", $_text);
}

function format_text (&$text) {
	return my_nl2br(emphasize($text));
}

function strip_tag_attributes ($tag) {
	return preg_replace("' (on[a-zA-Z]+)=(.*?) 'si", '', stripslashes($tag));
}

// Function enhanced by Raptor <XpL_Raptor@gmx.net>
// use $bn_allowed_tags instead of bn_banned_tags
function strip_banned_tags (& $text) {
	global $bn_banned_tags, $bn_allowed_tags, $allowed_tags, $banned_tags;

	// preserve escaped tags
	$_text = str_replace ("\\<", "&lt;", $text);
	$_text = str_replace ("\\>", "&gt;", $_text);

	// strip XML tags
	$_text = preg_replace ('/<'.'\?xml:[^>]*>/i', '', $_text);

	// PHP code
	$_text = preg_replace ('/<\?(\s|php)(.*?)\?>/', '<pre>&lt;?php\\1?&gt;</pre>', $_text);

	// remove extra "<P> .... </P>" and empty paragraphs (<P ... />)
	$_text = preg_replace ("'<p>(.*?)</p>'i", "\n\\1", $_text);
	$_text = preg_replace ("'<p([^>]*)/>'i", "", $_text);

	// remove double tags (eg. <b></b>)
	$_text = preg_replace ("'<([a-z][a-z]*)> *</\\1>'i", " ", $_text);

	// preserve '<' that are not part of HTML tags
	$_text = preg_replace ("'<([^/?!a-z])'i", "&lt;\\1", $_text);

	// use the $bn_allowed_tags variable FIRST
	if (!empty ($bn_allowed_tags)) {
//		$_text=strip_smileys($_text);
		$bn_allowed_tags .= $allowed_tags;
		if (minimum_phpversion('3.0.13')) {
			$allowable_tags = preg_replace("/(\w+)/", "<\\1>", $bn_allowed_tags);
			$_text = strip_tags ($_text, $allowable_tags);
		} else {
			$tags = split("[ ]+", $bn_allowed_tags);
			$_text = preg_replace("'<([\/\!]*[^>]*)>'si", "<!-- @@\\1 -->", $_text);
			// rebuild allowed tags
			foreach ($tags as $k=>$tag) {
				$_text = preg_replace("'<!-- @@(/*".$tag."[^>]*)-->'si", "<\\1>", $_text);
			}
		}

	} else {

		// strip banned tags
		$bn_banned_tags .= $banned_tags; // sensitive tags always stripped
		$tags = split("[ ]+", $bn_banned_tags);
		foreach ($tags as $k=>$tag) {
			$_text = preg_replace("'<([\/\!]*?".$tag."[^<>]*?)>'si", "<!-- @@\\1-->", $_text);
		}
	}

	// kill javascript & vbscript
	$_text = preg_replace ("/(java|vb)script:/i", "noscriptallowed:", $_text);

	// strip out Javascript event handling + unwanted attributes in HTML tags
	$_text = preg_replace('/<([^>]+)>/ie', "'<'.strip_tag_attributes('\\1').'>'", $_text);
	return $_text;
}

function checkURL($line) {
	if ($line != "") {
		$line = eregi_replace("([http|news|ftp|https]+://[^)<>\"[:space:][:cntrl:]]+)",
			"<A  Href=\"\\1\" target=\"_blank\">\\1</A>", $line);
		$line = eregi_replace("(mailto:[^@\"]+@([a-zA-Z0-9\-]+\.)+[a-zA-Z0-9\-]{2,4})",
			"<A  Href=\"\\1\">\\1</A>", $line);
		$line = eregi_replace("([href|src] *= *.{0,1})<A  Href=[^>]+>([^<]+)</A>", "\\1\\2", $line);
	}
	return $line;
}

function strip_url ($line) {
	// remove only Href added in checkUrl()
	return ereg_replace ("<A  Href=[^>]+>([^<]+)</A>", "\\1", $line);
}

/**
 * Converts embedded smileys to graphics
 *
 * Added by Trevor - trevor@unixforever.net - http://programmingphp.com/
 * modified MD (08/2000, 11/2000)
 * + contribs from Raptor <XpL_Raptor@gmx.net> and Pascal Cortial <pascal@citroen-web.com>
 */
function add_smileys ($text, $smileys="") {
	global $icon_dir;

	if (!is_array($smileys)) {
		$smileys = array (
			":D" => "icon10",
			":[Oo°O]\)?" => "icon11",
			":[\-^]?\)+" => "icon7",
			";[\-^]?\)+" => "icon12",
			"X[\-\^]?\(+" => "icon8",
			":[\-\^]?\(+" => "icon9",
			":[\-\^]?p" => "icon39",
			":logo:" => "icon50",
			":wahoo:" => "icon42",
			":crazy:" => "icon41",
			":hello:" => "icon40",
			":sweat:" => "icon38",
			":spookie:" => "icon37",
			":benetton:" => "icon36",
			":jap:" => "icon35",
			":sleep:" => "icon34",
			":bic:" => "icon33",
			":sarcastic:" => "icon32",
			":gun:" => "icon31",
			":fou:" => "icon30",
			":love:" => "icon29",
			":lol:" => "icon28",
			":sol:" => "icon27",
			":hot:" => "icon26",
			":hap:" => "icon25",
			":eek:" => "icon24",
			":ouch:" => "icon23",
			":cry:" => "icon22",
			":what:" => "icon21",
			":bounce:" => "icon20",
			":roll:" => "roll",
			":kill:" => "kill"
		);
	}

	$text = " ".$text;			// add dummy space to allow first matching
	foreach($smileys as $smile=>$icon) {
		$text = preg_replace("/([\n\s\.\>])($smile)([^\w]?)/i", "\\1<img src=\"$icon_dir/$icon.gif\" alt=\"\\2\" border=0 align='absmiddle'>\\3", $text);
		
	}
	return substr($text, 1);	// remove extra space
}

function strip_smileys ($text) {
	global $icon_dir;

	$text = ereg_replace("<img src=\"$icon_dir/[[:alnum:]]+\.gif\" alt=\"", "", $text);
	$text = str_replace("\" border=0 align='absmiddle'>", "", $text);
	return $text;
}

function stars($nb) {
	global $icon_dir;

	$rk[1] = "<img src=\"$icon_dir/star_blue.gif\" width=\"13\" height=\"12\" align=\"absmiddle\">";
	$rk[2] = str_repeat("<img src='$icon_dir/star_cyan.gif' width=\"13\" height=\"12\" align=\"absmiddle\">", 2);
	$rk[3] = str_repeat("<img src='$icon_dir/star_bronze.gif' width=\"13\" height=\"12\" align=\"absmiddle\">", 3);
	$rk[4] = str_repeat("<img src='$icon_dir/star_gold.gif' width=\"13\" height=\"12\" align=\"absmiddle\">", 4);
	
	$threshold[0] = 0;
	$threshold[1] = 10;
	$threshold[2] = 20;
	$threshold[3] = 50;
	$threshold[4] = 100;
	
	$nb_threshold = 5;

	$nb_stars = 1;
    
	if (empty($nb)) {
	    return '';
	}elseif ($nb > $threshold[$nb_threshold - 1]) {
	    return stars($threshold[$nb_threshold - 1]);
	}

	$i = 1;
	while (($threshold[$i] < $nb) && ($i < $nb_threshold)) {
		$i++;
	}
	$in_rk = $i;
	
	$ret = '';	
	while ($nb > $threshold[$in_rk - 1]) {
	    $ret .= $rk[$in_rk];
		$nb = $nb - (($threshold[$in_rk] - $threshold[$in_rk - 1]) / $nb_stars);
	}
	return $ret;
} // end func

function get_remote_ip () {
	return (empty($GLOBALS['HTTP_X_FORWARDED_FOR'])) ? $GLOBALS["REMOTE_ADDR"] : '['. $GLOBALS['REMOTE_ADDR'] .'] '.$GLOBALS['HTTP_X_FORWARDED_FOR'];
}

// Added by Franky Liedekef <liedekef@pandora.be>
function is_banned_ip ($ip) {
	global $bn_banned_ips;

	if (!empty ($bn_banned_ips)) {
		$banned_ips = split(" ", $bn_banned_ips);
	}
	
	if (is_array($banned_ips)) {
		while ( list (,$badip) = each($banned_ips) ) {
			if (preg_match("/\b$badip\b/",$ip)) {
				return 1;
			}
		}
	}
	return 0;
}


#	------------------------------------------------------------------
#				Attachments handling
#	------------------------------------------------------------------
/**
 * Display a file size in a human readable format.
 *
 * @param	integer	$size	The size (in bytes to be converted)
 * @param	integer	$precision	The precision 
 * @access	public
 * @return	string	the formated size
 */
function pretty_size ($size, $precision=2) {

	$format = '%01.'.$precision.'f';
	settype ($size, "integer");
	$mb = 1024*1024;
	if ( $size >= $mb ) {
		return sprintf ($format, $size/$mb) . " Mb";
	} elseif ( $size >= 1024 ) {
		return sprintf ($format, $size/1024) . " Kb";
	} else {
		return $size . " bytes";
	}
}

/**
 * Loads (once) the mimetypes and attachments configuration according to settings
 *
 * The function checks that the file has already be loaded then loads the file according
 * to the w-agora rules (forum, site, main).
 * The $bn_dir and $bn_dir_default must be set prior to call this function
 * @access	public
 * @see		include/mimetypes.php
 * @return	void
 */

function load_mimetypes () {
	global $ext, $inc_dir, $bn_dir, $bn_dir_default;
	global $mimetypes, $mimetype_default, $mime_dspinl, $mime_dspfmt, $mime_renderers, $att_icons, $att_icon_default, $att_icon_multiple;

	if (defined ('ATT_DSP_LINK')) {
		return;
	}

	if (file_exists("$bn_dir/mimetypes.$ext") ) {
		include ("$bn_dir/mimetypes.$ext");
	} elseif (file_exists("$bn_dir_default/mimetypes.$ext") ) {
		include ("$bn_dir_default/mimetypes.$ext");
	} else {
		include ("$inc_dir/mimetypes.$ext");
	}

}

/**
 * Return display mode for specified attachment
 *
 * @param	att_type	MIME type of attachment
 * @param	att_inline	inline flag from database
 * @since	4.1
 * @access	public
 * @return	integer displaymode	The value set in $mime_dspfmt (see include/mimetypes.php)
 */
function getAttDisplayMode ($att_type, $att_inline="A") {
	global $mime_dspfmt, $mimetype_default, $ext;

	load_mimetypes();

	if ($att_inline) {
		if (isset($mime_dspfmt[$att_type])) {
		    $display_mode = $mime_dspfmt[$att_type];
		} else {
		    $display_mode = $mime_dspfmt[$mimetype_default];
		}   
	} else {
	    $display_mode = ATT_DSP_LINK;
	}

	return $display_mode;
}

/**
 * get icon associated to a given file type
 *
 * Detail description
 * @param	$filename	The file name
 * @since	1.0
 * @access	public
 * @see		include/mimetypes.php
 * @return	the URL of the icons associated with this extension
 */

function att_icon ($filename) {

	global $att_icons, $att_icon_default, $att_icon_multiple;

	load_mimetypes();

	$suffix = strtoLower(substr(strrchr( $filename, '.' ), 1 ));
	return (isset($att_icons[$suffix]) ) ? $att_icons[$suffix] : $att_icon_default;
} 

/**
 * Return an attachment in a format that can be embedded into an HTML page
 *	
 * @param	key			external key of the note to which this attachement belongs to
 * @param	att_id		id of the attachment in the attachment table
 * @param	att_path	Pathname of attachment
 * @param	att_type	MIME type of attachment
 * @param	att_size	file size of attachement
 * @param	att_inline	inline flag from database
 * @access  public
 * @see		include/mimetypes.php
 * @see		getAttDisplayMode
 * @return	string		The attachement
 */
function getAttachmentUrl ($key, $att_id, $att_path, $att_type, $att_size, $att_inline=0) {

	global $bn, $ext, $icon_dir, $img_dir, $bn_max_img_width;
	global $mimetype_default, $mime_dspfmt, $mime_renderers;

	load_mimetypes();

	$att_name = substr(strstr (basename($att_path), '.'), 1);
	if (!@is_file($att_path)) {
	    return "<strong>file not found: $att_name</strong>";
	}

	if ($att_inline) {
		if (isset($mime_dspfmt[$att_type])) {
		    $display_mode = $mime_dspfmt[$att_type];
		} else {
		    $display_mode = $mime_dspfmt[$mimetype_default];
		}   
	} else {
	    $display_mode = ATT_DSP_LINK;
	}
	
	if ($GLOBALS["use_path_info"]) {
		$att_url = "getfile.$ext/$bn/$att_id/$att_name";	
	} else {
		$att_url = "getfile.$ext?bn=$bn&att_id=$att_id";
	}
	$att_size = pretty_size($att_size);
	$att_icon = att_icon($att_name);

	if (!isset($mime_renderers[$display_mode]) ) {
		$display_mode = ATT_DSP_LINK;
	}

	switch ($display_mode) {
		case ATT_DSP_IMG: // display as an embedded image
			$size = @getImageSize ("$att_path");
			$maxwidth = empty($bn_max_img_width) ? 400 : $bn_max_img_width;
			if ($size[0]>$maxwidth) {
				$w = $size[0];
				$h = $size[1];
				$maxheight =  ceil($maxwidth*$h/$w);
				$title = urlencode($att_name);
				$url = "showimg.$ext?url=".urlencode($att_url)."&w=$w&h=$h&title=$title";
				$img_size = "style='Cursor:HAND;' onclick=\"javascript:window.open('$url', '', 'scrollbars=0,toolbar=0,resizable=1,menubar=0,directories=0,status=0,width=$w,height=$h')\" width=$maxwidth height=$maxheight";
			} else {
				$img_size = $size[3];
			}
			$text = str_replace('"','\"', $mime_renderers[ATT_DSP_IMG]);
			eval ("\$ret=stripSlashes(\"$text\");");
			break;
		case ATT_DSP_PLAINTEXT: // display as embedded text, PRE-formatted
			$att_contents = str_replace ("\\", "\\\\", htmlSpecialChars (join ('', file ($att_path))));
			$att_contents = word_wrap ($att_contents);
			$text = str_replace('"','\"', $mime_renderers[ATT_DSP_PLAINTEXT]);
			eval ("\$ret=\"$text\";");
			break;
		case ATT_DSP_HTML: // display as embedded HTML text
			$att_contents = strip_banned_tags (join ("", file ($att_path))); 
			$text = str_replace('"','\"', $mime_renderers[ATT_DSP_HTML]);
			eval ("\$ret=stripSlashes(\"$text\");");
			break;
		case ATT_DSP_PHP: // display as highlithed PHP code
			$php_code = wordwrap(join ('', file ($att_path)), 80);
			if (minimum_phpversion('4.2')) {
				$att_contents = highlight_string ($php_code, true);
			} else {
				ob_start();
				highlight_string ($php_code);
				$att_contents = ob_get_contents();
				ob_end_clean();
// Old version (prior to 4.0.2)
//				$att_contents = str_replace ("\\", "\\\\", htmlSpecialChars (join ('', file ($att_path))));
//				$att_contents = "<pre>".word_wrap ($att_contents)."</pre>";
			}
 			$text = str_replace('"','\"', $mime_renderers[ATT_DSP_PHP]);
			eval ("\$ret=stripSlashes(\"$text\");");
			break;
		case ATT_DSP_SWF: // Embedded Macromedia Shockwave Flash
 			$size = @getImageSize ("$att_path");
			$img_size = $size[3];
 			$text = str_replace('"','\"', $mime_renderers[ATT_DSP_SWF]);
			eval ("\$ret=stripSlashes(\"$text\");");
			break;
		default: // display as link 
 			$text = str_replace('"','\"', $mime_renderers[$display_mode]);
			eval ("\$ret=stripSlashes(\"$text\");");
			break;
	}
	return $ret;
}

/**
 * Returns an array of search terms
 *
 * @param	string	$pattern		The pattern to search
 *
 * @access  public
 * @return	array	the array of terms
 */
function split_search_terms ($pattern) {
	
	// strip all extra spaces
	$pattern = ereg_replace ("[[:space:]]+", " ", trim($pattern));

	// first pull out all the double quoted strings
	if ( strstr ($pattern, '"' ) ) {
		if (strstr ($pattern, '"')) {
			$search_string = $pattern;
			while (ereg('-*"[^"]*"', $search_string, $match)) {
				$terms[]= trim(str_replace('"', "", $match[0]));
				$search_string=substr(strstr($search_string, $match[0]), strlen($match[0]));
			}
		}
		$pattern = ereg_replace('-*"[^"]*"', '', $pattern );
	}

	// pull out the rest words in the string and merge 
	$regular_terms = explode (" ", $pattern);

	// merge them all together and return
	reset ($regular_terms);
	while (list (, $term) = each ($regular_terms)) {
		if ($term!='') {
			$terms[]=trim($term);
		}
	}
	return $terms;

} // end func


# HTML elements
# -------------

function caption ($text, $tag="") {
	$bt = empty($tag) ? "" : "<$tag>";
	$et = empty($tag) ? "" : "</$tag>";
	printf ("<caption>%s%s%s</caption>\n", $bt, $text, $et);
}

function br () {
	print "<br />\n";
}

function hr ($width="", $size=0) {
	printf ("<hr%s%s />\n", (empty($width)) ? "" : " width=\"$width\"", ($size==0) ? "" : " size=\"$size\"");
}

function comment ($text) {
	printf ("<!-- %s -->\n", $text);
}


# Form elements
# -------------

function beginForm ($action="", $method="post", $multipart=false) {
	global $site, $bn, $WA_SELF;

	$action = (empty ($action)) ? $WA_SELF : $action;
	$enctype = ($multipart==true) ? "enctype=\"multipart/form-data\"" : '';
	printf ("<form method=\"%s\" action=\"%s\" %s>\n", $method, $action, $enctype);
	if (!empty($site))	hiddenField ("site", $site);
	if (!empty($bn))	hiddenField ("bn", $bn);
}

function endForm() {
	echo "</form>";
}

function getListBox ($name, $items, $current="", $multiple=0, $onChange="") {
	$oc = empty ($onChange) ? "" : " onchange=\"$onChange\"";
	$p = sprintf ("<select name=\"%s%s\"%s%s class=\"wa_select\">\n", $name, ($multiple == 1)?"[]":"",
					($multiple == 1)?" multiple=\"multiple\"":"", $oc);
	if (is_array($items)) {
		if (!is_array($current)) {
			$current = ($multiple==1) ? explode(",", $current) : array($current);
		}
		foreach($items as $k=>$v) {
			if (in_array("$k", $current)) {
				$selected = 'selected="selected"';
				$opt_class = 'wa_selected_option';
			} else {
				$selected = '';
				$opt_class = 'wa_option';
			}
			$p .= " <option value=\"$k\" $selected class=\"$opt_class\">$v</option>\n";
		}
	}
    return $p . "</select>\n";
}

function getCheckBox ($name, $value=1, $current='', $text='', $id='') {
	if (empty($id)) {
		$id = $name.'_'.$value;
	}
	if(!empty ($text)) {
		$label = "<label for=\"$id\">$text</label>";
	}
	$checked = ($current==$value) ? " checked=\"checked\"" : "";
	return "<input type=\"checkbox\" name=\"$name\" value=\"$value\"$checked id=\"$id\" class=\"wa_checkbox\"/>$label";
}

/**
 * returns a list of checkboxes, featuring the same behaviour as a multiple listbox
 *
 * @param	string $name		the name of the button
 * @param	array $items		the label displayed
 * @param	mixed $checked_values	The list of default checked options:  separated comma list
 *									(val1,val2,...) or array: array('val1', 'val2')
 * @since	4.1.2
 * @access	public
 * @see		getListBox
 * @see		getCheckBox
 * @return	string	the list
 */
function getListCheckBox ($name, $items, $checked_values="") {
    $p="";
	if(empty($checked_values)) {
		$checked_values = array();
	} elseif(!is_array($checked_values)) {
		$checked_values = explode(",", $checked_values);
	}
	
    if (is_array($items)) {
		foreach($items as $k=>$v) {
            $checked = (in_array("$k", $checked_values) ) ? ' checked="checked"' : '';
			$id = $name.'_'.$k;
			$label = "<label for=\"$id\">$v</label>";
            $p .= "<div class=\"wa_listcheckbox\"><input type=\"checkbox\" name=\"".$name."[]\" value=\"$k\" id=\"$id\" class=\"wa_checkbox\"$checked>$label</div>";
       }
    }
    return $p ;
}

function getTextField ($name, $value="", $size=0, $maxlength=0) {
	return sprintf ("<input type=\"text\" name=\"%s\"%s%s%s class=\"wa_textfield\" />\n",
			$name,
			($value == "") ? "" : " value=\"$value\"",
			($size==0) ? "": " size=\"$size\"",
			($maxlength==0) ? "": " maxlength=\"$maxlength\""
			);
}

function getPasswordField ($name, $value="", $size=0, $maxlength=0) {
	return sprintf ("<input type=\"password\" name=\"%s\"%s%s%s class=\"wa_password\" />\n",
			$name,
			($value == "") ? "" : " value=\"$value\"",
			($size==0) ? "": " size=\"$size\"",
			($maxlength==0) ? "": " maxlength=\"$maxlength\""
			);
}

function getHiddenField($name, $value, $kill_quotes=true) {
	if ($kill_quotes) {
		$value = kill_quotes($value);
//		$value = str_replace("'", '&#39;', htmlspecialchars($value));
	}
    return "<input type=\"hidden\" name=\"$name\" value=\"$value\" />";
} 

function getTextArea ($name, $value="", $rows=2, $cols=40) {
	return sprintf ("<textarea name=\"%s\" rows=\"%s\" cols=\"%s\" class=\"wa_textarea\">%s</textarea>\n", $name, $rows, $cols, $value );
}

function getRadioButton ($name, $value=1, $current, $text="", $id='') {

	if (empty($id)) {
		$id = $name.'_'.$value;
	}
	if(!empty ($text)) {
		$label = "<label for=\"$id\">$text</label>";
	}
	$checked = ($current==$value) ? " checked=\"checked\"" : "";
	return ("<input type=\"radio\" name=\"$name\" class=\"wa_radio\" value=\"$value\"$checked id=\"$id\"/>$label\n");
}

/**
 * returns a "<input type='submit'>" element
 *
 * If the label to be displayed is an image (<img src= ...>) then the function will generate an <INPUT TYPE=IMAGE> instead of a submit button.
 *
 * @param	$name		the name of the button
 * @param	$value		the label displayed
 * @since	4.1.2
 * @access	public
 * @see		getButton
 * @return	string	the button
 */
function getSubmitButton ($name="", $value="Save", $onclick="") {

	$oc = (empty($onclick)) ? "" : "onclick=\"$onclick\"";
	
	if (eregi ('<img ', $value)) {
		return eregi_replace ('<img ', "<input type=\"image\" $oc class=\"wa_image\" name=\"$name\" ", $value);
	} else {
		return sprintf ("<input type=\"submit\" %s value=\"%s\" class=\"wa_submit\" $oc />\n", empty($name) ? "" : "name=\"$name\"", strip_tags($value) );
	}
}

/**
 * returns a "<input type='button'>" element
 *
 * The function uses javacripts in order to display the button, so the button will not be displayed, if
 * the browser doesn't support javascript. If the label to be displayed is an image (<img src= ...>) 
 * then the function will generate an <INPUT TYPE=IMAGE> instead of button.
 *
 * @param	$name		the name of the button
 * @param	$value		the label displayed
 * @param	$onclick	the javascript called whenever the button is pressed.
 * @since	4.1.2
 * @access	public
 * @see		backButton
 * @return	string	the button
 */
function getButton ($name="", $value, $onclick) {
	if (eregi ('<img ', $value)) {
		$html = eregi_replace ('<img (.*)>', "<input type=\"image\" class=\"wa_image\" name=\"$name\" onclick=\"$onclick\" \\1>", $value);
	} else {
		$onclick = str_replace ('"', "'", addSlashes($onclick));
		$html = "<script type=\"text/javascript\">\n". '  <!-- // Hide for old browsers' . "\n";
		$html .= sprintf ("  document.write ('<input type=\"button\" %s VALUE=\"%s\" onclick=\"$onclick\" class=\"wa_button\" />');", empty($name) ? "" : "name=\"$name\"", addslashes(strip_tags($value)) );
		$html .= '  // End of script -->' . "\n" . '</script>';
	}
	return $html;
}

function listBox ($name, $values, $selected="", $multiple=0, $onChange="") {
	print getListBox ($name, $values, $selected, $multiple, $onChange);
}

function checkBox ($name, $value=1, $current, $text="") {
	print getCheckBox ($name, $value, $current, $text);
}

function textField ($name, $value="", $size=0, $maxlength=0) {
	print getTextField ($name, $value, $size, $maxlength);
}

function passwordField ($name, $value="", $size=0, $maxlength=0) {
	print getPasswordField ($name, $value, $size, $maxlength);
}

function hiddenField ($name, $value, $kill_quotes=true) {
	print getHiddenField ($name, $value, $kill_quotes);
}

function textArea ($name, $value="", $rows=2, $cols=40) {
	print getTextArea($name, $value, $rows, $cols);
}

function radioButton ($name, $value=1, $current, $text="") {
	print getRadioButton ($name, $value, $current, $text);
}

function submitButton ($name="", $value="Save", $onclick="") {
	print getSubmitButton ($name, $value, $onclick);
}

function backButton ($name="", $value=" << ") {
	print getButton ($name, $value, 'history.back()');
}

function resetButton ($name="", $value="Reset") {
	printf ("<input type=\"reset\" %s value=\"%s\" class=\"wa_reset\" />\n", empty($name) ? "" : "name=\"$name\"", $value);
}

/**
 * Return a menu with items taken from the custom_menus table
 *
 * @param	string $namename of the field
 * @param	string $default		default (ie selected) value 
 * @param	$multiple	1 if the multiple selection allowed
 * @param	$onChange	Javascript fired on item change
 * @see	customMenu
 * @return	string	the menu field to be returned
 */
function getCustomMenu ($name, $default='', $multiple=0, $onChange='') {
	global $site, $db;
	return getListBox ($name, $db->getMenu($site, $name), $default, $multiple, $onChange);
}

/**
 * Print a menu with items taken from the custom_menus table
 *
 * Detail description
 * @param	string $namename of the field
 * @param	string $default		default (ie selected) value 
 * @param	$multiple	1 if the multiple selection allowed
 * @param	$onChange	Javascript fired on item change
 * @see	getCustomMenu
 * @return	string	the menu field to be displayed
 */
function customMenu ($name, $default='', $multiple=0, $onChange='') {
	global $site, $db;
	print getListBox ($name, $db->getMenu($site, $name), $default, $multiple, $onChange);
}


function wa_version ($short=false) {

	$v = "4.2.0";
	return ($short) ? $v : "w-agora version $v";
}

function minimum_phpversion( $vercheck ) {
	if (function_exists('version_compare')) {
		return (version_compare(PHP_VERSION, $vercheck) >=0) ? true : false;
	}

    $minver = explode(".", $vercheck);
    $curver = explode(".", phpversion());
    if (($curver[0] < $minver[0])
      || (($curver[0] == $minver[0]) && ($curver[1] < $minver[1]))
      || (($curver[0] == $minver[0]) && ($curver[1] == $minver[1]) && ($curver[2][0] < $minver[2][0])))
        return false;
    else
        return true;
}     

?>
