PaperBag/www/webdata/init.php

282 lines
8.2 KiB
PHP

<?php
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
require_once 'config.php';
if(!isset($config) || empty($config)){
die("<h1>Configuration error</h1><p>Copy the webdata/config.sample.php file to webdata/config.php and fill out your connection settings.</p>");
}
$projectRoot = $config["general"]["projectRoot"];
function getConfig($val, $group = "general"){
global $config;
if(isset($config[$group][ $val ])){
return $config[$group][$val];
}
return false;
}
function database(){
global $config;
$db = new mysqli($config["db"]["host"], $config["db"]["user"], $config["db"]["pass"], $config["db"]["database"]);
if($db->connect_error){
die("Connection failed: " . $db->connect_error);
}
return $db;
}
function filter($data){
global $db;
if(gettype($data) !== "array"){
$data = trim(htmlentities(strip_tags($data)));
return $db->real_escape_string($data);
}
else if(gettype($data) == "array"){
foreach($data as $key => $value){
$data[$key] = filter($value);
}
return $data;
}
return false;
}
function getHtmlHeaders($prepend = ""){
return "<meta charset='UTF-8'>
<meta http-equiv='X-UA-Compatible' content='IE=edge'>
<meta name='viewport' content='width=device-width, initial-scale=1.0'>
<link rel='stylesheet' href='".$prepend."css/bootstrap.min.css' type='text/css' />
<link rel='stylesheet' href='".$prepend."css/index.css' type='text/css' />
<link rel='apple-touch-icon' sizes='180x180' href='".$prepend."/favicon/apple-touch-icon.png'>
<link rel='icon' type='image/png' sizes='32x32' href='".$prepend."/favicon/favicon-32x32.png'>
<link rel='icon' type='image/png' sizes='16x16' href='".$prepend."/favicon/favicon-16x16.png'>
<link rel='manifest' href='".$prepend."/favicon/site.webmanifest'>
<link rel='mask-icon' href='".$prepend."/favicon/safari-pinned-tab.svg' color='#5bbad5'>
<meta name='msapplication-TileColor' content='#da532c'>
<meta name='theme-color' content='#ffffff'>
<script src='".$prepend."js/jquery-3.5.1.min.js'></script>
<script src='".$prepend."js/popper.min.js'></script>
<script src='".$prepend."js/bootstrap.min.js'></script>
<!--<script src='//cdn.jsdelivr.net/npm/marked/marked.min.js'></script>-->
<script src='".$prepend."js/hammer.js'></script>
<script src='".$prepend."js/hammer.jquery.js'></script>
\n";
}
function loginUser($email, $pass, $stayLoggedIn = false) {
global $db;
$err = [];
// get user from database
$getUserSQL = "SELECT pwd, user_id, user_email FROM user WHERE user_email = '$email' LIMIT 1;";
$getUserRes = $db->query($getUserSQL);
$dbPass = "missingPassword";
$dbUserId = 0;
$dbUserName = "Unknown";
if($getUserRes->num_rows == 1){
// Verify password
list($dbPass, $dbUserId, $dbUserName) = $getUserRes->fetch_row();
}
if(password_verify(PwdGen($pass), $dbPass)){
if(!isset($_SESSION)){
session_start();
}
session_regenerate_id();
$md5agent = md5($_SERVER['HTTP_USER_AGENT']);
$userKey = GenKey();
$shaUserKey = sha1($userKey);
$expire = $stayLoggedIn?30:0; // if "stay logged in", stay logged in for 30 days.
$updateUserSQL = "INSERT INTO user_login (user_id, ckey, ctime, expire, agent) VALUES ('$dbUserId', '$userKey', '".time()."', $expire, '$md5agent');";
if($db->query($updateUserSQL)){
$_SESSION['user_id'] = $dbUserId;
$_SESSION['user_name'] = $dbUserName;
$_SESSION['user_agent'] = $md5agent;
$_SESSION['user_key'] = $shaUserKey;
if($stayLoggedIn){
setcookie("auth", $shaUserKey.".".$dbUserId, time() + (30 * 24*60*60), "/", $_SERVER['HTTP_HOST'], isset($_SERVER['HTTPS']), true );
}
return true;
}
else {
$err[] = "Failed to login.\n".$db->error;
}
}
else {
$err[] = "Username and/or Password is wrong.";
}
return $err;
}
function loginFromAuth($auth): bool {
global $db;
$db = $db ?? database();
$md5agent = md5($_SERVER['HTTP_USER_AGENT']);
$cookieSplode = explode('.', $auth);
if(count($cookieSplode) == 2){
$tkey = $cookieSplode[0];
$tuid = $cookieSplode[1];
$verifyLoginCookieRes = $db->query("SELECT ul.user_id, ul.ckey, ul.ctime, ul.expire, ul.agent, u.full_name FROM user_login ul INNER JOIN user u ON ul.user_id = u.user_id WHERE ul.user_id = '$tuid' ORDER BY ctime DESC");
while($row = $verifyLoginCookieRes->fetch_assoc()){
if($row['expire'] == 0){ $row['expire'] = 1; }
if(
sha1($row['ckey']) == $tkey &&
$row['agent'] == $md5agent &&
($row['ctime']+($row['expire']*24*60*60) > time())
){
session_regenerate_id();
$_SESSION['user_id'] = $row['user_id'];
$_SESSION['user_name'] = $row['full_name'];
$_SESSION['user_agent'] = $md5agent;
$_SESSION['user_key'] = sha1($row['ckey']);
return true;
}
}
}
return false;
}
function logoutUser($everywhere = false){
if(checkLogin()){
global $db;
$logoutSql = "DELETE FROM user_login WHERE user_id = $_SESSION[user_id]";
if(!$everywhere){ $logoutSql .= " AND agent = '".md5($_SERVER['HTTP_USER_AGENT'])."'"; }
$db = $db ?? database();
$db->query($logoutSql);
}
// Delete session-cookie
$params = session_get_cookie_params();
setcookie(session_name(), '', time() - 42000,
$params["path"], $params["domain"],
$params["secure"], $params["httponly"]
);
setcookie('auth', '', time() - 42000, "/", $_SERVER['HTTP_HOST'], isset($_SERVER['HTTPS']), true );
// Finally, destroy the session.
session_destroy();
}
function PwdGen($pass, $returnHashed = false): string {
global $config;
$pepper = $config['general']['pepper'] ?? 'IAmBadAtSecurity';
$pwd_peppered = hash_hmac("sha256", $pass, $pepper);
if(!$returnHashed){
return $pwd_peppered;
}
return password_hash($pwd_peppered, PASSWORD_ARGON2ID, ['threads' => 2]);
}
function GenKey($length = 21): string{
$password = "";
$possible = "0123456789abcdefghijkmnopqrstuvwxyz";
$i = 0;
while($i < $length){
$char = substr($possible, mt_rand(0, strlen($possible)-1), 1);
if(!strstr($password, $char)){
$password .= $char;
$i++;
}
}
return $password;
}
function checkLogin(): bool {
global $db, $_SESSION, $_COOKIE;
if($db == null){
$db = database();
}
if(!isset($_SESSION)){
session_start();
}
if(isset($_SESSION['user_id'])){
$md5agent = md5($_SERVER['HTTP_USER_AGENT']);
if($md5agent == @$_SESSION['user_agent']){
$verifyLoginSessionRes = $db->query("SELECT expire, ctime, ckey FROM user_login WHERE user_id = ".$_SESSION['user_id']." and agent = '$md5agent'");
if($verifyLoginSessionRes->num_rows > 0){
while ($row = $verifyLoginSessionRes->fetch_assoc()){
if(
(sha1($row['ckey']) == $_SESSION['user_key']) &&
($row['expire'] == 0 || $row['ctime']+($row['expire']*24*60*60) > time())
){
return true;
}
}
}
}
}
if(isset($_COOKIE['auth']) && loginFromAuth($_COOKIE['auth'])){
return true;
}
unset($_SESSION['user_id']);
return false;
}
function requireLogin(): bool{
global $config;
if(checkLogin()){
return true;
}
$_SESSION['loginRef'] = $_SERVER['PHP_SELF'];
header("Location: ".$config["general"]["projectRoot"]."/login.php?return=".str_ireplace('index.php', '', $_SERVER['PHP_SELF']));
return false;
}
function checkLoginSimple(): bool {
global $_SESSION;
if(!isset($_SESSION)){
session_start();
$_SERVER['HTTP_REFERER'] = "";
}
if(isset($_SESSION['user_id'])){
return true;
}
return false;
}