function msgShow(retcode,msg) { if(retcode == 0) { var alertType = 'success'; } else if(retcode == 2 || retcode == 1) { var alertType = 'danger'; } var htmlMsg = ''; return htmlMsg; } function createNetmaskAddr(bitCount) { var mask=[]; for(i=0;i<4;i++) { var n = Math.min(bitCount, 8); mask.push(256 - Math.pow(2, 8-n)); bitCount -= n; } return mask.join('.'); } function loadSummary(strInterface) { var csrfToken = $('meta[name=csrf_token]').attr('content'); $.post('ajax/networking/get_ip_summary.php',{'interface': strInterface, 'csrf_token': csrfToken},function(data){ jsonData = JSON.parse(data); if(jsonData['return'] == 0) { $('#'+strInterface+'-summary').html(jsonData['output'].join('
')); } else if(jsonData['return'] == 2) { $('#'+strInterface+'-summary').append(''); } }); } function getAllInterfaces() { $.get('ajax/networking/get_all_interfaces.php',function(data){ jsonData = JSON.parse(data); $.each(jsonData,function(ind,value){ loadSummary(value) }); }); } function setupTabs() { $('a[data-toggle="tab"]').on('shown.bs.tab',function(e){ var target = $(e.target).attr('href'); if(!target.match('summary')) { var int = target.replace("#",""); loadCurrentSettings(int); } }); } $(document).on("click", ".js-add-dhcp-static-lease", function(e) { e.preventDefault(); var container = $(".js-new-dhcp-static-lease"); var mac = $("input[name=mac]", container).val().trim(); var ip = $("input[name=ip]", container).val().trim(); var comment = $("input[name=comment]", container).val().trim(); if (mac == "" || ip == "") { return; } var row = $("#js-dhcp-static-lease-row").html() .replace("{{ mac }}", mac) .replace("{{ ip }}", ip) .replace("{{ comment }}", comment); $(".js-dhcp-static-lease-container").append(row); $("input[name=mac]", container).val(""); $("input[name=ip]", container).val(""); $("input[name=comment]", container).val(""); }); $(document).on("click", ".js-remove-dhcp-static-lease", function(e) { e.preventDefault(); $(this).parents(".js-dhcp-static-lease-row").remove(); }); $(document).on("submit", ".js-dhcp-settings-form", function(e) { $(".js-add-dhcp-static-lease").trigger("click"); }); $(document).on("click", ".js-add-dhcp-upstream-server", function(e) { e.preventDefault(); var field = $("#add-dhcp-upstream-server-field") var row = $("#dhcp-upstream-server").html().replace("{{ server }}", field.val()) if (field.val().trim() == "") { return } $(".js-dhcp-upstream-servers").append(row) field.val("") }); $(document).on("click", ".js-remove-dhcp-upstream-server", function(e) { e.preventDefault(); $(this).parents(".js-dhcp-upstream-server").remove(); }); $(document).on("submit", ".js-dhcp-settings-form", function(e) { $(".js-add-dhcp-upstream-server").trigger("click"); }); /** * mark a form field, e.g. a select box, with the class `.js-field-preset` * and give it an attribute `data-field-preset-target` with a text field's * css selector. * * now, if the element marked `.js-field-preset` receives a `change` event, * its value will be copied to all elements matching the selector in * data-field-preset-target. */ $(document).on("change", ".js-field-preset", function(e) { var selector = this.getAttribute("data-field-preset-target") var value = "" + this.value var syncValue = function(el) { el.value = value } if (value.trim() === "") { return } document.querySelectorAll(selector).forEach(syncValue) }); $(document).on("click", "#gen_wpa_passphrase", function(e) { $('#txtwpapassphrase').val(genPassword(63)); }); $(document).on("click", "#js-clearhostapd-log", function(e) { var csrfToken = $('meta[name=csrf_token]').attr('content'); $.post('ajax/logging/clearlog.php?',{'logfile':'/tmp/hostapd.log', 'csrf_token': csrfToken},function(data){ jsonData = JSON.parse(data); $("#hostapd-log").val(""); }); }); $(document).on("click", "#js-cleardnsmasq-log", function(e) { var csrfToken = $('meta[name=csrf_token]').attr('content'); $.post('ajax/logging/clearlog.php?',{'logfile':'/var/log/dnsmasq.log', 'csrf_token': csrfToken},function(data){ jsonData = JSON.parse(data); $("#dnsmasq-log").val(""); }); }); $(document).on("click", "#js-clearopenvpn-log", function(e) { var csrfToken = $('meta[name=csrf_token]').attr('content'); $.post('ajax/logging/clearlog.php?',{'logfile':'/tmp/openvpn.log', 'csrf_token': csrfToken},function(data){ jsonData = JSON.parse(data); $("#openvpn-log").val(""); }); }); // Enable Bootstrap tooltips $(function () { $('[data-toggle="tooltip"]').tooltip() }) function genPassword(pwdLen) { var pwdChars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; var rndPass = Array(pwdLen).fill(pwdChars).map(function(x) { return x[Math.floor(Math.random() * x.length)] }).join(''); return rndPass; } function setupBtns() { $('#btnSummaryRefresh').click(function(){getAllInterfaces();}); $('.intsave').click(function(){ var int = $(this).data('int'); saveNetworkSettings(int); }); $('.intapply').click(function(){ applyNetworkSettings(); }); } function setCSRFTokenHeader(event, xhr, settings) { var csrfToken = $('meta[name=csrf_token]').attr('content'); if (/^(POST|PATCH|PUT|DELETE)$/i.test(settings.type)) { xhr.setRequestHeader("X-CSRF-Token", csrfToken); } } function contentLoaded() { pageCurrent = window.location.href.split("/").pop(); switch(pageCurrent) { case "network_conf": getAllInterfaces(); setupTabs(); setupBtns(); break; case "hostapd_conf": loadChannel(); setHardwareModeTooltip(); break; case "dhcpd_conf": loadInterfaceDHCPSelect(); break; } } function loadWifiStations(refresh) { return function() { var complete = function() { $(this).removeClass('loading-spinner'); } var qs = refresh === true ? '?refresh' : ''; $('.js-wifi-stations') .addClass('loading-spinner') .empty() .load('ajax/networking/wifi_stations.php'+qs, complete); }; } $(".js-reload-wifi-stations").on("click", loadWifiStations(true)); /* Populates the DHCP server form fields Option toggles are set dynamically depending on the loaded configuration */ function loadInterfaceDHCPSelect() { var strInterface = $('#cbxdhcpiface').val(); $.get('ajax/networking/get_netcfg.php?iface='+strInterface,function(data){ jsonData = JSON.parse(data); $('#dhcp-iface')[0].checked = jsonData.DHCPEnabled; $('#txtipaddress').val(jsonData.StaticIP); $('#txtsubnetmask').val(jsonData.SubnetMask); $('#txtgateway').val(jsonData.StaticRouters); $('#chkfallback')[0].checked = jsonData.FallbackEnabled; $('#default-route').prop('checked', jsonData.DefaultRoute); if (strInterface.startsWith("wl")) { $('#nohook-wpa-supplicant').parent().parent().parent().show() $('#nohook-wpa-supplicant').prop('checked', jsonData.NoHookWPASupplicant); } else { $('#nohook-wpa-supplicant').parent().parent().parent().hide() } $('#txtrangestart').val(jsonData.RangeStart); $('#txtrangeend').val(jsonData.RangeEnd); $('#txtrangeleasetime').val(jsonData.leaseTime); $('#txtdns1').val(jsonData.DNS1); $('#txtdns2').val(jsonData.DNS2); $('#cbxrangeleasetimeunits').val(jsonData.leaseTimeInterval); $('#no-resolv')[0].checked = jsonData.upstreamServersEnabled; $('#cbxdhcpupstreamserver').val(jsonData.upstreamServers[0]); $('#txtmetric').val(jsonData.Metric); if (jsonData.StaticIP !== null && jsonData.StaticIP !== '' && !jsonData.FallbackEnabled) { $('#chkstatic').closest('.btn').button('toggle'); $('#chkstatic').closest('.btn').button('toggle').blur(); $('#chkstatic').blur(); $('#chkfallback').prop('disabled', true); } else { $('#chkdhcp').closest('.btn').button('toggle'); $('#chkdhcp').closest('.btn').button('toggle').blur(); $('#chkdhcp').blur(); $('#chkfallback').prop('disabled', false); } if (jsonData.FallbackEnabled || $('#chkdhcp').is(':checked')) { $('#dhcp-iface').prop('disabled', true); } }); } function setDHCPToggles(state) { if ($('#chkfallback').is(':checked') && state) { $('#chkfallback').prop('checked', state); } if ($('#dhcp-iface').is(':checked') && !state) { $('#dhcp-iface').prop('checked', state); } $('#chkfallback').prop('disabled', state); $('#dhcp-iface').prop('disabled', !state); //$('#dhcp-iface').prop('checked', state); } function loadChannel() { $.get('ajax/networking/get_channel.php',function(data){ jsonData = JSON.parse(data); loadChannelSelect(jsonData); }); } $('#hostapdModal').on('shown.bs.modal', function (e) { var seconds = 9; var countDown = setInterval(function(){ if(seconds <= 0){ clearInterval(countDown); } var pct = Math.floor(100-(seconds*100/9)); document.getElementsByClassName('progress-bar').item(0).setAttribute('style','width:'+Number(pct)+'%'); seconds --; }, 1000); }); $('#configureClientModal').on('shown.bs.modal', function (e) { }); $('#ovpn-confirm-delete').on('click', '.btn-delete', function (e) { var cfg_id = $(this).data('recordId'); var csrfToken = $('meta[name=csrf_token]').attr('content'); $.post('ajax/openvpn/del_ovpncfg.php',{'cfg_id':cfg_id, 'csrf_token': csrfToken},function(data){ jsonData = JSON.parse(data); $("#ovpn-confirm-delete").modal('hide'); var row = $(document.getElementById("openvpn-client-row-" + cfg_id)); row.fadeOut( "slow", function() { row.remove(); }); }); }); $('#ovpn-confirm-delete').on('show.bs.modal', function (e) { var data = $(e.relatedTarget).data(); $('.btn-delete', this).data('recordId', data.recordId); }); $('#ovpn-confirm-activate').on('click', '.btn-activate', function (e) { var cfg_id = $(this).data('record-id'); var csrfToken = $('meta[name=csrf_token]').attr('content'); $.post('ajax/openvpn/activate_ovpncfg.php',{'cfg_id':cfg_id, 'csrf_token': csrfToken},function(data){ jsonData = JSON.parse(data); $("#ovpn-confirm-activate").modal('hide'); setTimeout(function(){ window.location.reload(); },300); }); }); $('#ovpn-confirm-activate').on('shown.bs.modal', function (e) { var data = $(e.relatedTarget).data(); $('.btn-activate', this).data('recordId', data.recordId); }); $('#ovpn-userpw,#ovpn-certs').on('click', function (e) { if (this.id == 'ovpn-userpw') { $('#PanelCerts').hide(); $('#PanelUserPW').show(); } else if (this.id == 'ovpn-certs') { $('#PanelUserPW').hide(); $('#PanelCerts').show(); } }); $('#js-system-reset-confirm').on('click', function (e) { var progressText = $('#js-system-reset-confirm').attr('data-message'); var successHtml = $('#system-reset-message').attr('data-message'); var closeHtml = $('#js-system-reset-cancel').attr('data-message'); var csrfToken = $('meta[name=csrf_token]').attr('content'); var progressHtml = $('
').text(progressText).html() + ''; $('#system-reset-message').html(progressHtml); $.post('ajax/networking/do_sys_reset.php?',{'csrf_token':csrfToken},function(data){ setTimeout(function(){ jsonData = JSON.parse(data); if(jsonData['return'] == 0) { $('#system-reset-message').text(successHtml); } else { $('#system-reset-message').text('Error occured: '+ jsonData['return']); } $("#js-system-reset-confirm").hide(); $("#js-system-reset-cancel").text(closeHtml); },750); }); }); $('#js-sys-reboot, #js-sys-shutdown').on('click', function (e) { e.preventDefault(); var csrfToken = $('meta[name=csrf_token]').attr('content'); var action = $(this).data('action'); $.post('ajax/system/sys_actions.php?',{'a': action, 'csrf_token': csrfToken},function(data){ var response = JSON.parse(data); }); }); $(document).ready(function(){ $("#PanelManual").hide(); }); $('#wg-upload,#wg-manual').on('click', function (e) { if (this.id == 'wg-upload') { $('#PanelManual').hide(); $('#PanelUpload').show(); } else if (this.id == 'wg-manual') { $('#PanelUpload').hide(); $('#PanelManual').show(); } }); // Add the following code if you want the name of the file appear on select $(".custom-file-input").on("change", function() { var fileName = $(this).val().split("\\").pop(); $(this).siblings(".custom-file-label").addClass("selected").html(fileName); }); /* Sets the wirelss channel select options based on hw_mode and country_code. Methodology: In North America up to channel 11 is the maximum allowed WiFi 2.4Ghz channel, except for the US that allows channel 12 & 13 in low power mode with additional restrictions. Canada allows channel 12 in low power mode. Because it's unsure if low powered mode can be supported the channels are not selectable for those countries. Also Uzbekistan and Colombia allow up to channel 11 as maximum channel on the 2.4Ghz WiFi band. Source: https://en.wikipedia.org/wiki/List_of_WLAN_channels Additional: https://git.kernel.org/pub/scm/linux/kernel/git/sforshee/wireless-regdb.git */ function loadChannelSelect(selected) { // Fetch wireless regulatory data $.getJSON("config/wireless.json", function(json) { var hw_mode = $('#cbxhwmode').val(); var country_code = $('#cbxcountries').val(); var channel_select = $('#cbxchannel'); var data = json["wireless_regdb"]; var selectablechannels = Array.range(1,14); // Assign array of countries to valid frequencies (channels) var countries_2_4Ghz_max11ch = data["2_4GHz_max11ch"].countries; var countries_2_4Ghz_max14ch = data["2_4GHz_max14ch"].countries; var countries_5Ghz_max48ch = data["5Ghz_max48ch"].countries; // Map selected hw_mode and country to determine channel list if (hw_mode === 'a') { selectablechannels = data["5Ghz_max48ch"].channels; } else if (($.inArray(country_code, countries_2_4Ghz_max11ch) !== -1) && (hw_mode !== 'ac') ) { selectablechannels = data["2_4GHz_max11ch"].channels; } else if (($.inArray(country_code, countries_2_4Ghz_max14ch) !== -1) && (hw_mode === 'b')) { selectablechannels = data["2_4GHz_max14ch"].channels; } else if (($.inArray(country_code, countries_5Ghz_max48ch) !== -1) && (hw_mode === 'ac')) { selectablechannels = data["5Ghz_max48ch"].channels; } // Set channel select with available values selected = (typeof selected === 'undefined') ? selectablechannels[0] : selected; channel_select.empty(); $.each(selectablechannels, function(key,value) { channel_select.append($("").attr("value", value).text(value)); }); channel_select.val(selected); }); } /* Sets hardware mode tooltip text for selected interface. */ function setHardwareModeTooltip() { var iface = $('#cbxinterface').val(); var hwmodeText = ''; var csrfToken = $('meta[name=csrf_token]').attr('content'); // Explanatory text if 802.11ac is disabled if ($('#cbxhwmode').find('option[value="ac"]').prop('disabled') == true ) { var hwmodeText = $('#hwmode').attr('data-tooltip'); } $.post('ajax/networking/get_frequencies.php?',{'interface': iface, 'csrf_token': csrfToken},function(data){ var responseText = JSON.parse(data); $('#tiphwmode').attr('data-original-title', responseText + '\n' + hwmodeText ); }); } /* Updates the selected blocklist * Request is passed to an ajax handler to download the associated list. * Interface elements are updated to indicate current progress, status. */ function updateBlocklist() { var blocklist_id = $('#cbxblocklist').val(); var csrfToken = $('meta[name=csrf_token]').attr('content'); if (blocklist_id == '') { return; } $('#cbxblocklist-status').find('i').removeClass('fas fa-check').addClass('fas fa-cog fa-spin'); $('#cbxblocklist-status').removeClass('check-hidden').addClass('check-progress'); $.post('ajax/adblock/update_blocklist.php',{ 'blocklist_id':blocklist_id, 'csrf_token': csrfToken},function(data){ var jsonData = JSON.parse(data); if (jsonData['return'] == '0') { $('#cbxblocklist-status').find('i').removeClass('fas fa-cog fa-spin').addClass('fas fa-check'); $('#cbxblocklist-status').removeClass('check-progress').addClass('check-updated').delay(500).animate({ opacity: 1 }, 700); $('#'+blocklist_id).text("Just now"); } }) } function clearBlocklistStatus() { $('#cbxblocklist-status').removeClass('check-updated').addClass('check-hidden'); } // Handler for the wireguard generate key button $('.wg-keygen').click(function(){ var entity_pub = $(this).parent('div').prev('input[type="text"]'); var entity_priv = $(this).parent('div').next('input[type="hidden"]'); var updated = entity_pub.attr('name')+"-pubkey-status"; var csrfToken = $('meta[name=csrf_token]').attr('content'); $.post('ajax/networking/get_wgkey.php',{'entity':entity_pub.attr('name'), 'csrf_token': csrfToken},function(data){ var jsonData = JSON.parse(data); entity_pub.val(jsonData.pubkey); $('#' + updated).removeClass('check-hidden').addClass('check-updated').delay(500).animate({ opacity: 1 }, 700); }) }) // Handler for wireguard client.conf download $('.wg-client-dl').click(function(){ var req = new XMLHttpRequest(); var url = 'ajax/networking/get_wgcfg.php'; req.open('get', url, true); req.responseType = 'blob'; req.setRequestHeader('Content-type', 'text/plain; charset=UTF-8'); req.onreadystatechange = function (event) { if(req.readyState == 4 && req.status == 200) { var blob = req.response; var link=document.createElement('a'); link.href=window.URL.createObjectURL(blob); link.download = 'client.conf'; link.click(); } } req.send(); }) // Event listener for Bootstrap's form validation window.addEventListener('load', function() { // Fetch all the forms we want to apply custom Bootstrap validation styles to var forms = document.getElementsByClassName('needs-validation'); // Loop over them and prevent submission var validation = Array.prototype.filter.call(forms, function(form) { form.addEventListener('submit', function(event) { if (form.checkValidity() === false) { event.preventDefault(); event.stopPropagation(); } form.classList.add('was-validated'); }, false); }); }, false); // Static Array method Array.range = (start, end) => Array.from({length: (end - start)}, (v, k) => k + start); $(document).on("click", ".js-toggle-password", function(e) { var button = $(e.target) var field = $(button.data("target")); if (field.is(":input")) { e.preventDefault(); if (!button.data("__toggle-with-initial")) { $("i", this).removeClass("fas fa-eye").addClass(button.attr("data-toggle-with")); } if (field.attr("type") === "password") { field.attr("type", "text"); } else { $("i", this).removeClass("fas fa-eye-slash").addClass("fas fa-eye"); field.attr("type", "password"); } } }); $(function() { $('#theme-select').change(function() { var theme = themes[$( "#theme-select" ).val() ]; set_theme(theme); }); }); function set_theme(theme) { $('link[title="main"]').attr('href', 'app/css/' + theme); // persist selected theme in cookie setCookie('theme',theme,90); } $(function() { var currentTheme = getCookie('theme'); // Check if the current theme is a dark theme var isDarkTheme = currentTheme === 'lightsout.css' || currentTheme === 'material-dark.php'; $('#night-mode').prop('checked', isDarkTheme); $('#night-mode').change(function() { var state = $(this).is(':checked'); var currentTheme = getCookie('theme'); if (state == true) { if (currentTheme == 'custom.php') { set_theme('lightsout.css'); } else if (currentTheme == 'material-light.php') { set_theme('material-dark.php'); } } else { if (currentTheme == 'lightsout.css') { set_theme('custom.php'); } else if (currentTheme == 'material-dark.php') { set_theme('material-light.php'); } } }); }); function setCookie(cname, cvalue, exdays) { var d = new Date(); d.setTime(d.getTime() + (exdays*24*60*60*1000)); var expires = "expires="+ d.toUTCString(); document.cookie = cname + "=" + cvalue + ";" + expires + ";path=/"; } function getCookie(cname) { var regx = new RegExp(cname + "=([^;]+)"); var value = regx.exec(document.cookie); return (value != null) ? unescape(value[1]) : null; } // Define themes var themes = { "default": "custom.php", "hackernews" : "hackernews.css", "lightsout" : "lightsout.css", "material-light" : "material-light.php", "material-dark" : "material-dark.php", } // Toggles the sidebar navigation. // Overrides the default SB Admin 2 behavior $("#sidebarToggleTopbar").on('click', function(e) { $("body").toggleClass("sidebar-toggled"); $(".sidebar").toggleClass("toggled d-none"); }); // Overrides SB Admin 2 $("#sidebarToggle, #sidebarToggleTop").on('click', function(e) { var toggled = $(".sidebar").hasClass("toggled"); // Persist state in cookie setCookie('sidebarToggled',toggled, 90); }); $(function() { if ($(window).width() < 768) { $('.sidebar').addClass('toggled'); setCookie('sidebarToggled',false, 90); } }); $(window).on("load resize",function(e) { if ($(window).width() > 768) { $('.sidebar').removeClass('d-none d-md-block'); if (getCookie('sidebarToggled') == 'false') { $('.sidebar').removeClass('toggled'); } } }); // Adds active class to current nav-item $(window).bind("load", function() { var url = window.location; $('ul.navbar-nav a').filter(function() { return this.href == url; }).parent().addClass('active'); }); $(document) .ajaxSend(setCSRFTokenHeader) .ready(contentLoaded) .ready(loadWifiStations());