Merge BusinessAppTemplate
This commit is contained in:
commit
ec0e59e242
@ -32,7 +32,7 @@ function returnToSender($msg, $arg = "") {
|
|||||||
switch ($VARS['action']) {
|
switch ($VARS['action']) {
|
||||||
case "signout":
|
case "signout":
|
||||||
session_destroy();
|
session_destroy();
|
||||||
header('Location: index.php');
|
header('Location: index.php?logout=1');
|
||||||
die("Logged out.");
|
die("Logged out.");
|
||||||
case "savenote":
|
case "savenote":
|
||||||
if (!isset($VARS['content']) || empty($VARS['noteid'])) {
|
if (!isset($VARS['content']) || empty($VARS['noteid'])) {
|
||||||
@ -81,7 +81,7 @@ switch ($VARS['action']) {
|
|||||||
echo $note->getHTML(false);
|
echo $note->getHTML(false);
|
||||||
break;
|
break;
|
||||||
case "odt":
|
case "odt":
|
||||||
if (PANDOC_BIN != "") {
|
if ($SETTINGS['pandoc'] != "") {
|
||||||
header("Content-Type: application/vnd.oasis.opendocument.text");
|
header("Content-Type: application/vnd.oasis.opendocument.text");
|
||||||
header("Content-disposition: attachment; filename=\"" . $note->getCleanTitle() . "_" . $note->getModified() . ".odt\"");
|
header("Content-disposition: attachment; filename=\"" . $note->getCleanTitle() . "_" . $note->getModified() . ".odt\"");
|
||||||
$pandoc = new Pandoc\Pandoc();
|
$pandoc = new Pandoc\Pandoc();
|
||||||
|
33
api.php
33
api.php
@ -4,35 +4,6 @@
|
|||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
/**
|
|
||||||
* Simple JSON API to allow other apps to access data from this app.
|
|
||||||
*
|
|
||||||
* Requests can be sent via either GET or POST requests. POST is recommended
|
|
||||||
* as it has a lower chance of being logged on the server, exposing unencrypted
|
|
||||||
* user passwords.
|
|
||||||
*/
|
|
||||||
require __DIR__ . '/required.php';
|
|
||||||
header("Content-Type: application/json");
|
|
||||||
|
|
||||||
$username = $VARS['username'];
|
// Load in new API from legacy location (a.k.a. here)
|
||||||
$password = $VARS['password'];
|
require __DIR__ . "/api/index.php";
|
||||||
$user = User::byUsername($username);
|
|
||||||
if ($user->exists() !== true || Login::auth($username, $password) !== Login::LOGIN_OK) {
|
|
||||||
header("HTTP/1.1 403 Unauthorized");
|
|
||||||
die("\"403 Unauthorized\"");
|
|
||||||
}
|
|
||||||
|
|
||||||
// query max results
|
|
||||||
$max = 20;
|
|
||||||
if (preg_match("/^[0-9]+$/", $VARS['max']) === 1 && $VARS['max'] <= 1000) {
|
|
||||||
$max = (int) $VARS['max'];
|
|
||||||
}
|
|
||||||
|
|
||||||
switch ($VARS['action']) {
|
|
||||||
case "ping":
|
|
||||||
$out = ["status" => "OK", "maxresults" => $max, "pong" => true];
|
|
||||||
exit(json_encode($out));
|
|
||||||
default:
|
|
||||||
header("HTTP/1.1 400 Bad Request");
|
|
||||||
die("\"400 Bad Request\"");
|
|
||||||
}
|
|
5
api/.htaccess
Normal file
5
api/.htaccess
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
# Rewrite for Nextcloud Notes API
|
||||||
|
<IfModule mod_rewrite.c>
|
||||||
|
RewriteEngine on
|
||||||
|
RewriteRule ([a-zA-Z0-9]+) index.php?action=$1 [PT]
|
||||||
|
</IfModule>
|
9
api/actions/ping.php
Normal file
9
api/actions/ping.php
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
|
||||||
|
sendJsonResp();
|
15
api/apisettings.php
Normal file
15
api/apisettings.php
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
|
||||||
|
$APIS = [
|
||||||
|
"ping" => [
|
||||||
|
"load" => "ping.php",
|
||||||
|
"vars" => [
|
||||||
|
]
|
||||||
|
]
|
||||||
|
];
|
123
api/functions.php
Normal file
123
api/functions.php
Normal file
@ -0,0 +1,123 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build and send a simple JSON response.
|
||||||
|
* @param string $msg A message
|
||||||
|
* @param string $status "OK" or "ERROR"
|
||||||
|
* @param array $data More JSON data
|
||||||
|
*/
|
||||||
|
function sendJsonResp(string $msg = null, string $status = "OK", array $data = null) {
|
||||||
|
$resp = [];
|
||||||
|
if (!is_null($data)) {
|
||||||
|
$resp = $data;
|
||||||
|
}
|
||||||
|
if (!is_null($msg)) {
|
||||||
|
$resp["msg"] = $msg;
|
||||||
|
}
|
||||||
|
$resp["status"] = $status;
|
||||||
|
header("Content-Type: application/json");
|
||||||
|
exit(json_encode($resp));
|
||||||
|
}
|
||||||
|
|
||||||
|
function exitWithJson(array $json) {
|
||||||
|
header("Content-Type: application/json");
|
||||||
|
exit(json_encode($json));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the API key with most of the characters replaced with *s.
|
||||||
|
* @global string $key
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
function getCensoredKey() {
|
||||||
|
global $key;
|
||||||
|
$resp = $key;
|
||||||
|
if (strlen($key) > 5) {
|
||||||
|
for ($i = 2; $i < strlen($key) - 2; $i++) {
|
||||||
|
$resp[$i] = "*";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $resp;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the request is allowed
|
||||||
|
* @global type $VARS
|
||||||
|
* @global type $database
|
||||||
|
* @return bool true if the request should continue, false if the request is bad
|
||||||
|
*/
|
||||||
|
function authenticate(): bool {
|
||||||
|
global $VARS, $database;
|
||||||
|
if (empty($VARS['key'])) {
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
$key = $VARS['key'];
|
||||||
|
if ($database->has('apikeys', ['key' => $key]) !== TRUE) {
|
||||||
|
engageRateLimit();
|
||||||
|
http_response_code(403);
|
||||||
|
Log::insert(LogType::API_BAD_KEY, null, "Key: " . $key);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkVars($vars, $or = false) {
|
||||||
|
global $VARS;
|
||||||
|
$ok = [];
|
||||||
|
foreach ($vars as $key => $val) {
|
||||||
|
if (strpos($key, "OR") === 0) {
|
||||||
|
checkVars($vars[$key], true);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only check type of optional variables if they're set, and don't
|
||||||
|
// mark them as bad if they're not set
|
||||||
|
if (strpos($key, " (optional)") !== false) {
|
||||||
|
$key = str_replace(" (optional)", "", $key);
|
||||||
|
if (empty($VARS[$key])) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (empty($VARS[$key])) {
|
||||||
|
$ok[$key] = false;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$checkmethod = "is_$val";
|
||||||
|
if ($checkmethod($VARS[$key]) !== true) {
|
||||||
|
$ok[$key] = false;
|
||||||
|
} else {
|
||||||
|
$ok[$key] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ($or) {
|
||||||
|
$success = false;
|
||||||
|
$bad = "";
|
||||||
|
foreach ($ok as $k => $v) {
|
||||||
|
if ($v) {
|
||||||
|
$success = true;
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
$bad = $k;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!$success) {
|
||||||
|
http_response_code(400);
|
||||||
|
die("400 Bad request: variable $bad is missing or invalid");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
foreach ($ok as $key => $bool) {
|
||||||
|
if (!$bool) {
|
||||||
|
http_response_code(400);
|
||||||
|
die("400 Bad request: variable $key is missing or invalid");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
77
api/index.php
Normal file
77
api/index.php
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
|
||||||
|
require __DIR__ . '/../required.php';
|
||||||
|
require __DIR__ . '/functions.php';
|
||||||
|
require __DIR__ . '/apisettings.php';
|
||||||
|
|
||||||
|
$VARS = $_GET;
|
||||||
|
if ($_SERVER['REQUEST_METHOD'] != "GET") {
|
||||||
|
$VARS = array_merge($VARS, $_POST);
|
||||||
|
}
|
||||||
|
|
||||||
|
$requestbody = file_get_contents('php://input');
|
||||||
|
$requestjson = json_decode($requestbody, TRUE);
|
||||||
|
if (json_last_error() == JSON_ERROR_NONE) {
|
||||||
|
$VARS = array_merge($VARS, $requestjson);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we're not using the old api.php file, allow more flexible requests
|
||||||
|
if (strpos($_SERVER['REQUEST_URI'], "/api.php") === FALSE) {
|
||||||
|
$route = explode("/", substr($_SERVER['REQUEST_URI'], strpos($_SERVER['REQUEST_URI'], "api/") + 4));
|
||||||
|
|
||||||
|
if (count($route) > 1) {
|
||||||
|
$VARS["action"] = $route[0];
|
||||||
|
}
|
||||||
|
if (count($route) >= 2 && strpos($route[1], "?") !== 0) {
|
||||||
|
$VARS["key"] = $route[1];
|
||||||
|
|
||||||
|
for ($i = 2; $i < count($route); $i++) {
|
||||||
|
$key = explode("=", $route[$i], 2)[0];
|
||||||
|
$val = explode("=", $route[$i], 2)[1];
|
||||||
|
$VARS[$key] = $val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strpos($route[count($route) - 1], "?") === 0) {
|
||||||
|
$morevars = explode("&", substr($route[count($route) - 1], 1));
|
||||||
|
foreach ($morevars as $var) {
|
||||||
|
$key = explode("=", $var, 2)[0];
|
||||||
|
$val = explode("=", $var, 2)[1];
|
||||||
|
$VARS[$key] = $val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!authenticate()) {
|
||||||
|
http_response_code(403);
|
||||||
|
die("403 Unauthorized");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (empty($VARS['action'])) {
|
||||||
|
http_response_code(404);
|
||||||
|
die("404 No action specified");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isset($APIS[$VARS['action']])) {
|
||||||
|
http_response_code(404);
|
||||||
|
die("404 Action not defined");
|
||||||
|
}
|
||||||
|
|
||||||
|
$APIACTION = $APIS[$VARS["action"]];
|
||||||
|
|
||||||
|
if (!file_exists(__DIR__ . "/actions/" . $APIACTION["load"])) {
|
||||||
|
http_response_code(404);
|
||||||
|
die("404 Action not found");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!empty($APIACTION["vars"])) {
|
||||||
|
checkVars($APIACTION["vars"]);
|
||||||
|
}
|
||||||
|
|
||||||
|
require_once __DIR__ . "/actions/" . $APIACTION["load"];
|
10
app.php
10
app.php
@ -39,7 +39,7 @@ header("Link: <static/js/bootstrap.bundle.min.js>; rel=preload; as=script", fals
|
|||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
|
||||||
<title><?php echo SITE_TITLE; ?></title>
|
<title><?php echo $SETTINGS['site_title']; ?></title>
|
||||||
|
|
||||||
<link rel="icon" href="static/img/logo.svg">
|
<link rel="icon" href="static/img/logo.svg">
|
||||||
|
|
||||||
@ -127,7 +127,7 @@ END;
|
|||||||
</button>
|
</button>
|
||||||
<a class="navbar-brand py-0 mr-auto" href="app.php">
|
<a class="navbar-brand py-0 mr-auto" href="app.php">
|
||||||
<img src="static/img/logo.svg" alt="" class="d-none d-<?php echo $navbar_breakpoint; ?>-inline brand-img py-0" />
|
<img src="static/img/logo.svg" alt="" class="d-none d-<?php echo $navbar_breakpoint; ?>-inline brand-img py-0" />
|
||||||
<?php echo SITE_TITLE; ?>
|
<?php echo $SETTINGS['site_title']; ?>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
<div class="collapse navbar-collapse py-0" id="navbar-collapse">
|
<div class="collapse navbar-collapse py-0" id="navbar-collapse">
|
||||||
@ -163,7 +163,7 @@ END;
|
|||||||
</div>
|
</div>
|
||||||
<div class="navbar-nav ml-auto py-0" id="navbar-right">
|
<div class="navbar-nav ml-auto py-0" id="navbar-right">
|
||||||
<span class="nav-item py-<?php echo $navbar_breakpoint; ?>-0">
|
<span class="nav-item py-<?php echo $navbar_breakpoint; ?>-0">
|
||||||
<a class="nav-link py-<?php echo $navbar_breakpoint; ?>-0" href="<?php echo PORTAL_URL; ?>">
|
<a class="nav-link py-<?php echo $navbar_breakpoint; ?>-0" href="<?php echo $SETTINGS['accounthub']['home']; ?>">
|
||||||
<i class="fas fa-user fa-fw"></i><span> <?php echo $_SESSION['realname'] ?></span>
|
<i class="fas fa-user fa-fw"></i><span> <?php echo $_SESSION['realname'] ?></span>
|
||||||
</a>
|
</a>
|
||||||
</span>
|
</span>
|
||||||
@ -183,8 +183,8 @@ END;
|
|||||||
?>
|
?>
|
||||||
</div>
|
</div>
|
||||||
<div class="footer">
|
<div class="footer">
|
||||||
<?php echo FOOTER_TEXT; ?><br />
|
<?php echo $SETTINGS['footer_text']; ?><br />
|
||||||
Copyright © <?php echo date('Y'); ?> <?php echo COPYRIGHT_NAME; ?>
|
Copyright © <?php echo date('Y'); ?> <?php echo $SETTINGS['copyright']; ?>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<script src="static/js/jquery-3.3.1.min.js"></script>
|
<script src="static/js/jquery-3.3.1.min.js"></script>
|
||||||
|
18
cron.php
18
cron.php
@ -13,20 +13,20 @@ $libs = glob(__DIR__ . "/lib/*.lib.php");
|
|||||||
foreach ($libs as $lib) {
|
foreach ($libs as $lib) {
|
||||||
require_once $lib;
|
require_once $lib;
|
||||||
}
|
}
|
||||||
$Strings = new Strings(LANGUAGE);
|
$Strings = new Strings($SETTINGS['language']);
|
||||||
date_default_timezone_set(TIMEZONE);
|
date_default_timezone_set($SETTINGS['timezone']);
|
||||||
|
|
||||||
use Medoo\Medoo;
|
use Medoo\Medoo;
|
||||||
|
|
||||||
$database;
|
$database;
|
||||||
try {
|
try {
|
||||||
$database = new Medoo([
|
$database = new Medoo([
|
||||||
'database_type' => DB_TYPE,
|
'database_type' => $SETTINGS['database']['type'],
|
||||||
'database_name' => DB_NAME,
|
'database_name' => $SETTINGS['database']['name'],
|
||||||
'server' => DB_SERVER,
|
'server' => $SETTINGS['database']['server'],
|
||||||
'username' => DB_USER,
|
'username' => $SETTINGS['database']['user'],
|
||||||
'password' => DB_PASS,
|
'password' => $SETTINGS['database']['password'],
|
||||||
'charset' => DB_CHARSET
|
'charset' => $SETTINGS['database']['charset']
|
||||||
]);
|
]);
|
||||||
} catch (Exception $ex) {
|
} catch (Exception $ex) {
|
||||||
echo "Database error: $ex\n";
|
echo "Database error: $ex\n";
|
||||||
@ -51,7 +51,7 @@ foreach ($reminders as $r) {
|
|||||||
$lines = explode("\n", $note->getText(), $linelimit);
|
$lines = explode("\n", $note->getText(), $linelimit);
|
||||||
if (count($lines) == $linelimit) {
|
if (count($lines) == $linelimit) {
|
||||||
array_pop($lines);
|
array_pop($lines);
|
||||||
$lines[] = $Strings->build("Open {app} to read more", ["app" => SITE_TITLE], false);
|
$lines[] = $Strings->build("Open {app} to read more", ["app" => $SETTINGS['site_title']], false);
|
||||||
}
|
}
|
||||||
$content = implode("\n", $lines);
|
$content = implode("\n", $lines);
|
||||||
Notifications::add($note->getOwner(), $Strings->get("Note Reminder", false), $content);
|
Notifications::add($note->getOwner(), $Strings->get("Note Reminder", false), $content);
|
||||||
|
246
index.php
246
index.php
@ -1,175 +1,115 @@
|
|||||||
<?php
|
<?php
|
||||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
/*
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
|
||||||
require_once __DIR__ . "/required.php";
|
require_once __DIR__ . "/required.php";
|
||||||
|
|
||||||
// if we're logged in, we don't need to be here.
|
// if we're logged in, we don't need to be here.
|
||||||
if (!empty($_SESSION['loggedin']) && $_SESSION['loggedin'] === true && !isset($_GET['permissionerror'])) {
|
if (!empty($_SESSION['loggedin']) && $_SESSION['loggedin'] === true && !isset($_GET['permissionerror'])) {
|
||||||
header('Location: app.php');
|
header('Location: app.php');
|
||||||
|
die();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isset($_GET['permissionerror'])) {
|
if (!empty($_GET['logout'])) {
|
||||||
$alert = $Strings->get("no access permission", false);
|
// Show a logout message instead of immediately redirecting to login flow
|
||||||
}
|
?>
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
|
||||||
/* Authenticate user */
|
<title><?php echo $SETTINGS['site_title']; ?></title>
|
||||||
$userpass_ok = false;
|
|
||||||
$multiauth = false;
|
<link rel="icon" href="static/img/logo.svg">
|
||||||
if (Login::checkLoginServer()) {
|
|
||||||
if (empty($VARS['progress'])) {
|
<link href="static/css/bootstrap.min.css" rel="stylesheet">
|
||||||
// Easy way to remove "undefined" warnings.
|
<link href="static/css/svg-with-js.min.css" rel="stylesheet">
|
||||||
} else if ($VARS['progress'] == "1") {
|
<style nonce="<?php echo $SECURE_NONCE; ?>">
|
||||||
if (!CAPTCHA_ENABLED || (CAPTCHA_ENABLED && Login::verifyCaptcha($VARS['captcheck_session_code'], $VARS['captcheck_selected_answer'], CAPTCHA_SERVER . "/api.php"))) {
|
.display-5 {
|
||||||
$autherror = "";
|
font-size: 2.5rem;
|
||||||
$user = User::byUsername($VARS['username']);
|
font-weight: 300;
|
||||||
if ($user->exists()) {
|
line-height: 1.2;
|
||||||
$status = $user->getStatus()->getString();
|
|
||||||
switch ($status) {
|
|
||||||
case "LOCKED_OR_DISABLED":
|
|
||||||
$alert = $Strings->get("account locked", false);
|
|
||||||
break;
|
|
||||||
case "TERMINATED":
|
|
||||||
$alert = $Strings->get("account terminated", false);
|
|
||||||
break;
|
|
||||||
case "CHANGE_PASSWORD":
|
|
||||||
$alert = $Strings->get("password expired", false);
|
|
||||||
break;
|
|
||||||
case "NORMAL":
|
|
||||||
$username_ok = true;
|
|
||||||
break;
|
|
||||||
case "ALERT_ON_ACCESS":
|
|
||||||
$mail_resp = $user->sendAlertEmail();
|
|
||||||
if (DEBUG) {
|
|
||||||
var_dump($mail_resp);
|
|
||||||
}
|
|
||||||
$username_ok = true;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
if (!empty($error)) {
|
|
||||||
$alert = $error;
|
|
||||||
} else {
|
|
||||||
$alert = $Strings->get("login error", false);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if ($username_ok) {
|
|
||||||
if ($user->checkPassword($VARS['password'])) {
|
|
||||||
$_SESSION['passok'] = true; // stop logins using only username and authcode
|
|
||||||
if ($user->has2fa()) {
|
|
||||||
$multiauth = true;
|
|
||||||
} else {
|
|
||||||
Session::start($user);
|
|
||||||
header('Location: app.php');
|
|
||||||
die("Logged in, go to app.php");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
$alert = $Strings->get("login incorrect", false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else { // User does not exist anywhere
|
|
||||||
$alert = $Strings->get("login incorrect", false);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
$alert = $Strings->get("captcha error", false);
|
|
||||||
}
|
}
|
||||||
} else if ($VARS['progress'] == "2") {
|
|
||||||
$user = User::byUsername($VARS['username']);
|
.banner-image {
|
||||||
if ($_SESSION['passok'] !== true) {
|
max-height: 100px;
|
||||||
// stop logins using only username and authcode
|
margin: 2em auto;
|
||||||
sendError("Password integrity check failed!");
|
border: 1px solid grey;
|
||||||
|
border-radius: 15%;
|
||||||
}
|
}
|
||||||
if ($user->check2fa($VARS['authcode'])) {
|
|
||||||
Session::start($user);
|
.blank-image {
|
||||||
header('Location: app.php');
|
height: 100px;
|
||||||
die("Logged in, go to app.php");
|
margin: 2em auto;
|
||||||
} else {
|
|
||||||
$alert = $Strings->get("2fa incorrect", false);
|
|
||||||
}
|
}
|
||||||
}
|
</style>
|
||||||
} else {
|
|
||||||
$alert = $Strings->get("login server unavailable", false);
|
|
||||||
}
|
|
||||||
header("Link: <static/fonts/Roboto.css>; rel=preload; as=style", false);
|
|
||||||
header("Link: <static/css/bootstrap.min.css>; rel=preload; as=style", false);
|
|
||||||
header("Link: <static/css/material-color/material-color.min.css>; rel=preload; as=style", false);
|
|
||||||
header("Link: <static/css/index.css>; rel=preload; as=style", false);
|
|
||||||
header("Link: <static/js/jquery-3.3.1.min.js>; rel=preload; as=script", false);
|
|
||||||
header("Link: <static/js/bootstrap.bundle.min.js>; rel=preload; as=script", false);
|
|
||||||
?>
|
|
||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
||||||
|
|
||||||
<title><?php echo SITE_TITLE; ?></title>
|
<div class="container mt-4">
|
||||||
|
|
||||||
<link rel="icon" href="static/img/logo.svg">
|
|
||||||
|
|
||||||
<link href="static/css/bootstrap.min.css" rel="stylesheet">
|
|
||||||
<link href="static/css/material-color/material-color.min.css" rel="stylesheet">
|
|
||||||
<link href="static/css/index.css" rel="stylesheet">
|
|
||||||
<?php if (CAPTCHA_ENABLED) { ?>
|
|
||||||
<script src="<?php echo CAPTCHA_SERVER ?>/captcheck.dist.js"></script>
|
|
||||||
<?php } ?>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div class="row justify-content-center">
|
<div class="row justify-content-center">
|
||||||
<div class="col-auto">
|
<div class="col-12 text-center">
|
||||||
<img class="banner-image" src="static/img/logo.svg" />
|
<img class="banner-image" src="./static/img/logo.svg" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
<div class="row justify-content-center">
|
|
||||||
<div class="card col-11 col-xs-11 col-sm-8 col-md-6 col-lg-4">
|
|
||||||
<div class="card-body">
|
|
||||||
<h5 class="card-title"><?php $Strings->get("sign in"); ?></h5>
|
|
||||||
<form action="" method="POST">
|
|
||||||
<?php
|
|
||||||
if (!empty($alert)) {
|
|
||||||
?>
|
|
||||||
<div class="alert alert-danger">
|
|
||||||
<i class="fa fa-fw fa-exclamation-triangle"></i> <?php echo $alert; ?>
|
|
||||||
</div>
|
|
||||||
<?php
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($multiauth != true) {
|
<div class="col-12 text-center">
|
||||||
?>
|
<h1 class="display-5 mb-4"><?php $Strings->get("You have been logged out.") ?></h1>
|
||||||
<input type="text" class="form-control" name="username" placeholder="<?php $Strings->get("username"); ?>" required="required" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" autofocus /><br />
|
</div>
|
||||||
<input type="password" class="form-control" name="password" placeholder="<?php $Strings->get("password"); ?>" required="required" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" /><br />
|
|
||||||
<?php if (CAPTCHA_ENABLED) { ?>
|
<div class="col-12 col-sm-8 col-lg-6">
|
||||||
<div class="captcheck_container" data-stylenonce="<?php echo $SECURE_NONCE; ?>"></div>
|
<div class="card mt-4">
|
||||||
<br />
|
<div class="card-body">
|
||||||
<?php } ?>
|
<a href="./index.php" class="btn btn-primary btn-block"><?php $Strings->get("Log in again"); ?></a>
|
||||||
<input type="hidden" name="progress" value="1" />
|
</div>
|
||||||
<?php
|
|
||||||
} else if ($multiauth) {
|
|
||||||
?>
|
|
||||||
<div class="alert alert-info">
|
|
||||||
<?php $Strings->get("2fa prompt"); ?>
|
|
||||||
</div>
|
|
||||||
<input type="text" class="form-control" name="authcode" placeholder="<?php $Strings->get("authcode"); ?>" required="required" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" autofocus /><br />
|
|
||||||
<input type="hidden" name="progress" value="2" />
|
|
||||||
<input type="hidden" name="username" value="<?php echo $VARS['username']; ?>" />
|
|
||||||
<?php
|
|
||||||
}
|
|
||||||
?>
|
|
||||||
<button type="submit" class="btn btn-primary">
|
|
||||||
<?php $Strings->get("continue"); ?>
|
|
||||||
</button>
|
|
||||||
</form>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="footer">
|
|
||||||
<?php echo FOOTER_TEXT; ?><br />
|
|
||||||
Copyright © <?php echo date('Y'); ?> <?php echo COPYRIGHT_NAME; ?>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<script src="static/js/jquery-3.3.1.min.js"></script>
|
|
||||||
<script src="static/js/bootstrap.bundle.min.js"></script>
|
<script src="static/js/fontawesome-all.min.js"></script>
|
||||||
</body>
|
<?php
|
||||||
</html>
|
die();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (empty($_SESSION["login_code"])) {
|
||||||
|
$redirecttologin = true;
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
$uidinfo = AccountHubApi::get("checkloginkey", ["code" => $_SESSION["login_code"]]);
|
||||||
|
if ($uidinfo["status"] == "ERROR") {
|
||||||
|
throw new Exception();
|
||||||
|
}
|
||||||
|
if (is_numeric($uidinfo['uid'])) {
|
||||||
|
$user = new User($uidinfo['uid'] * 1);
|
||||||
|
Session::start($user);
|
||||||
|
$_SESSION["login_code"] = null;
|
||||||
|
header('Location: app.php');
|
||||||
|
die("Logged in, go to app.php");
|
||||||
|
} else {
|
||||||
|
throw new Exception();
|
||||||
|
}
|
||||||
|
} catch (Exception $ex) {
|
||||||
|
$redirecttologin = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($redirecttologin) {
|
||||||
|
try {
|
||||||
|
$urlbase = (isset($_SERVER['HTTPS']) ? "https" : "http") . "://" . $_SERVER['HTTP_HOST'] . (($_SERVER['SERVER_PORT'] != 80 && $_SERVER['SERVER_PORT'] != 443) ? ":" . $_SERVER['SERVER_PORT'] : "");
|
||||||
|
$iconurl = $urlbase . str_replace("index.php", "", $_SERVER["REQUEST_URI"]) . "static/img/logo.svg";
|
||||||
|
$codedata = AccountHubApi::get("getloginkey", ["appname" => $SETTINGS["site_title"], "appicon" => $iconurl]);
|
||||||
|
|
||||||
|
if ($codedata['status'] != "OK") {
|
||||||
|
throw new Exception($Strings->get("login server unavailable", false));
|
||||||
|
}
|
||||||
|
|
||||||
|
$redirecturl = $urlbase . $_SERVER['REQUEST_URI'];
|
||||||
|
|
||||||
|
$_SESSION["login_code"] = $codedata["code"];
|
||||||
|
|
||||||
|
header("Location: " . $codedata["loginurl"] . "?code=" . htmlentities($codedata["code"]) . "&redirect=" . htmlentities($redirecturl));
|
||||||
|
} catch (Exception $ex) {
|
||||||
|
sendError($ex->getMessage());
|
||||||
|
}
|
||||||
|
}
|
@ -1,17 +1,7 @@
|
|||||||
{
|
{
|
||||||
"sign in": "Sign In",
|
"You have been logged out.": "You have been logged out.",
|
||||||
"username": "Username",
|
"Log in again": "Log in again",
|
||||||
"password": "Password",
|
|
||||||
"continue": "Continue",
|
|
||||||
"authcode": "Authentication code",
|
|
||||||
"2fa prompt": "Enter the six-digit code from your mobile authenticator app.",
|
|
||||||
"2fa incorrect": "Authentication code incorrect.",
|
|
||||||
"login incorrect": "Login incorrect.",
|
|
||||||
"login server unavailable": "Login server unavailable. Try again later or contact technical support.",
|
"login server unavailable": "Login server unavailable. Try again later or contact technical support.",
|
||||||
"account locked": "This account has been disabled. Contact technical support.",
|
|
||||||
"password expired": "You must change your password before continuing.",
|
|
||||||
"account terminated": "Account terminated. Access denied.",
|
|
||||||
"account state error": "Your account state is not stable. Log out, restart your browser, and try again.",
|
|
||||||
"welcome user": "Welcome, {user}!",
|
"welcome user": "Welcome, {user}!",
|
||||||
"sign out": "Sign out",
|
"sign out": "Sign out",
|
||||||
"settings": "Settings",
|
"settings": "Settings",
|
||||||
|
56
lib/AccountHubApi.lib.php
Normal file
56
lib/AccountHubApi.lib.php
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class AccountHubApi {
|
||||||
|
|
||||||
|
public static function get(string $action, array $data = null, bool $throwex = false) {
|
||||||
|
global $SETTINGS;
|
||||||
|
|
||||||
|
$content = [
|
||||||
|
"action" => $action,
|
||||||
|
"key" => $SETTINGS['accounthub']['key']
|
||||||
|
];
|
||||||
|
if (!is_null($data)) {
|
||||||
|
$content = array_merge($content, $data);
|
||||||
|
}
|
||||||
|
$options = [
|
||||||
|
'http' => [
|
||||||
|
'method' => 'POST',
|
||||||
|
'content' => json_encode($content),
|
||||||
|
'header' => "Content-Type: application/json\r\n" .
|
||||||
|
"Accept: application/json\r\n",
|
||||||
|
"ignore_errors" => true
|
||||||
|
]
|
||||||
|
];
|
||||||
|
|
||||||
|
$context = stream_context_create($options);
|
||||||
|
$result = file_get_contents($SETTINGS['accounthub']['api'], false, $context);
|
||||||
|
$response = json_decode($result, true);
|
||||||
|
if ($result === false || !AccountHubApi::checkHttpRespCode($http_response_header) || json_last_error() != JSON_ERROR_NONE) {
|
||||||
|
if ($throwex) {
|
||||||
|
throw new Exception($result);
|
||||||
|
} else {
|
||||||
|
sendError($result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $response;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static function checkHttpRespCode(array $headers): bool {
|
||||||
|
foreach ($headers as $header) {
|
||||||
|
if (preg_match("/HTTP\/[0-9]\.[0-9] [0-9]{3}.*/", $header)) {
|
||||||
|
$respcode = explode(" ", $header)[1] * 1;
|
||||||
|
if ($respcode >= 200 && $respcode < 300) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
257
lib/FormBuilder.lib.php
Normal file
257
lib/FormBuilder.lib.php
Normal file
@ -0,0 +1,257 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class FormBuilder {
|
||||||
|
|
||||||
|
private $items = [];
|
||||||
|
private $hiddenitems = [];
|
||||||
|
private $title = "";
|
||||||
|
private $icon = "";
|
||||||
|
private $buttons = [];
|
||||||
|
private $action = "action.php";
|
||||||
|
private $method = "POST";
|
||||||
|
private $id = "editform";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a form with autogenerated HTML.
|
||||||
|
*
|
||||||
|
* @param string $title Form title/heading
|
||||||
|
* @param string $icon FontAwesone icon next to the title.
|
||||||
|
* @param string $action URL to submit the form to.
|
||||||
|
* @param string $method Form submission method (POST, GET, etc.)
|
||||||
|
*/
|
||||||
|
public function __construct(string $title = "Untitled Form", string $icon = "fas fa-file-alt", string $action = "action.php", string $method = "POST") {
|
||||||
|
$this->title = $title;
|
||||||
|
$this->icon = $icon;
|
||||||
|
$this->action = $action;
|
||||||
|
$this->method = $method;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the title of the form.
|
||||||
|
* @param string $title
|
||||||
|
*/
|
||||||
|
public function setTitle(string $title) {
|
||||||
|
$this->title = $title;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the icon for the form.
|
||||||
|
* @param string $icon FontAwesome icon (example: "fas fa-toilet-paper")
|
||||||
|
*/
|
||||||
|
public function setIcon(string $icon) {
|
||||||
|
$this->icon = $icon;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the URL the form will submit to.
|
||||||
|
* @param string $action
|
||||||
|
*/
|
||||||
|
public function setAction(string $action) {
|
||||||
|
$this->action = $action;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the form submission method (GET, POST, etc)
|
||||||
|
* @param string $method
|
||||||
|
*/
|
||||||
|
public function setMethod(string $method = "POST") {
|
||||||
|
$this->method = $method;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the form ID.
|
||||||
|
* @param string $id
|
||||||
|
*/
|
||||||
|
public function setID(string $id = "editform") {
|
||||||
|
$this->id = $id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add an input to the form.
|
||||||
|
*
|
||||||
|
* @param string $name Element name
|
||||||
|
* @param string $value Element value
|
||||||
|
* @param string $type Input type (text, number, date, select, tel...)
|
||||||
|
* @param bool $required If the element is required for form submission.
|
||||||
|
* @param string $id Element ID
|
||||||
|
* @param array $options Array of [value => text] pairs for a select element
|
||||||
|
* @param string $label Text label to display near the input
|
||||||
|
* @param string $icon FontAwesome icon (example: "fas fa-toilet-paper")
|
||||||
|
* @param int $width Bootstrap column width for the input, out of 12.
|
||||||
|
* @param int $minlength Minimum number of characters for the input.
|
||||||
|
* @param int $maxlength Maximum number of characters for the input.
|
||||||
|
* @param string $pattern Regex pattern for custom client-side validation.
|
||||||
|
* @param string $error Message to show if the input doesn't validate.
|
||||||
|
*/
|
||||||
|
public function addInput(string $name, string $value = "", string $type = "text", bool $required = true, string $id = null, array $options = null, string $label = "", string $icon = "", int $width = 4, int $minlength = 1, int $maxlength = 100, string $pattern = "", string $error = "") {
|
||||||
|
$item = [
|
||||||
|
"name" => $name,
|
||||||
|
"value" => $value,
|
||||||
|
"type" => $type,
|
||||||
|
"required" => $required,
|
||||||
|
"label" => $label,
|
||||||
|
"icon" => $icon,
|
||||||
|
"width" => $width,
|
||||||
|
"minlength" => $minlength,
|
||||||
|
"maxlength" => $maxlength
|
||||||
|
];
|
||||||
|
if (!empty($id)) {
|
||||||
|
$item["id"] = $id;
|
||||||
|
}
|
||||||
|
if (!empty($options) && $type == "select") {
|
||||||
|
$item["options"] = $options;
|
||||||
|
}
|
||||||
|
if (!empty($pattern)) {
|
||||||
|
$item["pattern"] = $pattern;
|
||||||
|
}
|
||||||
|
if (!empty($error)) {
|
||||||
|
$item["error"] = $error;
|
||||||
|
}
|
||||||
|
$this->items[] = $item;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a button to the form.
|
||||||
|
*
|
||||||
|
* @param string $text Text string to show on the button.
|
||||||
|
* @param string $icon FontAwesome icon to show next to the text.
|
||||||
|
* @param string $href If not null, the button will actually be a hyperlink.
|
||||||
|
* @param string $type Usually "button" or "submit". Ignored if $href is set.
|
||||||
|
* @param string $id The element ID.
|
||||||
|
* @param string $name The element name for the button.
|
||||||
|
* @param string $value The form value for the button. Ignored if $name is null.
|
||||||
|
* @param string $class The CSS classes for the button, if a standard success-colored one isn't right.
|
||||||
|
*/
|
||||||
|
public function addButton(string $text, string $icon = "", string $href = null, string $type = "button", string $id = null, string $name = null, string $value = "", string $class = "btn btn-success") {
|
||||||
|
$button = [
|
||||||
|
"text" => $text,
|
||||||
|
"icon" => $icon,
|
||||||
|
"class" => $class,
|
||||||
|
"type" => $type,
|
||||||
|
"id" => $id,
|
||||||
|
"href" => $href,
|
||||||
|
"name" => $name,
|
||||||
|
"value" => $value
|
||||||
|
];
|
||||||
|
$this->buttons[] = $button;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a hidden input.
|
||||||
|
* @param string $name
|
||||||
|
* @param string $value
|
||||||
|
*/
|
||||||
|
public function addHiddenInput(string $name, string $value) {
|
||||||
|
$this->hiddenitems[$name] = $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate the form HTML.
|
||||||
|
* @param bool $echo If false, returns HTML string instead of outputting it.
|
||||||
|
*/
|
||||||
|
public function generate(bool $echo = true) {
|
||||||
|
$html = <<<HTMLTOP
|
||||||
|
<form action="$this->action" method="$this->method" id="$this->id">
|
||||||
|
<div class="card">
|
||||||
|
<h3 class="card-header d-flex">
|
||||||
|
<div>
|
||||||
|
<i class="$this->icon"></i> $this->title
|
||||||
|
</div>
|
||||||
|
</h3>
|
||||||
|
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="row">
|
||||||
|
HTMLTOP;
|
||||||
|
|
||||||
|
foreach ($this->items as $item) {
|
||||||
|
$required = $item["required"] ? "required" : "";
|
||||||
|
$id = empty($item["id"]) ? "" : "id=\"$item[id]\"";
|
||||||
|
$pattern = empty($item["pattern"]) ? "" : "pattern=\"$item[pattern]\"";
|
||||||
|
|
||||||
|
$itemhtml = "";
|
||||||
|
$itemhtml .= <<<ITEMTOP
|
||||||
|
\n\n <div class="col-12 col-md-$item[width]">
|
||||||
|
<div class="form-group mb-3">
|
||||||
|
<label class="mb-0">$item[label]:</label>
|
||||||
|
<div class="input-group">
|
||||||
|
<div class="input-group-prepend">
|
||||||
|
<span class="input-group-text"><i class="$item[icon]"></i></span>
|
||||||
|
</div>
|
||||||
|
ITEMTOP;
|
||||||
|
if (empty($item['type']) || $item['type'] != "select") {
|
||||||
|
$itemhtml .= <<<INPUT
|
||||||
|
\n <input type="$item[type]" name="$item[name]" $id class="form-control" aria-label="$item[label]" minlength="$item[minlength]" maxlength="$item[maxlength]" $pattern value="$item[value]" $required />
|
||||||
|
INPUT;
|
||||||
|
} else {
|
||||||
|
$itemhtml .= <<<SELECT
|
||||||
|
\n <select class="form-control" name="$item[name]" aria-label="$item[label]" $required>
|
||||||
|
SELECT;
|
||||||
|
foreach ($item['options'] as $value => $label) {
|
||||||
|
$selected = "";
|
||||||
|
if (!empty($item['value']) && $value == $item['value']) {
|
||||||
|
$selected = " selected";
|
||||||
|
}
|
||||||
|
$itemhtml .= "\n <option value=\"$value\"$selected>$label</option>";
|
||||||
|
}
|
||||||
|
$itemhtml .= "\n </select>";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!empty($item["error"])) {
|
||||||
|
$itemhtml .= <<<ERROR
|
||||||
|
\n <div class="invalid-feedback">
|
||||||
|
$item[error]
|
||||||
|
</div>
|
||||||
|
ERROR;
|
||||||
|
}
|
||||||
|
$itemhtml .= <<<ITEMBOTTOM
|
||||||
|
\n </div>
|
||||||
|
</div>
|
||||||
|
</div>\n
|
||||||
|
ITEMBOTTOM;
|
||||||
|
$html .= $itemhtml;
|
||||||
|
}
|
||||||
|
|
||||||
|
$html .= <<<HTMLBOTTOM
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
HTMLBOTTOM;
|
||||||
|
|
||||||
|
if (!empty($this->buttons)) {
|
||||||
|
$html .= "\n <div class=\"card-footer\">";
|
||||||
|
foreach ($this->buttons as $btn) {
|
||||||
|
$btnhtml = "";
|
||||||
|
$inner = "<i class=\"$btn[icon]\"></i> $btn[text]";
|
||||||
|
$id = empty($btn['id']) ? "" : "id=\"$btn[id]\"";
|
||||||
|
if (!empty($btn['href'])) {
|
||||||
|
$btnhtml = "<a href=\"$btn[href]\" class=\"$btn[class]\" $id>$inner</a>";
|
||||||
|
} else {
|
||||||
|
$name = empty($btn['name']) ? "" : "name=\"$btn[name]\"";
|
||||||
|
$value = (!empty($btn['name']) && !empty($btn['value'])) ? "value=\"$btn[value]\"" : "";
|
||||||
|
$btnhtml = "<button type=\"$btn[type]\" class=\"$btn[class]\" $id $name $value>$inner</button>";
|
||||||
|
}
|
||||||
|
$html .= "\n $btnhtml";
|
||||||
|
}
|
||||||
|
$html .= "\n </div>";
|
||||||
|
}
|
||||||
|
|
||||||
|
$html .= "\n </div>";
|
||||||
|
foreach ($this->hiddenitems as $name => $value) {
|
||||||
|
$value = htmlentities($value);
|
||||||
|
$html .= "\n <input type=\"hidden\" name=\"$name\" value=\"$value\" />";
|
||||||
|
}
|
||||||
|
$html .= "\n</form>\n";
|
||||||
|
|
||||||
|
if ($echo) {
|
||||||
|
echo $html;
|
||||||
|
}
|
||||||
|
return $html;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -74,21 +74,7 @@ class Login {
|
|||||||
*/
|
*/
|
||||||
public static function checkLoginServer() {
|
public static function checkLoginServer() {
|
||||||
try {
|
try {
|
||||||
$client = new GuzzleHttp\Client();
|
$resp = AccountHubApi::get("ping");
|
||||||
|
|
||||||
$response = $client
|
|
||||||
->request('POST', PORTAL_API, [
|
|
||||||
'form_params' => [
|
|
||||||
'key' => PORTAL_KEY,
|
|
||||||
'action' => "ping"
|
|
||||||
]
|
|
||||||
]);
|
|
||||||
|
|
||||||
if ($response->getStatusCode() != 200) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
$resp = json_decode($response->getBody(), TRUE);
|
|
||||||
if ($resp['status'] == "OK") {
|
if ($resp['status'] == "OK") {
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
@ -107,19 +93,7 @@ class Login {
|
|||||||
*/
|
*/
|
||||||
function checkAPIKey($key) {
|
function checkAPIKey($key) {
|
||||||
try {
|
try {
|
||||||
$client = new GuzzleHttp\Client();
|
$resp = AccountHubApi::get("ping", null, true);
|
||||||
|
|
||||||
$response = $client
|
|
||||||
->request('POST', PORTAL_API, [
|
|
||||||
'form_params' => [
|
|
||||||
'key' => $key,
|
|
||||||
'action' => "ping"
|
|
||||||
]
|
|
||||||
]);
|
|
||||||
|
|
||||||
if ($response->getStatusCode() === 200) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
return false;
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -116,6 +116,7 @@ class Note {
|
|||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
public function getHTML(bool $fragment = true): string {
|
public function getHTML(bool $fragment = true): string {
|
||||||
|
global $SETTINGS;
|
||||||
$parsedown = new ParsedownCheckbox();
|
$parsedown = new ParsedownCheckbox();
|
||||||
$html = $parsedown->text($this->content);
|
$html = $parsedown->text($this->content);
|
||||||
$safehtml = Htmlawed::filter($html, ['safe' => 1]);
|
$safehtml = Htmlawed::filter($html, ['safe' => 1]);
|
||||||
@ -126,7 +127,7 @@ class Note {
|
|||||||
. "<meta charset=\"UTF-8\">\n"
|
. "<meta charset=\"UTF-8\">\n"
|
||||||
. "<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n"
|
. "<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n"
|
||||||
. "<meta name=\"author\" content=\"" . htmlentities($this->getOwner()->getName()) . "\">\n"
|
. "<meta name=\"author\" content=\"" . htmlentities($this->getOwner()->getName()) . "\">\n"
|
||||||
. "<meta name=\"generator\" content=\"" . SITE_TITLE . "\">\n"
|
. "<meta name=\"generator\" content=\"" . $SETTINGS['site_title'] . "\">\n"
|
||||||
. "<link rel=\"schema.dcterms\" href=\"http://purl.org/dc/terms/\">\n"
|
. "<link rel=\"schema.dcterms\" href=\"http://purl.org/dc/terms/\">\n"
|
||||||
. "<meta name=\"dcterms.modified\" content=\"" . date("Y-m-d", strtotime($this->getModified())) . "\">\n"
|
. "<meta name=\"dcterms.modified\" content=\"" . date("Y-m-d", strtotime($this->getModified())) . "\">\n"
|
||||||
. "\n"
|
. "\n"
|
||||||
|
@ -32,27 +32,15 @@ class Notifications {
|
|||||||
$timestamp = date("Y-m-d H:i:s", strtotime($timestamp));
|
$timestamp = date("Y-m-d H:i:s", strtotime($timestamp));
|
||||||
}
|
}
|
||||||
|
|
||||||
$client = new GuzzleHttp\Client();
|
$resp = AccountHubApi::get("addnotification", [
|
||||||
|
'uid' => $user->getUID(),
|
||||||
$response = $client
|
'title' => $title,
|
||||||
->request('POST', PORTAL_API, [
|
'content' => $content,
|
||||||
'form_params' => [
|
'timestamp' => $timestamp,
|
||||||
'key' => PORTAL_KEY,
|
'url' => $url,
|
||||||
'action' => "addnotification",
|
'sensitive' => $sensitive
|
||||||
'uid' => $user->getUID(),
|
]
|
||||||
'title' => $title,
|
);
|
||||||
'content' => $content,
|
|
||||||
'timestamp' => $timestamp,
|
|
||||||
'url' => $url,
|
|
||||||
'sensitive' => $sensitive
|
|
||||||
]
|
|
||||||
]);
|
|
||||||
|
|
||||||
if ($response->getStatusCode() > 299) {
|
|
||||||
sendError("Login server error: " . $response->getBody());
|
|
||||||
}
|
|
||||||
|
|
||||||
$resp = json_decode($response->getBody(), TRUE);
|
|
||||||
if ($resp['status'] == "OK") {
|
if ($resp['status'] == "OK") {
|
||||||
return $resp['id'] * 1;
|
return $resp['id'] * 1;
|
||||||
} else {
|
} else {
|
||||||
|
159
lib/User.lib.php
159
lib/User.lib.php
@ -17,22 +17,7 @@ class User {
|
|||||||
|
|
||||||
public function __construct(int $uid, string $username = "") {
|
public function __construct(int $uid, string $username = "") {
|
||||||
// Check if user exists
|
// Check if user exists
|
||||||
$client = new GuzzleHttp\Client();
|
$resp = AccountHubApi::get("userexists", ["uid" => $uid]);
|
||||||
|
|
||||||
$response = $client
|
|
||||||
->request('POST', PORTAL_API, [
|
|
||||||
'form_params' => [
|
|
||||||
'key' => PORTAL_KEY,
|
|
||||||
'action' => "userexists",
|
|
||||||
'uid' => $uid
|
|
||||||
]
|
|
||||||
]);
|
|
||||||
|
|
||||||
if ($response->getStatusCode() > 299) {
|
|
||||||
sendError("Login server error: " . $response->getBody());
|
|
||||||
}
|
|
||||||
|
|
||||||
$resp = json_decode($response->getBody(), TRUE);
|
|
||||||
if ($resp['status'] == "OK" && $resp['exists'] === true) {
|
if ($resp['status'] == "OK" && $resp['exists'] === true) {
|
||||||
$this->exists = true;
|
$this->exists = true;
|
||||||
} else {
|
} else {
|
||||||
@ -43,22 +28,7 @@ class User {
|
|||||||
|
|
||||||
if ($this->exists) {
|
if ($this->exists) {
|
||||||
// Get user info
|
// Get user info
|
||||||
$client = new GuzzleHttp\Client();
|
$resp = AccountHubApi::get("userinfo", ["uid" => $uid]);
|
||||||
|
|
||||||
$response = $client
|
|
||||||
->request('POST', PORTAL_API, [
|
|
||||||
'form_params' => [
|
|
||||||
'key' => PORTAL_KEY,
|
|
||||||
'action' => "userinfo",
|
|
||||||
'uid' => $uid
|
|
||||||
]
|
|
||||||
]);
|
|
||||||
|
|
||||||
if ($response->getStatusCode() > 299) {
|
|
||||||
sendError("Login server error: " . $response->getBody());
|
|
||||||
}
|
|
||||||
|
|
||||||
$resp = json_decode($response->getBody(), TRUE);
|
|
||||||
if ($resp['status'] == "OK") {
|
if ($resp['status'] == "OK") {
|
||||||
$this->uid = $resp['data']['uid'] * 1;
|
$this->uid = $resp['data']['uid'] * 1;
|
||||||
$this->username = $resp['data']['username'];
|
$this->username = $resp['data']['username'];
|
||||||
@ -71,22 +41,7 @@ class User {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static function byUsername(string $username): User {
|
public static function byUsername(string $username): User {
|
||||||
$client = new GuzzleHttp\Client();
|
$resp = AccountHubApi::get("userinfo", ["username" => $username]);
|
||||||
|
|
||||||
$response = $client
|
|
||||||
->request('POST', PORTAL_API, [
|
|
||||||
'form_params' => [
|
|
||||||
'key' => PORTAL_KEY,
|
|
||||||
'username' => $username,
|
|
||||||
'action' => "userinfo"
|
|
||||||
]
|
|
||||||
]);
|
|
||||||
|
|
||||||
if ($response->getStatusCode() > 299) {
|
|
||||||
sendError("Login server error: " . $response->getBody());
|
|
||||||
}
|
|
||||||
|
|
||||||
$resp = json_decode($response->getBody(), TRUE);
|
|
||||||
if (!isset($resp['status'])) {
|
if (!isset($resp['status'])) {
|
||||||
sendError("Login server error: " . $resp);
|
sendError("Login server error: " . $resp);
|
||||||
}
|
}
|
||||||
@ -105,22 +60,8 @@ class User {
|
|||||||
if (!$this->exists) {
|
if (!$this->exists) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
$client = new GuzzleHttp\Client();
|
|
||||||
|
|
||||||
$response = $client
|
$resp = AccountHubApi::get("hastotp", ['username' => $this->username]);
|
||||||
->request('POST', PORTAL_API, [
|
|
||||||
'form_params' => [
|
|
||||||
'key' => PORTAL_KEY,
|
|
||||||
'action' => "hastotp",
|
|
||||||
'username' => $this->username
|
|
||||||
]
|
|
||||||
]);
|
|
||||||
|
|
||||||
if ($response->getStatusCode() > 299) {
|
|
||||||
sendError("Login server error: " . $response->getBody());
|
|
||||||
}
|
|
||||||
|
|
||||||
$resp = json_decode($response->getBody(), TRUE);
|
|
||||||
if ($resp['status'] == "OK") {
|
if ($resp['status'] == "OK") {
|
||||||
return $resp['otp'] == true;
|
return $resp['otp'] == true;
|
||||||
} else {
|
} else {
|
||||||
@ -150,23 +91,7 @@ class User {
|
|||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
function checkPassword(string $password): bool {
|
function checkPassword(string $password): bool {
|
||||||
$client = new GuzzleHttp\Client();
|
$resp = AccountHubApi::get("auth", ['username' => $this->username, 'password' => $password]);
|
||||||
|
|
||||||
$response = $client
|
|
||||||
->request('POST', PORTAL_API, [
|
|
||||||
'form_params' => [
|
|
||||||
'key' => PORTAL_KEY,
|
|
||||||
'action' => "auth",
|
|
||||||
'username' => $this->username,
|
|
||||||
'password' => $password
|
|
||||||
]
|
|
||||||
]);
|
|
||||||
|
|
||||||
if ($response->getStatusCode() > 299) {
|
|
||||||
sendError("Login server error: " . $response->getBody());
|
|
||||||
}
|
|
||||||
|
|
||||||
$resp = json_decode($response->getBody(), TRUE);
|
|
||||||
if ($resp['status'] == "OK") {
|
if ($resp['status'] == "OK") {
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
@ -178,23 +103,8 @@ class User {
|
|||||||
if (!$this->has2fa) {
|
if (!$this->has2fa) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
$client = new GuzzleHttp\Client();
|
|
||||||
|
|
||||||
$response = $client
|
$resp = AccountHubApi::get("verifytotp", ['username' => $this->username, 'code' => $code]);
|
||||||
->request('POST', PORTAL_API, [
|
|
||||||
'form_params' => [
|
|
||||||
'key' => PORTAL_KEY,
|
|
||||||
'action' => "verifytotp",
|
|
||||||
'username' => $this->username,
|
|
||||||
'code' => $code
|
|
||||||
]
|
|
||||||
]);
|
|
||||||
|
|
||||||
if ($response->getStatusCode() > 299) {
|
|
||||||
sendError("Login server error: " . $response->getBody());
|
|
||||||
}
|
|
||||||
|
|
||||||
$resp = json_decode($response->getBody(), TRUE);
|
|
||||||
if ($resp['status'] == "OK") {
|
if ($resp['status'] == "OK") {
|
||||||
return $resp['valid'];
|
return $resp['valid'];
|
||||||
} else {
|
} else {
|
||||||
@ -209,23 +119,7 @@ class User {
|
|||||||
* @return boolean TRUE if the user has the permission (or admin access), else FALSE
|
* @return boolean TRUE if the user has the permission (or admin access), else FALSE
|
||||||
*/
|
*/
|
||||||
function hasPermission(string $code): bool {
|
function hasPermission(string $code): bool {
|
||||||
$client = new GuzzleHttp\Client();
|
$resp = AccountHubApi::get("permission", ['username' => $this->username, 'code' => $code]);
|
||||||
|
|
||||||
$response = $client
|
|
||||||
->request('POST', PORTAL_API, [
|
|
||||||
'form_params' => [
|
|
||||||
'key' => PORTAL_KEY,
|
|
||||||
'action' => "permission",
|
|
||||||
'username' => $this->username,
|
|
||||||
'code' => $code
|
|
||||||
]
|
|
||||||
]);
|
|
||||||
|
|
||||||
if ($response->getStatusCode() > 299) {
|
|
||||||
sendError("Login server error: " . $response->getBody());
|
|
||||||
}
|
|
||||||
|
|
||||||
$resp = json_decode($response->getBody(), TRUE);
|
|
||||||
if ($resp['status'] == "OK") {
|
if ($resp['status'] == "OK") {
|
||||||
return $resp['has_permission'];
|
return $resp['has_permission'];
|
||||||
} else {
|
} else {
|
||||||
@ -238,23 +132,7 @@ class User {
|
|||||||
* @return \AccountStatus
|
* @return \AccountStatus
|
||||||
*/
|
*/
|
||||||
function getStatus(): AccountStatus {
|
function getStatus(): AccountStatus {
|
||||||
|
$resp = AccountHubApi::get("acctstatus", ['username' => $this->username]);
|
||||||
$client = new GuzzleHttp\Client();
|
|
||||||
|
|
||||||
$response = $client
|
|
||||||
->request('POST', PORTAL_API, [
|
|
||||||
'form_params' => [
|
|
||||||
'key' => PORTAL_KEY,
|
|
||||||
'action' => "acctstatus",
|
|
||||||
'username' => $this->username
|
|
||||||
]
|
|
||||||
]);
|
|
||||||
|
|
||||||
if ($response->getStatusCode() > 299) {
|
|
||||||
sendError("Login server error: " . $response->getBody());
|
|
||||||
}
|
|
||||||
|
|
||||||
$resp = json_decode($response->getBody(), TRUE);
|
|
||||||
if ($resp['status'] == "OK") {
|
if ($resp['status'] == "OK") {
|
||||||
return AccountStatus::fromString($resp['account']);
|
return AccountStatus::fromString($resp['account']);
|
||||||
} else {
|
} else {
|
||||||
@ -262,24 +140,13 @@ class User {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function sendAlertEmail(string $appname = SITE_TITLE) {
|
function sendAlertEmail(string $appname = null) {
|
||||||
$client = new GuzzleHttp\Client();
|
global $SETTINGS;
|
||||||
|
if (is_null($appname)) {
|
||||||
$response = $client
|
$appname = $SETTINGS['site_title'];
|
||||||
->request('POST', PORTAL_API, [
|
|
||||||
'form_params' => [
|
|
||||||
'key' => PORTAL_KEY,
|
|
||||||
'action' => "alertemail",
|
|
||||||
'username' => $this->username,
|
|
||||||
'appname' => SITE_TITLE
|
|
||||||
]
|
|
||||||
]);
|
|
||||||
|
|
||||||
if ($response->getStatusCode() > 299) {
|
|
||||||
return "An unknown error occurred.";
|
|
||||||
}
|
}
|
||||||
|
$resp = AccountHubApi::get("alertemail", ['username' => $this->username, 'appname' => $SETTINGS['site_title']]);
|
||||||
|
|
||||||
$resp = json_decode($response->getBody(), TRUE);
|
|
||||||
if ($resp['status'] == "OK") {
|
if ($resp['status'] == "OK") {
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
|
@ -16,7 +16,7 @@ $route = explode("/", substr($_SERVER['REQUEST_URI'], strpos($_SERVER['REQUEST_U
|
|||||||
|
|
||||||
// HTTP authentication
|
// HTTP authentication
|
||||||
if (!isset($_SERVER['PHP_AUTH_USER'])) {
|
if (!isset($_SERVER['PHP_AUTH_USER'])) {
|
||||||
header('WWW-Authenticate: Basic realm="' . SITE_TITLE . '"');
|
header('WWW-Authenticate: Basic realm="' . $SETTINGS['site_title'] . '"');
|
||||||
header('HTTP/1.0 401 Unauthorized');
|
header('HTTP/1.0 401 Unauthorized');
|
||||||
exit;
|
exit;
|
||||||
} else {
|
} else {
|
||||||
|
@ -23,21 +23,7 @@ if ($VARS['action'] == "ping") {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function mobile_enabled() {
|
function mobile_enabled() {
|
||||||
$client = new GuzzleHttp\Client();
|
$resp = AccountHubApi::get("mobileenabled");
|
||||||
|
|
||||||
$response = $client
|
|
||||||
->request('POST', PORTAL_API, [
|
|
||||||
'form_params' => [
|
|
||||||
'key' => PORTAL_KEY,
|
|
||||||
'action' => "mobileenabled"
|
|
||||||
]
|
|
||||||
]);
|
|
||||||
|
|
||||||
if ($response->getStatusCode() > 299) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
$resp = json_decode($response->getBody(), TRUE);
|
|
||||||
if ($resp['status'] == "OK" && $resp['mobile'] === TRUE) {
|
if ($resp['status'] == "OK" && $resp['mobile'] === TRUE) {
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
@ -46,26 +32,15 @@ function mobile_enabled() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function mobile_valid($username, $code) {
|
function mobile_valid($username, $code) {
|
||||||
$client = new GuzzleHttp\Client();
|
try {
|
||||||
|
$resp = AccountHubApi::get("mobilevalid", ["code" => $code, "username" => $username], true);
|
||||||
|
|
||||||
$response = $client
|
if ($resp['status'] == "OK" && $resp['valid'] === TRUE) {
|
||||||
->request('POST', PORTAL_API, [
|
return true;
|
||||||
'form_params' => [
|
} else {
|
||||||
'key' => PORTAL_KEY,
|
return false;
|
||||||
"code" => $code,
|
}
|
||||||
"username" => $username,
|
} catch (Exception $ex) {
|
||||||
'action' => "mobilevalid"
|
|
||||||
]
|
|
||||||
]);
|
|
||||||
|
|
||||||
if ($response->getStatusCode() > 299) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
$resp = json_decode($response->getBody(), TRUE);
|
|
||||||
if ($resp['status'] == "OK" && $resp['valid'] === TRUE) {
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -45,4 +45,4 @@ define("PAGES", [
|
|||||||
"static/js/editnote.js"
|
"static/js/editnote.js"
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
]);
|
]);
|
||||||
|
24
pages/form.php
Normal file
24
pages/form.php
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file demonstrates creating a form with the FormBuilder class.
|
||||||
|
*/
|
||||||
|
|
||||||
|
$form = new FormBuilder("Sample Form", "fas fa-code", "", "GET");
|
||||||
|
|
||||||
|
$form->setID("sampleform");
|
||||||
|
|
||||||
|
$form->addHiddenInput("page", "form");
|
||||||
|
|
||||||
|
$form->addInput("name", "John", "text", true, null, null, "Your name", "fas fa-user", 6, 5, 20, "John(ny)?|Steve", "Invalid name, please enter John, Johnny, or Steve.");
|
||||||
|
$form->addInput("location", "", "select", true, null, ["1" => "Here", "2" => "There"], "Location", "fas fa-map-marker");
|
||||||
|
|
||||||
|
$form->addButton("Submit", "fas fa-save", null, "submit", "savebtn");
|
||||||
|
|
||||||
|
$form->generate();
|
@ -154,7 +154,7 @@ foreach ($colors as $c) {
|
|||||||
</a>
|
</a>
|
||||||
<?php
|
<?php
|
||||||
// Additional export formats
|
// Additional export formats
|
||||||
if (PANDOC_BIN != "") {
|
if ($SETTINGS['pandoc'] != "") {
|
||||||
?>
|
?>
|
||||||
<a class="p-2" href="./action.php?action=downloadnote¬eid=<?php echo $note->getID(); ?>&type=odt">
|
<a class="p-2" href="./action.php?action=downloadnote¬eid=<?php echo $note->getID(); ?>&type=odt">
|
||||||
<i class="fas fa-file-alt"></i> <?php $Strings->get('Office'); ?>
|
<i class="fas fa-file-alt"></i> <?php $Strings->get('Office'); ?>
|
||||||
|
22
required.php
22
required.php
@ -32,7 +32,7 @@ session_start(); // stick some cookies in it
|
|||||||
// renew session cookie
|
// renew session cookie
|
||||||
setcookie(session_name(), session_id(), time() + $session_length, "/", false, false);
|
setcookie(session_name(), session_id(), time() + $session_length, "/", false, false);
|
||||||
|
|
||||||
$captcha_server = (CAPTCHA_ENABLED === true ? preg_replace("/http(s)?:\/\//", "", CAPTCHA_SERVER) : "");
|
$captcha_server = ($SETTINGS['captcha']['enabled'] === true ? preg_replace("/http(s)?:\/\//", "", $SETTINGS['captcha']['server']) : "");
|
||||||
if ($_SESSION['mobile'] === TRUE) {
|
if ($_SESSION['mobile'] === TRUE) {
|
||||||
header("Content-Security-Policy: "
|
header("Content-Security-Policy: "
|
||||||
. "default-src 'self';"
|
. "default-src 'self';"
|
||||||
@ -69,7 +69,7 @@ foreach ($libs as $lib) {
|
|||||||
require_once $lib;
|
require_once $lib;
|
||||||
}
|
}
|
||||||
|
|
||||||
$Strings = new Strings(LANGUAGE);
|
$Strings = new Strings($SETTINGS['language']);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Kill off the running process and spit out an error message
|
* Kill off the running process and spit out an error message
|
||||||
@ -93,7 +93,7 @@ function sendError($error) {
|
|||||||
. "<p>" . htmlspecialchars($error) . "</p>");
|
. "<p>" . htmlspecialchars($error) . "</p>");
|
||||||
}
|
}
|
||||||
|
|
||||||
date_default_timezone_set(TIMEZONE);
|
date_default_timezone_set($SETTINGS['timezone']);
|
||||||
|
|
||||||
// Database settings
|
// Database settings
|
||||||
// Also inits database and stuff
|
// Also inits database and stuff
|
||||||
@ -102,12 +102,12 @@ use Medoo\Medoo;
|
|||||||
$database;
|
$database;
|
||||||
try {
|
try {
|
||||||
$database = new Medoo([
|
$database = new Medoo([
|
||||||
'database_type' => DB_TYPE,
|
'database_type' => $SETTINGS['database']['type'],
|
||||||
'database_name' => DB_NAME,
|
'database_name' => $SETTINGS['database']['name'],
|
||||||
'server' => DB_SERVER,
|
'server' => $SETTINGS['database']['server'],
|
||||||
'username' => DB_USER,
|
'username' => $SETTINGS['database']['user'],
|
||||||
'password' => DB_PASS,
|
'password' => $SETTINGS['database']['password'],
|
||||||
'charset' => DB_CHARSET
|
'charset' => $SETTINGS['database']['charset']
|
||||||
]);
|
]);
|
||||||
} catch (Exception $ex) {
|
} catch (Exception $ex) {
|
||||||
//header('HTTP/1.1 500 Internal Server Error');
|
//header('HTTP/1.1 500 Internal Server Error');
|
||||||
@ -115,7 +115,7 @@ try {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (!DEBUG) {
|
if (!$SETTINGS['debug']) {
|
||||||
error_reporting(0);
|
error_reporting(0);
|
||||||
} else {
|
} else {
|
||||||
error_reporting(E_ALL);
|
error_reporting(E_ALL);
|
||||||
@ -158,7 +158,7 @@ function checkDBError($specials = []) {
|
|||||||
|
|
||||||
function redirectIfNotLoggedIn() {
|
function redirectIfNotLoggedIn() {
|
||||||
if ($_SESSION['loggedin'] !== TRUE) {
|
if ($_SESSION['loggedin'] !== TRUE) {
|
||||||
header('Location: ' . URL . '/index.php');
|
header('Location: ' . $SETTINGS['url'] . '/index.php');
|
||||||
die();
|
die();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,50 +1,60 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
/*
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
|
||||||
// Whether to show debugging data in output.
|
// Settings for the app.
|
||||||
// DO NOT SET TO TRUE IN PRODUCTION!!!
|
// Copy to settings.php and customize.
|
||||||
define("DEBUG", false);
|
|
||||||
|
|
||||||
// Database connection settings
|
$SETTINGS = [
|
||||||
// See http://medoo.in/api/new for info
|
// Whether to output debugging info like PHP notices, warnings,
|
||||||
define("DB_TYPE", "mysql");
|
// and stacktraces.
|
||||||
define("DB_NAME", "notepost");
|
// Turning this on in production is a security risk and can sometimes break
|
||||||
define("DB_SERVER", "localhost");
|
// things, such as JSON output where extra content is not expected.
|
||||||
define("DB_USER", "notepost");
|
"debug" => false,
|
||||||
define("DB_PASS", "");
|
// Database connection settings
|
||||||
define("DB_CHARSET", "utf8");
|
// See http://medoo.in/api/new for info
|
||||||
|
"database" => [
|
||||||
// Name of the app.
|
"type" => "mysql",
|
||||||
define("SITE_TITLE", "NotePost");
|
"name" => "notepost",
|
||||||
|
"server" => "localhost",
|
||||||
// Location of the pandoc binary. Enables exporting notes as ODT.
|
"user" => "notepost",
|
||||||
// Leave as an empty string to hide/disable this feature in the GUI.
|
"password" => "",
|
||||||
define("PANDOC_BIN", "/usr/bin/pandoc");
|
"charset" => "utf8"
|
||||||
|
],
|
||||||
// URL of the AccountHub API endpoint
|
// Name of the app.
|
||||||
define("PORTAL_API", "http://localhost/accounthub/api.php");
|
"site_title" => "NotePost",
|
||||||
// URL of the AccountHub home page
|
// Location of the pandoc binary. Enables exporting notes as ODT.
|
||||||
define("PORTAL_URL", "http://localhost/accounthub/home.php");
|
// Leave as an empty string to hide/disable this feature in the GUI.
|
||||||
// AccountHub API Key
|
"pandoc" => "/usr/bin/pandoc",
|
||||||
define("PORTAL_KEY", "123");
|
// Settings for connecting to the AccountHub server.
|
||||||
|
"accounthub" => [
|
||||||
// For supported values, see http://php.net/manual/en/timezones.php
|
// URL for the API endpoint
|
||||||
define("TIMEZONE", "America/Denver");
|
"api" => "http://localhost/accounthub/api/",
|
||||||
|
// URL of the home page
|
||||||
// Base URL for site links.
|
"home" => "http://localhost/accounthub/home.php",
|
||||||
define('URL', '.');
|
// API key
|
||||||
|
"key" => "123"
|
||||||
// Use Captcheck on login screen
|
],
|
||||||
// https://captcheck.netsyms.com
|
// For supported values, see http://php.net/manual/en/timezones.php
|
||||||
define("CAPTCHA_ENABLED", FALSE);
|
"timezone" => "America/Denver",
|
||||||
define('CAPTCHA_SERVER', 'https://captcheck.netsyms.com');
|
// Use Captcheck on login screen to slow down bots
|
||||||
|
// https://captcheck.netsyms.com
|
||||||
// See lang folder for language options
|
"captcha" => [
|
||||||
define('LANGUAGE', "en");
|
"enabled" => false,
|
||||||
|
"server" => "https://captcheck.netsyms.com"
|
||||||
|
],
|
||||||
define("FOOTER_TEXT", "");
|
// Language to use for localization. See langs folder to add a language.
|
||||||
define("COPYRIGHT_NAME", "Netsyms Technologies");
|
"language" => "en",
|
||||||
|
// Shown in the footer of all the pages.
|
||||||
|
"footer_text" => "",
|
||||||
|
// Also shown in the footer, but with "Copyright <current_year>" in front.
|
||||||
|
"copyright" => "Netsyms Technologies",
|
||||||
|
// Base URL for building links relative to the location of the app.
|
||||||
|
// Only used when there's no good context for the path.
|
||||||
|
// The default is almost definitely fine.
|
||||||
|
"url" => "."
|
||||||
|
];
|
||||||
|
16
static/js/form.js
Normal file
16
static/js/form.js
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
/*
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
$("#savebtn").click(function (event) {
|
||||||
|
var form = $("#sampleform");
|
||||||
|
|
||||||
|
if (form[0].checkValidity() === false) {
|
||||||
|
event.preventDefault();
|
||||||
|
event.stopPropagation();
|
||||||
|
}
|
||||||
|
form.addClass('was-validated');
|
||||||
|
});
|
Loading…
x
Reference in New Issue
Block a user