true, 'data' => common_session_data__('array') ); } // --- CASE TWO --- -- -- - - - ## User POSTed credentials to authenticate elseif ($_SERVER['REQUEST_METHOD'] == 'POST') { // if data posted, then ... ## check if user made too many attempts; if so, add delay // ------------------------------------------------------------------- if (!isset($_SESSION['login_attempts'])) { $_SESSION['login_attempts'] = array(); $_SESSION['login_attempts'][] = time(); } else { // Check login attempts $TOTatts = sizeof($_SESSION['login_attempts']); // DENY if too many deny and force user to try later if (($TOTatts > 32) && (time()-$_SESSION['login_attempts'][$TOTatts - 1] < 600)) return array('success' => false, 'data' => "Can not check; please try again after 10 minutes."); if (($TOTatts > 16) && (time()-$_SESSION['login_attempts'][$TOTatts - 1] < 300)) return array('success' => false, 'data' => "Can not check; please try again after 5 minutes."); if (($TOTatts > 8) && (time()-$_SESSION['login_attempts'][$TOTatts - 1] < 55)) return array('success' => false, 'data' => "Can not check; please try after 1 minute."); if (($TOTatts > 4) && (time()-$_SESSION['login_attempts'][$TOTatts - 1] < 25)) return array('success' => false, 'data' => "Can not check; please try after 30 seconds. Forgot your password? Contact the administrator!"); // if too many attempts but stil ok on timings // remove the first 10 attempts if ($TOTatts > 75) { for ($ti = 0 ; $ti < 16 ; $ti++) array_shift($_SESSION['login_attempts']); } // if not gone already allow try to login; so log the attempt and continue $_SESSION['login_attempts'][] = time(); } ## validate posted data (email, password) // ------------------------------------------------------------------- // POST sent $post = array('user' => $_POST['user'], 'pass' => $_POST['pass']); // validation rules $rules = array('user' => FILTER_VALIDATE_EMAIL, 'pass' => true ); // sanitize input array $input = filter_var_array($post, $rules); // check if all valid and non empty; keep errors $valid = true; // valid (bool) $error = array(); // errors (array) $nonEmpty = array('user', 'pass'); // required fields foreach($input as $k => $v) { if ($v === false) { // check not validated $valid = false; $error[] = $k ." not validated"; } if ( (($v =="") || ($v === false)) && (in_array($k, $nonEmpty)) ) { // check required non empty $valid = false; $error[] = $k . " is required"; } } // echo "inp: "; print_r($input); echo "\nerr: "; print_r($error); die(); if (!$valid) { // if no valid data return array('success' => false, 'data' => join(", ", $error)); // return error(s) } ## CHECK DATABASE FOR USER // use prepare statements for security // ------------------------------------------------------------------- // init database connection $_dbc = new mysqli(DB_HOST, DB_USER, DB_PASS, DB_DBMS); if ($_dbc->connect_errno) { $_cError = "Database connection failed; Please try in a few minutes. "; if (TESTING) echo $_dbc->connect_error; $_dbc->close(); die(); } $_dbc->set_charset("utf8"); // prepare statemet $_stm = $_dbc->prepare("SELECT user_id, `user`, salt, pass, role, realname, birthstamp FROM `users` WHERE `user` = ?"); $_stm->bind_param("s", $post['user']); // bind values $_stm->execute(); // execute query $_stm->store_result(); // store result if ($_stm->num_rows == 1) { // only one user should exist $_stm->bind_result($uid, $user, $salt, $pass, $role, $name, $birth); // bind result variables $_stm->fetch(); // fetch FIRST record values } else { // return error(s) return array('success' => false, 'data' => "More than one users? Please contact system administrator"); } $_stm->close(); // close statement $_dbc->close(); // close connection ## decide if user is ok // ------------------------------------------------------------------- if ( $pass == md5($post['user'].$salt.$post['pass']) ) { // User is validated and ok session_unset(); // unset $_SESSION, and session_destroy(); // destroy current session's data before continue; session_start(); // then start a new session; session_regenerate_id(); // get a new session id to mitigate session fixation // setup his session data $_SESSION['user_status'] = 1; // update session status $_SESSION['sess_expire'] = time() + SESSION_TTL; // session will expire after SESS_TTL seconds $_SESSION['sess_update'] = time() + SESSION_UPD; // session need to update agter SESS_UPD sec // keep critical user info into session $_SESSION['uid'] = $uid; $_SESSION['name'] = $name; $_SESSION['role'] = $role; $_SESSION['email'] = $post['user']; $_SESSION['birth'] = $birth; return array('success' => true, 'data' => array('uid' => $uid, 'name' => $name, 'role' => $role) ); } else { // user is not ok unset critical session variables $_SESSION['user_status'] = 0; if (isset($_SESSION['uid'])) unset($_SESSION['uid']); if (isset($_SESSION['name'])) unset($_SESSION['name']); if (isset($_SESSION['role'])) unset($_SESSION['role']); if (isset($_SESSION['role'])) unset($_SESSION['role']); // then return failed return array('success' => false, 'data' => "Not valid user credentials."); } } // --- end CASE TWO // --- CASE THREE --- -- -- - - - ## credentials not send via POST else return array('success' => false, 'data' => "Data not sent correctly"); } ## LOGOUT -------------------------------------------------------------------- ////////////////////////////////////////////////////////////////////////////// function try_logout() { session_unset(); // unset, and session_destroy(); // destroy session data; session_start(); // then start a new session session_regenerate_id(); // get a new session id to mitigate session fixation // remove cookies if (isset($_COOKIE[MAIN_COOKIE])) unset($_COOKIE[MAIN_COOKIE]); if (isset($_COOKIE[USER_COOKIE])) unset($_COOKIE[USER_COOKIE]); return array('success' => true, 'data' => "User disconected!"); // no chance for the function to fail } ## -- 02. Items Catalog Management //////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// ## ADD ITEM ------------------------------------------------------------------ ////////////////////////////////////////////////////////////////////////////// function add_item() { if ((ROLE) && ($_SERVER['REQUEST_METHOD'] == 'POST')) { // POST sent $post = array( 'ccode' => $_POST['ccode'], 'summary' => $_POST['summary'], 'condition' => $_POST['condition'], 'decade' => $_POST['decade'], 'operator' => $_SESSION['name'], 'timestamp' => time(), 'box' => $_POST['box'], 'exhibition' => $_POST['exhibition'], 'record' => serialize($_POST) ); // VALIDATE RULES $rules = array( 'ccode' => true, 'summary' => FILTER_SANITIZE_STRING, 'condition' => array('filter' => FILTER_VALIDATE_REGEXP, "options" => array("regexp" => "/^[A-Za-z0-9,]+$/")), 'decade' => FILTER_VALIDATE_INT, 'operator' => true, 'timestamp' => true, 'box' => FILTER_SANITIZE_STRING, 'exhibition' => FILTER_SANITIZE_STRING, 'record' => true ); // SANITIZE input array $input = filter_var_array($post, $rules); // CHECK if all VALID and NON EMPTY // --- -- -- - - - $valid = true; // valid flag $error = array(); // errors array $nonEmpty = array( // required fields 'ccode','operator','timestamp' ); foreach($input as $k => $v) { // check not validated if ($v === false) { $valid = false; $error[] = $k ." not validated"; } // check empty from required if ( (($v =="") || ($v === false)) && (in_array($k, $nonEmpty)) ) { $valid = false; $error[] = $k . " is required"; } } // next line is check (uncomment for checking) // if (TESTING) { echo "\nses: "; print_r($_SESSION); echo "\npost:"; print_r($_POST); echo "\n, inp: "; print_r($input); echo "\nerr: "; print_r($error); die(); } // IF VALID add item // --- -- -- - - - if ($valid) { // init database connection $_dbc = new mysqli(DB_HOST, DB_USER, DB_PASS, DB_DBMS); if ($_dbc->connect_errno) { echo "Database connection failed; Please try in a few minutes."; if (TESTING) echo $_dbc->connect_error; $_dbc->close(); die(); } $_dbc->set_charset("utf8"); $_stm = $_dbc->prepare("INSERT INTO items (ccode, summary, `condition`, decade, operator, `timestamp`, `box`, exhibition, record) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)" ); $_stm->bind_param("sssisdsss", $post['ccode'], $post['summary'], $post['condition'], $post['decade'], $post['operator'], $post['timestamp'], $post['box'], $post['exhibition'], $post['record'] ); $_stm->execute(); $_newid = $_dbc->insert_id; $_stm->close(); if ($_newid > 0) { // update individual category table // ------------------------------------------------------------------- $cc = parse_ccode($post['ccode']); $_Table = 'tt_'. $cc->idx; // find table // do the insert $_stm2 = $_dbc->prepare("INSERT INTO {$_Table} ( id ) VALUES ( ? )"); $_stm2->bind_param("d", $_newid); $_stm2->execute(); $_iid = $_dbc->insert_id; // get new index $_stm2->close(); // update record with individual index // ------------------------------------------------------------------- $identity = $post['ccode'] .'.'. $_iid; // do the insert $_upd = $_dbc->prepare("UPDATE items SET identity = ? WHERE id = ?"); $_upd->bind_param("sd", $identity, $_newid); $_upd->execute(); $_upd->close(); return array('success' => true, 'data' => "Item added", id => $_newid ); } else return array('success' => false, 'data' => "Unknown database error. Please contact the administrator"); } else return array('success' => false, 'data' => implode(", ", $error)); } else return array('success' => false, 'data' => "Operation Denied."); } ## UPDATE ITEM --------------------------------------------------------------- ////////////////////////////////////////////////////////////////////////////// function update_item($id) { if ((ROLE) && ($_SERVER['REQUEST_METHOD'] == 'POST')) { // POST sent // * CCODE : sent correctly but WILL NOT CHANGE; exclude it from UPDATE statement // * OPERATOR, TIMESTAMP : not need to change $post = array( 'summary' => $_POST['summary'], 'condition' => $_POST['condition'], 'decade' => $_POST['decade'], 'box' => $_POST['box'], 'exhibition' => $_POST['exhibition'], 'record' => serialize($_POST) ); // VALIDATE RULES $rules = array( 'summary' => FILTER_SANITIZE_STRING, 'condition' => array('filter' => FILTER_VALIDATE_REGEXP, "options" => array("regexp" => "/^[A-Za-z0-9,]+$/")), 'decade' => FILTER_VALIDATE_INT, 'box' => FILTER_SANITIZE_STRING, 'exhibition' => FILTER_SANITIZE_STRING, 'record' => true ); // SANITIZE input array $input = filter_var_array($post, $rules); // CHECK if all VALID and NON EMPTY // * ALL required fields ARE ALREADY SET; no need to check if empty // --- -- -- - - - $valid = true; // valid flag $error = array(); // errors array foreach($input as $k => $v) { // check not validated if ($v === false) { $valid = false; $error[] = $k ." not validated"; } } // next line is check (uncomment for checking) // if (TESTING) { echo "\nses: "; print_r($_SESSION); echo "\npost:"; print_r($_POST); echo "\n, inp: "; print_r($input); echo "\nerr: "; print_r($error); die(); } // IF VALID add item // --- -- -- - - - if ($valid) { // init database connection $_dbc = new mysqli(DB_HOST, DB_USER, DB_PASS, DB_DBMS); if ($_dbc->connect_errno) { echo "Database connection failed; Please try in a few minutes."; if (TESTING) echo $_dbc->connect_error; $_dbc->close(); die(); } $_dbc->set_charset("utf8"); $_stm = $_dbc->prepare("UPDATE items SET summary = ?, `condition` = ?, decade = ?, `box` = ?, exhibition = ?, record = ? WHERE id = ?" ); $_stm->bind_param("ssisssd", $post['summary'], $post['condition'], $post['decade'], $post['box'], $post['exhibition'], $post['record'], $id ); $_stm->execute(); $_stm->close(); return array('success' => true, 'data' => "Item Updated", id => $_newid ); } else return array('success' => false, 'data' => implode(", ", $error)); } else return array('success' => false, 'data' => "Operation Denied."); } ## -- 10. SWITCH THE requested CASES /////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// // parse GET argument(s) $do = (isset($_GET['do'])) ? $_GET['do'] : "none"; // switch the 'do' cases switch ($do) { case 'login': $reply = try_login(); echo json_encode($reply, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE); break; case 'logout': $reply = try_logout(); echo json_encode($reply, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE); break; case 'additem': $reply = add_item(); echo json_encode($reply, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE); break; case 'upditem': if (isset($_GET['id']) && is_numeric($_GET['id']) && (($_GET['id'] != '0'))) { $item_id = $_GET['id']; // id of photo to upload $reply = update_item($item_id); } else { $reply = array('success' => false, 'data' => "ID error"); } echo json_encode($reply, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE); break; default: // code... break; }