Merge ssh://source.netsyms.com:2322/Business/BusinessAppTemplate

# Conflicts:
#	.gitignore
#	LICENSE.md
#	README.md
#	api.php
#	app.php
#	composer.json
#	composer.lock
#	lang/en_us.php
#	lib/login.php
#	lib/userinfo.php
#	mobile/index.php
#	pages.php
#	pages/404.php
#	required.php
#	settings.template.php
#	static/css/app.css
#	static/img/logo.png
#	static/js/app.js
master
Skylar Ittner 6 years ago
commit c99b739532

@ -1,4 +1,4 @@
Copyright (c) 2017 Netsyms Technologies. Copyright (c) 2018 Netsyms Technologies.
If you modify and redistribute this project, you must replace the branding If you modify and redistribute this project, you must replace the branding
assets with your own. assets with your own.

@ -17,6 +17,12 @@ if ($VARS['action'] !== "signout") {
dieifnotloggedin(); dieifnotloggedin();
} }
/**
* Redirects back to the page ID in $_POST/$_GET['source'] with the given message ID.
* The message will be displayed by the app.
* @param string $msg message ID (see lang/messages.php)
* @param string $arg If set, replaces "{arg}" in the message string when displayed to the user.
*/
function returnToSender($msg, $arg = "") { function returnToSender($msg, $arg = "") {
global $VARS; global $VARS;
if ($arg == "") { if ($arg == "") {

@ -18,6 +18,12 @@ if (!is_empty($_GET['page'])) {
$pageid = "404"; $pageid = "404";
} }
} }
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/app.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.min.js>; rel=preload; as=script", false);
?> ?>
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
@ -43,6 +49,7 @@ if (!is_empty($_GET['page'])) {
if (isset(PAGES[$pageid]['styles'])) { if (isset(PAGES[$pageid]['styles'])) {
foreach (PAGES[$pageid]['styles'] as $style) { foreach (PAGES[$pageid]['styles'] as $style) {
echo "<link href=\"$style\" rel=\"stylesheet\">\n"; echo "<link href=\"$style\" rel=\"stylesheet\">\n";
header("Link: <$style>; rel=preload; as=style", false);
} }
} }
?> ?>
@ -169,6 +176,7 @@ END;
if (isset(PAGES[$pageid]['scripts'])) { if (isset(PAGES[$pageid]['scripts'])) {
foreach (PAGES[$pageid]['scripts'] as $script) { foreach (PAGES[$pageid]['scripts'] as $script) {
echo "<script src=\"$script\"></script>\n"; echo "<script src=\"$script\"></script>\n";
header("Link: <$script>; rel=preload; as=script", false);
} }
} }
?> ?>

@ -72,6 +72,11 @@ if (checkLoginServer()) {
} else { } else {
$alert = lang("login server unavailable", false); $alert = lang("login server unavailable", 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.min.js>; rel=preload; as=script", false);
?> ?>
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>

@ -0,0 +1,127 @@
<?php
/**
* Check if a given ipv4 address is in a given cidr
* @param string $ip IP to check in IPV4 format eg. 127.0.0.1
* @param string $range IP/CIDR netmask eg. 127.0.0.0/24, also 127.0.0.1 is accepted and /32 assumed
* @return boolean true if the ip is in this range / false if not.
* @author Thorsten Ott <https://gist.github.com/tott/7684443>
*/
function ip4_in_cidr($ip, $cidr) {
if (strpos($cidr, '/') == false) {
$cidr .= '/32';
}
// $range is in IP/CIDR format eg 127.0.0.1/24
list( $cidr, $netmask ) = explode('/', $cidr, 2);
$range_decimal = ip2long($cidr);
$ip_decimal = ip2long($ip);
$wildcard_decimal = pow(2, ( 32 - $netmask)) - 1;
$netmask_decimal = ~ $wildcard_decimal;
return ( ( $ip_decimal & $netmask_decimal ) == ( $range_decimal & $netmask_decimal ) );
}
/**
* Check if a given ipv6 address is in a given cidr
* @param string $ip IP to check in IPV6 format
* @param string $cidr CIDR netmask
* @return boolean true if the IP is in this range, false otherwise.
* @author MW. <https://stackoverflow.com/a/7952169>
*/
function ip6_in_cidr($ip, $cidr) {
$address = inet_pton($ip);
$subnetAddress = inet_pton(explode("/", $cidr)[0]);
$subnetMask = explode("/", $cidr)[1];
$addr = str_repeat("f", $subnetMask / 4);
switch ($subnetMask % 4) {
case 0:
break;
case 1:
$addr .= "8";
break;
case 2:
$addr .= "c";
break;
case 3:
$addr .= "e";
break;
}
$addr = str_pad($addr, 32, '0');
$addr = pack("H*", $addr);
$binMask = $addr;
return ($address & $binMask) == $subnetAddress;
}
/**
* Check if the REMOTE_ADDR is on Cloudflare's network.
* @return boolean true if it is, otherwise false
*/
function validateCloudflare() {
if (filter_var($_SERVER["REMOTE_ADDR"], FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) {
// Using IPv6
$cloudflare_ips_v6 = [
"2400:cb00::/32",
"2405:8100::/32",
"2405:b500::/32",
"2606:4700::/32",
"2803:f800::/32",
"2c0f:f248::/32",
"2a06:98c0::/29"
];
$valid = false;
foreach ($cloudflare_ips_v6 as $cidr) {
if (ip6_in_cidr($_SERVER["REMOTE_ADDR"], $cidr)) {
$valid = true;
break;
}
}
} else {
// Using IPv4
$cloudflare_ips_v4 = [
"103.21.244.0/22",
"103.22.200.0/22",
"103.31.4.0/22",
"104.16.0.0/12",
"108.162.192.0/18",
"131.0.72.0/22",
"141.101.64.0/18",
"162.158.0.0/15",
"172.64.0.0/13",
"173.245.48.0/20",
"188.114.96.0/20",
"190.93.240.0/20",
"197.234.240.0/22",
"198.41.128.0/17"
];
$valid = false;
foreach ($cloudflare_ips_v4 as $cidr) {
if (ip4_in_cidr($_SERVER["REMOTE_ADDR"], $cidr)) {
$valid = true;
break;
}
}
}
return $valid;
}
/**
* Makes a good guess at the client's real IP address.
*
* @return string Client IP or `0.0.0.0` if we can't find anything
*/
function getClientIP() {
// If CloudFlare is in the mix, we should use it.
// Check if the request is actually from CloudFlare before trusting it.
if (isset($_SERVER["HTTP_CF_CONNECTING_IP"])) {
if (validateCloudflare()) {
return $_SERVER["HTTP_CF_CONNECTING_IP"];
}
}
if (isset($_SERVER["REMOTE_ADDR"])) {
return $_SERVER["REMOTE_ADDR"];
}
return "0.0.0.0"; // This will not happen unless we aren't a web server
}

@ -6,7 +6,7 @@
/** /**
* Authentication and account functions. Connects to a Portal instance. * Authentication and account functions. Connects to an AccountHub instance.
*/ */
/** /**

@ -9,6 +9,10 @@
* Mobile app API * Mobile app API
*/ */
// The name of the permission needed to log in.
// Set to null if you don't need it.
$access_permission = "TASKFLOOR";
require __DIR__ . "/../required.php"; require __DIR__ . "/../required.php";
require __DIR__ . "/../lib/login.php"; require __DIR__ . "/../lib/login.php";
@ -93,7 +97,7 @@ switch ($VARS['action']) {
if (user_exists($VARS['username'])) { if (user_exists($VARS['username'])) {
if (get_account_status($VARS['username']) == "NORMAL") { if (get_account_status($VARS['username']) == "NORMAL") {
if (authenticate_user($VARS['username'], $VARS['password'], $autherror)) { if (authenticate_user($VARS['username'], $VARS['password'], $autherror)) {
if (account_has_permission($VARS['username'], "TASKFLOOR")) { if (is_null($access_permission) || account_has_permission($VARS['username'], $access_permission)) {
doLoginUser($VARS['username'], $VARS['password']); doLoginUser($VARS['username'], $VARS['password']);
$_SESSION['mobile'] = true; $_SESSION['mobile'] = true;
exit(json_encode(["status" => "OK"])); exit(json_encode(["status" => "OK"]));

@ -12,10 +12,12 @@ ob_start(); // allow sending headers after content
// Unicode, solves almost all stupid encoding problems // Unicode, solves almost all stupid encoding problems
header('Content-Type: text/html; charset=utf-8'); header('Content-Type: text/html; charset=utf-8');
// l33t $ecurity h4x // Strip PHP version
header('X-Powered-By: PHP');
// Security
header('X-Content-Type-Options: nosniff'); header('X-Content-Type-Options: nosniff');
header('X-XSS-Protection: 1; mode=block'); header('X-XSS-Protection: 1; mode=block');
header('X-Powered-By: PHP'); // no versions makes it harder to find vulns
header('X-Frame-Options: "DENY"'); header('X-Frame-Options: "DENY"');
header('Referrer-Policy: "no-referrer, strict-origin-when-cross-origin"'); header('Referrer-Policy: "no-referrer, strict-origin-when-cross-origin"');
$SECURE_NONCE = base64_encode(random_bytes(8)); $SECURE_NONCE = base64_encode(random_bytes(8));
@ -80,7 +82,7 @@ function sendError($error) {
. "<h1>A fatal application error has occurred.</h1>" . "<h1>A fatal application error has occurred.</h1>"
. "<i>(This isn't your fault.)</i>" . "<i>(This isn't your fault.)</i>"
. "<h2>Details:</h2>" . "<h2>Details:</h2>"
. "<p>". htmlspecialchars($error) . "</p>"); . "<p>" . htmlspecialchars($error) . "</p>");
} }
date_default_timezone_set(TIMEZONE); date_default_timezone_set(TIMEZONE);

@ -11,7 +11,7 @@ function setupTooltips() {
$(document).ready(function () { $(document).ready(function () {
/* Fade out alerts */ /* Fade out alerts */
$(".alert .close").click(function (e) { $(".alert .close").click(function (e) {
$(this).parent().fadeOut('slow'); $(this).parent().fadeOut("slow");
}); });
/* Activate tooltips */ /* Activate tooltips */

Loading…
Cancel
Save