info_log[] = $string; } // error log var $error_log = array(); // Error logging function error($string) { $this->error_log[] = $string; } // all possible values for a hexadecimal number var $hex = "0123456789abcdef"; // all possible values for an ascii password, skewed a bit so the number to letter ratio is closer to 1:1 var $ascii = "0a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t0u1v2w3x4y5z6A7B8C9D0E1F2G3H4I5J6K7L8M9N0O1P2Q3R4S5T6U7V8W9X0Y1Z23456789"; // the regular expression for email matching (see http://www.regular-expressions.info/email.html) const emailregexp = "/[a-z0-9!#$%&'*+\/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+\/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?/"; // the regular expression for SHA1 hash matching const sha1regexp = "/[0123456789abcdef]{40,40}/"; // this will tell us whether the client that requested the page is authenticated or not. var $authenticated = false; // the guest user name const GUEST_USER = GUEST_HASH; // this will contain the user name for the user doing the page request var $username = User::GUEST_USER; // if this is a properly logged in user, this will contain the data directory location for this user var $userdir = false; // the user's email address, if logged in. var $email = ""; var $adminEmail = ""; var $adminList = array(); // the user's role in the system var $role = ""; var $group = ""; // global database handle var $database = false; //EMAIL SHIT function startEmail($email, $username, $subject, $body){ $mail = new PHPMailer; $mail->isSMTP(); $mail->Host = SMTPHOST; $mail->SMTPAuth = SMTPHOSTAUTH; $mail->Username = SMTPHOSTUSERNAME; $mail->Password = SMTPHOSTPASSWORD; $mail->SMTPSecure = SMTPHOSTTYPE; $mail->Port = SMTPHOSTPORT; $mail->setFrom(SMTPHOSTSENDEREMAIL, SMTPHOSTSENDERNAME); $mail->addReplyTo(SMTPHOSTSENDEREMAIL, SMTPHOSTSENDERNAME); $mail->isHTML(true); $mail->addAddress($email, $username); $mail->Subject = $subject; $mail->Body = $body; //$mail->send(); if(!$mail->send()) { $this->error('Mailer Error: ' . $mail->ErrorInfo); $this->error = 'Mailer Error: ' . $mail->ErrorInfo; } else { $this->info('E-Mail sent!'); } } // class object constructor function __construct($registration_callback=false) { // session management comes first. Warnings are repressed with @ because it will warn if something else already called session_start() @session_start(); if(!isset($_COOKIE['Organizr'])) { if (empty($_SESSION["username"]) || empty($_SESSION["token"])) $this->resetSession(); }else{ $_SESSION["username"] = $_COOKIE['OrganizrU']; } // file location for the user database $dbfile = DATABASE_LOCATION.'users.db'; // do we need to build a new database? $rebuild = false; if(!file_exists($dbfile)) { $rebuild = true;} // bind the database handler $this->database = new PDO("sqlite:" . $dbfile); // If we need to rebuild, the file will have been automatically made by the PDO call, // but we'll still need to define the user table before we can use the database. if($rebuild) { $this->rebuild_database($dbfile); } // finally, process the page request. $this->process($registration_callback); } // this function rebuilds the database if there is no database to work with yet function rebuild_database($dbfile) { $this->info("creating/rebuilding database as ".$dbfile); createSQLiteDB(); $this->database = new PDO("sqlite:" . $dbfile); } // process a page request function process(&$registration_callback=false) { $this->database->beginTransaction(); if(isset($_POST["op"])) { $operation = $_POST["op"]; // logging in or out, and dropping your registration, may change authentication status if($operation == "login") { $this->authenticated = $this->login(); } // logout and unregister will unset authentication if successful elseif($operation == "logout") { $this->authenticated = !$this->logout(); } elseif($operation == "unregister") { $this->authenticated = !$this->unregister(); } // anything else won't change authentication status. elseif($operation == "register") { $this->register($registration_callback); } elseif($operation == "update") { $this->update(); } elseif($operation == "invite") { $this->invite(); } elseif($operation == "deleteinvite") { $this->deleteInvite(); } // we only allow password resetting if we can send notification mails elseif($operation == "reset" && User::use_mail) { $this->reset_password(); } } // if the previous operations didn't authorise the current user, // see if they're already marked as authorised in the database. if(!$this->authenticated) { $username = $_SESSION["username"]; if($username != User::GUEST_USER) { $this->authenticated = $this->authenticate_user($username,""); if($this->authenticated) { $this->mark_user_active($username); }}} // at this point we can make some globals available. $this->username = $_SESSION["username"]; $this->userdir = ($this->username !=User::GUEST_USER? USER_HOME . $this->username : false); $this->email = $this->get_user_email($this->username); $this->adminEmail = $this->get_admin_email(); $this->adminList = $this->get_admin_list(); $this->role = $this->get_user_role($this->username); //$this->group = $this->get_user_group($this->username); // clear database $this->database->commit(); $this->database = null; } // --------------------- // validation passthroughs // --------------------- /** * Called when the requested POST operation is "login" */ function login() { // get relevant values $username = $_POST["username"]; $sha1 = $_POST["sha1"]; $password = $_POST["password"]; $rememberMe = $_POST["rememberMe"]; // step 1: someone could have bypassed the javascript validation, so validate again. if(!$this->validate_user_name($username)) { $this->info("log in error: user name did not pass validation"); return false; } if(preg_match(User::sha1regexp, $sha1)==0) { $this->info("log in error: password did not pass validation"); return false; } // step 2: if validation passed, log the user in return $this->login_user($username, $sha1, $rememberMe == "true", $password); } /** * Called when the requested POST operation is "logout" */ function logout() { // get relevant value $username = $_POST["username"]; // step 1: validate the user name. if(!$this->validate_user_name($username)) { $this->info("log in error: user name did not pass validation"); return false; } // step 2: if validation passed, log the user out return $this->logout_user($username); } /** * Users should always have the option to unregister */ function unregister() { // get relevant value $username = $_POST["username"]; // step 1: validate the user name. if(!$this->validate_user_name($username)) { $this->info("unregistration error: user name did not pass validation"); return false; } // step 2: if validation passed, drop the user from the system return $this->unregister_user($username); } /** * Called when the requested POST operation is "register" */ function register(&$registration_callback=false) { // get relevant values $username = $_POST["username"]; $email = $_POST["email"]; $sha1 = $_POST["sha1"]; $settings = $_POST["settings"]; $validate = (isset($_POST["validate"])) ? $_POST["validate"] : null; if(REGISTERPASSWORD != ""){ if($validate == REGISTERPASSWORD){ $validate = true; } }else{ $validate = null; } // step 1: someone could have bypassed the javascript validation, so validate again. if(!$this->validate_user_name($username)) { $this->info("registration error: user name did not pass validation"); return false; } if(preg_match(User::emailregexp, $email)==0) { $this->info("registration error: email address did not pass validation"); return false; } if(preg_match(User::sha1regexp, $sha1)==0) { $this->info("registration error: password did not pass validation"); return false; } // step 2: if validation passed, register user $registered = $this->register_user($username, $email, $sha1, $registration_callback, $settings, $validate); return $registered; } /** * Called when the requested POST operation is "update" */ function update() { // get relevant values @$username = trim($_POST["username"]); @$email = trim($_POST["email"]); @$sha1 = trim($_POST["sha1"]); @$role = trim($_POST["role"]); // step 1: someone could have bypassed the javascript validation, so validate again. if($email !="" && preg_match(User::emailregexp, $email)==0) { $this->info("registration error: email address did not pass validation"); return false; } if($sha1 !="" && preg_match(User::sha1regexp, $sha1)==0) { $this->info("registration error: password did not pass validation"); return false; } // step 2: if validation passed, update the user's information return $this->update_user($username, $email, $sha1, $role); } /** * Called when the requested POST operation is "invite" */ function invite() { // get relevant values @$username = trim($_POST["username"]); @$email = trim($_POST["email"]); @$server = trim($_POST["server"]); // step 1: someone could have bypassed the javascript validation, so validate again. if($email !="" && preg_match(User::emailregexp, $email)==0) { $this->info("invite error: email address did not pass validation"); writeLog("error", "$email didn't pass validation"); return false; } // step 2: if validation passed, send the user's information for invite return $this->invite_user($username, $email, $server); writeLog("success", "passing invite info for $email"); } /** * Reset a user's password */ function reset_password() { // get the email for which we should reset $email = $_POST["email"]; // step 1: someone could have bypassed the javascript validation, so validate again. if(preg_match(User::emailregexp, $email)==0) { $this->info("email address did not pass validation"); return false; } // step 2: if validation passed, see if there is a matching user, and reset the password if there is $newpassword = $this->random_ascii_string(20); $sha1 = sha1($newpassword); $query = "SELECT username, token FROM users WHERE email = '$email'"; $username = ""; $token = ""; foreach($this->database->query($query) as $data) { $username = $data["username"]; $token = $data["token"]; break; } // step 2a: if there was no user to reset a password for, stop. if($username == "" || $token == "") return false; // step 2b: if there was a user to reset a password for, reset it. $dbpassword = $this->token_hash_password($username, $sha1, $token); $update = "UPDATE users SET password = '$dbpassword' WHERE email= '$email'"; writeLog("success", "$username has reset their password"); $this->database->exec($update); //$this->info("Email has been sent with new password"); // step 3: notify the user of the new password $subject = DOMAIN . " Password Reset"; $language = new setLanguage; $domain = getServerPath(); $body = orgEmail( $header = $language->translate('EMAIL_RESET_HEADER'), $title = $language->translate('EMAIL_RESET_TITLE'), $user = $username, $mainMessage =$language->translate('EMAIL_RESET_MESSAGE')."
".$newpassword, $button = $language->translate('EMAIL_RESET_BUTTON'), $buttonURL = $domain, $subTitle = $language->translate('EMAIL_RESET_SUBTITLE'), $subMessage = $language->translate('EMAIL_RESET_SUBMESSAGE') ); $this->startEmail($email, $username, $subject, $body); } // ------------------ // specific functions // ------------------ // session management: set session values function setSession($username, $token) { $_SESSION["username"]=$username; $_SESSION["token"]=$token; } // session management: reset session values function resetSession() { $_SESSION["username"] = User::GUEST_USER; $_SESSION["token"] = -1; unset($_COOKIE['Organizr']); setcookie('Organizr', '', time() - 3600, '/', DOMAIN); setcookie('Organizr', '', time() - 3600, '/'); unset($_COOKIE['OrganizrU']); setcookie('OrganizrU', '', time() - 3600, '/', DOMAIN); setcookie('OrganizrU', '', time() - 3600, '/'); unset($_COOKIE['cookiePassword']); setcookie("cookiePassword", '', time() - 3600, '/', DOMAIN); setcookie("cookiePassword", '', time() - 3600, '/'); unset($_COOKIE['Auth']); setcookie("Auth", '', time() - 3600, '/', DOMAIN); setcookie("Auth", '', time() - 3600, '/'); unset($_COOKIE['mpt']); setcookie("mpt", '', time() - 3600, '/', DOMAIN); setcookie("mpt", '', time() - 3600, '/'); } /** * Validate a username. Empty usernames or names * that are modified by making them SQL safe are * considered not validated. */ function validate_user_name($username) { $cleaned = $this->clean_SQLite_string($username); $validated = ($cleaned != "" && $cleaned==$username); if(!$validated) { $this->error = "user name did not pass validation."; $this->error("user name did not pass validation."); } return $validated; } /** * Clean strings for SQL insertion as string in SQLite (single quote enclosed). * Note that if the cleaning changes the string, this system won't insert. * The validate_user_name() function will flag this as a validation failure and * the database operation is never carried out. */ function clean_SQLite_string($string) { $search = array("'", "\\", ";"); $replace = array('', '', ''); return trim(str_replace($search, $replace, $string)); } /** * Verify that the given username is allowed * to perform the given operation. */ function authenticate_user($username, $operation) { // actually logged in? if($this->is_user_active($username)===false) { return false; } // logged in, but do the tokens match? $token = $this->get_user_token($username); if(MULTIPLELOGIN == "false"){ if(isset($_COOKIE["Organizr"])){ if($_COOKIE["Organizr"] == $token){ return true; }else{ $this->error("cookie token mismatch for $username"); unset($_COOKIE['Organizr']); setcookie('Organizr', '', time() - 3600, '/', DOMAIN); setcookie('Organizr', '', time() - 3600, '/'); unset($_COOKIE['OrganizrU']); setcookie('OrganizrU', '', time() - 3600, '/', DOMAIN); setcookie('OrganizrU', '', time() - 3600, '/'); unset($_COOKIE['cookiePassword']); setcookie("cookiePassword", '', time() - 3600, '/', DOMAIN); setcookie("cookiePassword", '', time() - 3600, '/'); unset($_COOKIE['Auth']); setcookie("Auth", '', time() - 3600, '/', DOMAIN); setcookie("Auth", '', time() - 3600, '/'); unset($_COOKIE['mpt']); setcookie("mpt", '', time() - 3600, '/', DOMAIN); setcookie("mpt", '', time() - 3600, '/'); return false; } }else{ if($token != $_SESSION["token"]) { $this->error("token mismatch for $username"); return false; } // active, using the correct token -> authenticated setcookie("cookiePassword", COOKIEPASSWORD, time() + (86400 * 7), "/", DOMAIN); return true; } }else{ setcookie("cookiePassword", COOKIEPASSWORD, time() + (86400 * 7), "/", DOMAIN); return true; } } /** * Unicode friendly(ish) version of strtolower * see: http://ca3.php.net/manual/en/function.strtolower.php#91805 */ function strtolower_utf8($string) { $convert_to = array( "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "à", "á", "â", "ã", "ä", "å", "æ", "ç", "è", "é", "ê", "ë", "ì", "í", "î", "ï", "ð", "ñ", "ò", "ó", "ô", "õ", "ö", "ø", "ù", "ú", "û", "ü", "ý", "а", "б", "в", "г", "д", "е", "ё", "ж", "з", "и", "й", "к", "л", "м", "н", "о", "п", "р", "с", "т", "у", "ф", "х", "ц", "ч", "ш", "щ", "ъ", "ы", "ь", "э", "ю", "я" ); $convert_from = array( "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "À", "Á", "Â", "Ã", "Ä", "Å", "Æ", "Ç", "È", "É", "Ê", "Ë", "Ì", "Í", "Î", "Ï", "Ð", "Ñ", "Ò", "Ó", "Ô", "Õ", "Ö", "Ø", "Ù", "Ú", "Û", "Ü", "Ý", "А", "Б", "В", "Г", "Д", "Е", "Ё", "Ж", "З", "И", "Й", "К", "Л", "М", "Н", "О", "П", "Р", "С", "Т", "У", "Ф", "Х", "Ц", "Ч", "Ш", "Щ", "Ъ", "Ъ", "Ь", "Э", "Ю", "Я" ); return str_replace($convert_from, $convert_to, $string); } /** * This functions flattens user name strings for similarity comparison purposes */ function homogenise_username($string) { // cut off trailing numbers $string = preg_replace("/\d+$/", '', $string); // and then replace non-terminal numbers with // their usual letter counterparts. $s = array("1","3","4","5","7","8","0"); $r = array("i","e","a","s","t","ate","o"); $string = str_replace($s, $r, $string); // finally, collapse case return $this->strtolower_utf8($string); } /** * We don't require assloads of personal information. * A username and a password are all we want. The rest * is profile information that can be set, but in no way * needs to be, in the user's profile section */ function register_user($username, $email, $sha1, &$registration_callback = false, $settings, $validate) { $username = strtolower($username); $dbpassword = $this->token_hash_password($username, $sha1, ""); if($dbpassword==$sha1) die("password hashing is not implemented."); $newRole = "admin"; $queryAdmin = "SELECT username FROM users"; foreach($this->database->query($queryAdmin) as $data) { $newRole = "user"; } if($newRole == "user" && $validate == null){ writeLog("error", "$username on IP ".$_SERVER['REMOTE_ADDR']." is trying to hack your Organizr"); $this->error = "Hack attempt has been made. What are you doing? Logging your IP now...?"; $this->error("Hack attempt has been made. What are you doing? Logging your IP now..."); return false; } if($username && User::use_mail) { // send email notification $subject = "Welcome to ".DOMAIN; $language = new setLanguage; $domain = getServerPath(); $body = orgEmail( $header = $language->translate('EMAIL_NEWUSER_HEADER'), $title = $language->translate('EMAIL_NEWUSER_TITLE'), $user = $username, $mainMessage =$language->translate('EMAIL_NEWUSER_MESSAGE'), $button = $language->translate('EMAIL_NEWUSER_BUTTON'), $buttonURL = $domain, $subTitle = $language->translate('EMAIL_NEWUSER_SUBTITLE'), $subMessage = $language->translate('EMAIL_NEWUSER_SUBMESSAGE') ); $this->startEmail($email, $username, $subject, $body); } // Does user already exist? (see notes on safe reporting) if(User::unsafe_reporting) { $query = "SELECT username FROM users WHERE username LIKE '$username' COLLATE NOCASE"; foreach($this->database->query($query) as $data) { $this->info("user account for $username not created."); $this->error = "this user name is already being used by someone else."; $this->error("this user name is already being used by someone else."); return false; } } else { $query = "SELECT username FROM users"; $usernames = array(); foreach($this->database->query($query) as $data) { $usernames[] = $this->homogenise_username($data["username"]); } if(in_array($this->homogenise_username($username), $usernames)) { //$this->info("user account for $username not created."); $this->error = "$username is not allowed, because it is too similar to other user names."; $this->error("$username is not allowed, because it is too similar to other user names."); return false; } } // Is email address already in use? (see notes on safe reporting) if (isset($email) && $email) { $query = "SELECT * FROM users WHERE email = '$email' COLLATE NOCASE"; foreach($this->database->query($query) as $data) { $this->info("user account for $username not created."); $this->error = "this email address is already in use by someone else."; $this->error("this email address is already in use by someone else."); return false; } } else { $email = $this->random_ascii_string(32).'@placeholder.eml'; } // This user can be registered $insert = "INSERT INTO users (username, email, password, token, role, active, last) "; $insert .= "VALUES ('".strtolower($username)."', '$email', '$dbpassword', '', '$newRole', 'false', '') "; $this->database->exec($insert); $query = "SELECT * FROM users WHERE username = '$username'"; foreach($this->database->query($query) as $data) { $this->info("created user account for $username"); writeLog("success", "$username has just registered"); $this->update_user_token($username, $sha1, false); // make the user's data directory $dir = USER_HOME . $username; if(!mkdir($dir, 0760, true)) { $this->error("could not make user directory $dir"); return false; } //$this->info("created user directory $dir"); // if there is a callback, call it if($registration_callback !== false) { $registration_callback($username, $email, $dir); } if($settings !== 'true' && $settings !== true) { $this->login_user($username, $sha1, true, '', false); } return true; } $this->error = "unknown database error occured."; $this->error("unknown database error occured."); return false; } /** * Log a user in */ function login_user($username, $sha1, $remember, $password, $surface = true) { $username = strtolower($username); $buildLog = function($username, $authType) { if(file_exists(FAIL_LOG)) { $getFailLog = str_replace("\r\ndate", "date", file_get_contents(FAIL_LOG)); $gotFailLog = json_decode($getFailLog, true); } $failLogEntryFirst = array('logType' => 'login_log', 'auth' => array(array('date' => date("Y-m-d H:i:s"), 'username' => $username, 'ip' => $_SERVER['REMOTE_ADDR'], 'auth_type' => $authType))); $failLogEntry = array('date' => date("Y-m-d H:i:s"), 'username' => $username, 'ip' => $_SERVER['REMOTE_ADDR'], 'auth_type' => $authType); if(isset($gotFailLog)) { array_push($gotFailLog["auth"], $failLogEntry); $writeFailLog = str_replace("date", "\r\ndate", json_encode($gotFailLog)); } else { $writeFailLog = str_replace("date", "\r\ndate", json_encode($failLogEntryFirst)); } return $writeFailLog; }; // External Authentication $authSuccess = false; $function = 'plugin_auth_'.AUTHBACKEND; switch (AUTHTYPE) { case 'external': if (function_exists($function)) { $authSuccess = $function($username, $password); } break; case 'both': if (function_exists($function)) { $authSuccess = $function($username, $password); } default: // Internal if (!$authSuccess) { // perform the internal authentication step $query = "SELECT password FROM users WHERE username = '".$username."' COLLATE NOCASE"; foreach($this->database->query($query) as $data) { if (password_verify($password, $data["password"])) { // Better $authSuccess = true; } else { // Legacy - Less Secure $dbpassword = $this->token_hash_password($username, $sha1, $this->get_user_token($username)); if($dbpassword==$data["password"]) { $authSuccess = true; } } } } } if ($authSuccess) { // Make sure user exists in database $query = "SELECT username FROM users WHERE username = '".$username."' COLLATE NOCASE"; $userExists = false; foreach($this->database->query($query) as $data) { $userExists = true; break; } if ($userExists) { // authentication passed - 1) mark active and update token $this->mark_user_active($username); $this->setSession($username, $this->update_user_token($username, $sha1, false)); // authentication passed - 2) signal authenticated if($remember == "true") { setcookie("Organizr", $this->get_user_token($username), time() + (86400 * 7), "/", DOMAIN); setcookie("OrganizrU", $username, time() + (86400 * 7), "/", DOMAIN); } if(OMBIURL){ $ombiToken = getOmbiToken($username, $password); if($ombiToken){ setcookie("Auth", $ombiToken, time() + (86400 * 7), "/", DOMAIN); } } if(PLEXURL && isset($authSuccess['token'])){ setcookie("mpt", $authSuccess['token'], time() + (86400 * 7), "/", DOMAIN); } $this->info("Welcome $username"); file_put_contents(FAIL_LOG, $buildLog($username, "good_auth")); chmod(FAIL_LOG, 0660); setcookie("cookiePassword", COOKIEPASSWORD, time() + (86400 * 7), "/", DOMAIN); writeLog("success", "$username has logged in"); return true; } else if (AUTHBACKENDCREATE !== 'false' && $surface) { // Create User $falseByRef = false; $this->register_user($username, (is_array($authSuccess) && isset($authSuccess['email']) ? $authSuccess['email'] : ''), $sha1, $falseByRef, !$remember, true); } else { // authentication failed //$this->info("Successful Backend Auth, No User in DB, Create Set to False"); file_put_contents(FAIL_LOG, $buildLog($username, "bad_auth")); chmod(FAIL_LOG, 0660); if(User::unsafe_reporting) { $this->error = "Successful Backend Auth, $username not in DB, Create Set to False."; $this->error("Successful Backend Auth, $username not in DB, Create Set to False."); } else { $this->error = "Not permitted to login as this user, please contact an administrator."; $this->error("Not permitted to login as this user, please contact an administrator"); } return false; } } else if (!$authSuccess) { // authentication failed //$this->info("password mismatch for $username"); writeLog("error", "$username tried to sign-in with the wrong password"); file_put_contents(FAIL_LOG, $buildLog($username, "bad_auth")); chmod(FAIL_LOG, 0660); if(User::unsafe_reporting) { $this->error = "incorrect password for $username."; $this->error("incorrect password for $username."); } else { $this->error = "the specified username/password combination is incorrect."; $this->error("the specified username/password combination is incorrect."); } return false; } else { // authentication could not take place //$this->info("there was no user $username in the database"); file_put_contents(FAIL_LOG, $buildLog($username, "bad_auth")); chmod(FAIL_LOG, 0660); if(User::unsafe_reporting) { $this->error = "user $username is unknown."; $this->error("user $username is unknown."); } else { $this->error = "you either did not correctly input your username, or password (... or both)."; $this->error("you either did not correctly input your username, or password (... or both)."); } return false; } } /** * Update a user's information */ function update_user($username, $email, $sha1, $role) { //Admin bypass if(!in_arrayi($_SESSION["username"], $this->get_admin_list())){ // logged in, but do the tokens match? $token = $this->get_user_token($username); if($token != $_SESSION["token"]) { writeLog("error", "$username has requested info update using token: $token"); $this->error("token mismatch for $username"); return false; }else{ writeLog("success", "$username token has been validated"); } }else{ $token = $this->get_user_token($_SESSION["username"]); if($token != $_SESSION["token"]) { writeLog("error", $_SESSION["username"]." has requested info update using token: $token"); $this->error("token mismatch for ".$_SESSION["username"]); return false; }else{ writeLog("success", "Admin Override on update for $username info"); } } if($email !="") { $update = "UPDATE users SET email = '$email' WHERE username = '$username' COLLATE NOCASE"; $this->database->exec($update); } if($role !="") { $update = "UPDATE users SET role = '$role' WHERE username = '$username' COLLATE NOCASE"; $this->database->exec($update); } if($sha1 !="") { $dbpassword = $this->token_hash_password($username, $sha1, $this->get_user_token($username)); $update = "UPDATE users SET password = '$dbpassword' WHERE username = '$username'"; $this->database->exec($update); } writeLog("success", "information for $username has been updated"); $this->info("updated the information for $username"); } /** * Drop a invite from the system */ function deleteInvite() { @$id = trim($_POST["id"]); $delete = "DELETE FROM invites WHERE id = '$id' COLLATE NOCASE"; $this->database->exec($delete); $this->info("Plex Invite: $id has been deleted out of Organizr"); writeLog("success", "PLEX INVITE: $id has been deleted"); return true; } /** * Invite using a user's information */ function invite_user($username = "none", $email, $server) { //lang shit $language = new setLanguage; $domain = getServerPath(); $topImage = $domain."images/organizr-logo-h.png"; $uServer = strtoupper($server); $now = date("Y-m-d H:i:s"); $inviteCode = randomCode(6); $username = (!empty($username) ? $username : strtoupper($server) . " User"); $link = getServerPath()."?inviteCode=".$inviteCode; if($email !="") { $insert = "INSERT INTO invites (username, email, code, valid, date) "; $insert .= "VALUES ('".strtolower($username)."', '$email', '$inviteCode', 'Yes', '$now') "; $this->database->exec($insert); } writeLog("success", "$email has been invited to the $server server"); $this->info("$email has been invited to the $server server"); if($insert && User::use_mail) { // send email notification $subject = DOMAIN . " $uServer ".$language->translate('INVITE_CODE'); $body = orgEmail( $header = explosion($language->translate('EMAIL_INVITE_HEADER'), 0)." ".$uServer." ".explosion($language->translate('EMAIL_INVITE_HEADER'), 1), $title = $language->translate('EMAIL_INVITE_TITLE'), $user = $username, $mainMessage = explosion($language->translate('EMAIL_INVITE_MESSAGE'), 0)." ".$uServer." ".explosion($language->translate('EMAIL_INVITE_MESSAGE'), 1)." ".$inviteCode, $button = explosion($language->translate('EMAIL_INVITE_BUTTON'), 0)." ".$uServer." ".explosion($language->translate('EMAIL_INVITE_BUTTON'), 1), $buttonURL = $link, $subTitle = $language->translate('EMAIL_INVITE_SUBTITLE'), $subMessage = explosion($language->translate('EMAIL_INVITE_SUBMESSAGE'), 0)." ".$domain." ".explosion($language->translate('EMAIL_INVITE_SUBMESSAGE'), 1) ); $this->startEmail($email, $username, $subject, $body); } } /** * Log a user out. */ function logout_user($username) { $update = "UPDATE users SET active = 'false' WHERE username = '$username' COLLATE NOCASE"; $this->database->exec($update); $this->resetSession(); $this->info("Buh-Bye $username!"); unset($_COOKIE['Organizr']); setcookie('Organizr', '', time() - 3600, '/', DOMAIN); setcookie('Organizr', '', time() - 3600, '/'); unset($_COOKIE['OrganizrU']); setcookie('OrganizrU', '', time() - 3600, '/', DOMAIN); setcookie('OrganizrU', '', time() - 3600, '/'); unset($_COOKIE['cookiePassword']); setcookie("cookiePassword", '', time() - 3600, '/', DOMAIN); setcookie("cookiePassword", '', time() - 3600, '/'); unset($_COOKIE['Auth']); setcookie("Auth", '', time() - 3600, '/', DOMAIN); setcookie("Auth", '', time() - 3600, '/'); unset($_COOKIE['mpt']); setcookie("mpt", '', time() - 3600, '/', DOMAIN); setcookie("mpt", '', time() - 3600, '/'); writeLog("success", "$username has signed out"); return true; } /** * Drop a user from the system */ function unregister_user($username) { $delete = "DELETE FROM users WHERE username = '$username' COLLATE NOCASE"; $this->database->exec($delete); $this->info("$username has been kicked out of Organizr"); //$this->resetSession(); $dir = USER_HOME . $username; if(!rmdir($dir)) { $this->error("could not delete user directory $dir"); } $this->info("and we deleted user directory $dir"); writeLog("success", "$username has been deleted"); return true; } /** * The incoming password will already be a sha1 print (40 bytes) long, * but for the database we want it to be hased as sha256 (using 64 bytes). */ function token_hash_password($username, $sha1, $token) { return hash("sha256",($this->database->query('SELECT username FROM users WHERE username = \''.$username.'\' COLLATE NOCASE')->fetch()['username']).$sha1.$token); } /** * Get a user's email address */ function get_user_email($username) { if($username && $username !="" && $username !=User::GUEST_USER) { $query = "SELECT email FROM users WHERE username = '$username' COLLATE NOCASE"; foreach($this->database->query($query) as $data) { return $data["email"]; }} return ""; } function get_admin_email() { $query = "SELECT email FROM users WHERE role = 'admin' COLLATE NOCASE LIMIT 1"; foreach($this->database->query($query) as $data) { return $data["email"]; } return ""; } function get_admin_list() { $query = "SELECT username FROM users WHERE role = 'admin' COLLATE NOCASE"; foreach($this->database->query($query) as $data) { $list[] = $data['username']; } if(!empty($list)){ return $list; } else { return false; } } /** * Get a user's role */ function get_user_role($username) { if($username && $username !="" && $username !=User::GUEST_USER) { $query = "SELECT role FROM users WHERE username = '$username' COLLATE NOCASE"; foreach($this->database->query($query) as $data) { return $data["role"]; }} return "guest"; } /* function get_user_group($username) { if($username && $username !="" && $username !=User::GUEST_USER) { $query = "SELECT group FROM users WHERE username = '$username' COLLATE NOCASE"; foreach($this->database->query($query) as $data) { return $data["group"]; }} return User::GUEST_USER; }*/ /** * Get the user token */ function get_user_token($username) { $query = "SELECT token FROM users WHERE username = '$username' COLLATE NOCASE"; foreach($this->database->query($query) as $data) { return $data["token"]; } return false; } /** * Update the user's token and password upon successful login */ function update_user_token($username, $sha1, $noMsg) { // update the user's token $token = $this->random_hex_string(32); $update = "UPDATE users SET token = '$token' WHERE username = '$username' COLLATE NOCASE"; $this->database->exec($update); // update the user's password $newpassword = $this->token_hash_password($username, $sha1, $token); $update = "UPDATE users SET password = '$newpassword' WHERE username = '$username' COLLATE NOCASE"; $this->database->exec($update); if($noMsg == "false"){ $this->info("token and password updated for $username"); } return $token; } /** * Mark a user as active. */ function mark_user_active($username) { $update = "UPDATE users SET active = 'true', last = '" . time() . "' WHERE username = '$username' COLLATE NOCASE"; $this->database->exec($update); //$this->info("$username has been marked currently active."); return true; } /** * Check if user can be considered active */ function is_user_active($username) { $last = 0; $active = "false"; $query = "SELECT last, active FROM users WHERE username = '$username' COLLATE NOCASE"; foreach($this->database->query($query) as $data) { $last = intval($data["last"]); $active = $data["active"]; break; } if($active=="true") { $diff = time() - $last; if($diff >= User::time_out) { $this->logout_user($username); $this->error("$username was active but timed out (timeout set at " . User::time_out . " seconds, difference was $diff seconds)"); return false; } //$this->info("$username is active"); return true; } $this->error("$username is not active"); $this->resetSession(); return false; } /** * Random hex string generator */ function random_hex_string($len) { $string = ""; $max = strlen($this->hex)-1; while($len-->0) { $string .= $this->hex[mt_rand(0, $max)]; } return $string; } /** * Random password string generator */ function random_ascii_string($len) { $string = ""; $max = strlen($this->ascii)-1; while($len-->0) { $string .= $this->ascii[mt_rand(0, $max)]; } return $string; } } ?>