Browse Source

auto update script executed

Toby Chui 1 year ago
parent
commit
bf7d43b52d

+ 11 - 3
accesslist.go

@@ -4,6 +4,8 @@ import (
 	"encoding/json"
 	"net/http"
 
+	strip "github.com/grokify/html-strip-tags-go"
+	"imuslab.com/zoraxy/mod/geodb"
 	"imuslab.com/zoraxy/mod/utils"
 )
 
@@ -115,7 +117,7 @@ func handleListWhitelisted(w http.ResponseWriter, r *http.Request) {
 		bltype = "country"
 	}
 
-	resulst := []string{}
+	resulst := []*geodb.WhitelistEntry{}
 	if bltype == "country" {
 		resulst = geodbStore.GetAllWhitelistedCountryCode()
 	} else if bltype == "ip" {
@@ -134,7 +136,10 @@ func handleCountryWhitelistAdd(w http.ResponseWriter, r *http.Request) {
 		return
 	}
 
-	geodbStore.AddCountryCodeToWhitelist(countryCode)
+	comment, _ := utils.PostPara(r, "comment")
+	comment = strip.StripTags(comment)
+
+	geodbStore.AddCountryCodeToWhitelist(countryCode, comment)
 
 	utils.SendOK(w)
 }
@@ -158,7 +163,10 @@ func handleIpWhitelistAdd(w http.ResponseWriter, r *http.Request) {
 		return
 	}
 
-	geodbStore.AddIPToWhiteList(ipAddr)
+	comment, _ := utils.PostPara(r, "comment")
+	comment = strip.StripTags(comment)
+
+	geodbStore.AddIPToWhiteList(ipAddr, comment)
 }
 
 func handleIpWhitelistRemove(w http.ResponseWriter, r *http.Request) {

+ 1 - 0
go.mod

@@ -10,6 +10,7 @@ require (
 	github.com/gorilla/sessions v1.2.1
 	github.com/gorilla/websocket v1.5.0
 	github.com/grandcat/zeroconf v1.0.0
+	github.com/grokify/html-strip-tags-go v0.1.0 // indirect
 	github.com/likexian/whois v1.15.1
 	github.com/microcosm-cc/bluemonday v1.0.25
 	golang.org/x/net v0.14.0

+ 2 - 0
go.sum

@@ -740,6 +740,8 @@ github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWm
 github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
 github.com/grandcat/zeroconf v1.0.0 h1:uHhahLBKqwWBV6WZUDAT71044vwOTL+McW0mBJvo6kE=
 github.com/grandcat/zeroconf v1.0.0/go.mod h1:lTKmG1zh86XyCoUeIHSA4FJMBwCJiQmGfcP2PdzytEs=
+github.com/grokify/html-strip-tags-go v0.1.0 h1:03UrQLjAny8xci+R+qjCce/MYnpNXCtgzltlQbOBae4=
+github.com/grokify/html-strip-tags-go v0.1.0/go.mod h1:ZdzgfHEzAfz9X6Xe5eBLVblWIxXfYSQ40S/VKrAOGpc=
 github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
 github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
 github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=

+ 7 - 0
mod/dynamicproxy/dpcore/dpcore.go

@@ -261,11 +261,13 @@ func removeHeaders(header http.Header, noCache bool) {
 		}
 	}
 
+	//Restore the Upgrade header if any
 	if header.Get("Zr-Origin-Upgrade") != "" {
 		header.Set("Upgrade", header.Get("Zr-Origin-Upgrade"))
 		header.Del("Zr-Origin-Upgrade")
 	}
 
+	//Disable cache if nocache is set
 	if noCache {
 		header.Del("Cache-Control")
 		header.Set("Cache-Control", "no-store")
@@ -287,6 +289,11 @@ func addXForwardedForHeader(req *http.Request) {
 			req.Header.Set("X-Forwarded-Proto", "http")
 		}
 
+		if req.Header.Get("X-Real-Ip") == "" {
+			//Not exists. Fill it in with client IP
+			req.Header.Set("X-Real-Ip", clientIP)
+		}
+
 	}
 }
 

+ 57 - 19
mod/geodb/whitelist.go

@@ -1,6 +1,9 @@
 package geodb
 
-import "strings"
+import (
+	"encoding/json"
+	"strings"
+)
 
 /*
 	Whitelist.go
@@ -8,11 +11,29 @@ import "strings"
 	This script handles whitelist related functions
 */
 
+const (
+	EntryType_CountryCode int = 0
+	EntryType_IP          int = 1
+)
+
+type WhitelistEntry struct {
+	EntryType int    //Entry type of whitelist, Country Code or IP
+	CC        string //ISO Country Code
+	IP        string //IP address or range
+	Comment   string //Comment for this entry
+}
+
 //Geo Whitelist
 
-func (s *Store) AddCountryCodeToWhitelist(countryCode string) {
+func (s *Store) AddCountryCodeToWhitelist(countryCode string, comment string) {
 	countryCode = strings.ToLower(countryCode)
-	s.sysdb.Write("whitelist-cn", countryCode, true)
+	entry := WhitelistEntry{
+		EntryType: EntryType_CountryCode,
+		CC:        countryCode,
+		Comment:   comment,
+	}
+
+	s.sysdb.Write("whitelist-cn", countryCode, entry)
 }
 
 func (s *Store) RemoveCountryCodeFromWhitelist(countryCode string) {
@@ -22,20 +43,19 @@ func (s *Store) RemoveCountryCodeFromWhitelist(countryCode string) {
 
 func (s *Store) IsCountryCodeWhitelisted(countryCode string) bool {
 	countryCode = strings.ToLower(countryCode)
-	var isWhitelisted bool = false
-	s.sysdb.Read("whitelist-cn", countryCode, &isWhitelisted)
-	return isWhitelisted
+	return s.sysdb.KeyExists("whitelist-cn", countryCode)
 }
 
-func (s *Store) GetAllWhitelistedCountryCode() []string {
-	whitelistedCountryCode := []string{}
+func (s *Store) GetAllWhitelistedCountryCode() []*WhitelistEntry {
+	whitelistedCountryCode := []*WhitelistEntry{}
 	entries, err := s.sysdb.ListTable("whitelist-cn")
 	if err != nil {
 		return whitelistedCountryCode
 	}
 	for _, keypairs := range entries {
-		ip := string(keypairs[0])
-		whitelistedCountryCode = append(whitelistedCountryCode, ip)
+		thisWhitelistEntry := WhitelistEntry{}
+		json.Unmarshal(keypairs[1], &thisWhitelistEntry)
+		whitelistedCountryCode = append(whitelistedCountryCode, &thisWhitelistEntry)
 	}
 
 	return whitelistedCountryCode
@@ -43,8 +63,14 @@ func (s *Store) GetAllWhitelistedCountryCode() []string {
 
 //IP Whitelist
 
-func (s *Store) AddIPToWhiteList(ipAddr string) {
-	s.sysdb.Write("whitelist-ip", ipAddr, true)
+func (s *Store) AddIPToWhiteList(ipAddr string, comment string) {
+	thisIpEntry := WhitelistEntry{
+		EntryType: EntryType_IP,
+		IP:        ipAddr,
+		Comment:   comment,
+	}
+
+	s.sysdb.Write("whitelist-ip", ipAddr, thisIpEntry)
 }
 
 func (s *Store) RemoveIPFromWhiteList(ipAddr string) {
@@ -52,14 +78,14 @@ func (s *Store) RemoveIPFromWhiteList(ipAddr string) {
 }
 
 func (s *Store) IsIPWhitelisted(ipAddr string) bool {
-	var isWhitelisted bool = false
-	s.sysdb.Read("whitelist-ip", ipAddr, &isWhitelisted)
+	isWhitelisted := s.sysdb.KeyExists("whitelist-ip", ipAddr)
 	if isWhitelisted {
+		//single IP whitelist entry
 		return true
 	}
 
 	//Check for IP wildcard and CIRD rules
-	AllWhitelistedIps := s.GetAllWhitelistedIp()
+	AllWhitelistedIps := s.GetAllWhitelistedIpAsStringSlice()
 	for _, whitelistRules := range AllWhitelistedIps {
 		wildcardMatch := MatchIpWildcard(ipAddr, whitelistRules)
 		if wildcardMatch {
@@ -75,17 +101,29 @@ func (s *Store) IsIPWhitelisted(ipAddr string) bool {
 	return false
 }
 
-func (s *Store) GetAllWhitelistedIp() []string {
-	whitelistedIp := []string{}
+func (s *Store) GetAllWhitelistedIp() []*WhitelistEntry {
+	whitelistedIp := []*WhitelistEntry{}
 	entries, err := s.sysdb.ListTable("whitelist-ip")
 	if err != nil {
 		return whitelistedIp
 	}
 
 	for _, keypairs := range entries {
-		ip := string(keypairs[0])
-		whitelistedIp = append(whitelistedIp, ip)
+		//ip := string(keypairs[0])
+		thisEntry := WhitelistEntry{}
+		json.Unmarshal(keypairs[1], &thisEntry)
+		whitelistedIp = append(whitelistedIp, &thisEntry)
 	}
 
 	return whitelistedIp
 }
+
+func (s *Store) GetAllWhitelistedIpAsStringSlice() []string {
+	allWhitelistedIPs := []string{}
+	entries := s.GetAllWhitelistedIp()
+	for _, entry := range entries {
+		allWhitelistedIPs = append(allWhitelistedIPs, entry.IP)
+	}
+
+	return allWhitelistedIPs
+}

+ 14 - 5
web/components/access.html

@@ -615,8 +615,12 @@
     <p>Whitelist a certain IP or IP range</p>
     <div class="ui form">
         <div class="field">
-        <label>IP Address</label>
-        <input id="ipAddressInputWhitelist" type="text" placeholder="IP Address">
+            <label>IP Address</label>
+            <input id="ipAddressInputWhitelist" type="text" placeholder="IP Address">
+        </div>
+        <div class="field">
+            <label>Remarks (Optional)</label>
+            <input id="ipAddressCommentsWhitelist" type="text" placeholder="Comments or remarks for this IP range">
         </div>
         <button id="addIpButton" onclick="addIpWhitelist();" class="ui basic green button">
             <i class="green add icon"></i> Whitelist IP
@@ -634,6 +638,7 @@
         <thead>
         <tr>
             <th>IP Address</th>
+            <th>Remarks</th>
             <th>Remove</th>
         </tr>
         </thead>
@@ -793,11 +798,12 @@
             if (data.length === 0) {
                 $('#whitelistIpTable').append(`
                 <tr>
-                    <td colspan="2"><i class="green check circle icon"></i>There are no whitelisted IP addresses</td>
+                    <td colspan="3"><i class="green check circle icon"></i>There are no whitelisted IP addresses</td>
                 </tr>
                 `);
             } else {
-                $.each(data, function(index, ip) {
+                $.each(data, function(index, ipEntry) {
+                    let ip = ipEntry.IP;
                     let icon = "globe icon";
                     if (isLAN(ip)){
                         icon = "desktop icon";
@@ -807,6 +813,7 @@
                     $('#whitelistIpTable').append(`
                         <tr class="whitelistItem" ip="${encodeURIComponent(ip)}">
                             <td><i class="${icon}"></i> ${ip}</td>
+                            <td>${ipEntry.Comment}</td>
                             <td><button class="ui icon basic mini red button" onclick="removeIpWhitelist('${ip}');"><i class="trash alternate icon"></i></button></td>
                         </tr>
                     `);
@@ -1003,6 +1010,7 @@
 
     function addIpWhitelist(){
         let targetIp = $("#ipAddressInputWhitelist").val().trim();
+        let remarks = $("#ipAddressCommentsWhitelist").val().trim();
         if (targetIp == ""){
             alert("IP address is empty")
             return
@@ -1016,7 +1024,7 @@
         $.ajax({
             url: "/api/whitelist/ip/add",
             type: "POST",
-            data: {ip: targetIp.toLowerCase()},
+            data: {ip: targetIp.toLowerCase(), "comment": remarks},
             success: function(response) {
                 if (response.error !== undefined) {
                     msgbox(response.error, false, 6000);
@@ -1025,6 +1033,7 @@
                 }
 
                 $("#ipAddressInputWhitelist").val("");
+                $("#ipAddressCommentsWhitelist").val("");
                 $("#ipAddressInputWhitelist").parent().remvoeClass("error");
             },
             error: function() {

+ 1 - 1
web/components/cert.html

@@ -41,7 +41,7 @@
         <i class="ui checkmark icon"></i> Certificate for domain <span id="certUploadingDomain"></span> uploaded.
     </div>
     <div class="ui message">
-        <h4><i class="info circle icon"></i>Tips about Server Names & SNI</h4>
+        <h4>Tips about Server Names & SNI</h4>
         <div class="ui bulleted list">
             <div class="item">
                 If you have two subdomains like <code>a.example.com</code> and <code>b.example.com</code> ,

+ 2 - 1
web/components/redirection.html

@@ -110,6 +110,7 @@
                   $("#ruleAddSucc").stop().finish().slideDown("fast").delay(3000).slideUp("fast");
                 }
                 initRedirectionRuleList();
+                resetForm();
             }
         });
     }
@@ -141,7 +142,7 @@
         $.get("/api/redirect/list", function(data){
             data.forEach(function(entry){
                 $("#redirectionRuleList").append(`<tr>
-                    <td>${entry.RedirectURL} </td>
+                    <td><a href="${entry.RedirectURL}" target="_blank">${entry.RedirectURL}</a></td>
                     <td>${entry.TargetURL}</td>
                     <td>${entry.ForwardChildpath?"<i class='ui green checkmark icon'></i>":"<i class='ui red remove icon'></i>"}</td>
                     <td>${entry.StatusCode==307?"Temporary Redirect (307)":"Moved Permanently (301)"}</td>

+ 155 - 138
web/components/utils.html

@@ -3,166 +3,183 @@
         <h2>Utilities</h2>
         <p>You might find these tools or information helpful when setting up your gateway server</p>
     </div>
-    <div class="ui divider"></div>
-  
+    <div class="ui top attached tabular menu">
+        <a class="nettools item active" data-tab="tab1"><i class="ui user circle blue icon"></i> Accounts</a>
+        <a class="nettools item" data-tab="tab2"><i class="ui brown box icon"></i> Toolbox</a>
+        <a class="nettools item" data-tab="tab3"><i class="ui grey server icon"></i> Systems</a>
+    </div>
+
+    <div class="ui bottom attached tab segment nettoolstab active" data-tab="tab1">
+        <div class="selfauthOnly">
+            <h3>Change Password</h3>
+            <p>Update the current account credentials</p>
+            <div class="ui basic segment">
+                <h5><i class="chevron down icon"></i> Change Password</h5>
+                <div class="ui form">
+                    <div class="field">
+                        <label>Current Password</label>
+                        <input type="password" name="oldPassword" placeholder="Current Password">
+                    </div>
+                    <div class="field">
+                        <label>New Password</label>
+                        <input type="password" name="newPassword" placeholder="New Password">
+                    </div>
+                    <div class="field">
+                        <label>Confirm New Password</label>
+                        <input type="password" name="confirmNewPassword" placeholder="Confirm New Password">
+                    </div>
+                    <button class="ui basic button" onclick="changePassword()"><i class="ui teal key icon"></i> Change Password</button>
+                </div>
     
-    <div class="selfauthOnly">
-        <h3>Account Management</h3>
-        <p>Functions to help management the current account</p>
-        <div class="ui basic segment">
-            <h5><i class="chevron down icon"></i> Change Password</h5>
-            <div class="ui form">
-                <div class="field">
-                    <label>Current Password</label>
-                    <input type="password" name="oldPassword" placeholder="Current Password">
+                <div id="passwordChangeSuccMsg" class="ui green message" style="display:none;">
+                    <i class="ui circle checkmark green icon "></i> Password Updated
                 </div>
+            </div>
+            <div class="ui divider"></div>
+            <h3>Forget Password Email</h3>
+            <p>The following SMTP settings help you to reset your password in case you have lost your management account.</p>
+            <form id="email-form" class="ui form">
                 <div class="field">
-                    <label>New Password</label>
-                    <input type="password" name="newPassword" placeholder="New Password">
+                    <label>Sender Address</label>
+                    <input type="text" name="senderAddr" placeholder="E.g. [email protected]">
                 </div>
                 <div class="field">
-                    <label>Confirm New Password</label>
-                    <input type="password" name="confirmNewPassword" placeholder="Confirm New Password">
-                </div>
-                <button class="ui basic button" onclick="changePassword()"><i class="ui teal key icon"></i> Change Password</button>
-            </div>
-
-            <div id="passwordChangeSuccMsg" class="ui green message" style="display:none;">
-                <i class="ui circle checkmark green icon "></i> Password Updated
-            </div>
-        </div>
-        <div class="ui divider"></div>
-        <h3>Forget Password Email</h3>
-        <p>The following SMTP settings help you to reset your password in case you have lost your management account.</p>
-        <form id="email-form" class="ui form">
-            <div class="field">
-                <label>Sender Address</label>
-                <input type="text" name="senderAddr" placeholder="E.g. [email protected]">
-            </div>
-            <div class="field">
-                <p><i class="caret down icon"></i> Connection setup for email service provider</p>
-                <div class="fields">
-                    <div class="twelve wide field">
-                        <label>SMTP Provider Hostname</label>
-                        <input type="text" name="hostname" placeholder="E.g. mail.gandi.net">
-                    </div>
-        
-                    <div class="four wide field">
-                        <label>Port</label>
-                        <input type="number" name="port" placeholder="E.g. 587" value="587">
+                    <p><i class="caret down icon"></i> Connection setup for email service provider</p>
+                    <div class="fields">
+                        <div class="twelve wide field">
+                            <label>SMTP Provider Hostname</label>
+                            <input type="text" name="hostname" placeholder="E.g. mail.gandi.net">
+                        </div>
+            
+                        <div class="four wide field">
+                            <label>Port</label>
+                            <input type="number" name="port" placeholder="E.g. 587" value="587">
+                        </div>
                     </div>
                 </div>
-            </div>
-
-            <div class="field">
-                <p><i class="caret down icon"></i> Credentials for SMTP server authentications</p>
-                <div class="two fields">
-                    <div class="field">
-                        <label>Sender Username</label>
-                        <input type="text" name="username" placeholder="E.g. admin">
-                    </div>
-                
-                    <div class="field">
-                        <label>Sender Domain</label>
-                        <div class="ui labeled input">
-                            <div class="ui basic label">
-                              @
+    
+                <div class="field">
+                    <p><i class="caret down icon"></i> Credentials for SMTP server authentications</p>
+                    <div class="two fields">
+                        <div class="field">
+                            <label>Sender Username</label>
+                            <input type="text" name="username" placeholder="E.g. admin">
+                        </div>
+                    
+                        <div class="field">
+                            <label>Sender Domain</label>
+                            <div class="ui labeled input">
+                                <div class="ui basic label">
+                                  @
+                                </div>
+                                <input type="text" name="domain" min="1" max="65534" placeholder="E.g. arozos.com">
                             </div>
-                            <input type="text" name="domain" min="1" max="65534" placeholder="E.g. arozos.com">
                         </div>
                     </div>
                 </div>
+                <div class="field">
+                    <label>Sender Password</label>
+                    <input type="password" name="password" placeholder="Password of the email account">
+                    <small>Leave empty to use the old password</small>
+                </div>
+               
+                <p> <i class="caret down icon"></i> Email for sending account reset link</p>
+                <div class="field">
+                    <label>Admin / Receiver Address</label>
+                    <input type="text" name="recvAddr" placeholder="E.g. [email protected]">
+                </div>
+                
+                <button class="ui basic button" type="submit"><i class="blue save icon"></i> Set SMTP Configs</button>
+                <button class="ui basic button" onclick="event.preventDefault(); sendTestEmail(this);"><i class="teal mail icon"></i> Send Test Email</button>
+            </form>
+        </div>
+    </div>
+    <div class="ui bottom attached tab segment nettoolstab" data-tab="tab2">
+        <h3> IP Address to CIDR</h3>
+        <p>No experience with CIDR notations? Here are some tools you can use to make setting up easier.</p>
+        <div class="ui basic segment">
+            <h5><i class="chevron down icon"></i> IP Range to CIDR Conversion</h5>
+            <div class="ui message">
+                <i class="info circle icon"></i> Note that the CIDR generated here covers additional IP address before or after the given range. If you need more details settings, please use CIDR with a smaller range and add additional IPs for detail range adjustment.
             </div>
-            <div class="field">
-                <label>Sender Password</label>
-                <input type="password" name="password" placeholder="Password of the email account">
-                <small>Leave empty to use the old password</small>
+            <div class="ui input">
+                <input type="text" placeholder="Start IP" id="startIpInput">
             </div>
-           
-            <p> <i class="caret down icon"></i> Email for sending account reset link</p>
-            <div class="field">
-                <label>Admin / Receiver Address</label>
-                <input type="text" name="recvAddr" placeholder="E.g. [email protected]">
+            <div class="ui input">
+                <input type="text" placeholder="End IP" id="endIpInput">
             </div>
-            
-            <button class="ui basic button" type="submit"><i class="blue save icon"></i> Set SMTP Configs</button>
-            <button class="ui basic button" onclick="event.preventDefault(); sendTestEmail(this);"><i class="teal mail icon"></i> Send Test Email</button>
-        </form>
-    </div>
-    <div class="ui divider"></div>
-    <h3> IP Address to CIDR</h3>
-    <p>No experience with CIDR notations? Here are some tools you can use to make setting up easier.</p>
-    <div class="ui basic segment">
-        <h5><i class="chevron down icon"></i> IP Range to CIDR Conversion</h5>
-        <div class="ui message">
-            <i class="info circle icon"></i> Note that the CIDR generated here covers additional IP address before or after the given range. If you need more details settings, please use CIDR with a smaller range and add additional IPs for detail range adjustment.
+            <br>
+            <button style="margin-top: 0.6em;" class="ui basic button" onclick="convertToCIDR()">Convert</button>
+            <p>Results: <div id="cidrOutput">N/A</div></p>
         </div>
-        <div class="ui input">
-            <input type="text" placeholder="Start IP" id="startIpInput">
-        </div>
-        <div class="ui input">
-            <input type="text" placeholder="End IP" id="endIpInput">
+    
+        <div class="ui basic segment">
+            <h5><i class="chevron down icon"></i> CIDR to IP Range Conversion</h5>
+            <div class="ui action input">
+                <input type="text" placeholder="CIDR" id="cidrInput">
+                <button class="ui basic button" onclick="convertToIPRange()">Convert</button>
+            </div>
+            <p>Results: <div id="ipRangeOutput">N/A</div></p>
         </div>
-        <br>
-        <button style="margin-top: 0.6em;" class="ui basic button" onclick="convertToCIDR()">Convert</button>
-        <p>Results: <div id="cidrOutput">N/A</div></p>
+        <div class="ui divider"></div>
     </div>
-
-    <div class="ui basic segment">
-        <h5><i class="chevron down icon"></i> CIDR to IP Range Conversion</h5>
-        <div class="ui action input">
-            <input type="text" placeholder="CIDR" id="cidrInput">
-            <button class="ui basic button" onclick="convertToIPRange()">Convert</button>
+    <div class="ui bottom attached tab segment nettoolstab" data-tab="tab3">
+        <!-- Config Tools -->
+        <h3>System Backup & Restore</h3>
+        <p>Options related to system backup, migrate and restore.</p>
+        <button class="ui basic button" onclick="showSideWrapper('snippet/configTools.html');">Open Config Tools</button>
+        <div class="ui divider"></div>
+        <!-- System Information -->
+        <div id="zoraxyinfo">
+            <h3 class="ui header">
+                System Information
+            </h3>
+            <p>Basic information about this zoraxy host</p>
+            <table class="ui very basic collapsing celled table">
+                <tbody>
+                    <tr>
+                        <td>Host UUID</td>
+                        <td class="uuid"></td>
+                    </tr>
+                    <tr>
+                        <td>Version</td>
+                        <td class="version"></td>
+                    </tr>
+                    <tr>
+                        <td>Build</td>
+                        <td class="development"></td>
+                    </tr>
+                    <tr>
+                        <td>Running Since</td>
+                        <td class="boottime"></td>
+                    </tr>
+                    
+                    <tr>
+                        <td>ZeroTier Linked</td>
+                        <td class="zt"></td>
+                    </tr>
+                    <tr>
+                        <td>Enable SSH Loopback</td>
+                        <td class="sshlb"></td>
+                    </tr>
+                </tbody>
+            </table>
+            <p>Zoraxy is developed by tobychui for <a href="//imuslab.com" target="_blank">imuslab</a> and open source under <a href="https://www.gnu.org/licenses/agpl-3.0.txt">AGPL</a></p>
         </div>
-        <p>Results: <div id="ipRangeOutput">N/A</div></p>
-    </div>
-    <!-- Config Tools -->
-    <div class="ui divider"></div>
-    <h3>System Backup & Restore</h3>
-    <p>Options related to system backup, migrate and restore.</p>
-    <button class="ui basic button" onclick="showSideWrapper('snippet/configTools.html');">Open Config Tools</button>
-    <!-- System Information -->
-    <div class="ui divider"></div>
-    <div id="zoraxyinfo">
-        <h3 class="ui header">
-            System Information
-        </h3>
-        <p>Basic information about this zoraxy host</p>
-        <table class="ui very basic collapsing celled table">
-            <tbody>
-                <tr>
-                    <td>Host UUID</td>
-                    <td class="uuid"></td>
-                </tr>
-                <tr>
-                    <td>Version</td>
-                    <td class="version"></td>
-                </tr>
-                <tr>
-                    <td>Build</td>
-                    <td class="development"></td>
-                </tr>
-                <tr>
-                    <td>Running Since</td>
-                    <td class="boottime"></td>
-                </tr>
-                
-                <tr>
-                    <td>ZeroTier Linked</td>
-                    <td class="zt"></td>
-                </tr>
-                <tr>
-                    <td>Enable SSH Loopback</td>
-                    <td class="sshlb"></td>
-                </tr>
-            </tbody>
-          </table>
-          <p>Zoraxy is developed by tobychui for <a href="//imuslab.com" target="_blank">imuslab</a> and open source under <a href="https://www.gnu.org/licenses/agpl-3.0.txt">AGPL</a></p>
     </div>
+  
+    
+    
+    
+    
+    
+    
+    
+    
     <br>
 </div>
 <script>
-
+    $('.menu .nettools.item').tab();
     /*
         Account Password utilities
     */

+ 5 - 3
web/components/webserv.html

@@ -4,7 +4,7 @@
         <p>A simple static web server that serve html css and js files</p>
     </div>
     <div class="ui divider"></div>
-    <div class="ui basic segment">
+    <div class="ui basic segment webservRunningStateWrapper">
         <h4 class="ui header" id="webservRunningState">
             <i class="green circle icon"></i>
             <div class="content">
@@ -102,12 +102,14 @@
         function setWebServerRunningState(running){
             if (running){
                 $("#webserv_enable").parent().checkbox("set checked");
-                $("#webservRunningState").find("i").attr("class", "green circle icon");
+                $("#webservRunningState").find("i").attr("class", "white circle check icon");
                 $("#webservRunningState").find(".webserv_status").text("Running");
+                $(".webservRunningStateWrapper").addClass("enabled")
             }else{
                 $("#webserv_enable").parent().checkbox("set unchecked");
-                $("#webservRunningState").find("i").attr("class", "red circle icon");
+                $("#webservRunningState").find("i").attr("class", "white circle times icon");
                 $("#webservRunningState").find(".webserv_status").text("Stopped");
+                $(".webservRunningStateWrapper").removeClass("enabled")
             }
         }
 

+ 23 - 2
web/main.css

@@ -9,7 +9,7 @@
     --theme_background: linear-gradient(60deg, rgb(84, 58, 183) 0%, rgb(0, 172, 193) 100%);
     --theme_background_inverted: linear-gradient(215deg, rgba(38,60,71,1) 13%, rgba(2,3,42,1) 84%);
 
-    --theme_green: linear-gradient(60deg, #27e7ff, #00ca52);
+    --theme_green: linear-gradient(270deg, #27e7ff, #00ca52);
     --theme_red: linear-gradient(203deg, rgba(250,172,38,1) 17%, rgba(202,0,37,1) 78%);
 }
 body{
@@ -539,7 +539,6 @@ body{
 .acmeRenewStateWrapper{
     padding: 1em;
     border-radius: 1em !important;
-    
 }
 
 
@@ -556,6 +555,28 @@ body{
     background: var(--theme_green) !important;
 }
 
+/*
+    Static Web Server
+*/
+
+.webservRunningStateWrapper{
+    padding: 1em;
+    border-radius: 1em !important;
+}
+
+
+.webservRunningStateWrapper .ui.header, .webservRunningStateWrapper .sub.header{
+    color: white !important;
+}
+
+.webservRunningStateWrapper:not(.enabled){
+    background: var(--theme_red) !important;
+}
+
+.webservRunningStateWrapper.enabled{
+    background: var(--theme_green) !important;
+}
+
 
 /*
     Uptime Monitor

+ 1 - 1
web/snippet/configTools.html

@@ -45,7 +45,7 @@
             </b></p>
             <form class="ui form" id="uploadForm" action="/api/conf/import" method="POST" enctype="multipart/form-data">
               <input type="file" name="file" id="fileInput" accept=".zip">
-              <button style="margin-top: 0.6em;" class="ui basic button" type="submit"><i class="ui green upload icon"></i> Upload</button>
+              <button style="margin-top: 0.6em;" class="ui basic button" type="submit"><i class="ui green upload icon"></i> Restore & Exit</button>
             </form>
             <small>The current config will be backup to ./conf_old{timestamp}. If you screw something up, you can always restore it by ssh to your host and restore the configs from the old folder.</small>
             <br><br>

+ 7 - 7
www/templates/blacklist.html → www/templates_disabled/blacklist.html

@@ -1,8 +1,8 @@
-<html>
-    <head>
-        <title>Oops</title>
-    </head>
-    <body>
-        <h1>Your IP have been blacklisted</h1>
-    </body>
+<html>
+    <head>
+        <title>Oops</title>
+    </head>
+    <body>
+        <h1>Your IP have been blacklisted</h1>
+    </body>
 </html>

+ 7 - 7
www/templates/whitelist.html → www/templates_disabled/whitelist.html

@@ -1,8 +1,8 @@
-<html>
-    <head>
-        <title>Oops</title>
-    </head>
-    <body>
-        <h1>Your IP is not whitelisted on this site</h1>
-    </body>
+<html>
+    <head>
+        <title>Oops</title>
+    </head>
+    <body>
+        <h1>Your IP is not whitelisted on this site</h1>
+    </body>
 </html>