diff options
Diffstat (limited to 'public/includes')
| -rw-r--r-- | public/includes/functions.php | 135 | ||||
| -rw-r--r-- | public/includes/menu-contents.php | 50 | ||||
| -rw-r--r-- | public/includes/menu.php | 16 | ||||
| -rw-r--r-- | public/includes/sessions.php | 143 | ||||
| -rw-r--r-- | public/includes/ui-login.php | 98 | ||||
| -rw-r--r-- | public/includes/ui-message.php | 47 | ||||
| -rw-r--r-- | public/includes/ui-panel.php | 141 |
7 files changed, 630 insertions, 0 deletions
diff --git a/public/includes/functions.php b/public/includes/functions.php new file mode 100644 index 0000000..5e83994 --- /dev/null +++ b/public/includes/functions.php @@ -0,0 +1,135 @@ +<?php + +## Help Constants and Functions ------------------------------------------------ +//////////////////////////////////////////////////////////////////////////////// + + // Cache fields options (json format) //////////////////////////////////////// + // --------------------------------------------------------------------------- + $formJSON = file_get_contents('config/kallassa.json'); + define("FORMJSON", $formJSON); + + // Cache CCODE attributes (json format) ////////////////////////////////////// + // --------------------------------------------------------------------------- + $codeJSON = file_get_contents('config/ccode.json'); + define("CODEJSON", $codeJSON); + + // Parse anythig from a field //////////////////////////////////////////////// + // ARGS: + // $fkey = keyname (as in json fields oprions) + // $inp = input value (string) + // RETURN: array( + // 'label' = field label, + // 'multi' = (true|false) is multiple choice (select|radio|check) or not, + // 'value' = human readable value (or array of values if multi) + // ) ------------------------------------------------------------------------- + function parse_any($fkey, $inp ="") { + $formARRAY = json_decode(FORMJSON); + + foreach ($formARRAY as $key => $section) { + foreach ($section->childs as $kk => $field) { + + // find the field + if ($field->nam == $fkey) { + + $values = array(); // human readble values if select (comma separated) + + if ($field->typ == 'select') { + $multi = true; + + if ($inp !='') { + $codes = explode(",", $inp); // split coded values + foreach ($field->opt as $kkk => $v) { + if (in_array($v->id, $codes)) { // check if option is in array + $values[] = ($field->nam == 'ccode') ? ($v->id.": ".$v->tag) : $v->tag; + } + } + } + + } + else $multi = false; + + // return everything in an array + return array( + 'label' => $field->lab, + 'multi' => $multi, + 'value' => ($multi ? $values : $inp) + ); + } + } + } + + // if not escaped already, then name return same + return array('label' => $fkey, 'multi' => false, 'value' => $inp ); + } + + // Parse anythig from ccode + function parse_ccode($ckey) { + $ccARRAY = json_decode(CODEJSON); + + foreach ($ccARRAY as $key => $val) { + // find the field + if ($val->id == $ckey) { + // return everything in an array + return $val; + } + } + } + + + // Get totals of alla categories ///////////////////////////////////////////// + // RETURN array of items (value) per category (array key) + // --------------------------------------------------------------------------- + function get_totals() { + $result = array(); + $sum = 0; + + $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"); + + // prepare statemet + $stm = $dbc->prepare("SELECT ccode, count(id) total FROM `items` GROUP BY ccode"); + $stm->execute(); // execute query + $stm->store_result(); // store result + $stm->bind_result($c, $tot); + while ($stm->fetch()) { + // using md5() you can have any unicode string as key ;) + // credit: https://stackoverflow.com/questions/10696067/characters-allowed-in-php-array-keys -> Rob's answer + // but newer versions of php (v7+) seem to handle unicide keys nicely + $result[$c] = $tot; + $sum += $tot; + } + + $result['all'] = $sum; + + return $result; + } + + + // Preview Local Datetime //////////////////////////////////////////////////// + // (in Greek format and names ) + // --------------------------------------------------------------------------- + function local_dt($t) { + $day = array("Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"); + $dayL = array("Κυρ", "Δευ", "Τρι", "Τετ", "Πεμ", "Παρ", "Σαβ"); + $mon = array("Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"); + $monL = array("Ιαν", "Φεβ", "Μαρ", "Απρ", "Μαϊ", "Ιουν", "Ιουλ", "Αυγ", "Σεπ", "Οκτ", "Νοε", "Δεκ"); + $tm = array("am", "pm"); + $tmL = array("πμ", "μμ"); + $r = date("D. j M. Y, h:i:sa", $t); + $r = str_replace($day, $dayL, $r); + $r = str_replace($mon, $monL, $r); + $r = str_replace($tm, $tmL, $r); + return $r; + } + + + // Part of string + // UTF-8 SAFE + function str_part($str, $len) { + return (mb_strlen($str) > $len) ? mb_substr($str, 0, $len-1) ."…" : $str; + } diff --git a/public/includes/menu-contents.php b/public/includes/menu-contents.php new file mode 100644 index 0000000..7cdee94 --- /dev/null +++ b/public/includes/menu-contents.php @@ -0,0 +1,50 @@ +<?php + // dropdown-item(s) + // ------------------------------------------------------------------------- + // * are hosting the main menu options + // * are called via javascript (one script for all) + // * behaviour options are passed through data-* attributes + // --- -- -- - - - + // Format of data-goto attribute : {method} , {location-url} + // * method : url (goto url asap) | ajax (goto url after ajax request succeded) + // * location-url : the url to call +?> +<a class="dropdown-item disabled" href="#"></a> + +<?php if ((ROLE) && (ROLE != ADMIN)) : ?> + <a class="dropdown-item" data-goto="url,/" href="#">Πίνακας Ελέγχου</a> + <a class="dropdown-item" data-goto="url,ui-new-item.php" href="#">Εισαγωγή Αντικειμένου</a> + <a class="dropdown-item" data-goto="url,ui-search.php" href="#">Αναζήτηση</a> +<?php endif; ?> + + +<div class="dropdown-divider"></div> + + +<!-- Catalog Management --> +<?php if (ROLE >= ADMIN) : ?> + + <a class="dropdown-item disabled" href="#">Αρχειοθέτηση</a> + <a class="dropdown-item" data-goto="url,ui-catalogs.php" href="#">Κατάλογοι Αντικειμένων</a> + <a class="dropdown-item" data-goto="url,ui-backup.php" href="#">Τοπικό Backup</a> + +<?php endif; ?> + + +<div class="dropdown-divider"></div> + + + +<a class="dropdown-item disabled" href="#">Χρήστες</a> + +<a class="dropdown-item" data-goto="url,ui-profile.php" href="#">Προφίλ Χρήστη</a> + +<?php if (ROLE >= ADMIN) : ?> + <a class="dropdown-item" data-goto="url,ui-user-management.php" href="#">Διαχείριση Χρηστών</a> +<?php endif; ?> + + +<div class="dropdown-divider"></div> + + +<a class="dropdown-item" data-goto="ajax,ajax.php?do=logout" href="#">Αποσύνδεση</a> diff --git a/public/includes/menu.php b/public/includes/menu.php new file mode 100644 index 0000000..754a805 --- /dev/null +++ b/public/includes/menu.php @@ -0,0 +1,16 @@ + +<!-- menu --> +<div id="pi-menu"> + <div class="dropdown"> + <a class="btn btn-secondary dropdown-toggle" href="#" role="button" id="dropdown-Menu" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"> + Μενού Εργασιών + </a> + + <div class="dropdown-menu" aria-labelledby="dropdownMenuLink"> + <?php + include("includes/menu-contents.php") + ?> + </div> + </div> +</div> +<!-- / menu --> diff --git a/public/includes/sessions.php b/public/includes/sessions.php new file mode 100644 index 0000000..d33aa30 --- /dev/null +++ b/public/includes/sessions.php @@ -0,0 +1,143 @@ +<?php +// reset admin if needed +/* --- + $user = "admin@kallassa.dev"; + $pass = "1234!@!@"; + $time = time(); + $role = 5; + $salt = md5(rand(0,9999) .$time. rand(0,9999)); + $pass = md5($user.$salt.$pass); + $name = "Θάλεια Μελίσσα"; + $acid = 0; + + // 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"); + + $_hack = $_dbc->prepare("INSERT INTO users (user, salt, pass, acid, role, birthstamp, realname) VALUES (?, ?, ?, ?, ?, ?, ?)"); + $_hack->bind_param( "sssiids", $user, $salt, $pass, $acid, $role, $time, $name ); + $_chk = $_hack->execute(); + if ((TESTING) && (!$_chk)) echo "Database workaround failed; ". $_hack->error; + else echo "Workaround succeded!"; + $_hack->close(); + die(); +--- */ + + + +// -- 00. INITIALIZATION /////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// + +session_name(MAIN_COOKIE); // set a custom session name +session_start(); + + +if ( (isset($_SESSION['user_status'])) && ($_SESSION['user_status'] == 1) ) { + define("ROLE", $_SESSION['role']); +} +else + define("ROLE", 0); + +// -- 01. Session Functions needed ///////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// + +// check session existance ----------------------------------------------------- +//////////////////////////////////////////////////////////////////////////////// + function check_session_existance__() { + // session should exist from the first time of code + // what really matters is if has certain keys + if (!isset($_SESSION['user_status'])) { + $_SESSION['user_status'] = 0; + } + } + +// check and update SESSION ID ------------------------------------------------- +//////////////////////////////////////////////////////////////////////////////// + function check_update_session__() { + if (!isset($_SESSION['sess_update'])) { + $_SESSION['sess_update'] = time() + SESSION_UPD; // set sess_uddate limt if not exist + } + else if ($_SESSION['sess_update'] < time()) { // session needs to update id to mitigate session fixation + session_regenerate_id(); // change session ID (invalidate old session ID) + $_SESSION['sess_update'] = time() + SESSION_UPD; // shall re-update after SESS_UPD seconds + } + } + +// check and remove SESSION if expired ----------------------------------------- +//////////////////////////////////////////////////////////////////////////////// + function check_kill_session__() { + + if (isset($_SESSION['sess_expire']) && ($_SESSION['sess_expire'] < time())) { + session_unset(); // unset $_SESSION variable for the run-time + session_destroy(); // destroy session data in storage before continue + session_start(); + session_regenerate_id(); + + // TODO: + // should you save any data|indo before destroy? + } + $_SESSION['sess_expire'] = time() + SESSION_TTL; // set new expire limit; + } + +// common session data --------------------------------------------------------- +// format: json | string | array | or other format of data +// (includes data for user's browser via cookie) +//////////////////////////////////////////////////////////////////////////////// + function common_session_data__($format = 'json') { + + if ((isset($_SESSION['uid'])) && (isset($_SESSION['role']))) { + $arr = array( + "uid" => $_SESSION['uid'], + "name" => $_SESSION['realname'], + "role" => $_SESSION['role'] + ); + } + else $arr = array( + "uid" => '', "name" => '', "role" => '' + ); + + switch ($format) { + case 'array': + return $arr; + break; + + case ('semicolon'): + case (';'): + return implode(";", $arr); + break; + + default: + return json_encode($arr); + break; + } + } + + + + + +// -- 02. Handle Security Issues /////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// do it every time nomater what + +check_session_existance__(); + +check_kill_session__(); + +check_update_session__(); + + +// check_login_attempts__() +// check_inquire_attempts__() + // TODO + // all these should become a single function + // this function shall validate all session's keys + // print_r($_SESSION); die(); diff --git a/public/includes/ui-login.php b/public/includes/ui-login.php new file mode 100644 index 0000000..8ab4d9b --- /dev/null +++ b/public/includes/ui-login.php @@ -0,0 +1,98 @@ +<!DOCTYPE html> +<html prefix="og: http://ogp.me/ns#" xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-GB" lang="en-GB" dir="ltr"> + <head> + <!-- Metas + Title --> + <meta http-equiv="X-UA-Compatible" content="IE=edge"> + <meta name="viewport" content="width=device-width, initial-scale=1"> + <meta http-equiv="content-type" content="text/html; charset=utf-8" /> + + <title><?=PROJECT?> : Είσοδος</title> + + <!-- CSS needed --> + <link rel="stylesheet" href="/css/bootstrap.min.css" /><!-- v4.4.1 --> + <link rel="stylesheet" href="/css/select2.min.css" /><!-- v4.0.10 --> + <link rel="stylesheet" href="/css/pi.css" /> + </head> + <body> + + <div class="login-container"> + <div class="row"> + <div class="col-md-12"> + <h2><?=PROJECT?></h2> + <h4>Είσοδος στη βάση δεδομένων</h4> + <hr /> + + <form id="kallassa-login" method="post"> + + <div class="form-group"> + <label for="user">Email χρήστη</label> + <input class="form-control" type="email" name="email" required> + </div> + <div class="form-group"> + <label for="pass">Κωδικός πρόσβασης</label> + <input class="form-control" type="password" name="pass" required> + </div> + <br /> + + <input class="btn btn-primary" type="submit" value="Πιστοποίηση Χρήστη"> + + </form> + + </div> + </div> + </div> + + <!-- scripts and libraries + load and register one by one, so you don't need to worry about if they are ready --> + <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script> + <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-migrate/1.4.1/jquery-migrate.min.js"></script> + <script src="/js/bootstrap.min.js"></script> + <script> + // LOGIN + // ------------------------------------------------------------------------- + $('#kallassa-login').on('submit', function (e) { + if (e.isDefaultPrevented()) { // handle the invalid form... + alert('WTF validation error'); + } + else { // everything looks good! + + var postUrl = "/ajax.php?do=login"; + var data2send = { + user : $('#kallassa-login input[name=email]').val(), + pass : $('#kallassa-login input[name=pass]').val() + }; + + $.ajax({ + type: "POST", + url: postUrl, + data: data2send, + success: function(data) { + var json = $.parseJSON(data); + // ** Workaround + // ** for server may handle respond as json ready + // ** var json = data + + if (json.success) { // good! user is ok + + // reset form + $('#kallassa-login').trigger("reset"); + + // and goto root (will load control panel) + window.location.href = '/'; + + } + else { // nope! + alert("Login Failed; try again."); + } + + }, + error: function() { alert('WTF ajax error'); } + }); + return false; + } + }); + + </script> + + </body> +</html> diff --git a/public/includes/ui-message.php b/public/includes/ui-message.php new file mode 100644 index 0000000..55ff531 --- /dev/null +++ b/public/includes/ui-message.php @@ -0,0 +1,47 @@ +<?php +if (!defined("PROJECT")) { + define("PROJECT", "Application Error"); +} +if (!isset($deny)) { + $deny = array( + 'head' => 'Application Error!', + 'message' => "<p>Παρακαλώ ενημερώστε τον διαχειριστή του συστήματος. Στη σχετική ενημέρωση επισυνάψτε τα παρακάτω στοιχεία:</p> + <pre style='font: 11px 700 \"Ununt Mono\", Consolas, Monaco, Courier, monospace; white-space: pre-wrap; color:#b32;'>". + "\n". ((isset($_SERVER['REQUEST_URI'])) ? "URI: ".$_SERVER['REQUEST_URI'] : "") . + "\n". ((isset($_SERVER['REQUEST_METHOD'])) ? "Method: ".$_SERVER['REQUEST_METHOD'] : "") . + "\n". ((isset($_SERVER['HTTP_USER_AGENT'])) ? "Agent: ".$_SERVER['HTTP_USER_AGENT'] : "") . + "\nTimestamp: ". time() . ((isset($_SERVER['HTTP_REFERER'])) ? "\nRef: ".$_SERVER['HTTP_REFERER'] : "") ."</pre>" + ); +} +?><!DOCTYPE html> +<html prefix="og: http://ogp.me/ns#" xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-GB" lang="en-GB" dir="ltr"> + <head> + <!-- Metas + Title --> + <meta http-equiv="X-UA-Compatible" content="IE=edge"> + <meta name="viewport" content="width=device-width, initial-scale=1"> + <meta http-equiv="content-type" content="text/html; charset=utf-8" /> + + <title><?=PROJECT?> : Message</title> + + <!-- CSS needed --> + <link rel="stylesheet" href="/css/bootstrap.min.css" /><!-- v4.4.1 --> + <link rel="stylesheet" href="/css/pi.css" /> + </head> + <body> + + <div class="login-container"> + <div class="row"> + <div class="col-md-12"> + <h2><?=PROJECT?></h2> + <h4><?=$deny['head']?></h4> + <hr /> + <div><?=$deny['message']?></div> + <br /> + <hr /> + + </div> + </div> + </div> + + </body> +</html> diff --git a/public/includes/ui-panel.php b/public/includes/ui-panel.php new file mode 100644 index 0000000..1f40803 --- /dev/null +++ b/public/includes/ui-panel.php @@ -0,0 +1,141 @@ +<!DOCTYPE html> +<html prefix="og: http://ogp.me/ns#" xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-GB" lang="en-GB" dir="ltr"> + <head> + <!-- Metas + Title --> + <meta http-equiv="X-UA-Compatible" content="IE=edge"> + <meta name="viewport" content="width=device-width, initial-scale=1"> + <meta http-equiv="content-type" content="text/html; charset=utf-8" /> + + <title><?=PROJECT?> : Πίνακας Ελέγχου</title> + + <!-- CSS needed --> + <link href="https://fonts.googleapis.com/css?family=Ubuntu:400,700&display=swap" rel="stylesheet"> + <link rel="stylesheet" href="/css/bootstrap.min.css" /><!-- v4.4.1 --> + <link rel="stylesheet" href="/css/select2.min.css" /><!-- v4.0.10 --> + <link rel="stylesheet" href="/css/pi.css" /> + </head> + <body> + + <div class="pi-container"> + <div class="row"> + + <div class="col-md-12"> + <h2><?=PROJECT?></h2> + </div> + + <!-- menu section --> + <div class="col-md-4 col-lg-3"> + <h4>Πίνακας Ελέγχου</h4> + <hr /> + <?php + include("includes/menu-contents.php") + ?> + </div> + <!-- / menu section --> + + <div class="col-md-8 col-lg-9 panel-sections"> + + <!-- statistics section --> + <?php if (ROLE > EDITOR) : ?> + <p> + <a class="btn btn-warning" data-toggle="collapse" href="#collapse-stats" role="button">Στατιστικά</a> + </p> + <div class="collapse show stats" id="collapse-stats"> + <div class="card card-body"> + <table> + <?php + $stats = get_totals(); + $ccAr = json_decode(CODEJSON); + foreach ($ccAr as $key => $val) { + if (isset($stats[$val->id])) { + echo "<tr> + <td><span>". $val->id ."</span> ". $val->tag . "<a class='btn btn-pi-light' href='/ui-search.php?id=". $val->id ."'>Αναζήτηση</a></td> + <td style='width:45px; text-align:right;'>". $stats[$val->id] ."</td> + </tr> + "; + } + } + ?> + <tr class="summary"><td>Σύνολο</td><td style='width:45px; text-align:right;'><?=$stats['all']?></td></tr> + </table> + </div> + </div> + <?php endif; ?> + <!-- / statistics section --> + + <!-- last items section --> + + <!-- / last items section --> + + <!-- edits history --> + <!-- / edits history --> + + </div> + + </div> + </div> + + + + + + <!-- scripts and libraries + load and register one by one, so you don't need to worry about if they are ready --> + <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script> + <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-migrate/1.4.1/jquery-migrate.min.js"></script> + <script src="/js/bootstrap.min.js"></script> + <script> + + // functions needed + // --------------------------------------------------------------------------- + + // pure JS ajax GET request + // return data as JSON + // no fancy things like UTF8; if needed use base64 --------------------------- + function ajax_get(url, callback) { + var xmlhttp = new XMLHttpRequest(); + xmlhttp.onreadystatechange = function() { + if (xmlhttp.readyState == 4 && xmlhttp.status == 200) { + + try { + var data = JSON.parse(xmlhttp.responseText); + } catch(err) { + console.log(err.message + " in " + xmlhttp.responseText); + return; + } + callback(data); + } + }; + + xmlhttp.open("GET", url, true); + xmlhttp.send(); + } + + // menu management + // --------------------------------------------------------------------------- + $('.dropdown-item').on('click', function(e){ + e.preventDefault(); + + // all data-goto have the format: 'method,uri_address' + // uri_address is the url to call + // method options: + // * url : means goto url (redirect) + // * ajax : means call url via ajax; if 'success = true' then goto '/' after that + // ------------------------------------------------------------------------- + var opt = $(this).data('goto').split(','); // split data-goto + + if (opt[0] == 'url') { // if method = url + window.location.href = opt[1]; + } + else { // else, method = ajax + ajax_get(opt[1], function(response) { + if (response.success) { + window.location.href = '/'; + } + }); + } + }); + </script> + + </body> +</html> |
