<?php require_once($INC . "/util.inc.php"); require_once($INC . "/log.inc.php"); require_once($INC . "/sql.inc.php"); require_once($INC . "/sess.inc.php"); require_once($INC . "/rights.inc.php"); $rg_user_rights = array( "C" => "Create repositories", "U" => "Add users" ); rg_rights_register("user", $rg_user_rights); function rg_user_set_error($str) { global $_rg_user_error; rg_log("\tError: $str"); $_rg_user_error = $str; } function rg_user_error() { global $_rg_user_error; return $_rg_user_error; } /* * Computes password hash */ function rg_user_pass($salt, $pass) { global $rg_pass_key; return sha1($salt . "===" . $rg_pass_key . "===" . $pass); } /* * Validates a password */ function rg_user_pass_ok($pass) { if (strlen($pass) < 5) { rg_user_set_error("password is too short (less than 5 chars)"); return FALSE; } return TRUE; } /* * Returns true if the user is ok */ function rg_user_ok($user) { global $rg_user_allow; global $rg_user_min_len; global $rg_user_max_len; if (rg_chars_allow($user, $rg_user_allow) !== TRUE) { rg_user_set_error("invalid user name (invalid chars [$user] [$rg_user_allow])"); return FALSE; } if (strlen($user) < $rg_user_min_len) { rg_user_set_error("user name too short (shorter than $rg_user_min_len)"); return FALSE; } if (strlen($user) > $rg_user_max_len) { rg_user_set_error("user name too long (longer than $rg_user_max_len)"); return FALSE; } return TRUE; } /* * Add a user * If uid > 0 - edit, else, add */ function rg_user_edit($db, $uid, $user, $email, $pass, $is_admin, $disk_quota_mb, $rights, $session_time, $confirm_token) { rg_log("user_edit: uid=$uid, user=$user email=$email" . " pass=$pass is_admin=$is_admin" . " disk_quota_mb=$disk_quota_mb rights=$rights" . " session_time=$session_time, confirm_token=$confirm_token..."); if (rg_user_ok($user) !== TRUE) return FALSE; $now = time(); $e_user = rg_sql_escape($db, $user); $e_salt = rg_id(40); $e_pass = rg_user_pass($e_salt, $pass); $e_email = rg_sql_escape($db, $email); $e_rights = rg_sql_escape($db, $rights); if (empty($confirm_token)) { // no need to confirm account $confirmed = $now; } else { $confirmed = 0; } if ($uid == 0) { // add if (rg_user_pass_ok($pass) !== TRUE) return FALSE; $sql = "INSERT INTO users (username, salt, pass, email, itime" . ", is_admin, disk_quota_mb, rights, session_time" . ", confirmed, confirm_token)" . " VALUES ('$e_user', '$e_salt', '$e_pass'" . ", '$e_email', $now, $is_admin, $disk_quota_mb" . ", '$e_rights', $session_time" . ", $confirmed, '$confirm_token')"; } else { // edit $salt_pass_add = ""; if (!empty($pass)) $salt_pass_add = ", pass = '$e_pass', salt = '$e_salt'"; $sql = "UPDATE users SET username = '$e_user'" . $salt_pass_add . ", email = '$e_email'" . ", is_admin = $is_admin" . ", disk_quota_mb = $disk_quota_mb" . ", rights = '$e_rights'" . ", session_time = $session_time" . " WHERE uid = $uid"; } $res = rg_sql_query($db, $sql); if ($res === FALSE) { rg_user_set_error("cannot insert/update user (" . rg_sql_error() . ")"); return FALSE; } rg_sql_free_result($res); return TRUE; } /* * Delete a user */ function rg_user_remove($db, $uid) { $uid = sprintf("%u", $uid); $sql = "DELETE FROM users WHERE uid = $uid"; $res = rg_sql_query($db, $sql); if ($res === FALSE) { rg_user_set_error("cannot remove user $uid (" . rg_sql_error() . ")"); return FALSE; } rg_sql_free_result($res); return TRUE; } /* * Returns info about a user (by uid, user or e-mail) */ function rg_user_info($db, $uid, $user, $email) { rg_log("user_info: uid/user/email=$uid/$user/$email..."); $ret = array(); $ret['ok'] = 0; $ret['exists'] = 0; $ret['uid'] = 0; $ret['is_admin'] = 0; if ($uid > 0) { $add = " AND uid = " . sprintf("%u", $uid); } else if (!empty($user)) { if (rg_user_ok($user) !== TRUE) return FALSE; $e_user = rg_sql_escape($db, $user); $add = " AND username = '$e_user'"; } else if (!empty($email)) { $e_email = rg_sql_escape($db, $email); $add = " AND email = '$e_email'"; } else { return FALSE; } $sql = "SELECT * FROM users WHERE 1 = 1" . $add; $res = rg_sql_query($db, $sql); if ($res === FALSE) { rg_user_set_error("cannot get info (" . rg_sql_error() . ")"); return $ret; } $ret['ok'] = 1; $rows = rg_sql_num_rows($res); if ($rows > 0) $row = rg_sql_fetch_array($res); rg_sql_free_result($res); if ($rows == 0) { rg_user_set_error("user not found"); return $ret; } $row['ok'] = 1; $row['exists'] = 1; rg_log("\tUser found."); return $row; } /* * Loads rg_ui based on sid, if possible */ function rg_user_login_by_sid($db, $sid, &$rg_ui) { rg_log("user_login_by_sid: sid=$sid..."); // Make sure it is not passed by client $rg_ui = array(); $rg_ui['uid'] = 0; $rg_ui['is_admin'] = 0; if (empty($sid)) return FALSE; $uid = rg_sess_valid($db, $sid); if ($uid == 0) return FALSE; $rg_ui = rg_user_info($db, $uid, "", ""); if ($rg_ui['exists'] != 1) { rg_user_set_error("invalid uid"); return FALSE; } rg_sess_update($db, $sid); rg_user_set_last_seen($db, $rg_ui['uid']); return TRUE; } /* * Test if a password is valid */ function rg_user_pass_valid($db, $uid, $pass) { rg_log("user_pass_valid: uid=$uid, pass=$pass..."); if (empty($pass)) { rg_user_set_error("password is empty"); return FALSE; } $ui = rg_user_info($db, $uid, "", ""); if ($ui['exists'] != 1) { rg_user_set_error("user does not exists"); return FALSE; } $sha1pass = rg_user_pass($ui['salt'], $pass); if (strcmp($sha1pass, $ui['pass']) != 0) { rg_user_set_error("password is not ok"); return FALSE; } rg_log("\tPass is valid."); return TRUE; } /* * Auto login the user */ function rg_user_auto_login($db, $uid, &$rg_ui) { $rg_ui = rg_user_info($db, $uid, "", ""); if ($rg_ui['ok'] != 1) return FALSE; if ($rg_ui['exists'] != 1) return FALSE; $sid = rg_id(40); rg_sess_add($db, $uid, $sid, $rg_ui['session_time']); setcookie("sid", $sid, 0, "/", $_SERVER['SERVER_NAME'], @strcmp($_SERVER['HTTPS'], "on") == 0 /* secure */, TRUE /* httponly */); return TRUE; } /* * Test if login is OK */ function rg_user_login_by_user_pass($db, $user, $pass, &$rg_ui) { rg_log("user_login_by_user_pass: user=$user, pass=$pass..."); $rg_ui = array(); $rg_ui['uid'] = 0; $rg_ui['is_admin'] = 0; if (empty($user) || empty($pass)) { rg_user_set_error("invalid user or pass"); return FALSE; } $rg_ui0 = rg_user_info($db, 0, $user, ""); if ($rg_ui0['ok'] != 1) { rg_user_set_error("internal error"); return FALSE; } if ($rg_ui0['exists'] != 1) { rg_user_set_error("invalid user or pass"); return FALSE; } if ($rg_ui0['suspended'] > 0) { rg_user_set_error("invalid user or pass"); return FALSE; } if ($rg_ui0['confirmed'] == 0) { rg_user_set_error("invalid user or pass"); return FALSE; } $sha1pass = rg_user_pass($rg_ui0['salt'], $pass); if (strcmp($sha1pass, $rg_ui0['pass']) != 0) { rg_user_set_error("invalid user or pass"); return FALSE; } $rg_ui = $rg_ui0; rg_user_auto_login($db, $rg_ui['uid'], $rg_ui); rg_user_set_last_seen($db, $rg_ui['uid']); return TRUE; } /* * Suspend an account * 1=suspend, 0=unsuspend */ function rg_user_suspend($db, $uid, $op) { rg_log("user_suspend: uid=$uid, op=$op"); $now = time(); if ($op == 1) $v = $now; else $v = 0; $sql = "UPDATE users SET suspended = $v WHERE uid = $uid"; $res = rg_sql_query($db, $sql); if ($res === FALSE) { rg_user_set_error("cannot suspend (" . rg_sql_error() . ")"); return FALSE; } rg_sql_free_result($res); return TRUE; } /* * Make/remove admin * 1=make, 0=remove */ function rg_user_make_admin($db, $uid, $op) { rg_log("user_make_admin: uid=$uid, op=$op"); $sql = "UPDATE users SET is_admin = $op WHERE uid = $uid"; $res = rg_sql_query($db, $sql); if ($res === FALSE) { rg_user_set_error("cannot make admin (" . rg_sql_error() . ")"); return FALSE; } rg_sql_free_result($res); return TRUE; } /* * Update last_seen field */ function rg_user_set_last_seen($db, $uid) { rg_log("user_set_last_seen: uid=$uid"); $now = time(); $sql = "UPDATE users SET last_seen = $now WHERE uid = $uid"; $res = rg_sql_query($db, $sql); if ($res === FALSE) { rg_user_set_error("cannot update last seen (" . rg_sql_error() . ")"); return FALSE; } rg_sql_free_result($res); return TRUE; } /* * List users */ function rg_user_list($db, $url) { rg_log("user_list, url=$url..."); $ret = ""; $uid = rg_var_uint("uid"); $suspend = rg_var_uint("suspend"); if ($suspend == 1) { if (!rg_user_suspend($db, $uid, 1)) $ret .= "<font color=red>Cannot suspend!</font><br />"; } $unsuspend = rg_var_uint("unsuspend"); if ($unsuspend == 1) { if (!rg_user_suspend($db, $uid, 0)) $ret .= "<font color=red>Cannot unsuspend!</font><br />"; } $make_admin = rg_var_uint("make_admin"); if ($make_admin == 1) { if (!rg_user_make_admin($db, $uid, 1)) $ret .= "<font color=red>Cannot make admin!</font><br />"; } $remove_admin = rg_var_uint("remove_admin"); if ($remove_admin == 1) { if (!rg_user_make_admin($db, $uid, 0)) $ret .= "<font color=red>Cannot remove admin!</font><br />"; } $remove = rg_var_uint("remove"); if ($remove > 0) { if (!rg_user_remove($db, $uid)) $ret .= "<font color=red>Cannot remove!</font><br />"; } $sql = "SELECT * FROM users ORDER BY username"; $res = rg_sql_query($db, $sql); if ($res === FALSE) { rg_user_set_error("Cannot get info (" . rg_sql_error() . ")!"); return FALSE; } $ret .= "<table>\n"; $ret .= "<tr>\n"; $ret .= " <th>Name</th>\n"; $ret .= " <th>E-mail</th>\n"; $ret .= " <th>Admin?</th>\n"; $ret .= " <th>Creation date (UTC)</th>\n"; $ret .= " <th>Quota</th>\n"; $ret .= " <th>Suspended?</th>\n"; $ret .= " <th>Confirmed?</th>\n"; $ret .= " <th>Session time</th>\n"; $ret .= " <th>Last seen (UTC)</th>\n"; $ret .= " <th>Rights</th>\n"; $ret .= " <th>Operations</th>\n"; $ret .= "</tr>\n"; while (($row = rg_sql_fetch_array($res))) { $ret .= "<tr>\n"; $ret .= " <td>" . $row['username'] . "</td>\n"; $ret .= " <td>" . $row['email'] . "</td>\n"; $ret .= " <td>" . ($row['is_admin'] == 1 ? "Yes" : "No") . "</td>\n"; $ret .= " <td>" . gmdate("Y-m-d H:i:s", $row['itime']) . "</td>\n"; if ($row['disk_quota_mb'] > 0) $_v = rg_1024($row['disk_quota_mb'] * 1024 * 1024); else $_v = "unlimited"; $ret .= " <td>" . $_v . "</td>\n"; $ret .= " <td>" . ($row['suspended'] == 0 ? "No" : "Yes") . "</th>\n"; $ret .= " <td>" . ($row['confirmed'] == 0 ? "No" : gmdate("Y-m-d H:i:s", $row['confirmed'])) . "</th>\n"; $ret .= " <td>" . $row['session_time'] . "s</td>\n"; $v = $row['last_seen'] == 0 ? "-" : gmdate("Y-m-d", $row['last_seen']); $ret .= " <td>" . $v . "</td>\n"; $v = implode(", ", rg_rights_text("user", $row['rights'])); $ret .= " <td>" . $v . "</td>\n"; // operations $_url = $url . "&uid=" . $row['uid']; $ret .= " <td>"; // edit $ret .= "[<a href=\"$_url&subsubop=3\">Edit</a>]"; // suspend $v = "suspend=1"; $t = "Suspend"; if ($row['suspended'] > 0) { $t = "Unsuspend"; $v = "unsuspend=1"; } $ret .= "[<a href=\"$_url&subsubop=1&$v\">$t</a>]"; // admin $v = "make_admin=1"; $t = "Make admin"; if ($row['is_admin'] == 1) { $t = "Remove admin"; $v = "remove_admin=1"; } $ret .= "[<a href=\"$_url&subsubop=1&$v\">$t</a>]"; // remove if ($row['suspended'] > 0) $ret .= "[<a href=\"$_url&subsubop=1&remove=1\">Remove!</a>]"; $ret .= " </td>"; $ret .= "</tr>\n"; } $ret .= "</table>\n"; rg_sql_free_result($res); return $ret; } /* * Returns uid by token, if not expired */ function rg_user_forgot_pass_uid($db, $token) { $ret = array(); $ret['ok'] = 0; $ret['uid'] = 0; rg_log("user_forgot_pass_uid: token=$token"); $now = time(); $e_token = rg_sql_escape($db, $token); $sql = "SELECT uid FROM forgot_pass" . " WHERE token = '$e_token'" . " AND expire > $now"; $res = rg_sql_query($db, $sql); if ($res === FALSE) { rg_user_set_error("cannot lookup token (" . rg_sql_error() . ")"); return $ret; } $ret['ok'] = 1; $rows = rg_sql_num_rows($res); if ($rows > 0) $row = rg_sql_fetch_array($res); rg_sql_free_result($res); if ($rows == 0) return $ret; $ret['uid'] = $row['uid']; return $ret; } /* * Reset password function (send mail) - helper */ function rg_user_forgot_pass_mail_prepare($db, $email) { rg_log("user_forgot_pass_mail_prepare: email=$email"); $expire = time() + 24 * 3600; $token = rg_id(40); $r = rg_user_info($db, 0, "", $email); if ($r['ok'] == 0) return FALSE; if ($r['exists'] == 0) return FALSE; $uid = $r['uid']; // store token in database $sql = "INSERT INTO forgot_pass (token, uid, expire)" . " VALUES ('$token', $uid, $expire)"; $res = rg_sql_query($db, $sql); if ($res === FALSE) { rg_user_set_error("cannot query (" . rg_sql_error() . ")"); return FALSE; } rg_sql_free_result($res); return $token; } /* * Reset password function (send mail) */ function rg_user_forgot_pass_mail($db, $email) { global $rg_admin_name, $rg_admin_email; rg_log("user_forgot_pass_mail: email=$email"); $forgot_token = rg_user_forgot_pass_mail_prepare($db, $email); if ($forgot_token === FALSE) return FALSE; $headers = "From: $rg_admin_name <$rg_admin_email>"; if (!mail($email, "Forgot password", "Hello!\n\n" . "If you want to reset the password, follow:\n" . (@strcmp($_SERVER['HTTPS'], "on") == 0 ? "https://" : "http://") . @$_SERVER['HTTP_HOST'] . rg_re_url("forgot_link") . "&forgot_token=$forgot_token", $headers, "-f $rg_admin_email")) { rg_user_set_error("Cannot send mail ($php_errormsg)!"); return FALSE; } return TRUE; } /* * After reseting the pass, we have to destroy all 'reset pass' requests */ function rg_user_forgot_pass_destroy($db, $uid) { rg_log("user_forgot_pass_destroy: uid=$uid"); $sql = "DELETE FROM forgot_pass WHERE uid = $uid"; $res = rg_sql_query($db, $sql); if ($res === FALSE) { rg_user_set_error("cannot query (" . rg_sql_error() . ")"); return FALSE; } rg_sql_free_result($res); return TRUE; } function rg_user_set_pass($db, $uid, $pass) { rg_log("user_set_pass: uid=$uid pass=$pass"); $e_salt = rg_id(40); $e_sha1pass = rg_user_pass($e_salt, $pass); $sql = "UPDATE users SET" ." salt = '$e_salt'" . ", pass = '$e_sha1pass'" . " WHERE uid = " . $uid; $res = rg_sql_query($db, $sql); if ($res === FALSE) { rg_user_set_error("cannot update pass (" . rg_sql_error() . ")"); return FALSE; } rg_sql_free_result($res); return TRUE; } /* * Confirm account creation (send mail) */ function rg_user_confirm_send($email, $token) { global $rg_admin_name, $rg_admin_email; rg_log("user_confirm_send: email=$email, token=$token"); $headers = "From: $rg_admin_name <$rg_admin_email>"; if (!mail($email, "Account creation confirmation", "Hello!\n\n" . "Please confirm your account creation following:\n" . (@strcmp($_SERVER['HTTPS'], "on") == 0 ? "https://" : "http://") . @$_SERVER['HTTP_HOST'] . rg_re_url("confirm") . "&token=$token", $headers, "-f $rg_admin_email")) { rg_user_set_error("Cannot send mail ($php_errormsg)!"); return FALSE; } return TRUE; } /* * Confirm account creation */ function rg_user_confirm($db, $token) { $now = time(); $sql = "SELECT uid FROM users WHERE confirm_token = '$token'"; $res = rg_sql_query($db, $sql); if ($res === FALSE) { rg_user_set_error("cannot search for token (" . rg_sql_error() . ")"); return FALSE; } $rows = rg_sql_num_rows($res); if ($rows > 0) $row = rg_sql_fetch_array($res); rg_sql_free_result($res); if ($rows == 0) { rg_user_set_error("cannot find token (" . rg_sql_error() . ")"); return FALSE; } $uid = $row['uid']; $sql = "UPDATE users SET confirmed = $now" . " WHERE uid = $uid"; $res = rg_sql_query($db, $sql); if ($res === FALSE) { rg_user_set_error("cannot update confirmed (" . rg_sql_error() . ")"); return FALSE; } rg_sql_free_result($res); return $uid; } /* * Add a suggestion to database */ function rg_user_suggestion($db, $uid, $email, $suggestion) { $e_email = rg_sql_escape($db, $email); $e_suggestion = rg_sql_escape($db, $suggestion); $sql = "INSERT INTO suggestions (uid, email, suggestion)" . " VALUES ($uid, '$e_email', '$e_suggestion')"; $res = rg_sql_query($db, $sql); if ($res === FALSE) { rg_user_set_error("cannot add suggestion (" . rg_sql_error() . ")"); return FALSE; } rg_sql_free_result($res); return TRUE; } ?>