science-ation/user.inc.php
dave 986ce4ef44 - user.inc.php needs to generate a password without including common.inc.php
(install3 doesn't like including that file).  That's ok, because eventually
  all passwd handling will be done through user.inc.php (and the generate could
  even be inlined into set_password). But for now, just copy the existing
  generatePassword, and call it something different so the function names don't
  clash.
2008-07-09 18:24:49 +00:00

618 lines
15 KiB
PHP

<?
/*
This file is part of the 'Science Fair In A Box' project
SFIAB Website: http://www.sfiab.ca
Copyright (C) 2005 Sci-Tech Ontario Inc <info@scitechontario.org>
Copyright (C) 2005 James Grant <james@lightbox.org>
Copyright (C) 2007 David Grant <dave@lightbox.org>
This program 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, version 2.
This program 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; see the file COPYING. If not, write to
the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
*/
?>
<?
$user_types = array('student','judge','committee','volunteer','fair');
$user_what = array('student'=>'Participant', 'judge' => 'Judge',
'committee'=>'Committee Member','volunteer' => 'Volunteer',
'fair'=>'Science Fair');
/* Duplicate of common.inc.php:generatePassword, which will be deleted
* eventually when ALL users are handled through this file */
function user_generate_password($pwlen=8)
{
//these are good characters that are not easily confused with other characters :)
$available="ABCDEFGHJKLMNPQRSTUVWXYZabcdefghjkmnpqrstuvwxyz23456789";
$len=strlen($available) - 1;
$key="";
for($x=0;$x<$pwlen;$x++)
$key.=$available{rand(0,$len)};
return $key;
}
function user_load_fair($u)
{
/* Double check, make sure the user is of this type */
if(!in_array('fair', $u['types'])) return false;
$q = mysql_query("SELECT * FROM users_fair
WHERE users_id='{$u['id']}'
");
if(mysql_num_rows($q)!=1) return false;
$r = mysql_fetch_object($q);
$ret = array();
$ret['fairs_id'] = intval($r->fairs_id);
return $ret;
}
function user_load_student($u)
{
/* Double check, make sure the user is of this type */
if(!in_array('student', $u['types'])) return false;
$ret = array();
return $ret;
}
function user_load_judge($u)
{
/* Double check, make sure the user is of this type */
if(!in_array('judge', $u['types'])) return false;
$ret = array();
return $ret;
}
function user_load_committee($u)
{
/* Double check, make sure the user is of this type */
if(!in_array('committee', $u['types'])) return false;
$q = mysql_query("SELECT * FROM users_committee
WHERE users_id='{$u['id']}'");
if(mysql_num_rows($q)!=1) return false;
$r = mysql_fetch_object($q);
$ret = array();
$ret['emailprivate'] = $r->emailprivate;
$ret['ord'] = intval($r->ord);
$ret['displayemail'] = ($r->displayemail == 'yes') ? 'yes' : 'no';
$ret['access_admin'] = ($r->access_admin == 'yes') ? 'yes' : 'no';
$ret['access_config'] = ($r->access_config == 'yes') ? 'yes' : 'no';
$ret['access_super'] = ($r->access_super == 'yes') ? 'yes' : 'no';
return $ret;
}
function user_load_volunteer($u)
{
/* Double check, make sure the user is of this type */
if(!in_array('volunteer', $u['types'])) return false;
$ret = array();
return $ret;
}
function user_load($user, $load_full=false)
{
$id = 0;
/* Sort out the type first */
if(is_array($user)){
/* User already loaded, this is just an extended load */
$id = $user['id'];
$where = "id='$id'";
$load_base = false;
} else {
$id = intval($user);
if($id > 0) {
/* Load by ID FIXME: if we enable load-by-email below,
* then a user could use a number at the beginning of
* their email address to exploit here, must fix that.
* */
$where = "id='$id'";
} else {
return false;
/* Load by email */
// $e = stripslashes($user);
// $where = "email='$e'";
}
$load_base = true;
}
if($load_base) {
$q=mysql_query("SELECT * FROM users
WHERE
$where
AND deleted='no'
");
if(mysql_num_rows($q)!=1) return false;
$ret = mysql_fetch_assoc($q);
/* Do we need to do number conversions? */
$ret['id'] = intval($ret['id']);
/* Turn the type into an array, because there could be more than one */
$ts = explode(',', $ret['types']);
$ret['types'] = $ts; /* Now we can use in_array('judge', $ret['types']) ; */
} else {
$ret = $user;
}
if($load_full) {
$r = true;
foreach($ret['types'] as $t) {
if($ret['load_full'] == true) continue;
/* These all pass $ret by reference, and can modify
* $ret */
$r = call_user_func("user_load_$t", $ret);
if(!is_array($r)) return false;
/* It is important that each type database doesn't
have conflicting column names */
foreach($r as $k=>$v) {
if(array_key_exists($k, $ret)) {
echo "DATABASE DESIGN ERROR, duplicate user key $k";
exit;
}
}
$ret = array_merge($ret, $r);
}
$ret['load_full'] = true;
} else {
$ret['load_full'] = false;
}
/* Do this assignment without recursion :) */
unset($ret['orig']);
$orig = $ret;
$ret['orig'] = $orig;
// echo "<pre>User load returning:\n";
// print_r($ret);
// echo "</pre>";
return $ret;
}
function user_set_password($id, $password = NULL)
{
/* pass $u by reference so we can update it */
$save_old = false;
if($password == NULL) {
$q = mysql_query("SELECT passwordset FROM users WHERE id='$id'");
$u = mysql_fetch_assoc($q);
/* Generate a new password */
$password = user_generate_password(12);
/* save the old password only if it's not an auto-generated one */
if($u['passwordset'] != '0000-00-00') $save_old = true;
/* Expire the password */
$save_set = "'0000-00-00'";
} else {
/* Set the password, no expiry, save the old */
$save_old = true;
$save_set = 'NOW()';
}
$p = mysql_escape_string($password);
$set = ($save_old == true) ? 'oldpassword=password, ' : '';
$set .= "password='$p', passwordset=$save_set ";
$query = "UPDATE users SET $set WHERE id='$id'";
mysql_query($query);
echo mysql_error();
return $password;
}
function user_save_volunteer($u)
{
}
function user_save_committee($u)
{
$fields = array('emailprivate','ord','displayemail','access_admin',
'access_config','access_super');
//echo "<pre>";
// print_r($u);
// echo "</pre>";
$set = '';
foreach($fields as $f) {
if($u[$f] == $u['orig'][$f]) continue;
if($set != '') $set .=',';
$data = mysql_escape_string(stripslashes($u[$f]));
$set .= "$f='$data'";
}
if($set != "") {
$query = "UPDATE users_committee SET $set WHERE users_id='{$u['id']}'";
mysql_query($query);
}
}
function user_save_judge($u)
{
}
function user_save_student($u)
{
}
function user_save_fair($u)
{
}
function user_save($u)
{
$fields = array('firstname','lastname','username',
'email',
'phonehome','phonework','phonecell','fax','organization',
'address','address2','city','province','postalcode','sex',
'firstaid', 'cpr');
$set = "";
foreach($fields as $f) {
if($u[$f] == $u['orig'][$f]) continue;
if($set != "") $set .=',';
// if($f == 'types')
// $set .= "$f='".implode(',', $u[$f])."'";
$data = mysql_escape_string(stripslashes($u[$f]));
$set .= "$f='$data'";
}
//echo "<pre>";
//print_r($u);
//echo "</pre>";
if($set != "") {
$query = "UPDATE users SET $set WHERE id='{$u['id']}'";
mysql_query($query);
// echo "query=[$query]";
echo mysql_error();
}
/* Save the password if it changed */
if($u['password'] != $u['orig']['password'])
user_set_password($u['id'], $u['password']);
/* If this was a full load, do a full save */
if($u['load_full'] == true) {
foreach($u['types'] as $t) {
call_user_func("user_save_$t", $u);
}
}
}
function user_delete_committee($u)
{
mysql_query("DELETE FROM users_committee WHERE users_id='{$u['id']}'");
mysql_query("DELETE FROM committees_link WHERE users_id='{$u['id']}'");
}
function user_delete_volunteer($u)
{
}
function user_delete_judge($u)
{
}
function user_delete_fair($u)
{
}
function user_delete_student($u)
{
}
function user_delete($u, $type=false)
{
$finish_delete = false;
if(!is_array($u)) {
$u = user_load($u);
}
if($type != false) {
if(!in_array($type, $u['types'])) {
/* Hum, type specified, but the user is not this type,
* so, i guess we're done. */
return;
}
if(count($u['types']) > 1) {
/* Don't delete the whole user */
$types='';
foreach($u['types'] as $t) {
if($t == $type) continue;
if($types != '') $types .= ',';
$types .= $t;
}
mysql_query("UPDATE users SET types='$types' WHERE id='{$u['id']}'");
} else {
$finish_delete = true;
}
call_user_func("user_delete_$type", $u);
} else {
/* Delete the whole user */
foreach($u['types'] as $t) call_user_func("user_delete_$t", $u);
$finish_delete = true;
}
if($finish_delete == true) {
mysql_query("DELETE FROM users WHERE id='{$u['id']}'");
}
}
/* Returns true if loaded user ($u) is allowed to add role type $type to their
* profile. THis is intended as a last-stop mechanism, preventing, for example
* a student from co-existing with any other account type. */
function user_add_role_allowed($type, $u)
{
/* For example, a committee member can add a volunteer or judge role to
* their account. */
$allowed = array(
'committee' => array('volunteer', 'judge'),
'volunteer' => array('judge', 'committee'),
'judge' => array('volunteer', 'committee'),
'student' => array(),
'fair' => array() );
foreach($u['types'] as $ut) {
$allowed_array = $allowed[$ut];
if(in_array($type, $allowed[$ut])) return true;
}
return false;
}
function user_create($type, $u = NULL)
{
if(!is_array($u)) {
mysql_query("INSERT INTO users (`types`,`passwordset`,`created`)
VALUES ('$type', '0000-00-00', NOW())");
$uid = mysql_insert_id();
user_set_password($uid, NULL);
} else {
/* The user has been specified and already exists,
* just add a role */
$uid = $u['id'];
if(!user_add_role_allowed($type, $u)) {
/* If we get in here, someone is hand crafting URLs */
echo "HALT: invalid role add specified for operation.";
exit;
}
$new_types = implode(',', $u['types']).','.$type;
mysql_query("UPDATE users SET types='$new_types' WHERE id='$uid'");
}
switch($type) {
case 'volunteer':
case 'student':
case 'judge':
case 'fair':
mysql_query("INSERT INTO users_fair(`users_id`) VALUES ('$uid')");
break;
case 'committee':
mysql_query("INSERT INTO users_committee(`users_id`) VALUES ('$uid')");
break;
}
return user_load($uid, true);
}
function user_valid_user($user)
{
/* Find any character that doesn't match the valid username characters
* (^ inverts the matching remember */
$x = preg_match('[^a-zA-Z0-9@.-_]',$user);
/* If x==1, a match was found, and the input is bad */
return ($x == 1) ? false : true;
}
function user_valid_password($pass)
{
/* Same as user, but allow more characters */
$x = preg_match('[^a-zA-Z0-9 ~!@#$%^&*()-_=+|;:,<.>/?]',$pass);
/* If x==1, a match was found, and the input is bad */
if($x == 1) return false;
if(strlen($pass) < 6) return false;
return true;
}
/* A more strict version of isEmailAddress() */
function user_valid_email($str)
{
if(eregi('^[a-zA-Z0-9._-]+@[a-zA-Z0-9._-]+\.([a-zA-Z]{2,4})$', $str))
return true;
return false;
}
/* Perform some checks. Make sure the person is logged in, and that their
* password hasn't expired (the password_expired var is set in the login page)
*/
function user_auth_required($type, $access='')
{
global $config;
if(!isset($_SESSION['users_type'])) {
header("location: {$config['SFIABDIRECTORY']}/user_login.php?type=$type&notice=auth_required");
exit;
}
if($_SESSION['users_type'] != $type) {
header("location: {$config['SFIABDIRECTORY']}/user_login.php?type=$type&notice=auth_required");
exit;
}
if($_SESSION['password_expired'] == true) {
header("location: {$config['SFIABDIRECTORY']}/user_password.php");
exit;
}
if($access != '') {
if($type != 'committee') {
echo "CRITICAL ERROR, cannot check access in user_auth_required without specifying type=committee";
exit;
}
if(committee_auth_has_access($access) == false) {
header("Location: {$config['SFIABDIRECTORY']}/committee_main.php?notice=no_auth");
exit;
}
}
return true;
}
function user_volunteer_registration_status()
{
global $config;
// $now = date('Y-m-d H:i:s');
// if($now < $config['dates']['judgeregopen']) return "notopenyet";
// if($now > $config['dates']['judgeregclose']) return "closed";
return "open";
}
function user_judge_registration_status()
{
global $config;
$now = date('Y-m-d H:i:s');
if($now < $config['dates']['judgeregopen']) return "notopenyet";
if($now > $config['dates']['judgeregclose']) return "closed";
return "open";
}
$user_personal_fields_map = array(
'name' => array('firstname','lastname'),
'email' => array('email'),
'sex' => array('sex'),
'phonehome' => array('phonehome'),
'phonework' => array('phonework'),
'phonecell' => array('phonecell'),
'fax' => array('fax'),
'org' => array('organization'),
'birthdate' => array('birthdate'),
'lang' => array('lang'),
'address' => array('address', 'address2', 'postalcode'),
'city' => array('city'),
'province' => array('province'),
'firstaid' => array('firstaid','cpr'));
function user_personal_fields($type)
{
global $config, $user_personal_fields_map;
$ret = array('firstname','lastname','email');
$fields = $config["{$type}_personal_fields"];
if($fields != '') {
$fields = split(',', $fields);
foreach($fields as $f) {
$ret = array_merge($ret, $user_personal_fields_map[$f]);
}
}
return $ret;
}
function user_personal_required_fields($type)
{
global $config, $user_personal_fields_map;
$ret = array('firstname','lastname','email');
$required = $config["{$type}_personal_required"];
if($required != '') {
$fields = split(',', $required);
foreach($fields as $f) {
$ret = array_merge($ret, $user_personal_fields_map[$f]);
}
}
/* Filter some elements that are never required.
* - address2
*/
$ret = array_diff($ret, array('address2'));
return $ret;
}
function user_personal_info_status($u = false)
{
if($u == false) {
$u = user_load($_SESSION['users_id']);
}
$required = array();
foreach($u['types'] as $t) {
$required = array_merge($required,
user_personal_required_fields($t));
}
foreach($required as $r) {
$val = trim($u[$r]);
if(strlen($val) > 0) {
/* Ok */
} else {
return 'incomplete';
}
}
return 'complete';
}
function user_update_complete(&$u, $status)
{
if($status == 'complete' && $u['complete'] != 'yes') {
mysql_query("UPDATE users SET complete='yes' WHERE id='{$_SESSION['users_id']}'");
$u['complete'] = 'yes';
return;
}
if($status != 'complete' && $u['complete'] == 'yes') {
mysql_query("UPDATE users SET complete='no' WHERE id='{$_SESSION['users_id']}'");
$u['complete'] = 'no';
return;
}
}
function user_committee_login($u)
{
/* Double check, make sure the user is of this type */
if(!in_array('committee', $u['types'])) {
echo "ERROR: attempted to login committee on a non-committee user\n";
exit;
}
$u = user_load($u, true);
$_SESSION['access_admin'] = $u['access_admin'];// == 'yes') ? true : false;
$_SESSION['access_config'] = $u['access_config'];// == 'yes') ? true : false;
$_SESSION['access_super'] = $u['access_super'];// == 'yes') ? true : false;
}
function user_fair_login($u)
{
/* Double check, make sure the user is of this type */
if(!in_array('fair', $u['types'])) {
echo "ERROR: attempted to login fair on a non-fair user\n";
exit;
}
$u = user_load($u, true);
$_SESSION['fairs_id'] = $u['fairs_id'];// == 'yes') ? true : false;
}
?>