| const DEBUG = 0; | |||||
| const DIRECT_PROXY = { | |||||
| type: 'direct' | |||||
| }; | |||||
| const DEFAULT_PROXY_SETTINGS = { | |||||
| type: 'direct', | |||||
| host: '', | |||||
| port: 0, | |||||
| username: '', | |||||
| password: '', | |||||
| proxyDNS: false | |||||
| }; | |||||
| let proxies = [ DIRECT_PROXY, DIRECT_PROXY ]; | |||||
| var skipLocal = 1; | |||||
| var pendingRequests = []; | |||||
| var currentProxy = 0; | |||||
| function buttonClicked() { | |||||
| currentProxy = (currentProxy ? 0 : 1); | |||||
| if ( proxies[1].type == 'direct' ){ | |||||
| currentProxy = 0; | |||||
| } | |||||
| browser.storage.local.set({ currentProxy: currentProxy }); | |||||
| updateState(); | |||||
| } | |||||
| function updateState() { | |||||
| if(currentProxy==0) | |||||
| { | |||||
| browser.browserAction.setIcon({path: "icons/unlock48.png"}); | |||||
| browser.browserAction.setTitle({title: "Local IP"}); | |||||
| } | |||||
| else | |||||
| { | |||||
| browser.browserAction.setIcon({path: "icons/lock48.png"}); | |||||
| browser.browserAction.setTitle({title: "Biukop Secure Internet"}); | |||||
| } | |||||
| } | |||||
| function decodepass(pass) { | |||||
| var result = atob(pass); | |||||
| if (result.length <=3) | |||||
| return pass; | |||||
| if ("#!" != result.substring(result.length-3,result.length-1)) | |||||
| return pass; | |||||
| var tail = Number(result.substring(2,3)); | |||||
| result = result.substring(5, result.length - tail); | |||||
| return result; | |||||
| } | |||||
| function settingsChanged(settings) { | |||||
| if ("proxySettings" in settings){ | |||||
| proxies[1] = settings.proxySettings.newValue; | |||||
| proxies[1].password = decodepass(proxies[1].password); | |||||
| } | |||||
| if ("skipLocal" in settings){ | |||||
| skipLocal = settings.skipLocal.newValue; | |||||
| } | |||||
| if ("currentProxy" in settings) { | |||||
| currentProxy = settings.currentProxy.newValue; | |||||
| updateState(); | |||||
| } | |||||
| } | |||||
| function completed(requestDetails) { | |||||
| if (DEBUG) { | |||||
| console.log("completed request: " + requestDetails.requestId); | |||||
| } | |||||
| var index = pendingRequests.indexOf(requestDetails.requestId); | |||||
| if (index > -1) { | |||||
| pendingRequests.splice(index, 1); | |||||
| } | |||||
| console.log("completed"); | |||||
| } | |||||
| function provideCredentialsSync(requestDetails) { | |||||
| console.log("check credential"); | |||||
| if (!requestDetails.isProxy) | |||||
| return; | |||||
| if (!currentProxy == 1) | |||||
| return; | |||||
| if (pendingRequests.indexOf(requestDetails.requestId) != -1) { | |||||
| //if we've seen the request before, assume bad credentials and give up | |||||
| console.log("Bad proxy credentials for request: " + requestDetails.requestId); | |||||
| return {cancel:true}; | |||||
| } | |||||
| var credentials = { | |||||
| username: proxies[1].username, | |||||
| password: proxies[1].password | |||||
| } | |||||
| pendingRequests.push(requestDetails.requestId); | |||||
| if (DEBUG) { | |||||
| console.log(`Providing proxy credentials for request: ${requestDetails.requestId} username: ${credentials.username}`); | |||||
| } | |||||
| return {authCredentials: credentials}; | |||||
| } | |||||
| function isLocalIPv4(host) | |||||
| { | |||||
| var octets = /^(\d+)\.(\d+)\.(\d+)\.(\d+)$/.exec(host); | |||||
| if(!octets) | |||||
| return false; | |||||
| if(octets[1]>255||octets[2]>255||octets[3]>255||octets[4]>255) | |||||
| return false; | |||||
| if(octets[1]==10||octets[1]==127) //class A or local loopback | |||||
| return true; | |||||
| if(octets[1]==172&&octets[2]>=16&&octets[2]<=31) //class B | |||||
| return true; | |||||
| if(octets[1]==192&&octets[2]==168) //class C | |||||
| return true; | |||||
| return false; | |||||
| } | |||||
| function isLocal(host) | |||||
| { | |||||
| if(host.indexOf('biukop') != -1) | |||||
| return true; | |||||
| if(host.indexOf('.') == -1) | |||||
| return true; | |||||
| if(host.endsWith(".local")) | |||||
| return true; | |||||
| if(host=="::1") | |||||
| return true; | |||||
| return(isLocalIPv4(host)); | |||||
| } | |||||
| function handleProxyRequest(requestInfo) { | |||||
| const url = new URL(requestInfo.url); | |||||
| var host = url.hostname; | |||||
| var proxyNum = currentProxy; | |||||
| if (skipLocal) { | |||||
| if(isLocal(host)) { | |||||
| if (DEBUG) | |||||
| console.log(`Local host detected: ${host}`); | |||||
| proxyNum = 0; | |||||
| } | |||||
| } | |||||
| if (DEBUG) { | |||||
| console.log(`Proxying: ${url.hostname}`); | |||||
| console.log(proxies[proxyNum]); | |||||
| } | |||||
| return(proxies[proxyNum]); | |||||
| } | |||||
| browser.storage.local.get({ currentProxy: 0, skipLocal: true, proxySettings: DEFAULT_PROXY_SETTINGS }, items=>{ | |||||
| currentProxy = items.currentProxy; | |||||
| skipLocal = items.skipLocal; | |||||
| proxies[1] = items.proxySettings; | |||||
| proxies[1].password = decodepass(proxies[1].password); | |||||
| updateState(); | |||||
| }); | |||||
| browser.storage.onChanged.addListener(settingsChanged); | |||||
| browser.browserAction.onClicked.addListener(buttonClicked); | |||||
| browser.proxy.onRequest.addListener(handleProxyRequest, {urls: ["<all_urls>"]}); | |||||
| browser.proxy.onError.addListener(error => { | |||||
| console.error(`Proxy error: ${error.message}`); | |||||
| }); | |||||
| browser.webRequest.onAuthRequired.addListener( | |||||
| provideCredentialsSync, | |||||
| {urls: ["<all_urls>"]}, | |||||
| ["blocking"] | |||||
| ); | |||||
| browser.webRequest.onCompleted.addListener( | |||||
| completed, | |||||
| {urls: ["<all_urls>"]} | |||||
| ); | |||||
| browser.webRequest.onErrorOccurred.addListener( | |||||
| completed, | |||||
| {urls: ["<all_urls>"]} | |||||
| ); | |||||
| { | |||||
| "manifest_version": 2, | |||||
| "name": "Biukop Secure Internet", | |||||
| "version": "1.2.4", | |||||
| "description": "Enforced Security communication through professional network.", | |||||
| "icons": { | |||||
| "48": "icons/lock48.png", | |||||
| "96": "icons/lock96.png" | |||||
| }, | |||||
| "permissions": [ | |||||
| "storage", | |||||
| "proxy", | |||||
| "<all_urls>", | |||||
| "webRequest", | |||||
| "webRequestBlocking" | |||||
| ], | |||||
| "browser_action": { | |||||
| "browser_style": true, | |||||
| "default_icon": "icons/lock48.png", | |||||
| "default_title": "Secure Channel - Biukop" | |||||
| }, | |||||
| "commands": { | |||||
| "_execute_browser_action": { | |||||
| "suggested_key": { | |||||
| "default": "Ctrl+Shift+Y" | |||||
| }, | |||||
| "description": "Enable/Disable Secure Connection" | |||||
| } | |||||
| }, | |||||
| "background": { | |||||
| "scripts": [ | |||||
| "background.js" | |||||
| ] | |||||
| }, | |||||
| "options_ui": { | |||||
| "page": "settings.html", | |||||
| "browser_style": true | |||||
| }, | |||||
| "applications": { | |||||
| "gecko": { | |||||
| "strict_min_version": "68.0" | |||||
| } | |||||
| } | |||||
| } |
| #dnsrow{ | |||||
| display: none; | |||||
| } | |||||
| .configtable { | |||||
| border-collapse:collapse; | |||||
| margin: 0px; | |||||
| font-size: 12pt; | |||||
| width:100%; | |||||
| border: 0px dotted grey; | |||||
| box-shadow: 3px 3px 12px #000 inset; | |||||
| border-radius: 10px; | |||||
| } | |||||
| .configtable th,.configtable td { | |||||
| border: 1px solid white; | |||||
| padding: 10px; | |||||
| } | |||||
| .configtable th { | |||||
| color: #000; | |||||
| font-size: 18px; | |||||
| text-align: left; | |||||
| } | |||||
| .configtable td { | |||||
| width: 50%; | |||||
| } | |||||
| .configtable tr { | |||||
| background-color: lavender; | |||||
| transition: background-color 0.5s ease; | |||||
| } | |||||
| .configtable tr:hover { | |||||
| background-color: #fff; | |||||
| } | |||||
| td.authcode { | |||||
| width:90%; | |||||
| } |
| <!DOCTYPE html> | |||||
| <html> | |||||
| <head> | |||||
| <meta charset="utf-8"> | |||||
| <link rel="stylesheet" href="settings.css" /> | |||||
| <style> | |||||
| input, select { | |||||
| width: 100%; | |||||
| } | |||||
| </style> | |||||
| </head> | |||||
| <body> | |||||
| <form> | |||||
| <table class="configtable"> | |||||
| <tr> | |||||
| <th colspan="2"> | |||||
| License Code: | |||||
| </th> | |||||
| </tr> | |||||
| <tr> | |||||
| <td class='authcode'> | |||||
| <input type="text" id="license" > | |||||
| </td> | |||||
| <td class='register' colspan="2"> | |||||
| <button id="register"> Register </button> | |||||
| </td> | |||||
| </tr> | |||||
| <tr> | |||||
| <td colspan="2"> | |||||
| <div id="errMsg">abcd</div> | |||||
| <a id="msgLink"></a> | |||||
| </td> | |||||
| </tr> | |||||
| </table> | |||||
| <table class="configtable"> | |||||
| <tr> | |||||
| <th colspan="2"> | |||||
| Authorized Settings | |||||
| </th> | |||||
| </tr> | |||||
| <tr> | |||||
| <td>Type</td> | |||||
| <td> | |||||
| <select id="type" disabled> | |||||
| <option value="direct" >Not Enabled</option> | |||||
| <option value="http">HTTP</option> | |||||
| <option value="https">HTTPS</option> | |||||
| <option value="socks" selected >Protocol 5</option> | |||||
| <option value="socks4">Protocol 4</option> | |||||
| </select> | |||||
| </td> | |||||
| </tr> | |||||
| <tr> | |||||
| <td>Host</td> | |||||
| <td><input type="text" id="host" disabled></td> | |||||
| </tr> | |||||
| <tr> | |||||
| <td>Port</td> | |||||
| <td><input type="number" min="1" max="65535" id="port" disabled></td> | |||||
| </tr> | |||||
| <tr id="usernamerow"> | |||||
| <td>Username</td> | |||||
| <td><input type="text" id="username" disabled></td> | |||||
| </tr> | |||||
| <tr id="currentProxyRow"> | |||||
| <td>Enabled</td> | |||||
| <td><input type="checkbox" id="currentProxy" ></td> | |||||
| </tr> | |||||
| </table> | |||||
| </form> | |||||
| <script src="settings.js"></script> | |||||
| </body> | |||||
| </html> |
| var g_mid = ""; | |||||
| function saveCurrentProxy(e) { | |||||
| e.preventDefault(); | |||||
| browser.storage.local.set({ | |||||
| currentProxy: document.querySelector("#currentProxy").checked?1:0 | |||||
| }); | |||||
| } | |||||
| function showproxy(config){ | |||||
| document.querySelector("#host").value = config.host ; | |||||
| document.querySelector("#port").value = config.port ; | |||||
| document.querySelector('#type [value="socks"]').selected = true; | |||||
| document.querySelector("#username").value = config.username; | |||||
| if (config.host == ""){ | |||||
| document.querySelector("#currentProxy").checked = false; | |||||
| document.querySelector("#currentProxy").disabled = true; | |||||
| }else{ | |||||
| document.querySelector("#currentProxy").checked = config.enable; | |||||
| document.querySelector("#currentProxy").disabled = false; | |||||
| } | |||||
| updateState(); | |||||
| } | |||||
| function updateState() { | |||||
| if(currentProxy==0) | |||||
| { | |||||
| browser.browserAction.setIcon({path: "icons/unlock48.png"}); | |||||
| browser.browserAction.setTitle({title: "Local IP"}); | |||||
| } | |||||
| else | |||||
| { | |||||
| browser.browserAction.setIcon({path: "icons/lock48.png"}); | |||||
| browser.browserAction.setTitle({title: "Biukop Secure Internet"}); | |||||
| } | |||||
| } | |||||
| function IsJsonString(str) { | |||||
| try { | |||||
| JSON.parse(str); | |||||
| } catch (e) { | |||||
| return false; | |||||
| } | |||||
| return true; | |||||
| } | |||||
| function showMessage(msg) { | |||||
| var el = document.querySelector("#errMsg"); | |||||
| if (msg != undefined) | |||||
| el.innerText = msg; | |||||
| else{ | |||||
| el.innerText = ""; | |||||
| } | |||||
| } | |||||
| function showLink(href, text) { | |||||
| console.log(href); | |||||
| console.log(text); | |||||
| var el = document.querySelector("#msgLink"); | |||||
| if ( href != undefined && text !=undefined ) { | |||||
| el.href = href; | |||||
| el.innerText = text; | |||||
| el.visibility = 'visible'; | |||||
| }else{ | |||||
| el.innerText = ''; | |||||
| el.visibility = 'hidden'; | |||||
| } | |||||
| } | |||||
| function defaultConfig(){ | |||||
| return { | |||||
| type: 'direct', | |||||
| host: '', | |||||
| port: 0, | |||||
| username: '', | |||||
| password: '', | |||||
| proxyDNS: false, | |||||
| enable:false, | |||||
| } | |||||
| } | |||||
| function isValidResponse(msg){ | |||||
| if ( IsJsonString(xhr.responseText) ){ | |||||
| config = JSON.parse(xhr.responseText); | |||||
| config.success = true; | |||||
| } | |||||
| return false; | |||||
| } | |||||
| function license(val){ | |||||
| if ( val == undefined || val == "" || val.length < 5 ){ | |||||
| showMessage("Please enter a valid license"); | |||||
| return; | |||||
| } | |||||
| var xhr = new XMLHttpRequest(); | |||||
| xhr.onreadystatechange = function() { | |||||
| if (xhr.readyState === 4){ | |||||
| var config = defaultConfig(); | |||||
| if (IsJsonString(xhr.responseText)) { | |||||
| config = JSON.parse(xhr.responseText); | |||||
| showMessage(config.errMsg); | |||||
| showLink(config.link, config.linkText); | |||||
| }else{ | |||||
| showMessage(xhr.responseText); | |||||
| showLink('',''); | |||||
| } | |||||
| showproxy(config); | |||||
| browser.storage.local.set({ | |||||
| proxySettings: { | |||||
| type: config.type, | |||||
| host: config.host, | |||||
| port: config.port, | |||||
| username: config.username, | |||||
| password: config.password, | |||||
| proxyDNS: config.proxyDNS, | |||||
| }, | |||||
| skipLocal: true, | |||||
| mid: g_mid, | |||||
| license: val, | |||||
| currentProxy: config.enable? 1: 0 | |||||
| }); | |||||
| } | |||||
| }; | |||||
| xhr.open('POST', 'https://license.biukop.com.au/dedicatedip/'); | |||||
| //xhr.open('POST', 'https://lawipac.com/dumprequest.php'); | |||||
| xhr.setRequestHeader('Content-Type', 'application/json'); | |||||
| var data = { | |||||
| license: val, | |||||
| mid: g_mid | |||||
| }; | |||||
| xhr.send(JSON.stringify(data)); | |||||
| } | |||||
| function restoreOptions(e) { | |||||
| function onGot(item) { | |||||
| g_mid = item.mid; | |||||
| init_mid(item.mid); //just in case | |||||
| document.querySelector("#license").value = item.license; | |||||
| document.querySelector("#currentProxy").checked = item.currentProxy ==1; | |||||
| license(item.license); | |||||
| } | |||||
| function onError(error) { | |||||
| console.log(`Error: ${error}`); | |||||
| } | |||||
| var gettingItem = browser.storage.local.get({ | |||||
| mid: "", | |||||
| currentProxy: 0, | |||||
| skipLocal: true, | |||||
| license: "", | |||||
| proxySettings: { | |||||
| type: 'direct', | |||||
| host: '', | |||||
| port: 0, | |||||
| username: '', | |||||
| password: '', | |||||
| proxyDNS: false | |||||
| } | |||||
| }); | |||||
| gettingItem.then(onGot, onError); | |||||
| } | |||||
| function register(e) { | |||||
| e.preventDefault(); | |||||
| var license_code = document.querySelector("#license").value; | |||||
| license(license_code); | |||||
| } | |||||
| document.addEventListener("DOMContentLoaded", restoreOptions); | |||||
| document.querySelector("#currentProxy").addEventListener("change", saveCurrentProxy); | |||||
| document.querySelector("#register").addEventListener("click", register); | |||||
| function init_mid(existing_id) { | |||||
| function createUUID() { | |||||
| var uuid = new Date().valueOf(); | |||||
| return (uuid + '-xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx').replace(/[xy]/g, function(c) { | |||||
| var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8); | |||||
| return v.toString(16); | |||||
| }); | |||||
| } | |||||
| if ( existing_id== undefined || existing_id == "" || existing_id.length < 10 ){ | |||||
| var uuid = createUUID(); | |||||
| console.log("create new mid =:" + uuid) ; | |||||
| g_mid = uuid; | |||||
| browser.storage.local.set({mid: uuid}); | |||||
| } | |||||
| } |