<?php 
// functions.php - Set up global functions
// ------------------------------------------------------------------------
// Copyright (c) 2001, 2002 The phpBugTracker Group
// ------------------------------------------------------------------------
// This file is part of phpBugTracker
// phpBugTracker is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
// phpBugTracker is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with phpBugTracker; if not, write to the Free Software Foundation,
// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
// ------------------------------------------------------------------------
include_once("func_html.inc.php");
include_once("func_db.inc.php");
@include_once("mailClient.php");

$select['priority'] = array(1 => '1 - Low',
	2 => '2',
	3 => '3 - Medium',
	4 => '4',
	5 => '5 - High'
	);


function get_parent_domains($c_id) // private function, use getParents() instead
{
	global $recursion_allowed,$ProjectTree;
	$parents=array();
	$recursion_allowed--;
	if (count($ProjectTree[$c_id]['parent_project_id']))
	{
		foreach ($ProjectTree[$c_id]['parent_project_id'] as $p_id=>$present)
		{
			if ($p_id==0)
			{
				continue; 
			}
			elseif ($recursion_allowed>0)
			{
				$parents[]=$p_id;
				$res=get_parent_domains($p_id);
				if (count($res))
				{
					foreach($res as $parent)
					{
						$parents[]=$parent;
					}
				}
			}
		}
	}
	return $parents;
}

function getParents($parent_id)
{
	global $recursion_allowed;
	$recursion_allowed=150;
	return get_parent_domains($parent_id);
}

function get_child_domains($pj_id) // private function, use getChildren() instead
{
	global $recursion_allowed,$ProjectTree;
	$children=array();
	$recursion_allowed--;
	if (count($ProjectTree[$pj_id]['children_project_id']))
	{
		foreach ($ProjectTree[$pj_id]['children_project_id'] as $c_id=>$present)
		{
			if ($c_id==0)
			{
				continue; 
			}
			elseif ($recursion_allowed>0)
			{
				$children[]=$c_id;
				$res=get_child_domains($c_id);
				if (count($res))
				{
					foreach($res as $child)
					{
						$children[]=$child;
					}
				}
			}
		}
	}
	return $children;
}

function getChildren($pj_id)
{
	global $recursion_allowed;
	$recursion_allowed=150;
	return get_child_domains($pj_id);
}
	


// ///////////////////////////////////////////////////////////////////////////////
// / Show text to the browser - escape hatch
function show_text($text, $iserror = false) {
	global $t;

	$t->assign(array('text' => $text,
			'iserror' => $iserror
			));
	$t->wrap('error.html');
} 
// ///////////////////////////////////////////////////////////////////////////////
// / Build a select box with the item matching $value selected
function build_dynamic_select($params) {
	global $db, $select, $perm, $STRING, $restricted_projects, $QUERY;

	extract($params);
	if (!isset($selected)) {
		$selected = '';
	} 

	$res = listbox($name, $values, 11, $multiple, $selected,  $option, $titles); 
	// println(htmlspecialchars($res));
	echo $res;
} // end of build_dynamic_select($params)
// ///////////////////////////////////////////////////////////////////////////////
// / Build a select box with the item matching $value selected
function build_select($params) {
	global $db, $select, $perm, $STRING, $restricted_projects, $QUERY,$u,$permValue;

	extract($params);
	if (!isset($selected)) {
		$selected = '';
	} 
	// create hash to map tablenames
	$cfgDatabase = array('group' => TBL_AUTH_GROUP,
		'project' => TBL_PROJECT,
		'component' => TBL_COMPONENT,
		'status' => TBL_STATUS,
		'resolution' => TBL_RESOLUTION,
		'severity' => TBL_SEVERITY,
		'version' => TBL_VERSION,
		'database' => TBL_DATABASE,
		'site' => TBL_SITE
		);

	$text = '';

	if (isset($cfgDatabase[$box])) {
		$querystart = "select {$box}_id, {$box}_name from $cfgDatabase[$box]";
		$querymid = ' where sort_order > 0 order by sort_order';
		$queries = array('group' => $querystart . ' where group_name <> \'User\' order by group_name',
			'severity' => $querystart . $querymid,
			'site' => $querystart . $querymid,
			'status' => "select sbv.sv_id as 'status_id', sbv.sv_value as 'status_name' from " . TBL_FIELD_CONF . " fc, " . TBL_SELECTBOX_VALUE . " sbv where fc.field_conf_id=sbv.field_conf_id and fc.field_name='status_id' and sbv.sv_order>0 order by sbv.sv_order",
			'resolution' => $querystart . $querymid,
			'project' => $perm->have_perm('Admin')
			? $querystart . " where " .
			($selected ? "(active > 0 or project_id in ($selected))" : 'active > 0') . " order by {$box}_name"
			: $querystart . " where project_id not in ($restricted_projects)" . " and " .
			($selected ? " (active > 0 or project_id in ($selected))" : 'active > 0') . " order by {$box}_name",
			'component' => $querystart . " where project_id = $project and active = 1 order by {$box}_name",
			'version' => $querystart . " where project_id = $project and active = 1 order by {$box}_id desc",
			'database' => $querystart . $querymid
			);
	} 

	switch ($box) {
		case 'user_filter':
			foreach ($STRING['user_filter'] as $k => $v) {
				$text .= sprintf("<option value=\"%d\"%s>%s</option>",
					$k, ($k == $selected ? ' selected' : ''), $v);
			} 
			break;
		case 'group':
			if ($project) { // If we are building for project admin page
				if (!count($selected) or (count($selected) && in_array(0, $selected))) {
					$sel = ' selected';
				} else {
					$sel = '';
				} 
				$text = "<option value=\"all\"$sel>All Groups</option>";
			} 
			$rs = $db->query($queries[$box]);
			while ($rs->fetchInto($row)) {
				if (count($selected) && in_array($row[$box . '_id'], $selected)) {
					$sel = ' selected';
				} else {
					$sel = '';
				} 
				$text .= '<option value="' . $row[$box . '_id'] . "\"$sel>" . $row[$box . '_name'] . '</option>';
			} 
			break;
		case 'user_invite':
			if (!isset($permname))
			{
				$permname='Invite';
			}
		case 'user_request':
			if (!isset($permname))
			{
				$permname='Request';
			}
		case 'user_view':
			if (!isset($permname))
			{
				$permname='View';
			}
		case 'user_edit':
			if (!isset($permname))
			{
				$permname='Editbug';
			}
		case 'manager':
			if (!isset($permname))
			{
				$permname='Admin';
			}
			$rs = $db->query($sql="SELECT DISTINCT u.user_id, u.login FROM " . TBL_AUTH_USER . " u, " . TBL_PROJECT_PERM . " pp , " . TBL_AUTH_PERM . " ap
			WHERE u.active > 0 AND (u.user_id = pp.user_id AND pp.project_id=$project_id AND pp.perm_id=ap.perm_id AND ap.perm_name='$permname') 
			ORDER BY login");
//fast and complete
//			$rs = $db->query($sql="SELECT DISTINCT user_id, login FROM ((SELECT DISTINCT u.user_id, u.login FROM " . TBL_AUTH_USER . " u, " . TBL_PROJECT_PERM . " pp , " . TBL_AUTH_PERM . " ap
//			WHERE u.active > 0 AND (       (u.user_id = pp.user_id AND pp.project_id=$project_id AND pp.perm_id=ap.perm_id AND ap.perm_name='$permname')  ) ) UNION  (SELECT DISTINCT u.user_id, u.login FROM " . TBL_AUTH_USER . " u, " . TBL_USER_GROUP . " ug, " . TBL_PROJECT_GROUP . " pg , " . TBL_AUTH_PERM . " ap
//			WHERE u.active > 0 AND (       (u.user_id = ug.user_id AND ug.group_id = pg.group_id AND pg.project_id=$project_id AND pg.perm_id=ap.perm_id AND ap.perm_name='$permname') ) ) )as mysel
//			ORDER BY login");
//simple but very slow
//			$rs = $db->query($sql="SELECT DISTINCT u.user_id, u.login FROM " . TBL_AUTH_USER . " u, " . TBL_USER_GROUP . " ug, " . TBL_PROJECT_GROUP . " pg , " . TBL_PROJECT_PERM . " pp , " . TBL_AUTH_PERM . " ap
//			WHERE u.active > 0 AND (       (u.user_id = ug.user_id AND ug.group_id = pg.group_id AND pg.project_id=$project_id AND pg.perm_id=ap.perm_id AND ap.perm_name='$permname')
//								  OR (u.user_id = pp.user_id AND pp.project_id=$project_id AND pp.perm_id=ap.perm_id AND ap.perm_name='$permname')  )
//			ORDER BY u.login");


//			println("la derniere query vaut ". $db->last_query);die;
//			printarray($db->getAll($sql));
			while ($rs->fetchInto($row)) {
				if (count($selected) && in_array($row['user_id'], $selected)) {
					$sel = ' selected';
				} else {
					$sel = '';
				}
				$listed_user_id[]=$row['user_id'];
				$text .= "<option value=\"{$row['user_id']}\"$sel>{$row['login']}</option>";
			}
			break;
/*		case 'user_request':
			$rs = $db->query("SELECT first_name, last_name, user_id, access_project  FROM " . TBL_AUTH_USER . " ORDER BY first_name");
			while ($rs->fetchInto($row)) 
			{	
				if (isset($row['access_project']) && $row['access_project']!='')
				{
					$requested_project=unserialize($row['access_project']);
				}
				else
				{
					$requested_project=array();
				}
				if (count($requested_project) && in_array($project_id, $requested_project))
				{
					if (count($selected) && in_array($row['user_id'], $selected)) 
					{
						$sel = ' selected';
					} 
					else 
					{
						$sel = '';
					} 
					$text .= "<option value=\"{$row['user_id']}\"$sel>{$row['first_name']} {$row['last_name']}</option>";
				}
			} 
			break;*/
		case 'database': $text = '<option value="0">None</option>';
		case 'severity':
		case 'status':
			$rs = $db->query($queries[$box]);
			if ($flg_wkfw)
			{
				$res = $db->getCol($do_query="SELECT `sv_description` FROM " . TBL_SELECTBOX_VALUE . " WHERE `sv_id` = " . $selected);
				if(DB::isError($res))
				{
					echo ("<br>Error : " . $res->getMessage() . "<br>");
					print($do_query . "<br>");
					die();
				}
				$res=unserialize($res);
			}
			while ($rs->fetchInto($row)) 
			{
				if (!$flg_wkfw || ($flg_wkfw && !in_array($row[$box . '_id'],$res)) )
				{
					if (count($selected) && in_array($row[$box . '_id'], $selected)) 
					{
						$sel = ' selected';
					} 
					else 
					{
						$sel = '';
					} 
					$text .= "<option value=\"{$row['status_id']}\"$sel>{$row['status_name']}</option>";
				}
			} 
			break;

		case 'version':
			$rs = $db->query($queries[$box]);
			while ($rs->fetchInto($row)) {
				if ($selected == $row[$box . '_id'] and $selected != '') {
					$sel = ' selected';
				} else {
					$sel = '';
				} 
				$text .= '<option value="' . $row[$box . '_id'] . "\"$sel>" . $row[$box . '_name'] . '</option>';
			} 
			break;
		case 'invite_domain':
				$sql="(SELECT  DISTINCT p.project_name, p.project_id FROM " . TBL_PROJECT . " p, " . TBL_AUTH_USER . " au, " . TBL_PROJECT_PERM . " pp 
					WHERE (p.project_id=pp.project_id AND pp.user_id=$u AND pp.perm_id<={$permValue['Invite']} ) ) UNION 
					( SELECT DISTINCT p.project_name, p.project_id FROM " . TBL_PROJECT . " p, " . TBL_AUTH_PERM . " ap, " . TBL_USER_GROUP . " ug, " . TBL_PROJECT_GROUP . " pg 
					WHERE ( p.project_id=pg.project_id AND pg.group_id= ug.group_id AND ug.user_id=$u  AND pg.perm_id<={$permValue['Invite']} ))
					ORDER BY project_name "; 
			$rs = $db->query($sql);
			while ($rs->fetchInto($row)) {
				if (count($selected) && in_array($row['project_id'], $selected)) {
					$sel = ' selected';
				} else {
					$sel = '';
				} 
				$text .= "<option value=\"{$row['project_id']}\"$sel>{$row['project_name']}</option>";
			} 
			break;
		case 'project':
			$rs = $db->query("SELECT project_id, project_name FROM " . TBL_PROJECT . " WHERE project_id <> 1  ORDER BY project_name");
			while ($rs->fetchInto($row)) {
				if (count($selected) && in_array($row['project_id'], $selected)) {
					$sel = ' selected';
				} else {
					$sel = '';
				} 
				$text .= "<option value=\"{$row['project_id']}\"$sel>{$row['project_name']}</option>";
			} 
			break;
		case 'os':
			$rs = $db->query("select {$box}_id, {$box}_name, regex from " . TBL_OS . " where sort_order > 0 order by sort_order");
			while ($rs->fetchInto($row)) {
				if ($selected == '' and isset($row['Regex']) and
						preg_match($row['Regex'], $GLOBALS['HTTP_USER_AGENT'])) {
					$sel = ' selected';
				} elseif ($selected == $row[$box . '_id']) {
					$sel = ' selected';
				} else {
					$sel = '';
				} 
				$text .= '<option value="' . $row[$box . '_id'] . "\"$sel>" . $row[$box . '_name'] . "</option>";
			} 
			break;
		case 'owner':
			$rs = $db->query("select u.user_id, login from " . TBL_AUTH_USER . " u, " . TBL_USER_GROUP . " ug, " . TBL_AUTH_GROUP . " g where u.active > 0 and u.user_id = ug.user_id and ug.group_id = g.group_id and group_name = 'Developer' order by login");
			while ($rs->fetchInto($row)) {
				if ($selected == $row['user_id']) {
					$sel = ' selected';
				} else {
					$sel = '';
				} 
				$text .= "<option value=\"{$row['user_id']}\"$sel>{$row['login']}</option>";
			} 
			break;
		case 'bug_cc':
			$rs = $db->query(sprintf($QUERY['functions-bug-cc'], $selected));
			while (list($uid, $user) = $rs->fetchRow(DB_FETCHMODE_ORDERED)) {
				$text .= "<option value=\"$uid\">" . maskemail($user) . '</option>';
			} 
			// Pad the sucker
			$text .= '<option value="" disabled>';
			for ($i = 0; $i < 30; $i++) {
				$text .= '&nbsp;';
			} 
			$text .= '</option>';
			break;
		case 'LANGUAGE' :
			$dir = opendir('languages');
			while (false !== ($file = readdir($dir))) {
				if ($file != '.' && $file != '..' && $file != 'CVS' && substr($file, -3) == 'php') {
					$filelist[] = str_replace('.php', '', $file);
				} 
			} 
			closedir($dir);
			sort($filelist);
			foreach ($filelist as $file) {
				if ($file == $selected) {
					$sel = ' selected';
				} else {
					$sel = '';
				} 
				$text .= "<option value=\"$file\"$sel>$file</option>";
			} 
			break;
		case 'THEME' :
			$dir = opendir('templates');
			while (false !== ($file = readdir($dir))) {
				if ($file != '.' && $file != '..' && $file != 'CVS') {
					$filelist[] = str_replace('.php', '', $file);
				} 
			} 
			closedir($dir);
			sort($filelist);
			foreach ($filelist as $file) {
				if ($file == $selected) {
					$sel = ' selected';
				} else {
					$sel = '';
				} 
				$text .= "<option value=\"$file\"$sel>$file</option>";
			} 
			break;
		case 'STYLE' :
			$dir = opendir('styles');
			while (false !== ($file = readdir($dir))) {
				if ($file != '.' && $file != '..' && $file != 'CVS') {
					$filelist[] = str_replace('.css', '', $file);
				} 
			} 
			closedir($dir);
			sort($filelist);
			foreach ($filelist as $file) {
				if ($file == $selected) {
					$sel = ' selected';
				} else {
					$sel = '';
				} 
				$text .= "<option value=\"$file\"$sel>$file</option>";
			} 
			break;
		/*
		case 'BUG_UNCONFIRMED' :
		case 'BUG_PROMOTED' :
		case 'BUG_ASSIGNED' :
		case 'BUG_REOPENED' :
		case 'BUG_CLOSED' :
			static $bug_status_list = array();

			if (empty($bug_status_list)) {
				$bug_status_list = $db->getAssoc("select status_id, status_name" . " from " . TBL_STATUS . " order by status_name");
			} 
			foreach ($bug_status_list as $id => $name) {
				$sel = $id == $selected ? ' selected' : '';
				$text .= "<option value=\"$id\"$sel>$name</option>";
			} 
			break;
		*/
		default :
			$deadarray = $select[$box];
			while (list($val, $item) = each($deadarray)) {
				if ($selected == $val and $selected != '') {
					$sel = ' selected';
				} else {
					$sel = '';
				} 
				$text .= "<option value=\"$val\"$sel>$item</option>";
			} 
			break;
	} 
	echo ($text);
} // end of build_select($params)
// /
// / Divide the results of a database query into multiple pages
function multipages($nr, $page, $urlstr) {
	global $me, $selrange, $t;

	$pages = '';
	if (!$page) $page = 1;
	if ($page == 'all') {
		$selrange = $nr;
		$llimit = 0;
		$page = 0;
	} else {
		// $selrange = 60;
		$llimit = ($page-1) * $selrange;
	} 
	if ($nr) $npages = ceil($nr / $selrange);
	else $npages = 0;
	if ($npages == 1) $pages = 1;
	else {
		for ($i = 1; $i <= $npages; $i++) {
			$pages .= $i != $page ? " <a href='$me?page=$i&$urlstr'>$i</a> " : " $i ";
			$pages .= $i != $npages ? '|' : '';
		} 
	} 
	$t->assign(array('pages' => $pages,
			'first' => $llimit + 1,
			'last' => $llimit + $selrange > $nr ? $nr : $llimit + $selrange,
			'total' => $nr
			));

	return array($selrange, $llimit);
} 
// /
// / Sets variables in the templates for the column headers to sort database results
function sorting_headers($url, $headers, $order, $sort, $urlstr = '') {
	global $t;

	while (list($k, $v) = each($headers)) {
		$theader[$k]['url'] = "$url?order=$v&sort=" .
		($order == $v ? ($sort == 'asc' ? 'desc' : 'asc') : 'asc') .
		($urlstr ? '&' . $urlstr : '');
		$theader[$k]['color'] = $order == $v ? '#bbbbbb' : '#eeeeee';
		$theader[$k]['class'] = $order == $v ? 'selected' : ''; 
		// DEBUG
		// $theader[$k]['name'] = $k;
	} 
	// DEBUG
	// printarray($theader);
	$t->assign('headers', $theader);
} 
// /
// / Generates a somewhat random pronounceable password $length letters long
// / (From zend.com user Rival7)
function genpassword($length) {
	srand((double)microtime() * 1000000);

	$vowels = array("a", "e", "i", "o", "u");
	$cons = array("b", "c", "d", "g", "h", "j", "k", "l", "m", "n", "p", "r", "s", "t", "u", "v", "w", "tr", "cr", "br", "fr", "th", "dr", "ch", "ph", "wr", "st", "sp", "sw", "pr", "sl", "cl");
	$password = '';

	$num_vowels = count($vowels);
	$num_cons = count($cons);

	for($i = 0; $i < $length; $i++) {
		$password .= $cons[rand(0, $num_cons - 1)] . $vowels[rand(0, $num_vowels - 1)];
	} 

	return substr($password, 0, $length);
} 
// /
// / Wrap text - Picked up somewhere on the net - probably zend.com
function textwrap($text, $wrap = 72, $break = "\n") {
	$len = strlen($text);
	if ($len > $wrap) {
		$h = '';
		$lastWhite = 0;
		$lastChar = 0;
		$lastBreak = 0;
		while ($lastChar < $len) {
			$char = substr($text, $lastChar, 1);
			if (($lastChar - $lastBreak > $wrap) && ($lastWhite > $lastBreak)) {
				$h .= substr($text, $lastBreak, ($lastWhite - $lastBreak)) . $break;
				$lastChar = $lastWhite + 1;
				$lastBreak = $lastChar;
			} 
			/* You may wish to include other characters as  valid whitespace... */
			if ($char == ' ' || $char == chr(13) || $char == chr(10))
				$lastWhite = $lastChar;
			$lastChar = $lastChar + 1;
		} 
		$h .= substr($text, $lastBreak);
	} else $h = $text;
	return $h;
} 
// /
// / Return a delimited list if there is more than one element in $ary, otherwise
// / return the lone element as the list
function delimit_list($delimiter, $ary) {
	if (isset($ary[1])) return join($delimiter, $ary);
	elseif (isset($ary[0])) return ($ary[0]);
	else return '';
} 
// /
// / Check the validity of an email address
// / (From zend.com user russIndr)
function bt_valid_email($email) {
	return eregi('^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,6})$', $email);
} 
// /
// / If the constant is set do a little email masking to make harvesting a little harder
function maskemail($email) {
	global $_sv;
	if (HIDE_EMAIL && empty($_sv['uid'])) {
		return '******';
	} elseif (MASK_EMAIL) {
		/* FM255 denis.guinnepain@airliquide.com 26/02/2004 */
		return ereg_replace("@[a-zA-Z0-9-]+(\.[a-zA-Z0-9-]+)*(\.[a-zA-Z]{2,6})", "", $email); 
		// return str_replace('@', ' at ', str_replace('.', ' dot ', $email));
	} else {
		return $email;
	} 
} 
// /
// / Build the javascript for the dynamic project -> component -> version select boxes
function build_project_js($params) {
	global $db, $u, $perm, $_sv, $QUERY; 
	// TODO : update this function if needed
	death('ERROR', 'build_project_js() is no more compatible with Memento Plus');

	extract($params);
	$js = '';
	$js2 = ''; 
	// Build the javascript-powered select boxes
	if ($perm->have_perm('Admin')) {
		$rs = $db->query("select project_id, project_name from " . TBL_PROJECT . " where active = 1 order by project_name");
	} else {
		$rs = $db->query(sprintf($QUERY['functions-project-js'],
				delimit_list(',', $_sv['group_ids'])));
	} while (list($pid, $pname) = $rs->fetchRow(DB_FETCHMODE_ORDERED)) {
		$pname = addslashes($pname); 
		// Version arrays
		$js .= "versions['$pname'] = new Array(" .
		((!isset($no_all) or !$no_all) ? "new Array('','All')," : '');
		$js2 = "closedversions['$pname'] = new Array(" .
		((!isset($no_all) or !$no_all) ? "new Array('','All'),"
			: "new Array(0, 'Choose One'),");
		$rs2 = $db->query("select version_name, version_id from " . TBL_VERSION . " where project_id = $pid and active = 1");
		while (list($version, $vid) = $rs2->fetchRow(DB_FETCHMODE_ORDERED)) {
			$version = addslashes($version);
			$js .= "new Array($vid,'$version'),";
			$js2 .= "new Array($vid,'$version'),";
		} 
		if (substr($js, -1) == ',') $js = substr($js, 0, -1);
		$js .= ");\n";
		if (substr($js2, -1) == ',') $js2 = substr($js2, 0, -1);
		$js2 .= ");\n";
		$js .= $js2; 
		// Component array
		$js .= "components['$pname'] = new Array(";
		$js .= (!isset($no_all) || !$no_all) ? "new Array('','All')," : '';
		$rs2 = $db->query("select component_name, component_id from " . TBL_COMPONENT . " where project_id = $pid and active = 1");
		while (list($comp, $cid) = $rs2->fetchRow(DB_FETCHMODE_ORDERED)) {
			$comp = addslashes($comp);
			$js .= "new Array($cid,'$comp'),";
		} 
		if (substr($js, -1) == ',') $js = substr($js, 0, -1);
		$js .= ");\n";
	} 
	echo $js;
} 
// /
// / Database concat
function db_concat() {
	$pieces = func_get_args();

	switch (DB_TYPE) {
		case 'mysql' : $retstr = 'concat(' . delimit_list(', ', $pieces) . ')';
			break;
		case 'pgsql' :
		case 'oci8' :
		case 'sybase' :
		case 'ibase' : $retstr = delimit_list(' || ', $pieces);
			break;
		case 'fbsql' : $retstr = 'CONCAT(' . delimit_list(', ', $pieces) . ')';
			break;
		default : $retstr = delimit_list(' + ', $pieces);
			break;
	} 
	return $retstr;
} 
// Dump a var
function dump($var, $title = '') {
	if ($title) {
		echo "<b>$title</b><br>";
	} 
	echo '<pre>';
	print_r($var);
	echo '</pre>';
} 
// Handle a database error
function handle_db_error(&$obj) {
	die($obj->message . '<br>' . $obj->userinfo);
} 
// Date() wrapper for smarty
function bt_date($string, $format) {
	return date($format, $string);
} 

/* quoted-printable encoder function
    This encoding has all non-ascii (say >127, <32 and =61 chracters)
    encoded as "=" and it's hexadecimal value. Special case is space
    (32 decimal) at the end of line, which is converted to =20, other-
    wise it's not converted and it's returned as space (32 decimal). */

function qp_enc($input, $line_max = 76) {
	// Initialize variables
	$hex = array('0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F');
	$eol = "\n";
	$escape = "=";
	$output = ""; 
	// Do "dos2unix" and split $input into $lines by end of line
	$lines = split("\n", str_replace("\r\n", "\n", $input)); 
	// Loop throught $lines
	while (list(, $line) = each($lines)) {
		// Trim each line from right side
		$line = rtrim($line); 
		// Place line length to $linlen
		$linlen = strlen($line); 
		// Initialize $newline
		$newline = ""; 
		// Loop throught each line and process each character of the line
		for($i = 0; $i < $linlen; $i++) {
			// Place each character of $line to $c
			$c = substr($line, $i, 1); 
			// Place decimal value of $c to $dec
			$dec = ord($c); 
			// If $c equals to space (" ") and we are at the end of line place
			// space (" ") to $c
			if (($dec == 32) && ($i == ($linlen - 1))) {
				$c = "=20";
			} elseif (($dec == 61) || ($dec < 32) || ($dec > 126)) {
				// Or if $c is not printable character in ascii, convert the
				// character to it's quoted-printable value
				$h2 = floor($dec / 16);
				$h1 = floor($dec % 16);
				$c = $escape . $hex["$h2"] . $hex["$h1"];
			} 
			// If we are at the maximum line length, add whole line (converted)
			// with end of line character to $output
			if ((strlen($newline) + strlen($c)) >= $line_max) {
				$output .= $newline . $escape . $eol; 
				// And initialize $newline as empty
				$newline = "";
			} 
			// Add converted (or ascii) character to $newline
			$newline .= $c;
		} 
		// Add $newline with end of line character to output
		$output .= $newline . $eol;
	} 
	// Return trimmed output
	return (trim($output));
} 
// mailer with use of quoted-printable encoding (if configured so)
function qp_mail($to, $subject = 'No subject', $body, $headers = '') {
	global $STRING,$mail_WS;
	if ($headers != '') {
		$headers .= "\n"; 
		// There have to be no newline at the end of $headers
	} 
	$headers .= "Content-Type: text/plain; charset=" . $STRING['lang_charset'] . "\nContent-Transfer-Encoding: "; 
	// If configured to send MIME encoded emails
	if (SEND_MIME_EMAIL) {
		if ($mail_WS=="present")
		{
			$retval = mail_WS($to, $subject, qp_enc($body), $headers . "quoted-printable\nMIME-Version: 1.0");
		}
		else
		{
			$retval = mail($to, $subject, qp_enc($body), $headers . "quoted-printable\nMIME-Version: 1.0");
		}
	} else {
		if ($mail_WS=="present")
		{
			$retval = mail_WS($to, $subject, $body, $headers . "8bit");
		}
		else
		{
			$retval = mail($to, $subject, $body, $headers . "8bit");
		}
	} 
	// Returns true if mail is accepted for delivery, otherwise return false
	return ($retval);
} // end of qp_mail($to, $subject = 'No subject', $body, $headers = '')
// function which converts html coded chars into their original form
// ex : &amp; -> &
//function htmlspecialchars_decode($encoded) {
//	$trans = get_html_translation_table(HTML_SPECIALCHARS);
//	$trans = array_flip($trans);
//	return strtr($encoded, $trans);
//} 
// FM1248 david.han-sze-chuen@airliquide.com 22/07/2004 : the code is from bug.php in update_bug()
// function which filter protocol header in an url
function url_protocol_filter($url) {
	if (($url == 'http://') || ($url == 'https://') || ($url == 'ftp://')) {
		return '';
	} else {
		// if url doesn't start with one of these protocol header
		if (($url) && (strtolower(substr($url, 0, 7)) != 'http://') &&
				(strtolower(substr($v, 0, 8)) != 'https://') &&
				(strtolower(substr($v, 0, 6)) != 'ftp://')) {
			// default protocol is http://
			return 'http://' . $url;
		} 
	} 
	return $url;
} // end of url_protocol_filter($url)
// FM1248 david.han-sze-chuen@airliquide.com 21/07/2004 : used in templates
// function which returns an raw encoded url from an url which already has a header
function url_with_header_encode($url) {
	$l = strpos($url, "://");

	if ($l < 0)
		return $url;

	$header = substr($url, 0, $l);

	switch ($header) {
		case "ftp" :
		case "https" :
		case "http" :
			$parts = explode('/', substr($url, $l + 3));
			foreach($parts as $k => $v) {
				$parts[$k] = rawurldecode($v);
			} 
			return "{$header}://" . implode('/', $parts);
			break;
		default :
			return rawurldecode($url);
	} 
} // end of url_with_header_encode($url)
// function which returns the path from a file url
// ex: http://myserver10/MementoTest/MyMemento/test.php
// -> http://myserver10/MementoTest/MyMemento/
function getpath_from_url($url) {
	if (preg_match("/^(http:\/\/)?([^\/]+\/)+/i", $url, $matches))
		return $matches[0];
	else return false;
} 

/**
 * array_intersect_key()
 * Personal implementation of array_intersect_key().
 * Return an array of the array1 elements whose index value is in array2 index values
 * I did it because it doesn't exist in my version of PHP
 * If a parameter isn't an array : return null
 * 
 * @param  $array1 first array
 * @param  $array2 second array
 * @return mixed array of key intersection or null
 */
function _array_intersect_key($array1, $array2) {
	if (!is_array($array1) || !is_array($array2)) {
		return null;
	} 
	$keys1 = array_keys($array1);
	$keys2 = array_keys($array2);

	$keys3 = array_intersect($keys1, $keys2);

	$return = array();
	foreach($keys3 as $k => $v) {
		$return[$v] = $array1[$v];
	} 
	return $return;
} // end of _array_intersect_key($array1, $array2)      
// //////////////////////////////////////////////////////////////////////////////
/**
 * _array_diff_key()
 * Personal implementation of array_diff_key().
 * Return an array of the array1 elements whose index value is not in array2 index values
 * I did it because it doesn't exist in my version of PHP
 * If a parameter isn't an array : return null
 * 
 * @param  $array1 first array
 * @param  $array2 second array
 * @return mixed array or null
 */
function _array_diff_key($array1, $array2) {
	if (!is_array($array1) || !is_array($array2)) {
		return null;
	} 
	return _array_intersect_key($array1, array_flip(array_diff(array_keys($array1), array_keys($array2))));
} // end of _array_diff_key($array1, $array2)
// //////////////////////////////////////////////////////////////////////////////
/**
 * Convert an associative array into an url get vars format
 * ex: a['varA'] = 1;
 * a['varB'] = 'hi all !';
 * -> varA=1&varB=hi%20all%20!
 */
function array_to_getvars($a) {
	$s = array();
	foreach($a as $k => $v) {
		$s[] = rawurlencode($k) . '=' . rawurlencode($v);
	} 
	return implode('&', $s);
} // end of array_to_getvars($a)      
// //////////////////////////////////////////////////////////////////////////////
/**
 * Function to order selectbox rows by 'order'
 * Example :
 * $ordered_sb = $sb_array;
 * usort($ordered_sb, 'sb_order');
 */
/*
function sb_order($a, $b) {
	if ($a['order'] == $b['order']) return 0;
	return ($a['order'] > $b['order'])? 1 : -1;
} // end of sb_order($a, $b)
*/
// //////////////////////////////////////////////////////////////////////////////
/**
 * Function to order an array by an element value
 * Example :
 * $ordered = $array;
 * usort($ordered, 'order_by_element_of_array_function');
 */
$_order_by_element_of_array_element_name = '';
$_order_by_element_of_array_element_order = '';
function order_by_element_of_array_function($a, $b) {
	global $_order_by_element_of_array_element_name;
	global $_order_by_element_of_array_element_order;

	$order = &$_order_by_element_of_array_element_order;
	$n = &$_order_by_element_of_array_element_name; 
	// for nested arrays
	if (is_array($n)) {
		foreach($n as $v) { // for one level of name
			if (!is_array($a) || !is_array($b)) {
				death('ERROR', 'order_by_element_of_array_function() : one element is no more an array.');
			} 
			$a = $a[$v]; // get the value of a 
			$b = $b[$v]; // get the value of a 
		} 
	} else {
		if (!isset($a[$n]) || !isset($b[$n])) {
			death('ERROR', "order_by_element_of_array_function() : one element doesn't have a valid element.");
		} 
		$a = $a[$n];
		$b = $b[$n];
	} 
	// DEBUG
	// println("test : a = $a");
	// println("test : b = $b");
	if ($a == $b) {
		return 0;
	} else {
		return ($a > $b)? $order : $order * -1;
	} 
} // end of order_by_element_of_array($a, $b)      
// //////////////////////////////////////////////////////////////////////////////
/**
 * Function to sort an array by element.
 * $order = 'asc' or 'desc'
 * 
 * @param mixed $element_name : string : the element name, array('a', 'b', 'c') : the nested elements names to access to element $src_array['a']['b']['c']
 * @return array 
 */
function order_by_element_of_array($element_name, $order, $src_array) {
	global $_order_by_element_of_array_element_name;
	global $_order_by_element_of_array_element_order; 
	// what is the element to compare ?
	$_order_by_element_of_array_element_name = $element_name; 
	// what is the order ?
	switch ($order) {
		default :
		case 'asc' :
			$order = 1;
			break;
		case 'desc' :
			$order = -1;
			break;
	} 

	$_order_by_element_of_array_element_order = $order;

	$new_array = $src_array;
	usort($new_array, 'order_by_element_of_array_function');
	return $new_array;
} // end of order_by_element_of_array($element_name, $order, $src_array)       
// //////////////////////////////////////////////////////////////////////////////
/**
 * build_dynamic_input()
 * Build and print an input field in HTML to use in a form
 * Can adapt to any field type
 * Expected parameters are put into an associative array :
 * $params = array(
 * 	'name' : string = name of the field input box
 *   'value' : mixed = current value of the field
 * 	'mpfile' : object = instance of MPFile
 * 	'field_conf' : array = property of the current field   \
 * 	'field_conf_id' : integer                                            |-> one of those three parameters is mandatory
 * 	'field_name' : string                                                  /
 *   'file_id' : integer = file_id of the file carrying this value.
 * 	'input_option' : string = HTML option data for input box
 * 	'read_only' : bool = define the field as read only if true
 * 	'override_system' : bool = allow the function parameters to override some system configuration points
 * 	'prepare_options' : bool = if true, add some comparison input boxes for the search form
 *  'return' : bool = if true, return the output string instead of printing it
 * // for selectbox
 * 	'multiple' : bool = for select box, allow multiselection
 * 	'allow_void' : bool = allow the user to select an empty value
 * // style
 *   'bold_text' : bool = if true, the output text is bold (usually used with read_only=true) 
 *   'no_html' : bool = if true, the output text is plain text, read_only must be true too
 *   'txt_width' : int = width of a txt area if the field is a string field with maxlen = 0
 *   'txt_height' : int = height of a txt area if the field is a string field with maxlen = 0
 * )
 * 
 * @param  $params 
 * @return 
 */
function build_dynamic_input($params) {
	global $t, $STRING, $QUERY, $perm, $system_read_only_field_names, $db,
	$comparison_option_keys, $comparison_option_for_string_keys,$comparison_option_for_discret_keys,
	$primary_input_array, $secondary_input_array, $cmptype_input_array,$restricted_projects,$permValue; 
	// extract params but don't allow overwrite
	extract($params, EXTR_SKIP); 
	// check some params
	if (!isset($name)) {
		death('ERROR MISSING PARAMETER', "01.1 build_dynamic_input() : input name is missing.");
	} 
	if (!isset($mpfile) || !is_object($mpfile)) {
		if (isset($file_id)) {
			$mpfile = &new MPFile(MPFile::getProject_id($file_id));
		} else {
			death('ERROR MISSING PARAMETER', "01.2 build_dynamic_input() : cannot find field info without mpfile object.");
		} 
	} 
	// if $field_conf isn't set, find it
	if (!isset($field_conf)) {
		// we need the field name or fid
		if (!isset($field_name) && !isset($field_conf_id)) {
			death('ERROR MISSING PARAMETER', "02 build_dynamic_input() : doesn't know what field to edit.");
		} 
		// if field_name is known, find the fid
		if (isset($field_name)) {
			$fid = $mpfile->getField_property_by_another_property('field_conf_id',
				$searched_data = array('field_name' => $field_name));
		} else { // else, the fid must be known
			$field_name = $mpfile->getField_property_by_another_property('field_name',
				$searched_data = array('field_conf_id' => $fid));
		} 
		// the field properties
		$field_conf = $mpfile->project_field_properties[$field_name];
	} else {
		$fid = $field_conf['field_conf_id'];
		$field_name = $field_conf['field_name'];
	} 
	//DEBUG
	//println("testt " . gettype($value));
	//printarray($value);	
	// filter some data
	$secondaryInputName = $secondary_input_array . '[' . $name . ']';
	$cmptypeInputName = $cmptype_input_array . '[' . $name . ']';
	$name = $primary_input_array . '[' . $name . ']';
	$fid = intval($fid);
	$allow_void = !empty($allow_void);
	$multiple = !empty($multiple);
	$override_system = !empty($override_system);
	$prepare_options = !empty($prepare_options);
	$query_context = !empty($query_context);
	$file_id = intval($file_id);
	$bold_text = (isset($bold_text)? !empty($bold_text) : false);
	$no_html = (isset($no_html)? !empty($no_html) : false);
	$return = (isset($return)? !empty($return) : false);
	$txt_width = (isset($txt_width)? intval($txt_width) : DEFAULT_TEXTAREA_WIDTH);
	$txt_height = (isset($txt_height)? intval($txt_height) : DEFAULT_TEXTAREA_HEIGHT);
	// subproperties of the current field
	$sp = &$mpfile->sp_cache[$field_name]; 
	// $perm->have_perm('Admin');
	// $perm->have_perm('AdminProject');
	// READ ONLY parameter
	// if it's set read only by the system (our static config)
	if (!$override_system && in_array($field_name, $system_read_only_field_names)) {
		$read_only = true;
	} else {
		if (isset($params['read_only'])) { // follow the template parameter if it's been setup
			$read_only = !empty($read_only);
		} else { // apply this default read/write policy
			// if it's an admin
			if ($perm->have_perm('Admin') || $perm->have_perm('AdminProject')) {
				$read_only = false;
			} else {
				// is it a read only field ?
				if (!isset($sp->read_only) || ($sp->read_only == true)) {
					$read_only = true;
				} else {
					$read_only = false;
				} 
			} 
		} 
	} 
	// DEBUG
	/*
	println("value(" . gettype($value) . ") = '$value'");
	println("fid(" . gettype($fid) . ") = $fid");
	println("field_name(" . gettype($field_name) . ") = '$field_name'");
	println("read_only : " . (($read_only == true)? 'true' : 'false'));
	*/
	$s = '';

	if ($field_conf['field_type_title'] == TIMESTAMP_TYPE) {
		$cmp_javascript_checkDate .= "onChange=\"javascript:return checkDate(this)\"";
	} 
	// for special fields, we have to do special actions
	$doUsualAction = true; 
	// if (isset($sp->internal_system_use) && ($sp->internal_system_use == true)) {
	switch ($field_name) {
		case 'assigned_to' : 			
			$assigned_value = null;
			// if value is given
			if (is_array($value)) { // check it before using it
				$assigned_value = $value;
				//death('TEST', '01 build_dynamic_input() : invalid value type : for assignation, it must be an array of user ids.');			
			} else { // if undefined, do it yourself
				// get all the assigned users' id
				// $sql_query=sprintf($QUERY['get_assignated_user_id'], $db->quote($file_id));
				$assignation = $db->getAll(sprintf($QUERY['get_assignated_user_id'], $db->quote($file_id)));
				// println("test :$sql_query ");
				// printarray($assignation);
				// death('TEST', '02 build_dynamic_input()');			
				$assigned_value = array();
				foreach($assignation as $v) {
					$assigned_value[] = $v['user_id'];
				} 				
			}
			//DEBUG
			// println("assigned : ");
			// printarray($assigned_value);
			if (!$read_only) {
				// get all project names and ids, but not the public one
				$project_id=$mpfile->getProject_id();
				$selected_domains= delimit_list(',',getChildren($project_id));
				if ($selected_domains=="")
				{
					$selected_domains='0';
				}
				$sql="(SELECT au.user_id, au.email, au.first_name, au.last_name FROM " . TBL_AUTH_USER . " au, " . TBL_PROJECT_PERM . " pp 
					WHERE ( au.active > 0 and au.user_id = pp.user_id and pp.project_id IN ($project_id, $selected_domains) AND pp.perm_id<={$permValue['Editbug']} ) ) UNION 
					( SELECT au.user_id, au.email, au.first_name, au.last_name FROM " . TBL_AUTH_USER . " au, " . TBL_USER_GROUP . " ug , " . TBL_PROJECT_GROUP . " pg 
					WHERE ( au.active > 0 and au.user_id = ug.user_id and ug.group_id=pg.group_id AND pg.project_id IN ($project_id, $selected_domains) AND pg.perm_id<={$permValue['Editbug']} ))
					ORDER BY first_name, last_name "; 
				$res = $db->getAll($sql);
						
				// filter out some data
				$sb_values = array();
				$sb_titles = array(); 
				// printarray($res);
				if ($allow_void) {
					$sb_values['void'] = '';
					$sb_titles['void'] = $STRING['no_selected_value'];
				} 
				foreach($res as $v) {
					$sb_titles[$v['user_id']] = htmlspecialchars($v['email']);
					$sb_values[$v['user_id']] = htmlspecialchars($v['first_name'] . " " . $v['last_name']);
				} 

				$s = listbox($name, $sb_values, 11, true/* $multiple */ , $assigned_value, "size=\"" .DEFAULT_MULTI_SELECT. "\" " . $input_option, $sb_titles);
			} else {
				// if nobody is associated
				if (empty($assigned_value)) {
					$s = $STRING['nobody'];
					if (!$no_html) {
						$s = htmlspecialchars($s);
					}
				} else { // if some people are associated
					$res = $db->getAll("SELECT email, first_name, last_name FROM " . TBL_AUTH_USER
						 . " WHERE user_id IN (" . ((is_array($assigned_value))? implode(', ', $assigned_value) : $db->quote($assigned_value))
						 . ") ORDER BY first_name, last_name");

					$s = array();
					foreach($res as $r) {
						$email = $r['email'];
						$first_name = $r['first_name'];
						$last_name = $r['last_name'];
						if ($no_html) {
							$s[] = "$first_name $last_name <$email>";
						} else {
							$s[] = "<A href=\"mailto:" . htmlspecialchars($email) . "\" title=\"" . htmlspecialchars($email) . "\">" 
								. htmlspecialchars("$first_name $last_name") . "</A>\n";
						}
					} 
					if ($no_html) {
						$s = implode(', ', $s);
					} else {
						$s = textlist($s, $cmdtype = 11); 
					}					
				} 
			} 
			$doUsualAction = false;
			break;
//		case 'last_modified_by' :
//		case 'created_by' : // same as SELECTBOX_TYPE, but with other data
//			if (!$read_only) {
//				// get all project names and ids, but not the public one
//				$res = $db->getAll("SELECT user_id, email, first_name, last_name FROM " . TBL_AUTH_USER . " ORDER BY first_name, last_name "); 
//				// filter out some data
//				$sb_values = array();
//				// printarray($res);
//				if ($allow_void) {
//					$sb_values['void'] = '';
//				} 
//
//				foreach($res as $v) {
//					$sb_titles[$v['user_id']] = htmlspecialchars($v['email']);
//					$sb_values[$v['user_id']] = htmlspecialchars($v['first_name'] . " " . $v['last_name']);
//				$s = listbox($name, $sb_values, 11, $multiple, $value, "size=10 " . $input_option, $sb_titles);
//			} else {
//				// if nobody is associated
//				if ($value == null) {
//					$s = $STRING['nobody'];
//					if (!$no_html) {
//						$s = htmlspecialchars($s);
//					}
//				} else {
//					$res = $db->getAll("SELECT email, first_name, last_name FROM " . TBL_AUTH_USER . " WHERE user_id = " . $db->quote($value));
//
//					$s = array();
//					foreach($res as $r) {
//						$email = $r['email'];
//						$first_name = $r['first_name'];
//						if ($no_html) {
//							$s[] = "$first_name $last_name <$email>";
//						} else {
//							$s[] = "<A href=\"mailto:" . htmlspecialchars($email) . "\" title=\"" . htmlspecialchars($email) . "\">" .
//								htmlspecialchars("$first_name $last_name") . "</A>\n";
//						}
//					}
//					if ($no_html) {
//						$s = implode(', ', $s);
//					} else {
//						$s = implode("<BR>\n", $s);
//					}
//				} 
//			} 
//			$doUsualAction = false;
//			break;
		case 'project_id' : // same as SELECTBOX_TYPE, but with other data
			if (!$read_only){// && ( $perm->have_project_perm($value,'Admin'))) {
				// get all project names and ids, but not the public one
				$res = $db->getAll("SELECT project_id, project_name FROM " . TBL_PROJECT . " WHERE project_id != " . PUBLIC_PROJECT_ID . " AND project_id NOT IN($restricted_projects)"); 
				// filter out some data
				$sb_values = array();
				$sb_titles = null; 
				// printarray($res);
				if ($allow_void) {
					$sb_values['void'] = '';
					$sb_titles['void'] = $STRING['no_selected_value'];
				} 
				foreach($res as $v) {
					$sb_values[$v['project_id']] = htmlspecialchars($v['project_name']);
				}
				if ($query_context)
				{
					$multiple=1;
					$local_size=DEFAULT_MULTI_SELECT;
				}
				else
				{
					$local_size=1;
				}
				$s = listbox($name, $sb_values, 11, $multiple, $value, "size=$local_size" . $input_option, $sb_titles);
			} else {
				// get the project_name
				$s = $db->getOne("SELECT project_name FROM " . TBL_PROJECT . " WHERE project_id = " . $db->quote($value));
				if (!$no_html) {
					$s = ($bold_text? "<B>" : '') . htmlspecialchars($s) . ($bold_text? "</B>" : '') . "\n";
				}
			} 
			$doUsualAction = false;
			break;
		default : // it's an unhandled system field, apply the default display actions
			$doUsualAction = true;
			break;
	} 
	// }
	if ($doUsualAction) {
		// input differ from each data type
		switch ($field_conf['field_type_title']) {
			case SELECT_TWINBOX_TYPE :
			//the fid has to be transfert to the twin one
			 if (isset($sp->SB_twin_id)) 
			 {
			 	$fid=$sp->SB_twin_id;
				$fid = intval($fid);
			 }
			 else
		 	 {
			 printarray($params);
			 printarray($field_name);
			 printarray($mpfile->sp_cache);
				death('ERROR', '05 build_dynamic_input() : non specified twinbox.');
			 } 
			case SELECTBOX_TYPE :
				if ($fid==22 || $fid==23) //case 'last_modified_by' :case 'created_by' 
				{
					if (!$read_only) 
					{
						$project_id=$mpfile->getProject_id();
						$selected_domains= delimit_list(',',getChildren($project_id));
						if ($selected_domains=="")
						{
							$selected_domains='0';
						}
						$sql="(SELECT au.user_id, au.email, au.first_name, au.last_name FROM " . TBL_AUTH_USER . " au, " . TBL_PROJECT_PERM . " pp 
							WHERE ( au.active > 0 and au.user_id = pp.user_id and pp.project_id IN ($project_id, $selected_domains) AND pp.perm_id<={$permValue['New']} ) ) UNION 
							( SELECT au.user_id, au.email, au.first_name, au.last_name FROM " . TBL_AUTH_USER . " au, " . TBL_USER_GROUP . " ug , " . TBL_PROJECT_GROUP . " pg 
							WHERE ( au.active > 0 and au.user_id = ug.user_id and ug.group_id=pg.group_id AND pg.project_id IN ($project_id, $selected_domains) AND pg.perm_id<={$permValue['New']} ))
							ORDER BY first_name, last_name "; 
//						$sql="SELECT au.user_id, au.email, au.first_name, au.last_name FROM " . TBL_AUTH_USER . " au, " . TBL_PROJECT_PERM . " pp 
//							WHERE ( au.active > 0 and au.user_id = pp.user_id and pp.project_id IN ($project_id, $selected_domains) AND pp.perm_id<={$permValue['New']} )  
//							ORDER BY au.first_name, au.last_name "; 
						//println("$sql");
						$res = $db->getAll($sql);
						//printarray($res);
						// filter out some data
						$sb_values = array();
						$sb_titles = array(); 
						// printarray($res);
						if ($allow_void) 
						{
							$sb_values['void'] = '';
							$sb_titles['void'] = $STRING['no_selected_value'];
						} 
	
						foreach($res as $v) 
						{
							$sb_titles[$v['user_id']] = htmlspecialchars($v['email']);
							$sb_values[$v['user_id']] = htmlspecialchars($v['first_name'] . " " . $v['last_name']);
						} 
						if ($query_context)
						{
							$multiple=1;
							$local_size=DEFAULT_MULTI_SELECT;
						}
						else
						{
							$local_size=1;
						}
						$s = listbox($name, $sb_values, 11, $multiple, $value, "size=$local_size" . $input_option, $sb_titles);
					} 
					else 
					{
						// if nobody is associated
						if ($value == null) 
						{
							$s = $STRING['nobody'];
							if (!$no_html) 
							{
								$s = htmlspecialchars($s);
							}
						} 
						else 
						{
							$res = $db->getAll("SELECT email, first_name, last_name FROM " . TBL_AUTH_USER . " WHERE user_id = " . $db->quote($value));

							$s = array();
							foreach($res as $r) 
							{
								$email = $r['email'];
								$first_name = $r['first_name'];
								$last_name = $r['last_name'];
								if ($no_html) 
								{
									$s[] = "$first_name $last_name <$email>";
								} 
								else 
								{
									$s[] = "<A href=\"mailto:" . htmlspecialchars($email) . "\" title=\"" . htmlspecialchars($email) . "\">" .
									htmlspecialchars("$first_name $last_name") . "</A>\n";
								}
							}
							if ($no_html) 
							{
								$s = implode(', ', $s);
							} 
							else 
							{
								$s = implode("<BR>\n", $s);
							}
						} 
					} 
				}
				else
				{
					if (!$read_only) 
					{
						$selectbox_values = $mpfile->getSelectboxValues($fid); 
						// filter out some data
						$sb_values = array();
						$sb_titles = array();

						if ($allow_void) 
						{
							$sb_values['void'] = '';
							$sb_titles['void'] = $STRING['no_selected_value'];
						} 
					
						// reaffect the sv_id in the array
						foreach($selectbox_values as $k => $v) 
						{
							$selectbox_values[$k]['sv_id'] = $k;
						}
					
						$selectbox_values = order_by_element_of_array('order', 'asc', $selectbox_values);
						if ($field_name=='status_id')
						{
							if (!isset($file_id)|| $file_id==0)
							{
								$sequence=0;
								$flg_wkfw=0;
								$search=1;
							}
							else
							{
								$project_id = MPFile::getProject_id($file_id);
								$sequence=$db->getOne("SELECT sequence FROM " . TBL_PROJECT . " WHERE project_id = $project_id");
							}
							if ($flg_wkfw==1)
							{
								$res = $db->getOne($do_query="SELECT `sv_description` FROM " . TBL_SELECTBOX_VALUE . " WHERE `sv_id` = " . $value);
								if(DB::isError($res))
								{
									echo ("<br>Error : " . $res->getMessage() . "<br>");
									print($do_query . "<br>");
									die();
								}
								$res=unserialize($res);
							}
							elseif ($sequence==1) //if sequence order is important
							{
								$ref_order=1+$db->getOne("SELECT sv_order FROM " . TBL_SELECTBOX_VALUE . " WHERE sv_id=$value");
							}
						}

					
						foreach($selectbox_values as $v) 
						{
							if ($v['sv_id']==$value                                           || 
							    $search==1                                                    || 
								$field_name!='status_id'                                  || 
								(  $field_name=='status_id'                            &&
								   ( ($flg_wkfw==1 && !in_array($v['sv_id'],$res) ) ||
								     ($sequence==1 && $v['order']<=$ref_order  )    ||
								     ($flg_wkfw==0 && $sequence==0 )                  )  )  )
							{
							$sb_values[$v['sv_id']] = htmlspecialchars($v['value']);
								if ($field_name!='status_id')
								{
									$sb_titles[$v['sv_id']] = htmlspecialchars($v['description']);
								}
							}
						} 
						if ($field_name=='status_id')
						{
						//	printarray($res);
						//	printarray($sb_values};die;
						}
						if ($query_context)
						{
							$multiple=1;
							$local_size=DEFAULT_MULTI_SELECT;
						}
						else
						{
							$local_size=1;
						}
						$s = listbox($name, $sb_values, 11, $multiple, $value, "size=$local_size" . $input_option, $sb_titles);
					} 
					else 
					{
						$s = $mpfile->sb_cache[$value]['value'];
						if (!$no_html) 
						{
							$s = ($bold_text? "<B>" : '') . htmlspecialchars($s) . ($bold_text? "</B>" : '') . "\n";
						}
					}
				}
				break;
			case INTEGER_TYPE :
				if (!$prepare_options) {
					$value = intval($value);
				} 
				if (!$read_only) {
					$s = text($name, $value, 11, "size=" . DEFAULT_TEXT_SIZE . " " . $input_option);
				} else {
					$s = $value;
					if (!$no_html) {
						$s = ($bold_text? "<B>" : '') . $s . ($bold_text? "</B>" : '') . "\n";
					}
				} 
				break;
			case FLOAT_TYPE :
				if (!$prepare_options) {
					$value = floatval($value);
				} 
				if (!$read_only) {
					$s = text($name, $value, 11, "size=" . DEFAULT_TEXT_SIZE . " " . $input_option);
				} else {
					$s = $value;
					if (!$no_html) {
						$s = ($bold_text? "<B>" : '') . $s . ($bold_text? "</B>" : '') . "\n";
					}
				} 
				break;
			case STRING_TYPE :
				$isTextarea = ((isset($sp->maxlen) && ($sp->maxlen == 0))? true:false); // if it's a textarea
				$filtered_value = htmlspecialchars($value);
				
				if (!$read_only) {
					$maxlength = '';
					if (isset($mpfile->sp_cache[$field_name]->maxlen) && ($mpfile->sp_cache[$field_name]->maxlen != 0)) {
						$maxlength = " maxlength=\"" . intval($mpfile->sp_cache[$field_name]->maxlen) . "\" ";
					} 
					if ($isTextarea) {
						$s = textarea($name, $txt_width, $txt_height, $filtered_value, 11, $input_option);
					} else {
						$s = text($name, $filtered_value, 11, "size=" . DEFAULT_TEXT_SIZE . " " . $maxlength . $input_option);
					}
				} else {
					if ($no_html) {
						$s = $value;
					} else {
						$s = &$filtered_value;
						if ($isTextarea) {
							// there is two way of rendering data
							$s = htmltruespace(nl2br($s)); // <- this one does not preserve the real chars' position
							// $s = "<pre>" . htmltruespace($s) . "</pre>";
						}						
						$s = ($bold_text? "<B>" : '') . $s . ($bold_text? "</B>" : '') . "\n";
					}
				} 
				break;
			case TIMESTAMP_TYPE :
				if (!empty($value)) {
					/*
					$date_format = null;
					if (isset($mpfile->sp_cache[$field_name]->time_type)) {
						switch($mpfile->sp_cache[$field_name]->time_type) {
							case TIMESTAMP_TO_DATE :
								$date_format = DATE_FORMAT;
								break;
							case TIMESTAMP_TO_HOUR :
								$date_format = TIME_FORMAT;
								break;
							case TIMESTAMP_TO_TIME :
								$date_format = DATE_FORMAT_DETAILED;
								break;
							default :
								$date_format = DATE_FORMAT;
								break;
						}
					} else {
						$date_format = DATE_FORMAT;
					}
					$time_to_string = date($date_format, $value);
					*/
					$time_to_string = timestamp_to_string($value, $mpfile->sp_cache[$field_name]->time_type);
					$filtered_value = htmlspecialchars($time_to_string);
				} else {
					$time_to_string = '';
					$filtered_value = '';
				} 
				if (!$read_only) {
					$s = text($name, $filtered_value, 11, $input_option . " " . $cmp_javascript_checkDate);
				} else {					
					if ($no_html) {
						$s = $time_to_string;
					} else {
						$s = ($bold_text? "<B>" : '') . $filtered_value . ($bold_text? "</B>" : '') . "\n";
					}
				} 
				break;
			default:
				death('ERROR', '04 build_dynamic_input() : unhandled field type.' . $field_conf['field_type_title']);
		} // end of switch($field_conf['field_type_title'])
	} 
	// if it's for a search, add some search input options
	$comp_options = $comparison_option_keys; //  $comp_options[option key] = option string
	if ($prepare_options) {	
		switch ($field_conf['field_type_title']) {
			case STRING_TYPE :
				$comp_options = array_merge($comp_options, $comparison_option_for_string_keys);
			case INTEGER_TYPE :
				$comp_options = array_merge($comp_options, $comparison_option_for_discret_keys);
			case FLOAT_TYPE :
				$size_of_text = "size=" . DEFAULT_TEXT_SIZE . " ";
			case TIMESTAMP_TYPE :
				$cmp_options_values = array();
				$cmp_javascript_options = "onChange=\"javascript:enableSecondaryInput(this, form.elements['{$name}'], form.elements['{$secondaryInputName}'])\"";

				foreach($comp_options as $v) {
					$cmp_options_values[$v] = $STRING['comparison_type_name'][$v];
				} 

				$s .= "<BR>";
				$s .= $STRING['comparison'] . " : " . listbox($cmptypeInputName, $cmp_options_values, 11, null,
					current($comparison_option_keys), $cmp_javascript_options, null);
				$s .= text($secondaryInputName, $STRING['disabled'], 11, $size_of_text . 'disabled=true ' . $cmp_javascript_checkDate);
				break;
		} 
	} 

	if (!$return) {
		echo($s);
	}
	return $s;
} // end of build_dynamic_input($field_conf_id)
// //////////////////////////////////////////////////////////////////////////////
/**
 * Treat some data generated with build_dynamic_input()
 * Compare data between posted data and an original file.
 * if $original_file == null, the function will just analyse $posted_values and put them into $changed_fields
 * Changed fields are returned in an array : $ret[<field_name>] = <new_value>
 */
function treat_dynamic_input_data($posted_values, $mpfile, $original_file = null, $verbose = false) {
	$original = &$original_file;
	$changed_fields = array();
	$field_conf = &$mpfile->project_field_properties;
	$isNew = ($original_file == null);
	foreach($posted_values as $field_name => $p_value) {
		if ($verbose) {
			println("treat_dynamic_input_data() : analyse of '$field_name'");
		} 
		// 1. don't accept change on read_only fields, and project_id shall never change
		// 2. there's also no need to adapt to a new file because the project_id will be set automatically
		if (!isNew && (($field_name == 'project_id') ||
					isset($mpfile->sp_cache[$field_name]->read_only) && ($mpfile->sp_cache[$field_name]->read_only == true))) {
			continue;
		} elseif ($field_name == 'assigned_to') {
			$equal = true; 
			// check if all assigned users are the same as the posted data
			if (!$isNew && (count($original[$field_name]['value']) == count($p_value))) {
				foreach($original[$field_name]['value'] as $v) {
					if (!in_array($v, $p_value)) {
						$equal = false; 
						// DEBUG
						if ($verbose) {
							println('p_value');
							printarray($p_value);
							println('assigned');
							printarray($original[$field_name]['value']);
						}
						break;
					} 
				} 
			} else {
				$equal = false;
			} 
			if ($equal != true) {
				if (!in_array('void', $p_value)) {
					$changed_fields[$field_name] = $p_value;
				} else {
					$changed_fields[$field_name] = array();
				} 
			} 
			continue;
		} else { // if it's a normal type of field
			if (!is_array($p_value)) { // if it's not an array, it must be a string
				$p_value = stripslashes($p_value);
			} 
			// $p_value = stripslashes($p_value); // filter slashes
			// filter by type
			switch ($field_conf[$field_name]['field_type_title']) {
				case INTEGER_TYPE :
					$p_value = intval($p_value);
					break;
				case FLOAT_TYPE :
					$p_value = floatval($p_value);
					break;
				case STRING_TYPE :
					if (isset($mpfile->sp_cache[$field_name]->highlight_url) && ($mpfile->sp_cache[$field_name]->highlight_url == true)) {
						$p_value = url_protocol_filter($p_value);
					} 
					break;
				case SELECTBOX_TYPE :
					break;
				case TIMESTAMP_TYPE :
					if (!empty($p_value)) {
						$p_value = convertDate($p_value, $verbose);
					} else $p_value = 0;
					break;
			} 
			// DEBUG
			if ($verbose) {
				if (!is_array($p_value)) {
					println("posted_values[$field_name] = " . htmlspecialchars($p_value));
				} else {
					println("posted_values[$field_name] = ");
					printarray($p_value);
				} 
			} 

			if ($isNew || ($p_value != $original[$field_name]['value'])) {
				$changed_fields[$field_name] = $p_value;
				if ($verbose) {
					println("$field_name has changed : ");
				} 
			} 
		} 
	} 
	return $changed_fields;
} // end of treat_dynamic_input_data($posted_values, $mpfile, $original_file, $verbose = false)
// //////////////////////////////////////////////////////////////////////////////
/**
 * Convert a date formated with a regular expression into int.	
 * The regular expression is INTERNAL_DATE_FORMAT, defined in config.php.
 */
function convertDate($time_str, $verbose = false) {
	$date_elements = array();
	if (preg_match(INTERNAL_DATE_FORMAT, $time_str, $date_elements)) {
		$month = $date_elements[2];
		$day = $date_elements[1];
		$year = $date_elements[4];
		if (isset($date_elements[5])) {
			$hour = $date_elements[6];
			$minute = $date_elements[7];
		} else {
			$hour = 0;
			$minute = 0;
		} 
		// checkdate
		if (!checkdate ($month, $day, $year)) {
			death('ERROR', '01.2 convertDate() : this date doesn\'t exist : ' . htmlspecialchars($time_str) . ".");
		} 

		if ($verbose) {
			println("convertDate() : hour = $hour");
			println("convertDate() : minute = $minute");
			println("convertDate() : day = $day");
			println("convertDate() : month = $month");
			println("convertDate() : year = $year");
		} 

		$ret = mktime ($hour, $minute, $second = null, $month, $day, $year);

		if ($verbose) {
			println("convertedDate : from '" . htmlspecialchars($time_str) . "' to '" . date('d-m--Y H:i', $ret) . "'.");
		} 
		return $ret;
	} else {
		death('ERROR', '01.1 convertDate() : date format is invalid : a date should look like dd/mm/yyyy hh:mm. Hour and minutes are optional.');
	} 
} // end of convertDate($time_str, $verbose = false)
// //////////////////////////////////////////////////////////////////////////////
/**
 * Concat a string ($concat) to another string ($src)
 * If $src is an array of string, concat will append $concat to each element
 * 
 * @param String $concat the string to append
 * @param mixed $src The source string or array of strings
 * @return mixed A string or an array of string depending on $src type
 */
function strcat($concat, $src) {
	if (is_array($src)) {
		foreach($src as $k => $v) {
			$src[$k] = $v . $concat;
		} 
	} else $src .= $concat;
	return $src;
} // end of strcat($concat, $src)
// //////////////////////////////////////////////////////////////////////////////
/**
 * Return the value of a selectbox from a given sv_id
 * 
 * @param integer $sv_id selectbox id
 * @return string the value of the selectbox
 */
function getSelectbox_value($sv_id) {
	global $db;
	return $db->getOne("SELECT sv_value FROM " . TBL_SELECTBOX_VALUE . " WHERE sv_id = " . intval($sv_id));
} // end of getSelectbox_value($sv_id)
// //////////////////////////////////////////////////////////////////////////////
/**
 * Assemble data from $_GET and create a SQL query.
 * Gather paramters by their field_name and their options.
 * ex : 
 * $_GET[$field_name] : primary searched value
 * $_GET[$field_name . '_2nd]
 * 
 * If the search applies to several file tables, the result is an array of sql queries
 * 
 * @param boolean $verbose print debug info
 * @return array SQL queries to execute
 */
function build_query($primary_params, $cmptype_params, $secondary_params = null, $primary_comment= null, $cmptype_comment= null, $secondary_comment = null, $project_id = null, $meet_all_conditions = 1, $personal_select = null, $order_statement=false,$verbose = false) {
	global $STRING, $db, //$comparison_option_keys, $comparison_option_for_string_keys,
	//$primary_input_array, $secondary_input_array, $cmptype_input_array, 
	$restricted_projects; 
	// if (!isset($_GET[$primary_input_array])) {
	// death('ERROR', '01.1 build_query() : unable to find all query parameters.');
	// }
	// it's not obliged to have secondary params
	// if (!isset($_GET[$secondary_input_array])) {
	// death('ERROR', '01.1 build_query() : unable to find parameters.');
	// }
	// if (!isset($_GET['op_between_params'])) {
	// death('ERROR', '01.2 build_query() : unable to find all query parameters.');
	// }
	// array of parameters
	/*
	$primary_params = &$_GET[$primary_input_array];
	$secondary_params = isset($_GET[$secondary_input_array])? ($_GET[$secondary_input_array]) : null;
	$cmptype_params = &$_GET[$cmptype_input_array];
	$meet_all_conditions = isset($_GET['meet_all_conditions'])? true : false;
	*/

	$field_names = array();
	foreach($primary_params as $k => $v) {
		$field_names[] = $db->quote($k);
	} 
	// get all required field conf properties
	$sql = "SELECT fc.*, ty.field_type_title FROM " . TBL_FIELD_CONF . " fc, " . TBL_FIELD_TYPE . " ty WHERE fc.field_type_id = ty.field_type_id AND field_name IN (" . implode(', ', $field_names) . ")"; 
	// DEBUG
	if ($verbose) {
		println("build_query() : Primary params : ");
		printarray($primary_params);
		println("build_query() : cmptype params : ");
		printarray($cmptype_params);
		println("build_query() : Secondary params : ");
		printarray($secondary_params);
		println("build_query() : field_names : ");
		printarray($field_names);
		println("build_query() : project_id = $project_id");
		printarray($project_id);
		println("build_query() : sql = '$sql'");
		println("build_query() : meet all conditions : $meet_all_conditions");
	} 
	$field_names = $db->getAll($sql); 
	// DEBUG
	// if ($verbose) {
	// println('Field_names :');
	// printarray($field_names);
	// }
	// do we have to search on all file tables or only on one ?
	if ($project_id==null)
	{
	$project_id_to_search = 'all'; // by default, search all
	}
	else
	{
		$project_id_to_search= $project_id['0'];
	}
	foreach($field_names as $v) { // test all fields
		if ($v['project_id'] != PUBLIC_PROJECT_ID) { // a field isn't in the public project
			if ($project_id_to_search == 'all') { // it's the first time such a field is found
				$project_id_to_search = $v['project_id']; // store its project_id				
			} elseif ($v['project_id'] != $project_id_to_search) { // it's not the first time we find a private field ;
				// if this one doesn't belong to the same specific project, there's an error
				//death('ERROR', '02 build_query() : some search fields belong to different projects. Ex : ' . htmlspecialchars($v['field_name']));
			} 
		} 
	} 

	if ($verbose) {
		println("build_query() : \$project_id_to_search = $project_id_to_search");
	} 
	// build sql query
	$select = "SELECT ";
	//$from = "FROM " . TBL_FILE_INDEX . " fi"; 
	// if it's only on one file table
	if ($project_id_to_search != 'all') 
	{
		// search the file table name
		$file_table_names = $db->getAll("SELECT file_table_name,project_id FROM " . TBL_PROJECT . " WHERE project_id = " . $db->quote($project_id_to_search));
	} 
	else 
	{ // prepare as many $from as needed for all file table names
		// search all file table names
		$file_table_names = $db->getAll("SELECT file_table_name,project_id FROM " . TBL_PROJECT . " WHERE project_id != " . $db->quote(PUBLIC_PROJECT_ID) . " AND project_id not in ($restricted_projects)");
	}
	if (empty($file_table_names)) 
	{
		return array();
		//death('ERROR', '03 build_query() : the file table name can\'t be found.');
	} 
	$array = array(); 
	foreach($file_table_names as $v) 
	{
		if ($personal_select == null) 
		{
			$pre_from =" f.bug_id as file_id, {$v['project_id']} as project_id ";
		}
		else
		{
			$pre_from=$personal_select;
		}
	
		$array[] = " $pre_from FROM {$v['file_table_name']} f";
	} 
	$from = $array;
	 

	$where = array();
//	$where[] = "fi.file_id = f.bug_id"; 
	// build the where clause
	foreach($field_names as $v) {
		// make some reference variables and filter
		$field_name = &$v['field_name'];
		$p_value = $primary_params[$field_name]; 
		// if($v['field_type_title'] != SELECTBOX_TYPE) {
		if (is_array($p_value)) { // if it's an array
			if (count($p_value) == 0) { // check that it's not empty
				continue;
			} 
		} else {
			$p_value = stripslashes(trim($p_value));
		} 

		$s_value = ($secondary_params != null)? stripslashes(trim($secondary_params[$field_name])) : null;
		$cmptype = $cmptype_params[$field_name]; 
		// DEBUG
		if ($verbose) {
			println("field_name = {$v['field_name']}");
			println("p_value = $p_value");
			println("s_value = " . (($s_value != null)? $s_value : 'null'));
			println("cmptype = $cmptype");
		} 
		// if empty, don't use it in the query
		if ((trim($p_value)) == '') {
			// DEBUG
			if ($verbose) {
				println("skip $field_name ");
			} 
			continue;
		} 
		$built_sql_query=array();
		// if it's a special system field
		switch ($field_name) {
			case 'assigned_to' : 
				// $from = strcat(", " . TBL_ASSIGNATION . " a", $from);
	//			if ($meet_all_conditions)
	//			{
					if (is_array($from)) {
						foreach($from as $k2 => $v2) {
//							$from[$k2] .= ", " . TBL_ASSIGNATION . " a";
							$from[$k2] .= " LEFT JOIN " . TBL_ASSIGNATION . " a ON (f.bug_id=a.file_id) ";
						} 
					} else {
						death("ERROR", "from as to be an array, contact system admin");
//						$from .= ", " . TBL_ASSIGNATION . " a";
						$from .= " LEFT JOIN " . TBL_ASSIGNATION . " a ON (f.bug_id=a.file_id) ";
					} 

					$where[] = "( a.user_id IN (" . (is_array($p_value)? implode(', ', $p_value) : $p_value) . "))";
	/*			}
				else
				{
					$built_sql_query[]="SELECT fi.* FROM " . TBL_FILE_INDEX . " fi, " . TBL_ASSIGNATION . " a WHERE (a.file_id = fi.file_id AND a.user_id IN (" . (is_array($p_value)? implode(', ', $p_value) : $p_value) . "))";
				}
*/
				continue(2);
			case 'last_modified_by' :
			case 'created_by' :
				break;
			case 'project_id' :
				foreach($from as $k2 => $v2) 
				{
					$from[$k2] .= " LEFT JOIN " . TBL_FILE_INDEX . " fi ON (fi.file_id=f.bug_id ) ";
				}
				$where[] = "( fi.project_id IN (" . (is_array($p_value)? implode(', ', $p_value) : $p_value) . " ))";

				continue(2);
		} 
		// for each data type
		switch ($v['field_type_title']) {
			case INTEGER_TYPE :
				if ($cmptype=='one_element' and !is_array($p_value))
				{
					$p_values = explode(KEY_WORD_SEPARATOR, $p_value);
				}
				else
				{
					$p_value = intval($p_value);
				}
				break;
			case FLOAT_TYPE :
				$p_value = floatval($p_value);
				break;
			case STRING_TYPE :
				break;
			case SELECT_TWINBOX_TYPE : //non testé 
			case SELECTBOX_TYPE : 
				// $p_value is an array
				// printarray($p_value);
				$where[] = "( f.$field_name IN (" . (is_array($p_value)? implode(', ', $p_value) : $p_value) . "))";
				continue;
			case TIMESTAMP_TYPE : 
				// we have to test de date format and convert them
				$p_value = convertDate($p_value);
				if (!empty($s_value)) {
					$s_value = convertDate($s_value);
				} 
				break;
		} 
		// it depends on the compare type
		switch ($cmptype) {
			case 'eq' : // equal
				$where[] = "f.$field_name = " . $db->quote($p_value);
				break;
			case 'ne' : // not equal
				$where[] = "f.$field_name != " . $db->quote($p_value);
				break;
			case 'gt' : // greater than
				$where[] = "f.$field_name > " . $db->quote($p_value);
				break;
			case 'lt' : // lesser than
				$where[] = "f.$field_name < " . $db->quote($p_value);
				break;
			case 'ge' : // greater or equal
				$where[] = "f.$field_name >= " . $db->quote($p_value);
				break;
			case 'le' : // lesser or equal
				$where[] = "f.$field_name <= " . $db->quote($p_value);
				break;
			case 'in' : // in interval
				$where[] = "(f.$field_name >= " . $db->quote($p_value) . " AND f.$field_name <= " . $db->quote($s_value) . ')';
				break;
			case 'ni' : // not in interval
				$where[] = "(f.$field_name < " . $db->quote($p_value) . " OR f.$field_name > " . $db->quote($s_value) . ')';
				break;
			case 'like' : // like
				if ($v['field_type_title'] == STRING_TYPE) {
					$where[] = "f.$field_name LIKE " . $db->quote("%{$p_value}%");
				} else {
					death('ERROR', '04.1 build_query() : bad comparison type.');
				} 
				break;
			case 'one_element' : // contains one of several words
				if ($v['field_type_title'] == INTEGER_TYPE) {
					$where[] = "( f.$field_name IN (" . (is_array($p_value)? implode(', ', $p_value) : $p_value) . "))";
					
				} else {
					death('ERROR', '04.11 build_query() : bad comparison type.');
				} 
				break;
			case 'one_word' : // contains one of several words
				if ($v['field_type_title'] == STRING_TYPE) {
					$values = explode(KEY_WORD_SEPARATOR, $p_value);
					$s = array();
					foreach($values as $val) {
						if (trim($val)) {
							// escape some special chars : \ -> \\, % -> \%
							$s[] = "f.$field_name LIKE " . $db->quote("%" . str_replace(array("\\", '%'), array("\\\\", '\%'), $val) . "%");
						} 
					} 
					$where[] = '(' . implode(' OR ', $s) . ')';
				} else {
					death('ERROR', '04.2 build_query() : bad comparison type.');
				} 
				break;
			case 'all_words' : // contain all words
				if ($v['field_type_title'] == STRING_TYPE) {
					$values = explode(KEY_WORD_SEPARATOR, $p_value);
					$s = array();
					foreach($values as $val) {
						if (trim($val)) {
							// escape some special chars : \ -> \\, % -> \%
							$s[] = "f.$field_name LIKE " . $db->quote("%" . str_replace(array("\\", '%'), array("\\\\", '\%'), $val) . "%");
						} 
					} 
					$where[] = '(' . implode(' AND ', $s) . ')';
				} else {
					death('ERROR', '04.3 build_query() : bad comparison type.');
				} 
				break;
		} // end of switch($cmptype) {
	} // end of foreach($field_names as $v)

// Comments treatment
	if (!empty($primary_comment)) 
	{
//		if ($meet_all_conditions)
//		{
			if (is_array($from)) 
			{
				foreach($from as $k2 => $v2) 
				{
//					$from[$k2] .= ", " . TBL_COMMENT . " cm";
					$from[$k2] .= " LEFT JOIN " . TBL_COMMENT . " cm ON (f.bug_id=cm.bug_id) ";
				} 
			} 
			else 
			{
//				$from .= ", " . TBL_COMMENT . " cm";
				$from .= " LEFT JOIN " . TBL_COMMENT . " cm ON (f.bug_id=cm.bug_id) ";
			} 
//		}
		switch ($cmptype_comment) {
			case 'eq' : // equal
				$where_comment = "( cm.comment_text = " . $db->quote($primary_comment) . ")";
				break;
			case 'ne' : // not equal
				$where_comment = "( cm.comment_text != " . $db->quote($primary_comment) . ")";
				break;
			case 'gt' : // greater than
				$where_comment = "( cm.comment_text > " . $db->quote($primary_comment) . ")";
				break;
			case 'lt' : // lesser than
				$where_comment = "( cm.comment_text < " . $db->quote($primary_comment) . ")";
				break;
			case 'ge' : // greater or equal
				$where_comment = "( cm.comment_text >= " . $db->quote($primary_comment) . ")";
				break;
			case 'le' : // lesser or equal
				$where_comment = "( cm.comment_text <= " . $db->quote($primary_comment) . ")";
				break;
			case 'in' : // in interval
				$where_comment = "(cm.comment_text >= " . $db->quote($primary_comment) . " AND f.$field_name <= " . $db->quote($secondary_comment) . ')';
				break;
			case 'ni' : // not in interval
				$where_comment = "( ( cm.comment_text < " . $db->quote($primary_comment) . " OR cm.comment_text > " . $db->quote($secondary_comment) . '))';
				break;
			case 'like' : // like
				$where_comment = "( cm.comment_text LIKE " . $db->quote("%{$primary_comment}%") . ")";
				break;
			case 'one_word' : // contains one of several words
				$values = explode(KEY_WORD_SEPARATOR, $primary_comment);
				$s = array();
				foreach($values as $val) 
				{
					if (trim($val)) 
					{
						// escape some special chars : \ -> \\, % -> \%
						$s[] = "(cm.comment_text LIKE " . $db->quote("%" . str_replace(array("\\", '%'), array("\\\\", '\%'), $val) . "%") . ")";
					} 
				}
				$where_comment = '(' . implode(' OR ', $s) . ' )'; 
				break;
			case 'all_words' : // contain all words
				$values = explode(KEY_WORD_SEPARATOR, $primary_comment);
				$s = array();
				foreach($values as $val) 
				{
					if (trim($val)) 
					{
						// escape some special chars : \ -> \\, % -> \%
						$s[] = "( cm.comment_text LIKE " . $db->quote("%" . str_replace(array("\\", '%'), array("\\\\", '\%'), $val) . "%") . ")";
					} 
				} 
				$where_comment = '(' . implode(' AND ', $s) . ')';
				break;
				default:
				break;
			} // end of switch($cmptype_comment) 
//			if ($meet_all_conditions)
//			{
				$where[]=$where_comment;
/*			}
			else
			{
				$built_sql_query[]="SELECT " . TBL_FILE_INDEX . " fi, " . TBL_COMMENT . " a WHERE $where_comment";
			}
*/
	}//end of if (!empty($primary_comment))

	if (count($where)) 
	{
		$where = " WHERE ((" . implode((($meet_all_conditions)? ' AND ' : ' order_section ) OR ( '), $where) . "))" ;
		if ($meet_all_conditions)
		{
			$where.=' order_section ';
		};
	} 
	else 
	{
		$where = " WHERE 1 order_section ";
	}
	if (!$order_statement)
	{
		$where = preg_replace('/order_section/i',"",$where);
	}
//println (" where vaut $where ");	

	// if there's only one project to search
//	if ($project_id_to_search != 'all') {
//		$built_sql_query[] = "$select $from $where";
//	} else {
		foreach($from as $one_from) {
			$built_sql_query[] = "$select $one_from $where";
		} 
//	} 

	if ($verbose) {
		if ($project_id_to_search != 'all') {
			println("<b>build_query() : generated sql query</b> = $built_sql_query");
		} else {
			foreach($built_sql_query as $s) {
				println("<b>build_query() : generated sql query</b> = $s");
			} 
		} 
	}
	//printarray($built_sql_query);
	return $built_sql_query;
} // end of build_query($verbose)
// //////////////////////////////////////////////////////////////////////////////
/**
 * Create a query url to use with query.php.
 * Returns : 
 * ex :
 * - {$script_name}?{$primary_input_array}[{$field_name}]={$value}&meet_all_conditions=1&order={$order}&sort={$sort}
 * if a value is an array :
 * - {$script_name}?{$primary_input_array}[$field_name][$field_key]={$value}&meet_all_conditions=1&order={$order}&sort={$sort}
 * 
 * @param array $field_values 
 * @param string $order 
 * @param string $sort 
 * @param boolean $meet_all_conditions 
 * @param string $script_name 
 * @return string 
 */
function build_common_query_url($field_values, $order = 'bug_id', $sort = 'asc', $meet_all_conditions = 1, $script_name = 'query.php?') {
	global $primary_input_array;

	/* 
primary_input[assigned_to][]=38
primary_input[status_id][]=3
meet_all_conditions=1
order=last_modified_date&sort=asc&op=doquery
*/

	$url = array();
	foreach($field_values as $field_name => $value) {
		$s = null;
		if (is_array($value)) {
			$s = array();
			if (count($value) == 0) {
				death('ERROR', 'build_common_query_url() : a field_value is an empty array.');
			} 
			foreach($value as $k => $v) {
				// $s[] = rawurlencode("{$primary_input_array}[{$field_name}][{$k}]") . '=' . rawurlencode($v);
				$s[] = "{$primary_input_array}[{$field_name}][{$k}]" . '=' . $v;
			} 
			$s = implode('&', $s);
		} else {
			// $s = rawurlencode("{$primary_input_array}[{$field_name}]") . '=' . rawurlencode($value);
			$s = "{$primary_input_array}[{$field_name}]" . '=' . $value;
		} 
		$url[] = $s;
	} 
	if ($meet_all_conditions) {
		$url[] = "meet_all_conditions=1";
	} 
	$url[] = "order=" . rawurlencode($order);
	$url[] = "sort=" . (($sort == 'asc')? 'asc' : 'desc');
	$url[] = 'op=doquery';
	$url = implode('&', $url);
	$url = $script_name . $url;

	return $url;
} // end of build_common_query_url($field_values, $order = 'bug_id', $sort = 'asc', $meet_all_conditions = 1, $script_name = 'query.php')
// //////////////////////////////////////////////////////////////////////////////
/**
 * Determine the closed status ids
 */
function get_closed_status_ids() {
	global $db, $QUERY;
	$closed_status_ids = array();
	$mpfile = &new MPFile(PUBLIC_PROJECT_ID); // make an mpfile object
	$sql = sprintf($QUERY['get_selectbox_from_option'], $db->quote('status_id'), $db->quote(OPTION_CLOSED));
	$res = $db->getAll($sql);
	foreach($res as $v) {
		$closed_status_ids[] = $v['sv_id'];
	} 
	return $closed_status_ids;
} // end of get_closed_status_ids()
// //////////////////////////////////////////////////////////////////////////////
/**
 * Determine the open status ids
 */
function get_open_status_ids($closed_status_ids = null) {
	global $db, $QUERY;
	if ($closed_status_ids == null) {
		$closed_status_ids = get_closed_status_ids();
	} 
	$open_status_ids = array();
	$sql = sprintf($QUERY['get_selectbox'], $db->quote('status_id'));
	$res = $db->getAll($sql);
	foreach($res as $v) {
		$open_status_ids[] = $v['sv_id']; // actually, we have all status sv_ids
	} 
	$open_status_ids = array_diff($open_status_ids, $closed_status_ids);
	return $open_status_ids;
} // end of get_open_status_ids()
// //////////////////////////////////////////////////////////////////////////////
/**
 * calculate data from the db to show the number of assigned files to the user (open/closed) and created files.
 */
function build_common_file_links() {
	global $db, $t, $u, $QUERY;

	$mpfile = &new MPFile(PUBLIC_PROJECT_ID); // make an mpfile object
	$closed_status_ids = get_closed_status_ids();
	$open_status_ids = get_open_status_ids($closed_status_ids); 
	// prepare build query parameters
	$cmdtype = array();
	$owner_open_nb = $owner_closed_nb = $reporter_open_nb = $reporter_closed_nb = 0; 
	// owner_open_nb
	$pr_input_array = array('assigned_to' => $u, 'status_id' => $open_status_ids);
	
/*	foreach(build_query($pr_input_array, $cmdtype, null, null, null, null, null, 1, "count(bug_id) as nb", $verbose) as $sql) {
		$sql = preg_replace('/order_section/i',"",$sql);
		$owner_open_nb += $db->getOne($sql);
	}
	
*/
	$owner_open_nb = $db->getOne("SELECT COUNT(file_id) FROM " . TBL_ASSIGNATION . " WHERE user_id=$u ");
	// owner_closed_nb
//	$pr_input_array = array('assigned_to' => $u, 'status_id' => $closed_status_ids);
//	foreach(build_query($pr_input_array, $cmdtype, null, null, null, null, null, 1, "count(bug_id) as nb", $verbose) as $sql) {
//		$sql = preg_replace('/order_section/i',"",$sql);
//		$owner_closed_nb += $db->getOne($sql);
//	} 
	// reporter_open_nb
	$pr_input_array = array('created_by' => $u, 'status_id' => $open_status_ids);
	foreach(build_query($pr_input_array, $cmdtype, null, null, null, null, null, 1, "count(bug_id) as nb", $verbose) as $sql) {
		$sql = preg_replace('/order_section/i',"",$sql);
		$reporter_open_nb += $db->getOne($sql);
	} 
	// reporter_closed_nb
	$pr_input_array = array('created_by' => $u, 'status_id' => $closed_status_ids);
	foreach(build_query($pr_input_array, $cmdtype, null, null, null, null, null, 1, "count(bug_id) as nb", $verbose) as $sql) {
		$sql = preg_replace('/order_section/i',"",$sql);
		$reporter_closed_nb += $db->getOne($sql);
	} 

	//$order = (isset($_SESSION['queryinfo']['order'])? $_SESSION['queryinfo']['order'] : 'last_modified_date');//not working with private field
	//$sort = (isset($_SESSION['queryinfo']['sort'])? $_SESSION['queryinfo']['sort'] : 'asc'); 
	$order = 'last_modified_date';
	$sort = 'asc'; 
	// prepare the query url array
	$field_values = array('assigned_to' => $u,
		'status_id' => $open_status_ids
		);
	if ((count($open_status_ids) == 0) || ($owner_open_nb == 0)) {
		$owner_open = false;
	} else {
		$owner_open = build_common_query_url($field_values, $order, $sort, 1);
	} 

	$field_values['status_id'] = $closed_status_ids;
	if ((count($closed_status_ids) == 0) || ($owner_closed_nb == 0)) {
		$owner_closed = false;
	} else {
		$owner_closed = build_common_query_url($field_values, $order, $sort, 1);
	} 

	unset($field_values['assigned_to']);
	$field_values['created_by'] = $u;

	if ((count($closed_status_ids) == 0) || ($reporter_closed_nb == 0)) {
		$reporter_closed = false;
	} else {
		$reporter_closed = build_common_query_url($field_values, $order, $sort, 1);
	} 
	$field_values['status_id'] = $open_status_ids;
	if ((count($open_status_ids) == 0) || ($reporter_open_nb == 0)) {
		$reporter_open = false;
	} else {
		$reporter_open = build_common_query_url($field_values, $order, $sort, 1);
	} 

	$t->assign(
		array('owner_open' => $owner_open,
			'owner_closed' => $owner_closed,
			'reporter_open' => $reporter_open,
			'reporter_closed' => $reporter_closed
			)
		);

	$t->assign(
		array('owner_open_nb' => $owner_open_nb,
			'owner_closed_nb' => $owner_closed_nb,
			'reporter_open_nb' => $reporter_open_nb,
			'reporter_closed_nb' => $reporter_closed_nb
			)
		);
} // end of build_common_file_links()
// ///////////////////////////////////////////////////////////////////////////////
/**
 * Filter an associative array of field_conf by key and sort it.
 * Filter out by using $system_hidden_field_names and the given array argument : $filter_out
 */
function filter_fields($input_array, $filter_out, $order, $sort) {
	global $system_hidden_field_names;
	$fc_filtered = _array_diff_key($input_array, array_flip($system_hidden_field_names));
	$fc_filtered = _array_diff_key($fc_filtered, array_flip($filter_out)); 
	// order fields by 'edit_order'
	$fc_filtered = order_by_element_of_array($order, $sort, $fc_filtered); // this function alter the key values	 
	// reaffect field_name as array keys
	$temp = array();
	foreach($fc_filtered as $k => $v) {
		$temp[$v['field_name']] = $v;
	} 
	return $temp;
} // end of filter_fields($input_array, $filter_out, $order, $sort)
// ///////////////////////////////////////////////////////////////////////////////
/**
	Return a string date representation of a timestamp.
	The date format depends on the time type = TIMESTAMP_TO_DATE, TIMESTAMP_TO_HOUR or TIMESTAMP_TO_TIME
	@return string date string
*/
function timestamp_to_string($time, $time_type = null) {
	$date_format = null;
	switch($time_type) {
		case TIMESTAMP_TO_DATE :
			$date_format = DATE_FORMAT;
			break;
		case TIMESTAMP_TO_HOUR :
			$date_format = TIME_FORMAT;
			break;
		case TIMESTAMP_TO_TIME :
			$date_format = DATE_FORMAT_DETAILED;
			break;
		default :
			$date_format = DATE_FORMAT;
			break;
	}
	return date($date_format, $time);
} // end of timestamp_to_string($time, $time_type)
// ///////////////////////////////////////////////////////////////////////////////
/**
Print html code to make a checkbox to select a file.
Use automatically $selected_files_array to make the checkbox name : $selected_files_array[$name]
So, posted data is stored in this array.
To use with smarty template.
	elements in parameters :

	'name' = name of the checkbox
	'value' = value
	'checked' = if true, the checkbox is checked
	'post_array_name' = the name of the post array in which the selectbox will be stored
	'input_options' = addition html code
	
	@param array $params array of parameters
	@return void
*/
function select_file_by_id($params) {
	global $selected_files_array;
	// extract params but don't allow overwrite
	extract($params, EXTR_SKIP);
	checkbox("sel" . '[' . htmlspecialchars($name) . ']', $value, $checked, 1, $input_options);
} // end of select_file_by_id($params)
// ///////////////////////////////////////////////////////////////////////////////
/**
	Add the selected file ids to the stored selected files array : $_SESSION['queryinfo']['sel']
	If the array is empty, the function doesn't modify the selected files' array.
	If project_id >= 0, the file id is added
	If project_id == -1, the file id is removed (if in the selected ids array)
	@param array $posted_selected_file_ids array of posted selected ids
	@return mixed array of selected ids, from session data, or string : 'all' or 'none'
*/
function add_selected_file_ids($posted_selected_file_ids, $posted_listed_file_ids, $verbose = false) {
	//DEBUG
	if ($verbose) {
		println("add_selected_file_ids() :  add");
		printarray($posted_selected_file_ids);
	}
	
	$selected_file_ids = &$_SESSION['queryinfo']['sel'];
	if (!is_array($posted_listed_file_ids)) {
		death('ERROR', 'add_selected_file_ids() : $posted_listed_file_ids must be an array.');
	}
	
	if (count($posted_listed_file_ids) > 0) {
		foreach($posted_listed_file_ids as $k => $v) {
			if ($verbose) {
				println("Treat $k : $v");
			}
			if (isset($posted_selected_file_ids[$k])) { // if >0, add it
				$selected_file_ids[$k] = $v;				
				if ($verbose) {
					println("add it");
				}				
			} else { // else, remove it if present
				unset($selected_file_ids[$k]);
				if ($verbose) {
					println("remove it");
				}
			}
		}
		// $selected_file_ids = array_merge($selected_file_ids, $posted_selected_file_ids);		 
	}	
	return $selected_file_ids;
} // end of add_selected_file_ids($posted_selected_file_ids)
// ///////////////////////////////////////////////////////////////////////////////
/**
	Execute sql queries in an array of strings.
	Return a result ids array and the number of found files.
	
	@param array $built_sql_query sql queries
	@param boolean $verbose if true, print debug info
	@return array $return = array($result_ids, $fileCount);
*/
function executeQueryAndOrder($built_sql_query, $order, $sort, $pageNb, $pageSize, $verbose ) 
{
	global $db;
	//printarray($built_sql_query);
	$result_ids = array();
	$fileCount = 0;
	$count_sql = "";
	$ordered_sql = "";
	$table_j1="";
	// if a file use OR condition and assignation or comment table, then we use the file number as criteria
	// type of the ordered field
	$type_sql = "SELECT field_type_title, field_conf_id, properties FROM " . TBL_FIELD_TYPE . " ft, " . TBL_FIELD_CONF . " fc WHERE ft.field_type_id=fc.field_type_id AND fc.field_name=\"$order\"" ;
	$res =  $db->getRow($type_sql);
	$order_type=$res['field_type_title'];
	$order_id=$res['field_conf_id'];
	$order_properties=$res['properties'];
	//print "type : $order_type <br> id : $order_id <br> properties : $order_properties"; 

	$doJoin = false;
	// some special fields are ordered differently
	switch($order) 
	{
		case 'project_id' :
			$join_table=TBL_FILE_INDEX . " fii, " . TBL_PROJECT;
			$field_readable="project_id";
			$order_select="project_id AND fii.file_id=f.bug_id";
			$order_value="fii.project_id";
			$doJoin = true;
			$table_j1="jt";
			break;
		case 'assigned_to' :
			$join_table=TBL_ASSIGNATION . " asst, " . TBL_AUTH_USER;
			$field_readable="user_id";
			$order_select="user_id and asst.file_id = f.bug_id";
			$order_value=db_concat(" jt.first_name ", "\" \"", " jt.last_name ");
			//$order_value="jt.first_name, jt.last_name";
			$doJoin = true;
			$table_j1="asst";
			break;
		default :
			switch ($order_type) 
			{
				case SELECT_TWINBOX_TYPE : 
					$sp = new MPSubProperty($order_properties);
					if (isset($sp->SB_twin_id)) 
			 		{
						$order_id=$sp->SB_twin_id;
						$order_id = intval($order_id);
					}
				case SELECTBOX_TYPE :
					if ($order_id==22 || $order_id==23) //modified_by and created_by
					{
						$join_table=TBL_AUTH_USER;
						$field_readable="user_id";
						$order_select=$order;
						$order_value=db_concat(" jt.first_name ", "\" \"", " jt.last_name ");
						//$order_value="jt.first_name, jt.last_name";
						$doJoin = true;
						$table_j1="f";
					}
					else
					{
						$join_table=TBL_SELECTBOX_VALUE;
						$field_readable="sv_id";
						$order_select=$order;
						$order_value="jt.sv_order";
						$doJoin = true;
						$table_j1="f";
					}
					break;
				default :
					$doJoin = false;
					$order_value="f." . $order;
					break;
			}
			break;
	}
		

	if (is_string($built_sql_query)) 
	{
		$built_sql_query = array($built_sql_query);
	}

	
	//printarray($built_sql_query); 
	foreach($built_sql_query as $sql) 
	{
		if ($ordered_sql=="")
		{
			if ($doJoin)
			{
				$sql = preg_replace('/FROM/i', "FROM $join_table jt,", $sql);
				$sql = preg_replace('/SELECT /i', "SELECT DISTINCT $order_value AS criteria, ", $sql);
				$sql = preg_replace('/order_section/i'," AND jt.$field_readable = $table_j1.$order_select ",$sql);
				//$sql .= " AND jt.$field_readable = $table_j1.$order_select"; 
			}
			else
			{
				$sql = preg_replace('/SELECT /i', "SELECT DISTINCT $order_value AS criteria, ", $sql);
				$sql = preg_replace('/order_section/i'," ",$sql);
			}
			$ordered_sql = "($sql)";
//			$sql_count = preg_replace('/SELECT .* FROM/i', "SELECT COUNT(DISTINCT fi.file_id) FROM", $sql);
//			$Count=$db->getOne($sql_count);
			$isMultiProject = false;
		}
		else
		{
			if ($doJoin)
			{
				$sql = preg_replace('/FROM/i', "FROM $join_table jt,", $sql);
				$sql = preg_replace('/SELECT /i', "SELECT DISTINCT $order_value AS criteria, ", $sql);
				$sql = preg_replace('/order_section/i'," AND jt.$field_readable = $table_j1.$order_select ",$sql);
				//$sql .= " AND jt.$field_readable = $table_j1.$order_select"; 
			}
			else
			{
				$sql = preg_replace('/SELECT /i', "SELECT DISTINCT $order_value AS criteria, ", $sql);
				$sql = preg_replace('/order_section/i'," ",$sql);
			}
//			$sql_count = preg_replace('/SELECT .* FROM/i', "SELECT COUNT(DISTINCT fi.file_id) FROM", $sql);
//			$Count+=$db->getOne($sql_count);
			$ordered_sql .= " UNION ($sql) ";
//			$sql_count = preg_replace('/SELECT .* FROM/i', "SELECT COUNT(DISTINCT fi.file_id) FROM", $sql);
			$isMultiProject = true;
		}
	}

	// count nbfile
//	$fileCount=$Count;
	
	// add  order statement to the query
//	if ($pageNb<1)
//	{
//		$pageNb=((int) ($fileCount / $pageSize)) + ((($fileCount % $pageSize) == 0)? 0 : 1);
//	}
	//$position=($pageNb-1) * $pageSize;
	$ordered_sql2 =  "$ordered_sql" ." ORDER BY criteria $sort LIMIT $position,$pageSize";
//	println("sql request $ordered_sql2 positon $position et pageSize $pageSize");
	$DBres= $db->query( "$ordered_sql" ." ORDER BY criteria $sort");//,$position,$pageSize);
	//$res = $db->getAll($ordered_sql2);
	//printarray($res);
	//foreach($res as $r) 
	//{
	//	// $result_ids[$r['project_id']][$r['file_id']] = 0;
	//	$result_ids[$r['project_id']][] = $r['file_id'];
	//} 
	
	return array( $isMultiProject,$DBres);

	
}

function executeQuery($built_sql_query, $verbose) {
	global $db;
	$result_ids = array();
	$fileCount = 0;
	if (is_string($built_sql_query)) {
		$built_sql_query = array($built_sql_query);
	}
	// execute queries and sort them by project_id and file_id
	foreach($built_sql_query as $sql) {
	println("SQL query : $sql \n");
		$res = $db->getAll($sql);
	println("fin");
		foreach($res as $r) {
			// $result_ids[$r['project_id']][$r['file_id']] = 0;
			$result_ids[$r['project_id']][] = $r['file_id'];
			$fileCount++;
		} 
	} 
	/*
	// reassemble the array => $result_ids[project_id] = array(file_id);
	foreach($result_ids as $k => $v) {
		$result_ids[$k] = array_keys($v);
	} 
	*/
	return array($result_ids, $fileCount);
} // end of executeQuery($sql_queries, $verbose)
// ///////////////////////////////////////////////////////////////////////////////

function mailtoDomainAdmin($project_id,$subject,$content)
{
	global $db,$u;
	$ProjectPermAdmin = $db->getOne('select perm_id from ' . TBL_AUTH_PERM . " where perm_name ='Admin'");
	$useradmin = $db->getCol('select user_id from ' . TBL_PROJECT_PERM . " where project_id = $project_id and perm_id = $ProjectPermAdmin ORDER BY user_id"); 
	if (isset($useradmin) and is_array($useradmin) and count($useradmin))
	{
		$sql = 'SELECT email FROM ' . TBL_AUTH_USER . " u, " . TBL_USER_PREF . " p WHERE u.user_id IN (" . implode(', ', $useradmin) . ") AND u.user_id = p.user_id AND p.email_notices = 1 AND u.user_id != " . $db->quote($u);
   		$mail_admin=$db->getCol($sql);
   		if (isset($mail_admin) and is_array($mail_admin) and count($mail_admin)) 
   		{
			$toemail=implode(', ', $mail_admin);
			$headers = sprintf("From: %s\nReply-To: %s\nErrors-To: %s", ADMIN_EMAIL, ADMIN_EMAIL, ADMIN_EMAIL);
	
			qp_mail($toemail, $subject, $content, $headers);
		}
	}
}

?>
