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

2
.gitignore vendored

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

@ -1,18 +1,18 @@
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.
The branding assets include:
The branding assets include:
* the application icon
* the Netsyms N punchcard logo
* the Netsyms for Business graph logo
If you are unsure if your usage is allowed, please contact us:
If you are unsure if your usage is allowed, please contact us:
https://netsyms.com/contact
legal@netsyms.com
All other portions of this application,
All other portions of this application,
unless otherwise noted (in comments, headers, etc), are licensed as follows:
Mozilla Public License Version 2.0
@ -20,24 +20,24 @@ Mozilla Public License Version 2.0
### 1. Definitions
**1.1. “Contributor”**
**1.1. “Contributor”**
means each individual or legal entity that creates, contributes to
the creation of, or owns Covered Software.
**1.2. “Contributor Version”**
**1.2. “Contributor Version”**
means the combination of the Contributions of others (if any) used
by a Contributor and that particular Contributor's Contribution.
**1.3. “Contribution”**
**1.3. “Contribution”**
means Covered Software of a particular Contributor.
**1.4. “Covered Software”**
**1.4. “Covered Software”**
means Source Code Form to which the initial Contributor has attached
the notice in Exhibit A, the Executable Form of such Source Code
Form, and Modifications of such Source Code Form, in each case
including portions thereof.
**1.5. “Incompatible With Secondary Licenses”**
**1.5. “Incompatible With Secondary Licenses”**
means
* **(a)** that the initial Contributor has attached the notice described
@ -46,22 +46,22 @@ Mozilla Public License Version 2.0
version 1.1 or earlier of the License, but not also under the
terms of a Secondary License.
**1.6. “Executable Form”**
**1.6. “Executable Form”**
means any form of the work other than Source Code Form.
**1.7. “Larger Work”**
means a work that combines Covered Software with other material, in
**1.7. “Larger Work”**
means a work that combines Covered Software with other material, in
a separate file or files, that is not Covered Software.
**1.8. “License”**
**1.8. “License”**
means this document.
**1.9. “Licensable”**
**1.9. “Licensable”**
means having the right to grant, to the maximum extent possible,
whether at the time of the initial grant or subsequently, any and
all of the rights conveyed by this License.
**1.10. “Modifications”**
**1.10. “Modifications”**
means any of the following:
* **(a)** any file in Source Code Form that results from an addition to,
@ -70,7 +70,7 @@ Mozilla Public License Version 2.0
* **(b)** any new file in Source Code Form that contains any Covered
Software.
**1.11. “Patent Claims” of a Contributor**
**1.11. “Patent Claims” of a Contributor**
means any patent claim(s), including without limitation, method,
process, and apparatus claims, in any patent Licensable by such
Contributor that would be infringed, but for the grant of the
@ -78,16 +78,16 @@ Mozilla Public License Version 2.0
made, import, or transfer of either its Contributions or its
Contributor Version.
**1.12. “Secondary License”**
**1.12. “Secondary License”**
means either the GNU General Public License, Version 2.0, the GNU
Lesser General Public License, Version 2.1, the GNU Affero General
Public License, Version 3.0, or any later versions of those
licenses.
**1.13. “Source Code Form”**
**1.13. “Source Code Form”**
means the form of the work preferred for making modifications.
**1.14. “You” (or “Your”)**
**1.14. “You” (or “Your”)**
means an individual or a legal entity exercising rights under this
License. For legal entities, “You” includes any entity that
controls, is controlled by, or is under common control with You. For

@ -17,6 +17,12 @@ if ($VARS['action'] !== "signout") {
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 = "") {
global $VARS;
if ($arg == "") {

@ -165,4 +165,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>

@ -82,4 +82,4 @@ define("STRINGS", [
"finished on" => "Finished on: {date}",
"started on" => "Started on: {date}",
"add task" => "Add Task"
]);
]);

@ -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.
*/
/**

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

@ -9,6 +9,10 @@
* 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__ . "/../lib/login.php";
@ -93,7 +97,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'], "TASKFLOOR")) {
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 +111,4 @@ switch ($VARS['action']) {
default:
http_response_code(404);
die(json_encode(["status" => "ERROR", "msg" => "The requested action is not available."]));
}
}

@ -9,4 +9,4 @@
<div class="col-12 col-sm-6 col-md-4 col-lg-4">
<div class="alert alert-warning"><b><?php lang("404 error");?></b><br /> <?php lang("page not found"); ?></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));
@ -80,7 +82,7 @@ function sendError($error) {
. "<h1>A fatal application error has occurred.</h1>"
. "<i>(This isn't your fault.)</i>"
. "<h2>Details:</h2>"
. "<p>". htmlspecialchars($error) . "</p>");
. "<p>" . htmlspecialchars($error) . "</p>");
}
date_default_timezone_set(TIMEZONE);

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

@ -122,4 +122,4 @@ body {
.easy-autocomplete input {
border-radius: 0px !important;
}
}

@ -11,7 +11,7 @@ function setupTooltips() {
$(document).ready(function () {
/* Fade out alerts */
$(".alert .close").click(function (e) {
$(this).parent().fadeOut('slow');
$(this).parent().fadeOut("slow");
});
/* Activate tooltips */
@ -31,4 +31,4 @@ try {
window.history.replaceState("", "", getniceurl());
} catch (ex) {
}
}

Loading…
Cancel
Save