forked from science-ation/science-ation
557 lines
17 KiB
PHP
557 lines
17 KiB
PHP
<?
|
|
/*
|
|
This file is part of the 'Science Fair In A Box' project
|
|
SFIAB Website: http://www.sfiab.ca
|
|
|
|
Copyright (C) 2010 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.
|
|
*/
|
|
?>
|
|
<?
|
|
|
|
function account_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 account_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;
|
|
}
|
|
|
|
/* Duplicate of common.inc.php:generatePassword, which will be deleted
|
|
* eventually when ALL users are handled through this file */
|
|
function account_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 account_set_password($accounts_id, $password = NULL)
|
|
{
|
|
$save_old = false;
|
|
if($password == NULL) {
|
|
$q = mysql_query("SELECT passwordset FROM accounts WHERE id='$accounts_id'");
|
|
$a = mysql_fetch_assoc($q);
|
|
/* Generate a new password */
|
|
$password = account_generate_password(12);
|
|
/* save the old password only if it's not an auto-generated one */
|
|
if($a['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 accounts SET $set WHERE id='$accounts_id'";
|
|
mysql_query($query);
|
|
echo mysql_error();
|
|
|
|
return $password;
|
|
}
|
|
|
|
function account_load($id)
|
|
{
|
|
$id = intval($id);
|
|
//we dont want password or the pending email code in here
|
|
$q = mysql_query("SELECT id,
|
|
username,
|
|
link_username_to_email,
|
|
passwordset,
|
|
email,
|
|
pendingemail,
|
|
superuser,
|
|
deleted,
|
|
deleted_datetime,
|
|
created
|
|
FROM accounts WHERE id='$id'");
|
|
if(mysql_num_rows($q) == 0) {
|
|
return false;
|
|
}
|
|
if(mysql_num_rows($q) > 1) {
|
|
return false;
|
|
}
|
|
|
|
$a = mysql_fetch_assoc($q);
|
|
return $a;
|
|
}
|
|
|
|
function account_get_password($id) {
|
|
$id=intval($id);
|
|
$q=mysql_query("SELECT password FROM accounts WHERE id='$id'");
|
|
$r=mysql_fetch_object($q);
|
|
return $r->password;
|
|
}
|
|
|
|
|
|
|
|
function account_load_by_username($username)
|
|
{
|
|
$un = mysql_real_escape_string($username);
|
|
$q = mysql_query("SELECT * FROM accounts WHERE username='$un'");
|
|
if(mysql_num_rows($q) == 0) {
|
|
return false;
|
|
}
|
|
if(mysql_num_rows($q) > 1) {
|
|
return false;
|
|
}
|
|
|
|
$a = mysql_fetch_assoc($q);
|
|
return $a;
|
|
}
|
|
|
|
|
|
function account_create($username,$password=NULL)
|
|
{
|
|
global $config;
|
|
$errMsg = '';
|
|
|
|
/* Sanity check username */
|
|
if(!account_valid_user($username)) {
|
|
$errMsg .= i18n('Invalid user name "%1"', array($username)) . "\n";
|
|
}else{
|
|
/* Make sure the account doesn't exist */
|
|
$us = mysql_real_escape_string($username);
|
|
$q = mysql_query("SELECT * FROM accounts WHERE username='$us'");
|
|
if(mysql_num_rows($q)) {
|
|
$errMsg .= i18n("The username %1 is already in use", array($username)) . "\n";
|
|
}
|
|
}
|
|
|
|
//if the password is set, make sure its valid, if its null, thats OK, it'll get generated and set by account_set_password
|
|
if($password && !account_valid_password($password)) {
|
|
$errMsg .= i18n("Invalid password") . "\n";
|
|
}
|
|
|
|
if($errMsg != '') return $errMsg;
|
|
|
|
/* Create the account */
|
|
mysql_query("INSERT INTO accounts (`username`,`created`,`deleted`,`superuser`)
|
|
VALUES ('$us', NOW(),'no','no')");
|
|
echo mysql_error();
|
|
|
|
$accounts_id = mysql_insert_id();
|
|
|
|
account_set_password($accounts_id, $password);
|
|
$a = account_load($accounts_id);
|
|
|
|
return $a;
|
|
}
|
|
|
|
function account_set_email($accounts_id,$email) {
|
|
global $config;
|
|
//we dont actually set the email until its confirmed, we only set the pending email :p
|
|
if(isEmailAddress($email)) {
|
|
$code=generatePassword(24);
|
|
mysql_query("UPDATE accounts SET email=NULL, pendingemail='".mysql_real_escape_string($email)."', pendingemailcode='$code' WHERE id='$accounts_id'");
|
|
$link = account_build_email_confirmation_link($accounts_id);
|
|
email_send('account_email_confirmation',$email,array(),array("EMAIL"=>$email,"EMAILCONFIRMATIONLINK"=>$link));
|
|
}
|
|
}
|
|
|
|
// generate the email confirmation URL. Separated from account_set_email for use elsewhere.
|
|
// returns null if no confirmation code is set for this account
|
|
function account_build_email_confirmation_link($accounts_id){
|
|
global $config;
|
|
$q = mysql_query("SELECT pendingemail, pendingemailcode FROM accounts WHERE id = $accounts_id");
|
|
$row = mysql_fetch_assoc($q);
|
|
$code = $row['pendingemailcode'];
|
|
$email = $row['pendingemail'];
|
|
if(trim($code) == ''){
|
|
return null;
|
|
}
|
|
|
|
$urlproto = $_SERVER['SERVER_PORT'] == 443 ? "https://" : "http://";
|
|
$urlmain = "$urlproto{$_SERVER['HTTP_HOST']}{$config['SFIABDIRECTORY']}";
|
|
$urlemailconfirm = "emailconfirmation.php?i=$accounts_id&e=".rawurlencode($email)."&c=".$code;
|
|
return $urlmain."/".$urlemailconfirm;
|
|
}
|
|
|
|
// add the specified role to the account's user record for the specified conference
|
|
// return true on success, false on failure
|
|
function account_add_role($accounts_id, $roles_id, $conferences_id, $password = null){
|
|
global $config;
|
|
global $conference;
|
|
|
|
//if we get role as a type string instead of an id (eg, 'teacher'), lets just look it up
|
|
if(!is_numeric($roles_id)) {
|
|
$tq=mysql_query("SELECT id FROM roles WHERE type='".mysql_real_escape_string($roles_id)."'");
|
|
$tr=mysql_fetch_object($tq);
|
|
$roles_id=$tr->id;
|
|
}
|
|
// avoid injections
|
|
$accounts_id=intval($accounts_id);
|
|
$roles_id=intval($roles_id);
|
|
$conferences_id=intval($conferences_id);
|
|
$password=mysql_real_escape_string($password);
|
|
|
|
// make sure the specified id's actually exist
|
|
if(mysql_result(mysql_query("SELECT COUNT(*) FROM accounts WHERE id = $accounts_id"), 0) != 1){
|
|
return "invalidaccount";
|
|
}
|
|
if(mysql_result(mysql_query("SELECT COUNT(*) FROM roles WHERE id = $roles_id"), 0) != 1){
|
|
return "invalidrole";
|
|
}
|
|
if(mysql_result(mysql_query("SELECT COUNT(*) FROM conferences WHERE id = $conferences_id"), 0) != 1){
|
|
return "invalidconference";
|
|
}
|
|
|
|
// find out if this account has a user record for this conference
|
|
$data = mysql_fetch_array(mysql_query("
|
|
SELECT * FROM users
|
|
WHERE conferences_id = $conferences_id
|
|
AND accounts_id = $accounts_id
|
|
"));
|
|
if(is_array($data)){
|
|
// they do indeed have a user record for this conference. Let's load it
|
|
$u = user_load($data['id']);
|
|
$users_id = $data['id'];
|
|
}else{
|
|
// They're not actually connected to this conference, let's hook 'em up
|
|
$u = user_create($accounts_id, $conferences_id);
|
|
$users_id = $u['id'];
|
|
|
|
// if this applies to their current session, update their session user id
|
|
if($_SESSION['accounts_id'] == $accounts_id && $_SESSION['conferences_id'] == $conferences_id){
|
|
$_SESSION['users_id'] = $users_id;
|
|
}
|
|
}
|
|
|
|
// we now have the user id that we need, let's check to see whether or not they
|
|
// already have the specified role.
|
|
if(mysql_result(mysql_query("SELECT COUNT(*) FROM user_roles WHERE users_id = $users_id AND roles_id = $roles_id"), 0) != 0){
|
|
// they already have this role. shell_exec("man true");
|
|
return 'ok';
|
|
}
|
|
|
|
// see if this role conflicts with existing ones
|
|
if(!account_add_role_allowed($accounts_id, $conferences_id, $roles_id)){
|
|
return 'invalidrole(account_add_role_allowed)';
|
|
}
|
|
|
|
// get the type of the role (eg. "judge", "participant", etc.)
|
|
$role = mysql_result(mysql_query("SELECT type FROM roles WHERE id = $roles_id"), 0);
|
|
|
|
if($_SESSION['superuser']!='yes') {
|
|
// and see if it's a valid one for this conference
|
|
if(!array_key_exists($role . '_registration_type', $config)){
|
|
return 'invalidrole(_registration_type)';
|
|
}
|
|
}
|
|
|
|
|
|
if( in_array("admin",$_SESSION['roles']) ||
|
|
in_array("config",$_SESSION['roles']) ||
|
|
$_SESSION['superuser']=="yes")
|
|
{
|
|
//do nothing, we're logged in a a superuser, admin or config, so we
|
|
//dont want/need to check the types, just go ahead and invite them
|
|
//its easie than reversing the logic of the if above.
|
|
}
|
|
else {
|
|
|
|
// and let's see if we meet the conditions for the registration type
|
|
$error = "";
|
|
switch($config[$role . '_registration_type']){
|
|
case 'open':
|
|
case 'openorinvite':
|
|
// this is allowed.
|
|
break;
|
|
case 'singlepassword':
|
|
if($password != $config[$role . '_registration_singlepassword']){
|
|
$error = "invalidpassword";
|
|
}
|
|
break;
|
|
case 'schoolpassword':
|
|
if($password != null){
|
|
$schoolId = $u['schools_id'];
|
|
$schoolDat = mysql_fetch_assoc(mysql_query("SELECT registration_password FROM schools WHERE id=$schoolId"));
|
|
if(is_array($schoolDat)){
|
|
if($password == $schoolDat['registration_password']) $valid = true;
|
|
$error = "invalidpassword";
|
|
}
|
|
}
|
|
break;
|
|
case 'invite':
|
|
if( in_array("teacher",$_SESSION['roles']) && $role=='participant') {
|
|
//if they are a teacher, they can add a participant role a-ok
|
|
$error = '';
|
|
}
|
|
else {
|
|
$error = 'invalidrole(invite_only)';
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
if($error != ""){
|
|
return $error;
|
|
}
|
|
|
|
// *whew* all conditions have been met. Let's go ahead and create the record
|
|
if(!mysql_query("INSERT INTO user_roles (accounts_id, users_id, roles_id, active, complete) VALUES($accounts_id, $users_id, $roles_id, 'yes', 'no')")){
|
|
return "mysqlerror:" . mysql_error();
|
|
}
|
|
|
|
$a=account_load($accounts_id);
|
|
$password=account_get_password($accounts_id);
|
|
|
|
//in this case, we want to send to pendingemail if thats all we have, because
|
|
//its possible that this is a new user that was just added and we just sent
|
|
//the email confirmation email as well, so on new user invitation, they will get
|
|
//the invite email as well as the email confirmation email.
|
|
if($a['email']) $e=$a['email'];
|
|
else if($a['pendingemail']) $e=$a['pendingemail'];
|
|
|
|
email_send("{$role}_new_invite",
|
|
$e,
|
|
array("FAIRNAME"=>$conference['name']),
|
|
array("FAIRNAME"=>$conference['name'],
|
|
"EMAIL"=>$e,
|
|
"USERNAME"=>$a['username'],
|
|
"PASSWORD"=>$password,
|
|
"ROLE"=>$role)
|
|
);
|
|
|
|
// if we made it this far, the role was successfully added
|
|
return 'ok';
|
|
}
|
|
|
|
// find out if the specifed role can be added to this account at the specified conference
|
|
function account_add_role_allowed($accounts_id, $roles_id, $conferences_id){
|
|
$returnval = true;
|
|
|
|
// avoid injections
|
|
$accounts_id *= 1;
|
|
$roles_id *= 1;
|
|
$conferences_id *= 1;
|
|
|
|
// get the user id for this account/conference
|
|
$userdat = mysql_fetch_assoc(mysql_query("SELECT id FROM users WHERE accounts_id = $accounts_id AND conferences_id = $conferences_id"));
|
|
|
|
// If this condition isn't met, then the account is not connected to the conference.
|
|
// In that case, the role can be allowed as there is no conflict.
|
|
if(is_array($userdat)){
|
|
$users_id = $userdat['id'];
|
|
|
|
// get the roles for the specified account at the specified conference
|
|
$query = mysql_query("
|
|
SELECT * FROM user_roles
|
|
WHERE users_id = $users_id
|
|
");
|
|
|
|
while($returnval && $row = mysql_fetch_assoc($query)){
|
|
switch($row['type']){
|
|
case 'participant':
|
|
// Student cant' add any other role
|
|
$returnval = false;
|
|
break;
|
|
default:
|
|
if($role == 'participant') {
|
|
// No role can add the participant role
|
|
$returnval = false;
|
|
}
|
|
|
|
// All other roles can coexist (even the fair role)
|
|
break;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
return $returnval;
|
|
}
|
|
|
|
// remove the specified role from the account's user record for the specified conference
|
|
// return true on success, false on failure
|
|
function account_remove_role($accounts_id, $roles_id, $conferences_id){
|
|
// avoid injections
|
|
$accounts_id *= 1;
|
|
$roles_id *= 1;
|
|
$conferences_id *= 1;
|
|
|
|
// make sure the specified id's actually exist
|
|
if(mysql_result(mysql_query("SELECT COUNT(*) FROM accounts WHERE id = $accounts_id"), 0) != 1){
|
|
return "invalidaccount";
|
|
}
|
|
if(mysql_result(mysql_query("SELECT COUNT(*) FROM roles WHERE id = $roles_id"), 0) != 1){
|
|
return "invalidrole";
|
|
}
|
|
if(mysql_result(mysql_query("SELECT COUNT(*) FROM conferences WHERE id = $conferences_id"), 0) != 1){
|
|
return "invalidconference";
|
|
}
|
|
|
|
// very little error catching needed here. If the role's there, we hopfully succeed in
|
|
// removing it. If it's not, then we succeed in doing nothing
|
|
$data = mysql_fetch_array(mysql_query("
|
|
SELECT * FROM users
|
|
WHERE conferences_id = $conferences_id
|
|
AND accounts_id = $accounts_id
|
|
"));
|
|
if(is_array($data)){
|
|
// they do indeed have a user record for this conference.
|
|
$users_id = $data['id'];
|
|
|
|
// Do role-specific remove actions
|
|
$role = mysql_result(mysql_query("SELECT `type` FROM roles WHERE id = $roles_id"), 0);
|
|
switch($role) {
|
|
case 'committee':
|
|
mysql_query("DELETE FROM committees_link WHERE accounts_id='{$accounts_id}'");
|
|
break;
|
|
|
|
case 'judge':
|
|
mysql_query("DELETE FROM judges_teams_link WHERE users_id='$users_id'");
|
|
mysql_query("DELETE FROM judges_specialawards_sel WHERE users_id='$users_id'");
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
// and now we can remove the role link itself
|
|
mysql_query("DELETE FROM user_roles WHERE roles_id={$roles_id} AND users_id='$users_id'");
|
|
}
|
|
return 'ok';
|
|
}
|
|
|
|
// A function for handling updates of any fields that can be modified through an API call.
|
|
// returns 'ok' on success, error message otherwise.
|
|
function account_update_info($fields){
|
|
if($_SESSION['accounts_id']) {
|
|
$accounts_id = $_SESSION['accounts_id'];
|
|
}else{
|
|
return 'you must be logged in to change your account settings';
|
|
}
|
|
|
|
if(!is_array($fields)) return 'account_update_info expects an array';
|
|
$message = 'ok';
|
|
$updates = array();
|
|
foreach($fields as $index => $value){
|
|
switch($index){
|
|
case 'username':
|
|
if(account_valid_user($value)){
|
|
$u = mysql_real_escape_string($value);
|
|
$q = mysql_query("SELECT id FROM accounts WHERE username = '$u' AND deleted = 'no' AND id != $accounts_id");
|
|
if(mysql_num_rows($q) != 0){
|
|
$message = "username already in use";
|
|
}else{
|
|
$updates[$index] = $value;
|
|
}
|
|
}else{
|
|
$message = "invalid username";
|
|
}
|
|
break;
|
|
|
|
case 'password':
|
|
$q = mysql_query("SELECT password FROM accounts WHERE id='$accounts_id' AND password='" . mysql_real_escape_string($value) . "'");
|
|
if(mysql_num_rows($q)){
|
|
// ignore this parameter. The password has not changed
|
|
}else if(!account_valid_password($value)){
|
|
$message = "invalid password";
|
|
}else{
|
|
$updates[$index] = $value;
|
|
}
|
|
break;
|
|
|
|
case 'link_username_to_email':
|
|
if(in_array($value, array('yes', 'no'))){
|
|
if($value=='yes') {
|
|
//if its yes, we can only do it if username==email
|
|
if($fields['username']==$fields['email']) {
|
|
$updates[$index] = $value;
|
|
} else {
|
|
$message="username and email must match for link_username_toemail";
|
|
}
|
|
}
|
|
else {
|
|
$updates[$index] = $value;
|
|
}
|
|
}else{
|
|
$message = '"link_username_to_email" must be either a "yes" or "no" value';
|
|
}
|
|
break;
|
|
|
|
case 'email':
|
|
if(isEmailAddress($value)){
|
|
$updates[$index] = $value;
|
|
}else{
|
|
$message = 'invalid e-mail address';
|
|
}
|
|
break;
|
|
|
|
default:
|
|
$message = 'invalid field name';
|
|
}
|
|
}
|
|
|
|
if($message != 'ok'){
|
|
return $message;
|
|
}
|
|
|
|
// the data's all been validated, so we can continue with the actual update.
|
|
// doing it separately from the above loop to ensure that it's an all-or nothing update;
|
|
// none of it will happen if any one part is erroneous.
|
|
foreach($updates as $index => $value){
|
|
switch($index){
|
|
case 'username':
|
|
$username = mysql_real_escape_string($value);
|
|
mysql_query("UPDATE accounts SET username = '$username' WHERE id = $accounts_id");
|
|
break;
|
|
|
|
case 'password':
|
|
account_set_password($accounts_id, mysql_real_escape_string($value));
|
|
break;
|
|
|
|
case 'link_username_to_email':
|
|
mysql_query("UPDATE accounts SET link_username_to_email = '$value' WHERE id = $accounts_id");
|
|
break;
|
|
|
|
case 'email':
|
|
account_set_email($accounts_id, $value);
|
|
break;
|
|
}
|
|
}
|
|
|
|
return $message;
|
|
}
|
|
|
|
?>
|