diff --git a/sources/controller.php b/sources/controller.php index d40717f..c24b78f 100644 --- a/sources/controller.php +++ b/sources/controller.php @@ -60,6 +60,14 @@ function ipv6_compressed($ip) { return $output[0]; } +function getArray($str) { + return explode('|', $str); +} + +function noneValue($str) { + return $str == 'none' ? '' : $str; +} + function is_connected_through_hotspot($ip6_net, $ip4_nat_prefix) { $ip = $_SERVER['REMOTE_ADDR']; $ip6_regex = '/^'.preg_quote(preg_replace('/::$/', '', $ip6_net)).':/'; @@ -71,6 +79,8 @@ function is_connected_through_hotspot($ip6_net, $ip4_nat_prefix) { dispatch('/', function() { exec('sudo iwconfig', $devs); $wifi_device = moulinette_get('wifi_device'); + $multissid = moulinette_get('multissid'); + $ssids = array(); $devs_list = ''; foreach($devs AS $dev) { @@ -83,24 +93,43 @@ dispatch('/', function() { } } + $wifi_ssid = getArray(moulinette_get('wifi_ssid')); + $wifi_secure = getArray(moulinette_get('wifi_secure')); + $wifi_passphrase = getArray(moulinette_get('wifi_passphrase')); + $wifi_channel = getArray(moulinette_get('wifi_channel')); + $ip6_net = getArray(moulinette_get('ip6_net')); + $ip6_dns0 = getArray(moulinette_get('ip6_dns0')); + $ip6_dns1 = getArray(moulinette_get('ip6_dns1')); + $ip4_nat_prefix = getArray(moulinette_get('ip4_nat_prefix')); + $ip4_dns0 = getArray(moulinette_get('ip4_dns0')); + $ip4_dns1 = getArray(moulinette_get('ip4_dns1')); + + for($i = 0; $i < $multissid; $i++) { + $ssid = [ + 'id' => $i, + 'wifi_ssid' => noneValue($wifi_ssid[$i]), + 'wifi_secure' => noneValue($wifi_secure[$i]), + 'wifi_passphrase' => noneValue($wifi_passphrase[$i]), + 'wifi_channel' => noneValue($wifi_channel[$i]), + 'ip6_net' => noneValue($ip6_net[$i]), + 'ip6_dns0' => noneValue($ip6_dns0[$i]), + 'ip6_dns1' => noneValue($ip6_dns1[$i]), + 'ip4_nat_prefix' => noneValue($ip4_nat_prefix[$i]), + 'ip4_dns0' => noneValue($ip4_dns0[$i]), + 'ip4_dns1' => noneValue($ip4_dns1[$i]), + ]; + + array_push($ssids, $ssid); + } + $ip6_net = moulinette_get('ip6_net'); $ip6_net = ($ip6_net == 'none') ? '' : $ip6_net; $ip4_nat_prefix = moulinette_get('ip4_nat_prefix'); set('service_enabled', moulinette_get('service_enabled')); - set('wifi_ssid', moulinette_get('wifi_ssid')); - set('wifi_secure', moulinette_get('wifi_secure')); - set('wifi_passphrase', moulinette_get('wifi_passphrase')); - set('wifi_channel', moulinette_get('wifi_channel')); - set('wifi_n', moulinette_get('wifi_n')); + set('ssids', $ssids); set('wifi_device', $wifi_device); set('wifi_device_list', $devs_list); - set('ip6_net', $ip6_net); - set('ip6_dns0', moulinette_get('ip6_dns0')); - set('ip6_dns1', moulinette_get('ip6_dns1')); - set('ip4_nat_prefix', $ip4_nat_prefix); - set('ip4_dns0', moulinette_get('ip4_dns0')); - set('ip4_dns1', moulinette_get('ip4_dns1')); set('faststatus', service_faststatus() == 0); set('is_connected_through_hotspot', is_connected_through_hotspot($ip6_net, $ip4_nat_prefix)); @@ -109,113 +138,118 @@ dispatch('/', function() { dispatch_put('/settings', function() { exec('ip link show '.escapeshellarg($_POST['wifi_device']), $output, $retcode); - $wifi_device_exists = ($retcode == 0); - $ip6_net = empty($_POST['ip6_net']) ? 'none' : $_POST['ip6_net']; - $ip6_addr = 'none'; - $ip6_dns0 = $_POST['ip6_dns0']; - $ip6_dns1 = $_POST['ip6_dns1']; + $wifi_device_exists = ($retcode == 0); $service_enabled = isset($_POST['service_enabled']) ? 1 : 0; - $wifi_secure = isset($_POST['wifi_secure']) ? 1 : 0; + $ssids = array(); + $id = 0; if($service_enabled == 1) { try { - if(empty($_POST['wifi_ssid']) || empty($_POST['wifi_passphrase']) || empty($_POST['wifi_channel'])) { - throw new Exception(T_('Your Wifi Hotspot needs a name, a password and a channel')); - } - - if(strlen($_POST['wifi_passphrase']) < 8 || strlen($_POST['wifi_passphrase']) > 63) { - throw new Exception(T_('Your password must from 8 to 63 characters (WPA2 passphrase)')); - } - - if(preg_match('/[^[:print:]]/', $_POST['wifi_passphrase'])) { - throw new Exception(T_('Only printable ASCII characters are permitted in your password')); - } - - if(!$wifi_device_exists) { - throw new Exception(T_('The wifi antenna interface seems not exist on the system')); - } - - if($ip6_net != 'none') { - $ip6_net = ipv6_expanded($ip6_net); - - if(empty($ip6_net)) { - throw new Exception(T_('The IPv6 Delegated Prefix format looks bad')); + foreach($_POST['ssid'] as $key => $ssid) { + $id = $key + 1; + + $ssid['ip6_net'] = empty($ssid['ip6_net']) ? 'none' : $ssid['ip6_net']; + $ssid['ip6_addr'] = 'none'; + $ssid['wifi_secure'] = isset($ssid['wifi_secure']) ? 1 : 0; + + if(!$ssid['wifi_secure']) { + $ssid['wifi_passphrase'] = 'none'; } - $ip6_blocs = explode(':', $ip6_net); - $ip6_addr = "${ip6_blocs[0]}:${ip6_blocs[1]}:${ip6_blocs[2]}:${ip6_blocs[3]}:${ip6_blocs[4]}:${ip6_blocs[5]}:${ip6_blocs[6]}:42"; - - $ip6_net = ipv6_compressed($ip6_net); - $ip6_addr = ipv6_compressed($ip6_addr); - } - - if(!empty($ip6_dns0)) { - $ip6_dns0 = ipv6_expanded($ip6_dns0); - - if(empty($ip6_dns0)) { - throw new Exception(T_('The format of the first IPv6 DNS Resolver looks bad')); + if(empty($ssid['wifi_ssid']) || empty($ssid['wifi_passphrase']) || empty($ssid['wifi_channel'])) { + throw new Exception(T_('Your Wifi Hotspot needs a name, a password and a channel')); } - - $ip6_dns0 = ipv6_compressed($ip6_dns0); - - if(!empty($ip6_dns1)) { - $ip6_dns1 = ipv6_expanded($ip6_dns1); - - if(empty($ip6_dns1)) { - throw new Exception(T_('The format of the second IPv6 DNS Resolver looks bad')); + + if($ssid['wifi_secure'] && (strlen($ssid['wifi_passphrase']) < 8 || strlen($ssid['wifi_passphrase']) > 63)) { + throw new Exception(T_('Your password must from 8 to 63 characters (WPA2 passphrase)')); + } + + if($ssid['wifi_secure'] && preg_match('/[^[:print:]]/', $ssid['wifi_passphrase'])) { + throw new Exception(T_('Only printable ASCII characters are permitted in your password')); + } + + if(!$wifi_device_exists) { + throw new Exception(T_('The wifi antenna interface seems not exist on the system')); + } + + if($ssid['ip6_net'] != 'none') { + $ssid['ip6_net'] = ipv6_expanded($ssid['ip6_net']); + + if(empty($ssid['ip6_net'])) { + throw new Exception(T_('The IPv6 Delegated Prefix format looks bad')); } - - $ip6_dns1 = ipv6_compressed($ip6_dns1); + + $ip6_blocs = explode(':', $ssid['ip6_net']); + $ssid['ip6_addr'] = "${ip6_blocs[0]}:${ip6_blocs[1]}:${ip6_blocs[2]}:${ip6_blocs[3]}:${ip6_blocs[4]}:${ip6_blocs[5]}:${ip6_blocs[6]}:42"; + + $ssid['ip6_net'] = ipv6_compressed($ssid['ip6_net']); + $ssid['ip6_addr'] = ipv6_compressed($ssid['ip6_addr']); } + + if(!empty($ssid['ip6_dns0'])) { + $ssid['ip6_dns0'] = ipv6_expanded($ssid['ip6_dns0']); + + if(empty($ssid['ip6_dns0'])) { + throw new Exception(T_('The format of the first IPv6 DNS Resolver looks bad')); + } + + $ssid['ip6_dns0'] = ipv6_compressed($ssid['ip6_dns0']); + + if(!empty($ssid['ip6_dns1'])) { + $ssid['ip6_dns1'] = ipv6_expanded($ssid['ip6_dns1']); + + if(empty($ssid['ip6_dns1'])) { + throw new Exception(T_('The format of the second IPv6 DNS Resolver looks bad')); + } + + $ssid['ip6_dns1'] = ipv6_compressed($ssid['ip6_dns1']); + } + } + + if(inet_pton($ssid['ip4_dns0']) === false) { + throw new Exception(T_('The format of the first IPv4 DNS Resolver looks bad')); + } + + if(inet_pton($ssid['ip4_dns1']) === false) { + throw new Exception(T_('The format of the second IPv4 DNS Resolver looks bad')); + } + + if(inet_pton("${ssid['ip4_nat_prefix']}.0") === false) { + throw new Exception(T_('The format of the IPv4 NAT Prefix (/24) looks bad : x.x.x expected)')); + } + + if(filter_var("${ssid['ip4_nat_prefix']}.0", FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE) !== false) { + throw new Exception(T_('The IPv4 NAT Prefix must be from a private range')); + } + + array_push($ssids, $ssid); } - - if(inet_pton($_POST['ip4_dns0']) === false) { - throw new Exception(T_('The format of the first IPv4 DNS Resolver looks bad')); - } - - if(inet_pton($_POST['ip4_dns1']) === false) { - throw new Exception(T_('The format of the second IPv4 DNS Resolver looks bad')); - } - - if(inet_pton("${_POST['ip4_nat_prefix']}.0") === false) { - throw new Exception(T_('The format of the IPv4 NAT Prefix (/24) looks bad : x.x.x expected)')); - } - - if(filter_var("${_POST['ip4_nat_prefix']}.0", FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE) !== false) { - throw new Exception(T_('The IPv4 NAT Prefix must be from a private range')); - } - } catch(Exception $e) { - flash('error', $e->getMessage().' ('.T_('configuration not updated').').'); + flash('error', T_('SSID')." $id: ".$e->getMessage().' ('.T_('configuration not updated').').'); goto redirect; } } - stop_service(); + //stop_service(); moulinette_set('service_enabled', $service_enabled); + $settings = array(); if($service_enabled == 1) { - moulinette_set('wifi_ssid', $_POST['wifi_ssid']); - moulinette_set('wifi_secure', $wifi_secure); - - if($wifi_secure == 1) { - moulinette_set('wifi_passphrase', $_POST['wifi_passphrase']); + foreach($ssids as $ssid) { + foreach($ssid as $setting => $value) { + $settings[$setting] .= "$value|"; + } } - moulinette_set('wifi_channel', $_POST['wifi_channel']); - moulinette_set('wifi_n', isset($_POST['wifi_n']) ? 1 : 0); - moulinette_set('wifi_device', $_POST['wifi_device']); - moulinette_set('ip6_net', $ip6_net); - moulinette_set('ip6_addr', $ip6_addr); - moulinette_set('ip6_dns0', $_POST['ip6_dns0']); - moulinette_set('ip6_dns1', $_POST['ip6_dns1']); - moulinette_set('ip4_nat_prefix', $_POST['ip4_nat_prefix']); - moulinette_set('ip4_dns0', $_POST['ip4_dns0']); - moulinette_set('ip4_dns1', $_POST['ip4_dns1']); + moulinette_set('multissid', count($ssids)); - $retcode = start_service(); + foreach($settings as $setting => $value) { + moulinette_set($setting, preg_replace('/\|$/', '', $value)); + } + + //$retcode = start_service(); if($retcode == 0) { flash('success', T_('Configuration updated and service successfully reloaded')); diff --git a/sources/public/css/style.css b/sources/public/css/style.css index aa94d97..8674676 100644 --- a/sources/public/css/style.css +++ b/sources/public/css/style.css @@ -140,3 +140,15 @@ div#wifiparty_passphrase span.passother { div#wifiparty_passphrase span.passspace { color: #CCC; } + +ul.nav-tabs { + margin-top: 5px; +} + +div.tabs { + padding: 14px 14px 0 10px; +} + +div.tabs a { + outline: none; +} diff --git a/sources/public/js/custom.js b/sources/public/js/custom.js index d2a651f..1c8449e 100644 --- a/sources/public/js/custom.js +++ b/sources/public/js/custom.js @@ -16,35 +16,47 @@ * along with this program. If not, see . */ +function wifiSecureBtn() { + if($(this).parent().hasClass('off')) { + $(this).closest('.form-group').next().hide('slow'); + } else { + $(this).closest('.form-group').next().show('slow'); + } +} + +function tabsClick() { + var ssid = $(this).closest('.ssid'); + var tab = $(this).parent().attr('data-tab'); + + ssid.find('li.active').removeClass('active'); + $(this).parent().addClass('active'); + + ssid.find('.tabs').hide(); + ssid.find('.tab' + tab).show(); + + return false; +} + +function dropDownClick() { + var menu = $(this).parent(); + var items = menu.children(); + var button = menu.prev(); + var input = button.prev(); + + items.removeClass('active'); + $(this).addClass('active'); + + button.text($(this).text()); + button.append(' '); + + input.val($(this).text()); +} + $(document).ready(function() { $('.btn-group').button(); $('[data-toggle="tooltip"]').tooltip(); - $('.fileinput').click(function() { - var realinputid = '#' + $(this).attr('id').replace(/_chooser.*/, ''); - $(realinputid).click(); - }); - - $('input[type="file"]').change(function() { - var choosertxtid = '#' + $(this).attr('id') + '_choosertxt'; - - $(choosertxtid).val($(this).val().replace(/^.*[\/\\]/, '')); - }); - - $('.dropdown-menu li').click(function() { - var menu = $(this).parent(); - var items = menu.children(); - var button = menu.prev(); - var input = button.prev(); - - items.removeClass('active'); - $(this).addClass('active'); - - button.text($(this).text()); - button.append(' '); - - input.attr('value', $(this).text()); - }); + $('.dropdown-menu li').click(dropDownClick); $('.switch').bootstrapToggle(); @@ -78,7 +90,7 @@ $(document).ready(function() { } }); - $('#wifiparty').click(function() { + $('.wifiparty').click(function() { $('#wifiparty_screen').show('slow'); }); @@ -102,13 +114,7 @@ $(document).ready(function() { $('#wifiparty_screen').hide(); }); - $('#wifi_secure').change(function() { - if($('#wifi_secure').parent().hasClass('off')) { - $('.secure').hide('slow'); - } else { - $('.secure').show('slow'); - } - }); + $('.wifi_secure').change(wifiSecureBtn); $('#service_enabled').change(function() { if($('#service_enabled').parent().hasClass('off')) { @@ -117,6 +123,54 @@ $(document).ready(function() { $('.enabled').show('slow'); } }); + + $('.nav-tabs a').click(tabsClick); + + $('#newssid').click(function() { + var clone = $('#ssids').children().first().clone(); + var id = parseInt($('.ssid').length); + + clone.find('.dropdownmenu').each(function(i) { + var initial = $('#ssids').children().first().find('.dropdownmenu'); + var clone = initial.eq(i).clone(true, true); + + $(this).after(clone); + $(this).remove(); + }); + + clone.find('[name]').each(function() { + $(this).attr('name', $(this).attr('name').replace('[0]', '[' + id + ']')); + }); + + clone.find('[data-toggle="tooltip"]').tooltip(); + + clone.find('input[type=text]').each(function() { + if($(this).attr('name').match('dns')) { + $(this).val($(this).attr('placeholder')); + + } else { + $(this).val(''); + } + }); + + clone.find('input[type=checkbox]').each(function() { + $(this).parent().after($(this)); + $(this).prev().remove(); + $(this).attr('checked', false); + }); + + clone.find('.switch').bootstrapToggle(); + clone.find('.wifi_secure').change(wifiSecureBtn); + clone.find('.nav-tabs a').click(tabsClick); + clone.find('.dropdown-menu li').click(dropDownClick); + clone.find('.wifi_passphrase').hide(); + + clone.find('h3').each(function() { + $(this).text($(this).data('label') + ' ' + (id + 1)); + }); + + $('#ssids').append(clone); + }); }); $(document).keydown(function(e) { diff --git a/sources/views/_ssid.html.php b/sources/views/_ssid.html.php new file mode 100644 index 0000000..0ab93da --- /dev/null +++ b/sources/views/_ssid.html.php @@ -0,0 +1,118 @@ +
> +
+

">

+
+ + + + +
+
+ +
+ +
+
+ +
+ +
+
+ /> +
+
+
+ +
> + +
+ + +
+
+ +
+ +
+ +
+
+
+ + + + + + +
+ diff --git a/sources/views/settings.html.php b/sources/views/settings.html.php index 71812b0..d7af571 100644 --- a/sources/views/settings.html.php +++ b/sources/views/settings.html.php @@ -70,78 +70,13 @@
- +
/>
-
- - -
> -
-

-
- -
-
- -
- -
-
- -
- -
-
- /> -
-
-
- -
> - -
- - -
-
- -
- -
-
- - - -
-
-
- - -
@@ -157,71 +92,14 @@
-
> -
-

-
- -
- - - - -
- -
- -
-
- -
- -
- -
-
- -
- -
- -
-
-
+
+ + + +
-
> -
-

-
- -
-
- -
- -
-
- -
- -
- -
-
- -
- -
- -
-
-
-
+