<?php

//  edex.php -- interface for uploading bulk user data
//
//  $Id: edex.php,v 1.2 2006/10/15 19:08:55 fstuurman Exp $
//
//  Copyright (C) 2004 Peter Fokker, <peter@berestijn.nl>
//
//  This file is part of Janitor.
//
//  Janitor 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.
//
//  Janitor 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 this program; if not, write to the Free Software
//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//

// 2005-04-19/PF - chmod output files to 0400 and 0500, (owner=www group=www)
//                 Effectively this limits processing of the generated file(s)
//                 to the root account because the www user is not a member of
//                 the janitors group, and hence members of the janitors group
//                 are not allowed to read the file. We don't want to create
//                 world readable files here, so there. Need to put this on the
//                 ToDo-list.
// 2005-04-19/PF - we now have an orange(ish) warning when a new group name is
//                 user more than once OR when the same user apparently is about
//                 to be re-created under another name, too. We do allow this
//                 'double' user, but it may lead to a mess. Oh well. As a rule
//                 all checks should yield yellow or blue and not orange or red.
//                 It's all up to the user.

//2005-12-20/FcS changed coding to be able to use the import function
//		of janitor in site@school CMS.
if (!defined('IN_SAS'))
{
	die("Hacking attempt");
}
// globals
$MAX_FILE_SIZE = return_bytes(get_cfg_var("upload_max_filesize"));
$tempfile = $sas_config['serverpath'] . $sas_config['user_path'] . "/" . $sas_config['media_dir'];
$UPLOADDIR = $tempfile;
$edexgr = array ();
$edexll = array ();
$allgroups = "";
$allusers = "";
$users = array ();
$allnewgroups = "";
$allnewusers = "";

$fileformat = array (
	1 => "&nbsp; " . $sas_lang['fixed_record_length'] . " &nbsp;",
	2 => "&nbsp; " . $sas_lang['CVS_format1'] . " &nbsp;",
	3 => "&nbsp; " . $sas_lang['CVS_format2'] . " &nbsp;",
	4 => "&nbsp; " . $sas_lang['CVS_format3'] . " &nbsp;"
);
$fieldlist = array (
	1 => $sas_lang['unique_key'],
	2 => $sas_lang['first_name'],
	3 => $sas_lang['infix'],
	4 => $sas_lang['last_name'],
	5 => $sas_lang['class'],
	6 => $sas_lang['birthday'],
	7 => $sas_lang['birthday_year'],
	8 => $sas_lang['birthday_month'],
	9 => $sas_lang['birthday_day']
);

// About the default values in $edex_defaults:
// This array is defined in config/config.php. It defines the default file format
// for uploaded files. The 0'th element is the default $fileformat, elements 1,..,9
// define arrays with 3 numbers each. The first of these numbers is the start of the
// field in a fixed record length file (1-based), the second defines the length of the
// field. The third field is the 1-based index in the CSV-file. If a value equates to
// 0 the corresponding field is not used during import.

function edex_screen($target, $type)
//added the type parameter : 1 = pupil, 2 = teacher
{
	//------------------------------------------------------------
	global $Message, $PHP_SELF, $MAX_FILE_SIZE, $UPLOADDIR, $edexll, $edexgr, $sas_lang, $newgroups;
	global $table_users, $table_configuration, $suboption;
	$filename = $UPLOADDIR . "/file" . strftime("%Y%m%d%H%M%S");
	$href = $GLOBALS['PHP_SELF'];

	$button = $_REQUEST[PARAM_BUTTON];
	$s = "";
	if ($button == BUTTON_CANCEL)
	{
		menu(3); // back to tools menu
		return;
	}
	elseif ($button == BUTTON_UPLOAD)
	{
		if (!store_upload($filename))
		{
			$Message = __("Upload failed: ") . $Message;
			upload_screen();
			return;
		}
		// got $filename; go process it.
		if (!arrays_from_file($filename))
		{
			$Message = __("Upload failed: ") . $Message;
			upload_screen();
			return;
		}
		// got 4 arrays in core; go analyse them  generate screen
		if (valid_arrays($s) == 0)
			$Message = $sas_lang['everything_looks_OK'];
		else
			$Message = $sas_lang['more_editing'];
		print start_page(__("upload pupils' data")) .
		$s;
		//end_page();
	}
	elseif ($button == BUTTON_RECALC)
	{
		if (!arrays_from_postvars())
		{
			menu(3);
			exit;
		}
		// got 4 arrays in core; go analyse them  generate screen
		if (valid_arrays($s) == 0)
			$Message = $sas_lang['everything_looks_OK'];
		else
			$Message = $sas_lang['more_editing'];
		print start_page(__("upload pupils' data")) .
		$s;
		//end_page();
	}
	elseif ($button == BUTTON_GENERATE)
	{
		if (!arrays_from_postvars())
		{
			menu(3);
			exit;
		}
		// got 4 arrays in core; go analyse them  generate screen
		if (valid_arrays($s) == 0)
		{
			// everything looks OK; go write outputfile

			if (output_batchfile($s, $type) == 0)
			{
				$Message = $sas_lang['everything_looks_OK'] . $sas_lang['results_written'];

				foreach ($edexll as $key => $row)
				{
					$fullname[$key] = $row['fullname'];
					$gid[$key] = $row['gid'];
					$userid[$key] = $row['userid'];
					$password[$key] = $row['password'];
				}

				// Sort the edexll array with gid
				array_multisort($gid, SORT_ASC, $fullname, SORT_ASC, $userid, SORT_ASC, $password, SORT_ASC, $edexll);

				$u = start_table(array (
					"width" => "80%",
					"border" => "1"
				)) .
				table_row(table_cell("<h3>" . $sas_lang['users'] . "</h3>", array (
					"bgcolor" => APP_TITLECOLOR,
					"colspan" => "5"
				))) .
				table_row(table_cell("<b>" . $sas_lang['class'] . "</b>", array (
					"bgcolor" => APP_TITLECOLOR,
					"width" => "10%"
				)), table_cell("<b>" .
				$sas_lang['username'] . "</b>", array (
					"bgcolor" => APP_TITLECOLOR,
					"width" => "15%"
				)), table_cell("<b>" .
				$sas_lang['fullname'] . "</b>", array (
					"bgcolor" => APP_TITLECOLOR,
					"width" => "20%"
				)), table_cell("<b>" .
				$sas_lang['password'] . "</b>", array (
					"bgcolor" => APP_TITLECOLOR,
					"width" => "10%"
				)));

				foreach ($fullname as $key => $value)
				{
					$class_new = $newgroups[$gid[$key]];
					if ($class_new != $class_old)
					{
						$u .= table_row(table_cell("<b>" . $class_new . "</b>", array (
							"bgcolor" => APP_TITLECOLOR,
							"colspan" => "5",
							"align" => "center"
						)));
					}

					$u .= table_row(table_cell($newgroups[$gid[$key]], array (
						"bgcolor" => "#FFFFFF"
					)) .
					table_cell(cleanup_text($userid[$key]), 24, 16), array (
						"bgcolor" => "#FFFFFF"
					), table_cell(cleanup_text($fullname[$key]), 36, 80), array (
						"bgcolor" => "#FFFFFF"
					), table_cell($password[$key], array (
						"bgcolor" => "#FFFFFF"
					)));
					$export .= $newgroups[$gid[$key]] . "," . $userid[$key] . "," . $fullname[$key] . "," . $password[$key] . "\n";
					$class_old = $newgroups[$gid[$key]];

				}
				$u .= end_table();
				print $u;

				include ("core/cryptography.php"); //include encryption script
				$today = date("m d y H i s"); //create a random filename with date and time
				$filename = md5($today);
				mysql_query("UPDATE $table_configuration SET config_value = '$filename' WHERE config_key = 'edex_file_name'");
				$fl = fopen("media/" . $filename, 'w');
				$encryp = new cryptography;
				$query = "SELECT password FROM $table_users WHERE id = '$_SESSION[userid]'";
				$result = mysql_query($query); //get user password , used as a key for encryption
				$encryp->set_key(mysql_result($result, 0)); //use password as encryption key
				$encrypted = $encryp->encrypt($export);
				fwrite($fl, $encrypted);
				fclose($fl);
			}
			else
				$Message .= ' ' . __("Something wrong with saving data to %s?");
		}
		else
			$Message = $sas_lang['more_editing'];

		print start_page(__("upload pupils' data")) .
		$s;
	}
	else
	{
		// show upload dialog
		upload_screen(TRUE); // TRUE = use default values
	}
	//------------------------------------------------------------
} // edex_screen()

function upload_screen($usedefaults = FALSE)
{
	//------------------------------------------------------------
	global $fieldlist, $fileformat, $MAX_FILE_SIZE, $edex_defaults, $sas_lang, $suboption;
	$href = $GLOBALS['PHP_SELF'];

	for ($i = 1; $i <= 9; ++ $i)
	{
		for ($j = 0; $j < 3; ++ $j)
		{
			if ($usedefaults)
			{
				$v[$i][$j] = abs(intval($edex_defaults[$i][$j]));
			}
			else
			{
				$v[$i][$j] = abs(intval($_REQUEST['i' . $i . 'j' . $j]));
			}
		}
	}
	// set default file format in dialog
	if ($usedefaults)
	{
		$f = intval($edex_defaults[0]);
	}
	else
	{
		$f = intval($_REQUEST['fileformat']);
	}
	$s = start_form($GLOBALS['PHP_SELF'] . "?option=configuration&suboption=$suboption&modoption=import&action=screen", array (
		"method" => "post",
		"enctype" => "multipart/form-data"
	)) .
	hidden_field("MAX_FILE_SIZE", $MAX_FILE_SIZE) .
	start_table(array (
		"border" => "0",
		"cellpadding" => "2",
		"width" => "90%"
	)) .
	table_row(table_cell("&nbsp;", array (
		"width" => "40%"
	)), table_cell("&nbsp;", array (
		"width" => "20%"
	)), table_cell("&nbsp;", array (
		"width" => "20%"
	)), table_cell("&nbsp;", array (
		"width" => "20%"
	))) .
	table_row(table_cell($sas_lang['fileformat']), table_cell(select_field("fileformat", $fileformat, $f), array (
		"colspan" => "3"
	))) .
	table_row(table_cell(__($sas_lang['file'])), table_cell(file_field("file", "", 60, 128), array (
		"colspan" => "3"
	))) .
		//table_row(table_cell(
		//	'<i>'.sprintf(__("Note: maximum file size %s bytes."),$MAX_FILE_SIZE),array("colspan" => "4"))).'</i>'.
	table_row(table_cell('&nbsp;', array (
		"colspan" => "4"
		))) . // spacer
	table_row(table_cell('<b>' . $sas_lang['field_definitions'] . '</b>'), table_cell('<b>' .
	$sas_lang['fixed_start'] . '</b>'), table_cell('<b>' .
	$sas_lang['fixed_length'] . '</b>'), table_cell('<b>' .
	$sas_lang['CSV_index'] . '</b>'));
	for ($i = 1; $i < 6; ++ $i)
	{
		$s .= table_row(table_cell($fieldlist[$i]), table_cell(number_field('i' .
		$i . 'j0', $v[$i][0], 10, 10)), table_cell(number_field('i' .
		$i . 'j1', $v[$i][1], 10, 10)), table_cell(number_field('i' .
		$i . 'j2', $v[$i][2], 10, 10)));
	}
	$s .= table_row(table_cell($fieldlist[6]), table_cell("&nbsp;", array (
		"bgcolor" => APP_TITLECOLOR
	)), table_cell("&nbsp;", array (
		"bgcolor" => APP_TITLECOLOR
	)), table_cell(number_field('i6j2', $v[6][2], 10, 10)));
	for ($i = 7; $i < 10; ++ $i)
	{
		$s .= table_row(table_cell($fieldlist[$i]), table_cell(number_field('i' .
		$i . 'j0', $v[$i][0], 10, 10)), table_cell(number_field('i' .
		$i . 'j1', $v[$i][1], 10, 10)), table_cell("&nbsp;", array (
			"bgcolor" => APP_TITLECOLOR
		)));
	}

	$s .= end_table() .
	button_bar(array (
		submit_field(PARAM_BUTTON,
		BUTTON_UPLOAD
	))) .
	end_form();

	print start_page(__("upload pupils' data")) .
	$s;
	//end_page();
	return;
	//------------------------------------------------------------
} // upload_screen()

function store_upload($target)
{
	//------------------------------------------------------------
	global $_FILES, $Message, $MAX_FILE_SIZE, $UPLOADDIR;
	$Message = "";

	umask(0077);

	$ftype = substr(stripslashes($_FILES['file']['type']), 0, 32);
	$fsize = intval($_FILES['file']['size']);
	$ftemp = substr($_FILES['file']['tmp_name'], 0, 512);
	$fname = substr(stripslashes($_FILES['file']['name']), 0, 512);

	if ($fsize > $MAX_FILE_SIZE)
	{
		$Message = sprintf(__("file too large (max %s bytes allowed)"), $MAX_FILE_SIZE);
		return FALSE;
	}
	elseif ($fsize <= 0)
	{
		$Message = __("file is empty");
		return FALSE;
	}
	if (!(is_uploaded_file($ftemp)))
	{
		$Message = sprintf(__("invalid filename %s"), $ftemp);
		return FALSE;
	}
	if (!(move_uploaded_file($ftemp, $target)))
	{
		$Message = sprintf(__("could not store file %s in %s"), $ftemp, $target);
		return FALSE;
	}

	$Message = sprintf(__("stored %s bytes in %s"), $fsize, $target);
	return TRUE;
	//------------------------------------------------------------
} // store_upload()

function arrays_from_file($fname)
{
	//------------------------------------------------------------
	// parse file $fname and dump in 2 arrays: edexgr and edexll.
	// get all existing groups, users in arrays groups and users
	// kill file
	// step through edexgr and detect name clashes for groups
	// step through edexll and detect name clashes for users
	// finish with Recalc and Generate buttons
	// simple, huh?
	global $Message, $edexgr, $edexll, $allgroups, $allusers, $users, $allnewgroups, $allnewusers, $grade_prefix;

	// Input still has Y2K-problems. We use a sliding window; any 2-digit years
	// greater than $year2000pivot are assumed to be within the 20th century (i.e. 19xx)
	// whereas years less or equal are 21st century (20xx). This is based on the assumption
	// that we do NOT have to deal with birthdays in the future, so if this year is 2005
	// then birthdays in '00, '01, '02, '03, '04 and '05 are 21st century, others are 20th.
	// Kinda stupid that we have to do this, but never mind. Guess this will work until at
	// least 2038 ;-)... (PF/2005-04-05)
	$year2000pivot = intval(strftime("%y"));

	//
	// Step 0 -- Start with system data (existing users & groups)
	//
	if (!data_from_system())
	{
		return FALSE;
	}
	//
	// Step 1 -- Try to open the file
	//
	if (($fp = fopen($fname, "r")) == FALSE)
	{
		$Message = sprintf(__("can't open %s"), $fname);
		return FALSE;
	}
	//
	// Step 2 -- Get the file definition from the posted variables
	//
	for ($i = 1; $i <= 9; ++ $i)
	{
		for ($j = 0; $j < 3; ++ $j)
		{
			$v[$i][$j] = abs(intval($_REQUEST['i' . $i . 'j' . $j]));
		}
	}
	$f = intval($_REQUEST['fileformat']);

	// At this point the array $v has the definitions and $f indicates which
	// file format is to be used: 1=Fixed, 2,3,4=CSV

	$allnewusers = "  ";

	if ($f == 1)
	{ // File is a Fixed Record Length file
		while (!feof($fp))
		{
			$line = rtrim(fgets($fp, 512));
			if (!empty ($line))
			{
				$line = strip8859_1($line);
				for ($i = 1; $i <= 9; ++ $i)
				{
					if (($v[$i][0]) && ($v[$i][1]))
					{
						$field[$i] = rtrim(substr($line, $v[$i][0] - 1, $v[$i][1]));
					}
					else
					{
						$field[$i] = "";
					}
				}
				$yy = intval($field[7]);
				$mm = intval($field[8]);
				$dd = intval($field[9]);
				if (($dd) && ($mm))
				{
					// month and day MUST be at least non-zero
					// Deal with Y2K.... Aaarghhhhhh
					if ($yy < 100)
					{
						// we MUST assume that values below our pivot
						// are in 21st century, the rest must be in 20th
						$yy += ($yy <= $year2000pivot) ? 2000 : 1900;
					}
					$dob = sprintf("%04d%02d%02d", $yy, $mm, $dd);
				}
				else
				{
					$dob = "00000000";
				}
				$fullname = trim(trim($field[2] . ' ' . $field[3]) . ' ' . $field[4]);
				$userid = strtolower($field[2]); // initial guess: first name
				if (!empty ($field[5]))
				{ // keep track of various grades in this input file
					$edexgr[$field[5]] = $field[5];
				}
				// Now see if we possibly have an already matching user
				// Criteria: the key and (dob or full name) match
				$user = $users[$field[1]];
				if (!empty ($user))
				{
					if (($user['dob'] == $dob) || ($user['fullname'] == $fullname))
					{
						// looks like this is the same user; use existing userid
						$userid = $user['userid'];
					}
				}
				$allnewusers .= $userid . ' ';
				$edexll = array_merge($edexll, array (
					array (
						"userid" => $userid,
						"fullname" => $fullname,
						"dob" => $dob,
						"key" => $field[1],
					"password" => random_password(),
					"gid" => $field[5]
				)));
			}
		}
	}
	else
	{ // File is in CSV format
		while (!feof($fp))
		{
			$line = rtrim(fgets($fp, 512));
			if (!empty ($line))
			{
				$line = strip8859_1($line);
				$aline = explode(',', $line); // array $aline has individual fields
				for ($i = 1; $i <= 6; ++ $i)
				{
					if ($v[$i][2])
					{
						$field[$i] = rtrim($aline[$v[$i][2] - 1]);
					}
					else
					{
						$field[$i] = "";
					}
				}
				if (empty ($field[6]))
				{
					$dob = "00000000";
				}
				else
				{
					if ($f == 4)
					{
						list ($dd, $mm, $yy) = split('[/.-]', $field[6]);
					}
					elseif ($f == 3)
					{
						list ($mm, $dd, $yy) = split('[/.-]', $field[6]);
					}
					else
					{
						list ($yy, $mm, $dd) = split('[/.-]', $field[6]);
					}
					$yy = intval($yy);
					$mm = intval($mm);
					$dd = intval($dd);
					if (($dd) && ($mm))
					{
						// month and day MUST be at least non-zero
						// Deal with Y2K.... Aaarghhhhhh
						if ($yy < 100)
						{
							// we MUST assume that values below our pivot
							// are in 21st century, the rest must be in 20th
							$yy += ($yy <= $year2000pivot) ? 2000 : 1900;
						}
						$dob = sprintf("%04d%02d%02d", $yy, $mm, $dd);
					}
					else
					{
						$dob = "00000000";
					}
				}
				if (!empty ($field[5]))
					$edexgr[$field[5]] = $field[5];
				$userid = strtolower($field[2]); // first name
				$allnewusers .= $userid . ' ';
				$edexll = array_merge($edexll, array (
					array (
						"userid" => $userid,
						"fullname" => trim(trim($field[2] . ' ' . $field[3]
					) . ' ' . $field[4]
				), "dob" => $dob, "key" => $field[1], "password" => random_password(), "gid" => $field[5])));
			}
		}
	}
	fclose($fp);
	unlink($fname);

	// massage the groups; construct array
	asort($edexgr);
	$allnewgroups = "  ";
	foreach ($edexgr as $k => $v)
	{
		if (!ctype_alpha(substr($v, 0, 1)))
		{
			$v = $grade_prefix . $v;
		}
		$v = strtolower($v);
		$edexgr["$k"] = $v;
		$allnewgroups .= $v . ' ';
	}
	// Done with edexgr[]
	// now sort the pupils array
	asort($edexll);
	return TRUE;
	//------------------------------------------------------------
} // arrays_from_file()

function arrays_from_postvars()
{
	//------------------------------------------------------------
	// fill edexgr and edexll.
	// get all existing groups, users in arrays groups and users
	global $Message, $edexgr, $edexll, $allgroups, $allusers, $allnewgroups, $allnewusers;

	// Start with system data (existing users & groups)
	if (!data_from_system())
	{
		return FALSE;
	}
	$ngroups = $_REQUEST['groups'];
	$allnewgroups = "  ";
	$edexgr = array ();
	for ($i = 1; $i <= $ngroups; ++ $i)
	{
		$k = $_REQUEST["gid" . $i];
		$v = $_REQUEST["group" . $i];
		$edexgr["$k"] = "$v";
		$allnewgroups .= "$v ";
	}

	$nusers = $_REQUEST['users'];
	$allnewusers = "  ";
	$edexll = array ();
	for ($i = 1; $i <= $nusers; ++ $i)
	{
		$userid = $_REQUEST["userid" . $i];
		$uid = $_REQUEST["uid" . $i];
		$ugid = $_REQUEST["ugid" . $i];
		$dob = $_REQUEST["dob" . $i];
		$fullname = $_REQUEST["fullname" . $i];
		$edexll = array_merge($edexll, array (
			array (
				"userid" => "$userid",
				"fullname" => "$fullname",
				"dob" => "$dob",
				"key" => "$uid",
			"password" => random_password(),
			"gid" => "$ugid"
		)));
		$allnewusers .= "$userid ";
	}
	// massage the groups; sort array
	asort($edexgr);
	asort($edexll);
	return TRUE;
	//------------------------------------------------------------
} // arrays_from_postvars()

function data_from_system()
{
	//------------------------------------------------------------
	global $allgroups, $allusers, $users, $table_classes, $table_users;

	//
	// Step 1 -- groups
	//
	$query = "SELECT id, name FROM $table_classes WHERE project = 0";
	$result = mysql_query($query) or die_script($query, mysql_error());

	$allgroups = '  ';
	while ($class_list = mysql_fetch_array($result))
	{
		$allgroups .= $class_list[1] . ' ';
	}

	//
	// Step 2 -- users
	//
	$query = "SELECT username FROM $table_users";
	$result = mysql_query($query) or die_script($query, mysql_error());
	$allusers = "  ";
	while ($user_list = mysql_fetch_array($result))
	{
		$allusers .= $user_list[0] . ' ';
	}

	// $allusers and $allgroups are spacedelimited lists with trailing
	// and leading spaces; $users is an array with the user accounts
	// indexed by key.
	return TRUE;
	//------------------------------------------------------------
} // data_from_system()

function valid_arrays(& $output)
{
	//------------------------------------------------------------
	global $edexll, $edexgr, $allgroups, $allusers, $users, $sas_lang, $suboption;

	$retval = 0;
	$bg = 0;
	$bgcol = array (
			APP_EDEXOK, // 0 blue for correct entries
		APP_EDEXWARN1, // 1 yellow(ish) for groupnames used more than once and existing users
		APP_EDEXWARN2, // 2 orange(ish) for already existing entries, but with the same key 
		//   + (dob or fullname) but different userid
		APP_EDEXERR // 3 red for invalid entries
	
	);

	$g = start_table(array (
		"width" => "90%",
		"border" => "1"
	)) .
	table_row(table_cell("<h3>" . $sas_lang['classes'] . "</h3>", array (
		"bgcolor" => APP_TITLECOLOR,
		"colspan" => "3"
	))) .
	table_row(table_cell("<b>" . $sas_lang['class'] . " id</b>", array (
		"bgcolor" => APP_TITLECOLOR,
		"width" => "10%"
	)), table_cell("<b>" .
	$sas_lang['class'] . "</b>", array (
		"bgcolor" => APP_TITLECOLOR,
		"width" => "20%"
	)), table_cell("<b>" .
	$sas_lang['comments'] . "</b>", array (
		"bgcolor" => APP_TITLECOLOR,
		"width" => "70%"
	)));
	$i = 0;
	foreach ($edexgr as $k => $v)
	{
		$i++;
		$retval += check_group($bg, $comment, $v);
		$g .= table_row(table_cell(cleanup_text($k) .
		hidden_field("gid" . $i, cleanup_text($k)), array (
			"bgcolor" => $bgcol[$bg]
		)), table_cell(text_field("group" .
		$i, cleanup_text($v), 24, 16), array (
			"bgcolor" => $bgcol[$bg]
		)), table_cell($comment, array (
			"bgcolor" => $bgcol[$bg]
		)));
	}
	$g .= end_table() .
	hidden_field("groups", "$i");

	$u = start_table(array (
		"width" => "90%",
		"border" => "1"
	)) .
	table_row(table_cell("<h3>" . $sas_lang['users'] . "</h3>", array (
		"bgcolor" => APP_TITLECOLOR,
		"colspan" => "4"
	))) .
	table_row(table_cell("<b>" . $sas_lang['class'] . " id</b>", array (
		"bgcolor" => APP_TITLECOLOR,
		"width" => "10%"
	)), table_cell("<b>" .
	$sas_lang['username'] . "</b>", array (
		"bgcolor" => APP_TITLECOLOR,
		"width" => "15%"
	)), table_cell("<b>" .
	$sas_lang['fullname'] . "</b>", array (
		"bgcolor" => APP_TITLECOLOR,
		"width" => "20%"
	)), table_cell("<b>" .
	$sas_lang['comments'] . "</b>", array (
		"bgcolor" => APP_TITLECOLOR,
		"width" => "50%"
	)));
	$i = 0;
	foreach ($edexll as $a)
	{
		$i++;
		$comment = "&nbsp;";
		$uid = $a['key'];
		$ugid = $a['gid'];
		$userid = $a['userid'];
		$fullname = $a['fullname'];
		$dob = $a['dob'];
		$retval += check_user($bg, $comment, $a);
		$u .= table_row(table_cell(
		//cleanup_text($uid." (".cleanup_text($ugid).")").
		cleanup_text($ugid) .
		hidden_field("uid" . $i, cleanup_text($uid)) .
		hidden_field("ugid" . $i, cleanup_text($ugid)) .
		hidden_field("dob" . $i, cleanup_text($dob)), array (
			"bgcolor" => $bgcol[$bg]
		)) .
		table_cell(text_field("userid" .
		$i, cleanup_text($userid), 24, 16), array (
			"bgcolor" => $bgcol[$bg]
		)), table_cell(text_field("fullname" .
		$i, cleanup_text($fullname), 36, 80), array (
			"bgcolor" => $bgcol[$bg]
		)), table_cell("(" .
		cleanup_text($dob) . ") " . $comment, array (
			"bgcolor" => $bgcol[$bg]
		)));
	}
	$u .= end_table() .
	hidden_field("users", "$i");

	$output = "<p>\n" .
	start_form($GLOBALS['PHP_SELF'] . "?option=configuration&suboption=$suboption&modoption=import&action=screen", array (
		"method" => "post"
	)) .
	$g .
	"<p>\n" .
	$u;
	if ($retval)
	{
		// Don't show button 'GENERATE' if there are still errors
		$output .= button_bar(array (
			submit_field(PARAM_BUTTON,
			BUTTON_RECALC
		)));
	}
	else
	{
		$output .= button_bar(array (
			submit_field(PARAM_BUTTON,
			BUTTON_RECALC
		), submit_field(PARAM_BUTTON, BUTTON_GENERATE)));
	}
	$output .= end_form();
	return $retval;
	//------------------------------------------------------------
} // valid_arrays()

function valid_ugname($name)
{
	//------------------------------------------------------------
	// valig_ugname() -- check for validity of name
	// alphanumeric lowercase, initial letter, less than 16 chars.
	// we return a modified string that is acceptable
	global $Message;
	$s = strtolower(preg_replace("/[^[:alnum:]]*/", "", $name));
	if (!ctype_alpha($s {
		0 }))
	$s = "x" . $s;
	$s = substr($s, 0, 16);
	return $s;
	//------------------------------------------------------------
} // valid_ugname()

function check_group(& $verdict, & $comment, $value)
{
	//------------------------------------------------------------
	// return either 0 (ok) or 1 (group already exists) 
	// 2 (same groupname used more than once) or 3 (oops) in verdict
	//
	global $allnewgroups, $allgroups, $sas_lang;
	if (valid_ugname($value) != $value)
	{
		$comment = __("Invalid name: max 16 lowercase alphanumeric, initial alpha, no punctuation");
		$verdict = 3; // oops
		return 1;
	}
	if (strpos($allgroups, " $value "))
	{
		$comment = $sas_lang['existing_name_used'];
		$verdict = 1; // so we won't recreate this account but simply accept it 'as is'
		return 0;
	}
	$n = strpos($allnewgroups, " $value ") + 1; // this is us
	if (strpos($allnewgroups, " $value ", $n))
	{ // a 2nd occurrance?
		$comment = $sas_lang['student_name_exists'];
		$verdict = 2; // we allow 'double' group names, but flag them via verdict 2
		return 0;
	}
	$comment = "&nbsp;";
	$verdict = 0; // indicate group ok
	return 0;
	//------------------------------------------------------------
} // check_group()

function check_user(& $verdict, & $comment, $auser)
{
	//------------------------------------------------------------
	// return either 0 (ok), 1 (existing, same userid) or 2 (existing, other userid) or 3 (error) in verdict
	// $auser is a complete array with new user data
	global $allnewusers, $allusers, $users, $sas_lang;
	$userid = $auser['userid'];
	if (valid_ugname($userid) != $userid)
	{
		$comment = __("Invalid name: max 16 lowercase alphanumeric, initial alpha, no punctuation");
		$verdict = 3; // oops: more editing required
		return 1;
	}
	$n = strpos($allnewusers, ' ' . $userid . ' ') + 1; // this is us
	if (strpos($allnewusers, ' ' . $userid . ' ', $n))
	{ // a 2nd occurrance in NEW users?
		$comment = $sas_lang['name_used_more_once'];
		$verdict = 3; // oops, more editing required
		return 1;
	}

	// Check if user already exists with this userid or another.
	// Criterion: key matches and also either dob or fullname.
	// check it out
	$user = $users[$auser['key']];
	if (!empty ($user))
	{
		// The user does in fact exist otherwise $user would be empty
		if (($user['dob'] == $auser['dob']) || ($user['fullname'] == $auser['fullname']))
		{
			// looks like this is the same user but what is the userid?
			if ($user['userid'] == $userid)
			{
				// yes. Nothing to do but inform the user that this user will be updated
				$comment = sprintf(__('This user %s (%s, %s) already exists and will not be added to the system database'), $user['fullname'], $auser['key'], $user['dob']);
				$verdict = 1; // existing user with this userid is the same one; simply reuse account
				return 0; // indicate success (for now); this is OK with us
			}
			else
			{
				// no. a user with this key + (dob or fullname) exist, but with another userid
				$comment = sprintf(__("This account already exists as '%s' (%s, %s, %s)"), $user['userid'], $user['fullname'], $auser['key'], $user['dob']);
				$verdict = 2; // existing user is the same but with a different userid
				return 0; // indicate success (for now); this is OK with us
			}
		}
	}

	if (strpos($allusers, ' ' . $userid . ' '))
	{
		// this userid already exist in the system database
		$comment = $sas_lang['student_name_exists'];
		$verdict = 3; // oops. more editing required
		return 1;
	}
	$comment = "&nbsp;";
	$verdict = 0;
	return 0;
	//------------------------------------------------------------
} // check_user()

function output_batchfile(& $output, $type)
{
	//------------------------------------------------------------
	//This function is completely different than the version used in Server@School
	//
	global $edexgr, $edexll, $users, $Message, $newgroups, $sas_config;
	global $grade_pupils, $grade_passwd, $table_classes, $table_users;

	$verdict = 0;
	$comment = '';

	//
	// 1 -- Handle name clashes for grades (classes)
	//

	foreach ($edexgr as $key => $v)
	{
		if (check_group($verdict, $comment, $v))
		{
			// Mmmm, weird, this shouldn't happen?
			// We expect a retval 0 with verdict either 0, 1 or 2.
			$Message = sprintf(__("error checking grade %s (should't happen)"), $v);
			return 1;
		}
		// OK. We have a verdict. What is it?
		// If it is 0 or 2 we have to create a new account
		// and if it is 1, we don't have to do anything.
		// At this point verdict 3 is not possible because in that case
		// we wouldn't be here.
		if (($verdict == 0) || ($verdict == 2))
		{
			mysql_query("INSERT INTO $table_classes (id, name, teachers, project) VALUES (NULL, '$v', '', '0')");
			$edexgr[$key] = mysql_insert_id();
		}
		else
		{
			//class already exists, get id from classes table
			$query = "SELECT id FROM $table_classes WHERE name = '$v'";
			$result = mysql_query($query);
			$edexgr[$key] = mysql_result($result, 0, 0);
		}
		$newgroups[$key] = $v;
	}

	//
	// Step 2 -- go for the users
	//

	// We need to step through the user array. Here, too, we may need to skip
	// a few users because the already exist and we will reuse the existing account
	//
	// Possible return values from check_user can be either non-0 (shouldn't happen)
	// and 0 with verdict = 0 => OK, verdict = 1 => existing user account to be reused. 
	// In the former case the user is added to the batch file, in the latter case we
	// only add a line to the file_sh with the changed values + the grade.
	//

	foreach ($edexll as $a)
	{
		$userid = $a['userid'];
		if (check_user($verdict, $comment, $a))
		{
			// Weird. Oh well. Bye (this shouldn't happen)
			$Message = sprintf(__("error checking user %s (should't happen)"), $userid);
			return 1;
		}
		if (($verdict == 0) || ($verdict == 2))
		{
			$gid = $a['gid'];
			$fullname = $a['fullname'];
			$class = $edexgr["$gid"];
			$password = $a['password'];
			if ($sas_config['use_encryption'] == 1) //passwords are encrypted
			{
				$password = md5($password);
			}
			//print "INSERT INTO $table_users (id, username, password, name, class, type, email, access, highvisibility, project) 
			//			 VALUES (NULL, '$userid', '$password',  '$fullname', '$class', '1', '', '000000000000,000000000000', '1', '')";
			mysql_query("INSERT INTO $table_users (id, username, password, name, class, type, email, access, highvisibility, project,initial) 
								VALUES (NULL, '$userid', '$password',  '$fullname', '$class', '$type', '', '000000000000,000000000000', '0', '','1')");
		}

	}
	//
	// At this point everything is inserted into the DB, so we are dismissed.
	// Finish off by letting the user know what happened via $output.
	// (and present an OK button)
	//

	$output = " ";
	return 0;
	//------------------------------------------------------------
} // output_batchfile()

function return_bytes($val)
{
	//------------------------------------------------------------
	// Convert php.ini shorthand to integers.
	// Reference: http://nl3.php.net/manual/en/function.ini-get.php
	//
	$val = trim($val);
	$last = strtolower($val {
		strlen($val) - 1 });
	switch ($last)
	{
		// The 'G' modifier is available since PHP 5.1.0
		case 'g' :
			$val *= 1024;
		case 'm' :
			$val *= 1024;
		case 'k' :
			$val *= 1024;
	}
	return $val;
	//------------------------------------------------------------
} // return_bytes()

//  eof

function random_password()
{
	// generate an random alphanumeric code 12 positions long.
	$final_rand = "";
	srand((double) microtime() * 10000000);
	$alpha = array (
		"A",
		"B",
		"C",
		"D",
		"E",
		"F",
		"G",
		"H",
		"I",
		"J",
		"K",
		"L",
		"M",
		"N",
		"O",
		"P",
		"Q",
		"R",
		"S",
		"T",
		"U",
		"V",
		"X",
		"Y",
		"Z"
	);
	$rand_keys = array_rand($alpha, 4);
	for ($i = 0; $i <= 3; $i++)
	{
		$final_rand .= $alpha[$rand_keys[$i]];
	}
	$numbers = array (
		"1",
		"2",
		"3",
		"4",
		"5",
		"6",
		"7",
		"8",
		"9",
		"0"
	);
	$rand_keys = array_rand($numbers, 4);
	for ($i = 0; $i <= 3; $i++)
	{
		$final_rand .= $numbers[$rand_keys[$i]];
	}
	return $final_rand;
}
?>
