Browse Source

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 1 year ago
parent
commit
0d3cc46dca
16 changed files with 163 additions and 17 deletions
  1. 1
    1
      .gitignore
  2. 1
    1
      README.md
  3. 1
    1
      action.php
  4. 1
    1
      api.php
  5. 9
    1
      app.php
  6. 6
    1
      index.php
  7. 1
    1
      lang/en_us.php
  8. 127
    0
      lib/iputils.php
  9. 1
    1
      lib/userinfo.php
  10. 6
    2
      mobile/index.php
  11. 1
    1
      pages/404.php
  12. 1
    1
      pages/home.php
  13. 4
    2
      required.php
  14. 1
    1
      settings.template.php
  15. 1
    1
      static/css/app.css
  16. 1
    1
      static/js/app.js

+ 1
- 1
.gitignore View File

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

+ 1
- 1
README.md View File

@@ -36,4 +36,4 @@ Installing
36 36
 4. Set the location of the AccountHub API in `settings.php` (see "PORTAL_API") and enter an API key ("PORTAL_KEY")
37 37
 5. Set the location of the AccountHub home page ("PORTAL_URL")
38 38
 6. Set the URL of this app ("URL")
39
-7. Run `composer install` (or `composer.phar install`) to install dependency libraries.
39
+7. Run `composer install` (or `composer.phar install`) to install dependency libraries.

+ 1
- 1
action.php View File

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

+ 1
- 1
api.php View File

@@ -176,4 +176,4 @@ switch ($VARS['action']) {
176 176
     default:
177 177
         http_response_code(404);
178 178
         die("\"404 Action not found\"");
179
-}
179
+}

+ 9
- 1
app.php View File

@@ -18,6 +18,12 @@ if (!is_empty($_GET['page'])) {
18 18
         $pageid = "404";
19 19
     }
20 20
 }
21
+
22
+header("Link: <static/css/bootstrap.min.css>; rel=preload; as=style", false);
23
+header("Link: <static/css/material-color/material-color.min.css>; rel=preload; as=style", false);
24
+header("Link: <static/css/app.css>; rel=preload; as=style", false);
25
+header("Link: <static/js/jquery-3.3.1.min.js>; rel=preload; as=script", false);
26
+header("Link: <static/js/bootstrap.min.js>; rel=preload; as=script", false);
21 27
 ?>
22 28
 <!DOCTYPE html>
23 29
 <html>
@@ -43,6 +49,7 @@ if (!is_empty($_GET['page'])) {
43 49
         if (isset(PAGES[$pageid]['styles'])) {
44 50
             foreach (PAGES[$pageid]['styles'] as $style) {
45 51
                 echo "<link href=\"$style\" rel=\"stylesheet\">\n";
52
+                header("Link: <$style>; rel=preload; as=style", false);
46 53
             }
47 54
         }
48 55
         ?>
@@ -169,8 +176,9 @@ END;
169 176
         if (isset(PAGES[$pageid]['scripts'])) {
170 177
             foreach (PAGES[$pageid]['scripts'] as $script) {
171 178
                 echo "<script src=\"$script\"></script>\n";
179
+                header("Link: <$script>; rel=preload; as=script", false);
172 180
             }
173 181
         }
174 182
         ?>
175 183
     </body>
176
-</html>
184
+</html>

+ 6
- 1
index.php View File

@@ -72,6 +72,11 @@ if (checkLoginServer()) {
72 72
 } else {
73 73
     $alert = lang("login server unavailable", false);
74 74
 }
75
+header("Link: <static/css/bootstrap.min.css>; rel=preload; as=style", false);
76
+header("Link: <static/css/material-color/material-color.min.css>; rel=preload; as=style", false);
77
+header("Link: <static/css/index.css>; rel=preload; as=style", false);
78
+header("Link: <static/js/jquery-3.3.1.min.js>; rel=preload; as=script", false);
79
+header("Link: <static/js/bootstrap.min.js>; rel=preload; as=script", false);
75 80
 ?>
76 81
 <!DOCTYPE html>
77 82
 <html>
@@ -147,4 +152,4 @@ if (checkLoginServer()) {
147 152
     <script src="static/js/jquery-3.3.1.min.js"></script>
148 153
     <script src="static/js/bootstrap.min.js"></script>
149 154
 </body>
150
-</html>
155
+</html>

+ 1
- 1
lang/en_us.php View File

@@ -157,4 +157,4 @@ define("STRINGS", [
157 157
     "shift name" => "Shift Name",
158 158
     "workers" => "Workers",
159 159
     "current job" => "Current job: "
160
-]);
160
+]);

+ 127
- 0
lib/iputils.php View File

@@ -0,0 +1,127 @@
1
+<?php
2
+
3
+/**
4
+ * Check if a given ipv4 address is in a given cidr
5
+ * @param  string $ip    IP to check in IPV4 format eg. 127.0.0.1
6
+ * @param  string $range IP/CIDR netmask eg. 127.0.0.0/24, also 127.0.0.1 is accepted and /32 assumed
7
+ * @return boolean true if the ip is in this range / false if not.
8
+ * @author Thorsten Ott <https://gist.github.com/tott/7684443>
9
+ */
10
+function ip4_in_cidr($ip, $cidr) {
11
+    if (strpos($cidr, '/') == false) {
12
+        $cidr .= '/32';
13
+    }
14
+    // $range is in IP/CIDR format eg 127.0.0.1/24
15
+    list( $cidr, $netmask ) = explode('/', $cidr, 2);
16
+    $range_decimal = ip2long($cidr);
17
+    $ip_decimal = ip2long($ip);
18
+    $wildcard_decimal = pow(2, ( 32 - $netmask)) - 1;
19
+    $netmask_decimal = ~ $wildcard_decimal;
20
+    return ( ( $ip_decimal & $netmask_decimal ) == ( $range_decimal & $netmask_decimal ) );
21
+}
22
+
23
+/**
24
+ * Check if a given ipv6 address is in a given cidr
25
+ * @param string $ip IP to check in IPV6 format
26
+ * @param string $cidr CIDR netmask
27
+ * @return boolean true if the IP is in this range, false otherwise.
28
+ * @author MW. <https://stackoverflow.com/a/7952169>
29
+ */
30
+function ip6_in_cidr($ip, $cidr) {
31
+    $address = inet_pton($ip);
32
+    $subnetAddress = inet_pton(explode("/", $cidr)[0]);
33
+    $subnetMask = explode("/", $cidr)[1];
34
+
35
+    $addr = str_repeat("f", $subnetMask / 4);
36
+    switch ($subnetMask % 4) {
37
+        case 0:
38
+            break;
39
+        case 1:
40
+            $addr .= "8";
41
+            break;
42
+        case 2:
43
+            $addr .= "c";
44
+            break;
45
+        case 3:
46
+            $addr .= "e";
47
+            break;
48
+    }
49
+    $addr = str_pad($addr, 32, '0');
50
+    $addr = pack("H*", $addr);
51
+
52
+    $binMask = $addr;
53
+    return ($address & $binMask) == $subnetAddress;
54
+}
55
+
56
+/**
57
+ * Check if the REMOTE_ADDR is on Cloudflare's network.
58
+ * @return boolean true if it is, otherwise false
59
+ */
60
+function validateCloudflare() {
61
+    if (filter_var($_SERVER["REMOTE_ADDR"], FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) {
62
+        // Using IPv6
63
+        $cloudflare_ips_v6 = [
64
+            "2400:cb00::/32",
65
+            "2405:8100::/32",
66
+            "2405:b500::/32",
67
+            "2606:4700::/32",
68
+            "2803:f800::/32",
69
+            "2c0f:f248::/32",
70
+            "2a06:98c0::/29"
71
+        ];
72
+        $valid = false;
73
+        foreach ($cloudflare_ips_v6 as $cidr) {
74
+            if (ip6_in_cidr($_SERVER["REMOTE_ADDR"], $cidr)) {
75
+                $valid = true;
76
+                break;
77
+            }
78
+        }
79
+    } else {
80
+        // Using IPv4
81
+        $cloudflare_ips_v4 = [
82
+            "103.21.244.0/22",
83
+            "103.22.200.0/22",
84
+            "103.31.4.0/22",
85
+            "104.16.0.0/12",
86
+            "108.162.192.0/18",
87
+            "131.0.72.0/22",
88
+            "141.101.64.0/18",
89
+            "162.158.0.0/15",
90
+            "172.64.0.0/13",
91
+            "173.245.48.0/20",
92
+            "188.114.96.0/20",
93
+            "190.93.240.0/20",
94
+            "197.234.240.0/22",
95
+            "198.41.128.0/17"
96
+        ];
97
+        $valid = false;
98
+        foreach ($cloudflare_ips_v4 as $cidr) {
99
+            if (ip4_in_cidr($_SERVER["REMOTE_ADDR"], $cidr)) {
100
+                $valid = true;
101
+                break;
102
+            }
103
+        }
104
+    }
105
+    return $valid;
106
+}
107
+
108
+/**
109
+ * Makes a good guess at the client's real IP address.
110
+ *
111
+ * @return string Client IP or `0.0.0.0` if we can't find anything
112
+ */
113
+function getClientIP() {
114
+    // If CloudFlare is in the mix, we should use it.
115
+    // Check if the request is actually from CloudFlare before trusting it.
116
+    if (isset($_SERVER["HTTP_CF_CONNECTING_IP"])) {
117
+        if (validateCloudflare()) {
118
+            return $_SERVER["HTTP_CF_CONNECTING_IP"];
119
+        }
120
+    }
121
+
122
+    if (isset($_SERVER["REMOTE_ADDR"])) {
123
+        return $_SERVER["REMOTE_ADDR"];
124
+    }
125
+
126
+    return "0.0.0.0"; // This will not happen unless we aren't a web server
127
+}

+ 1
- 1
lib/userinfo.php View File

@@ -210,4 +210,4 @@ function getGroupsByUsername($username) {
210 210
     } else {
211 211
         return [];
212 212
     }
213
-}
213
+}

+ 6
- 2
mobile/index.php View File

@@ -9,6 +9,10 @@
9 9
  * Mobile app API
10 10
  */
11 11
 
12
+// The name of the permission needed to log in.
13
+// Set to null if you don't need it.
14
+$access_permission = "QWIKCLOCK";
15
+
12 16
 require __DIR__ . "/../required.php";
13 17
 
14 18
 require __DIR__ . "/../lib/login.php";
@@ -93,7 +97,7 @@ switch ($VARS['action']) {
93 97
         if (user_exists($VARS['username'])) {
94 98
             if (get_account_status($VARS['username']) == "NORMAL") {
95 99
                 if (authenticate_user($VARS['username'], $VARS['password'], $autherror)) {
96
-                    if (account_has_permission($VARS['username'], "QWIKCLOCK")) {
100
+                    if (is_null($access_permission) || account_has_permission($VARS['username'], $access_permission)) {
97 101
                         doLoginUser($VARS['username'], $VARS['password']);
98 102
                         $_SESSION['mobile'] = true;
99 103
                         exit(json_encode(["status" => "OK"]));
@@ -107,4 +111,4 @@ switch ($VARS['action']) {
107 111
     default:
108 112
         http_response_code(404);
109 113
         die(json_encode(["status" => "ERROR", "msg" => "The requested action is not available."]));
110
-}
114
+}

+ 1
- 1
pages/404.php View File

@@ -9,4 +9,4 @@
9 9
     <div class="col-12 col-sm-6 col-md-4 col-lg-4">
10 10
         <div class="alert alert-warning"><b><?php lang("404 error");?></b><br /> <?php lang("page not found"); ?></div>
11 11
     </div>
12
-</div>
12
+</div>

+ 1
- 1
pages/home.php View File

@@ -61,4 +61,4 @@ redirectifnotloggedin();
61 61
         </div>
62 62
     </div>
63 63
 
64
-</div>
64
+</div>

+ 4
- 2
required.php View File

@@ -11,10 +11,12 @@ ob_start(); // allow sending headers after content
11 11
 // Unicode, solves almost all stupid encoding problems
12 12
 header('Content-Type: text/html; charset=utf-8');
13 13
 
14
-// l33t $ecurity h4x
14
+// Strip PHP version
15
+header('X-Powered-By: PHP');
16
+
17
+// Security
15 18
 header('X-Content-Type-Options: nosniff');
16 19
 header('X-XSS-Protection: 1; mode=block');
17
-header('X-Powered-By: PHP'); // no versions makes it harder to find vulns
18 20
 header('X-Frame-Options: "DENY"');
19 21
 header('Referrer-Policy: "no-referrer, strict-origin-when-cross-origin"');
20 22
 $SECURE_NONCE = base64_encode(random_bytes(8));

+ 1
- 1
settings.template.php View File

@@ -64,4 +64,4 @@ define('LANGUAGE', "en_us");
64 64
 
65 65
 
66 66
 define("FOOTER_TEXT", "");
67
-define("COPYRIGHT_NAME", "Netsyms Technologies");
67
+define("COPYRIGHT_NAME", "Netsyms Technologies");

+ 1
- 1
static/css/app.css View File

@@ -54,4 +54,4 @@ body {
54 54
 #seconds_bar_line {
55 55
     background-color: #ffc107;
56 56
     height: 5px;
57
-}
57
+}

+ 1
- 1
static/js/app.js View File

@@ -27,4 +27,4 @@ function getniceurl() {
27 27
     url = url.substring(url.lastIndexOf("/") + 1);
28 28
     url = url.replace(/&?msg=([^&]$|[^&]*)/i, "");
29 29
     return url;
30
-}
30
+}

Loading…
Cancel
Save