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

# Conflicts:
#	.gitignore
#	README.md
#	action.php
#	api.php
#	app.php
#	composer.json
#	composer.lock
#	index.php
#	lang/en_us.php
#	lang/messages.php
#	lib/login.php
#	lib/userinfo.php
#	mobile/index.php
#	nbproject/project.properties
#	nbproject/project.xml
#	pages.php
#	pages/404.php
#	pages/home.php
#	required.php
#	settings.template.php
#	static/css/app.css
#	static/img/logo.png
#	static/img/logo.svg
#	static/js/app.js
master
Skylar Ittner 6 years ago
commit 0593f4c6d4

2
.gitignore vendored

@ -2,4 +2,4 @@ vendor
settings.php
nbproject/private
database.mwb.bak
*.sync-conflict*
*.sync-conflict*

@ -1,7 +1,7 @@
BinStack
========
BinStack is the easy way to keep track of your business assets.
BinStack is the easy way to keep track of your business assets.
Never wander in search of the stapler again.
https://netsyms.biz/apps/binstack
@ -9,20 +9,20 @@ https://netsyms.biz/apps/binstack
Features
--------
**Asset Tracking**
Easily manage locations, tag numbers, assigned users, and other important item
**Asset Tracking**
Easily manage locations, tag numbers, assigned users, and other important item
properties.
**Fully Searchable**
Start typing in the search box to instantly filter hundreds of results down to
**Fully Searchable**
Start typing in the search box to instantly filter hundreds of results down to
only a few. Sorting also built in.
**Autofill**
You don't need to remember category codes or usernames. Just start typing and
**Autofill**
You don't need to remember category codes or usernames. Just start typing and
BinStack will figure out what you're looking for.
**Mobile-ready**
Take inventory or find what you need on the go. BinStack looks and works
**Mobile-ready**
Take inventory or find what you need on the go. BinStack looks and works
great on modern smartphones and tablets.
Installing

@ -223,4 +223,4 @@ switch ($VARS['action']) {
session_destroy();
header('Location: index.php');
die("Logged out.");
}
}

@ -38,4 +38,4 @@ switch ($VARS['action']) {
default:
header("HTTP/1.1 400 Bad Request");
die("\"400 Bad Request\"");
}
}

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

@ -72,6 +72,11 @@ if (checkLoginServer()) {
} else {
$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>
<html>
@ -147,4 +152,4 @@ if (checkLoginServer()) {
<script src="static/js/jquery-3.3.1.min.js"></script>
<script src="static/js/bootstrap.min.js"></script>
</body>
</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/2534036>
*/
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
}

@ -40,6 +40,33 @@ function checkLoginServer() {
}
}
/**
* Checks if the given AccountHub API key is valid by attempting to
* access the API with it.
* @param String $key The API key to check
* @return boolean TRUE if the key is valid, FALSE if invalid or something went wrong
*/
function checkAPIKey($key) {
try {
$client = new GuzzleHttp\Client();
$response = $client
->request('POST', PORTAL_API, [
'form_params' => [
'key' => $key,
'action' => "ping"
]
]);
if ($response->getStatusCode() === 200) {
return true;
}
return false;
} catch (Exception $e) {
return false;
}
}
////////////////////////////////////////////////////////////////////////////////
// Account handling //
////////////////////////////////////////////////////////////////////////////////

@ -124,4 +124,4 @@ function getManagedUIDs($manageruid) {
} else {
return [];
}
}
}

@ -1,14 +1,13 @@
<?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/. */
/*
* Mobile app API
*/
// The name of the permission needed to log in.
// Set to null if you don't need it.
$access_permission = "INV_VIEW";
require __DIR__ . "/../required.php";
require __DIR__ . "/../lib/login.php";
@ -93,7 +92,7 @@ switch ($VARS['action']) {
if (user_exists($VARS['username'])) {
if (get_account_status($VARS['username']) == "NORMAL") {
if (authenticate_user($VARS['username'], $VARS['password'], $autherror)) {
if (account_has_permission($VARS['username'], "INV_VIEW")) {
if (is_null($access_permission) || account_has_permission($VARS['username'], $access_permission)) {
doLoginUser($VARS['username'], $VARS['password']);
$_SESSION['mobile'] = true;
exit(json_encode(["status" => "OK"]));
@ -107,4 +106,4 @@ switch ($VARS['action']) {
default:
http_response_code(404);
die(json_encode(["status" => "ERROR", "msg" => "The requested action is not available."]));
}
}

@ -52,4 +52,4 @@ redirectifnotloggedin();
<a href="app.php?page=items&filter=stock" class="text-light"><i class="fas fa-arrow-right"></i> <?php lang("view understocked"); ?></a>
</div>
</div>
</div>
</div>

@ -12,10 +12,12 @@ ob_start(); // allow sending headers after content
// Unicode, solves almost all stupid encoding problems
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-XSS-Protection: 1; mode=block');
header('X-Powered-By: PHP'); // no versions makes it harder to find vulns
header('X-Frame-Options: "DENY"');
header('Referrer-Policy: "no-referrer, strict-origin-when-cross-origin"');
$SECURE_NONCE = base64_encode(random_bytes(8));
@ -142,6 +144,7 @@ function lang($key, $echo = true) {
if (array_key_exists($key, STRINGS)) {
$str = STRINGS[$key];
} else {
trigger_error("Language key \"$key\" does not exist in " . LANGUAGE, E_USER_WARNING);
$str = $key;
}
@ -164,6 +167,7 @@ function lang2($key, $replace, $echo = true) {
if (array_key_exists($key, STRINGS)) {
$str = STRINGS[$key];
} else {
trigger_error("Language key \"$key\" does not exist in " . LANGUAGE, E_USER_WARNING);
$str = $key;
}

@ -54,4 +54,4 @@ define('LANGUAGE', "en_us");
define("FOOTER_TEXT", "");
define("COPYRIGHT_NAME", "Netsyms Technologies");
//////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////

@ -65,4 +65,4 @@ body {
.mobile-app-display {
display: none;
}
}

@ -23,4 +23,4 @@ try {
window.history.replaceState("", "", getniceurl());
} catch (ex) {
}
}

Loading…
Cancel
Save