diff options
-rw-r--r-- | src/usr/local/www/firewall_nat.php | 76 | ||||
-rw-r--r-- | src/usr/local/www/firewall_nat_edit.php | 8 | ||||
-rw-r--r-- | src/usr/local/www/firewall_rules.php | 170 | ||||
-rw-r--r-- | src/usr/local/www/jquery/pfSenseHelpers.js | 156 |
4 files changed, 250 insertions, 160 deletions
diff --git a/src/usr/local/www/firewall_nat.php b/src/usr/local/www/firewall_nat.php index 869fbff..8b481d1 100644 --- a/src/usr/local/www/firewall_nat.php +++ b/src/usr/local/www/firewall_nat.php @@ -87,6 +87,16 @@ if (array_key_exists('order-store', $_POST)) { $a_nat = $a_nat_new; + + $config['nat']['separator'] = ""; + + if ($_POST['separator']) { + $idx = 0; + foreach ($_POST['separator'] as $separator) { + $config['nat']['separator']['sep' . $idx++] = $separator; + } + } + if (write_config()) { mark_subsystem_dirty('filter'); } @@ -130,6 +140,16 @@ if ($_GET['act'] == "del") { } unset($a_nat[$_GET['id']]); + // Update the separators + $a_separators = &$config['nat']['separator']; + + for ($idx=0; isset($a_separators['sep' . $idx]); $idx++ ) { + $seprow = substr($a_separators['sep' . $idx]['row']['0'], 2); + if ($seprow >= $_GET['id']) { + $a_separators['sep' . $idx]['row']['0'] = 'fr' . ($seprow - 1); + } + } + if (write_config()) { mark_subsystem_dirty('natconf'); if ($want_dirty_filter) { @@ -145,8 +165,11 @@ if ($_GET['act'] == "del") { if (isset($_POST['del_x'])) { /* delete selected rules */ if (is_array($_POST['rule']) && count($_POST['rule'])) { + $a_separators = &$config['nat']['separator']; + foreach ($_POST['rule'] as $rulei) { - $target = $rule['target']; + $target = $rule['target']; + // Check for filter rule associations if (isset($a_nat[$rulei]['associated-rule-id'])) { delete_id($a_nat[$rulei]['associated-rule-id'], $config['filter']['rule']); @@ -155,6 +178,14 @@ if (isset($_POST['del_x'])) { } unset($a_nat[$rulei]); + + // Update the separators + for ($idx=0; isset($a_separators['sep' . $idx]); $idx++ ) { + $seprow = substr($a_separators['sep' . $idx]['row']['0'], 2); + if ($seprow >= $rulei) { + $a_separators['sep' . $idx]['row']['0'] = 'fr' . ($seprow - 1); + } + } } if (write_config()) { @@ -197,13 +228,15 @@ $tab_array[] = array(gettext("1:1"), false, "firewall_nat_1to1.php"); $tab_array[] = array(gettext("Outbound"), false, "firewall_nat_out.php"); $tab_array[] = array(gettext("NPt"), false, "firewall_nat_npt.php"); display_top_tabs($tab_array); + +$columns_in_table = 13; ?> <form action="firewall_nat.php" method="post" name="iform"> <div class="panel panel-default"> <div class="panel-heading"><h2 class="panel-title"><?=gettext('Rules')?></h2></div> <div class="panel-body table-responsive"> - <table class="table table-striped table-hover table-condensed"> + <table id="ruletable" class="table table-striped table-hover table-condensed"> <thead> <tr> <th><!-- Checkbox --></th> @@ -226,6 +259,15 @@ display_top_tabs($tab_array); $nnats = $i = 0; +// There can be a separator before any rules are listed +if ($config['nat']['separator']['sep0']['row'][0] == "fr-1") { + $cellcolor = $config['nat']['separator']['sep0']['color']; + print('<tr class="ui-sortable-handle separator">' . + '<td class="' . $cellcolor . '" colspan="' . ($columns_in_table -1) . '">' . '<span class="' . $cellcolor . '">' . $config['nat']['separator']['sep0']['text'] . '</span></td>' . + '<td class="' . $cellcolor . '"><a href="#"><i class="fa fa-trash no-confirm sepdel" title="delete this separator"></i></a></td>' . + '</tr>' . "\n"); +} + foreach ($a_nat as $natent): $alias = rule_columns_with_alias( @@ -386,6 +428,18 @@ foreach ($a_nat as $natent): </td> </tr> <?php + + if (isset($config['nat']['separator']['sep0'])) { + foreach ($config['nat']['separator'] as $rulesep) { + if ($rulesep['row']['0'] == "fr" . $nnats) { + $cellcolor = $rulesep['color']; + print('<tr class="ui-sortable-handle separator">' . + '<td class="' . $cellcolor . '" colspan="' . ($columns_in_table -1) . '">' . '<span class="' . $cellcolor . '">' . $rulesep['text'] . '</span></td>' . + '<td class="' . $cellcolor . '"><a href="#"><i class="fa fa-trash no-confirm sepdel" title="delete this separator"></i></a></td>' . + '</tr>' . "\n"); + } + } + } $i++; $nnats++; endforeach; @@ -412,11 +466,23 @@ endforeach; <i class="fa fa-save icon-embed-btn"></i> <?=gettext("Save")?> </button> + <button type="submit" id="addsep" name="addsep" class="btn btn-sm btn-warning" title="<?=gettext('Add separator')?>"> + <i class="fa fa-plus icon-embed-btn"></i> + <?=gettext("Separator")?> + </button> </nav> </form> <script type="text/javascript"> //<![CDATA[ +//Need to create some variables here so that jquert/pfSenseHelpers.php can read them +iface = "<?=strtolower($if)?>"; +cncltxt = '<?=gettext("Cancel")?>'; +svtxt = '<?=gettext("Save")?>'; +svbtnplaceholder = '<?=gettext("Enter a description, Save, then drag to final location.")?>'; +configsection = "nat"; +dirty = false; + events.push(function() { // Make rules sortable @@ -425,6 +491,8 @@ events.push(function() { update: function(event, ui) { $('#order-store').removeAttr('disabled'); dirty = true; + reindex_rules(ui.item.parent('tbody')); + dirty = true; } }); @@ -432,8 +500,12 @@ events.push(function() { $('#order-store').click(function () { $('[id^=frc]').prop('checked', true); + // Save the separator bar configuration + save_separators(); + // Suppress the "Do you really want to leave the page" message saving = true; + }); // Globals diff --git a/src/usr/local/www/firewall_nat_edit.php b/src/usr/local/www/firewall_nat_edit.php index 65316f0..c23c9d7 100644 --- a/src/usr/local/www/firewall_nat_edit.php +++ b/src/usr/local/www/firewall_nat_edit.php @@ -514,6 +514,14 @@ if ($_POST) { $natent['created'] = make_config_revision_entry(); if (is_numeric($after)) { array_splice($a_nat, $after+1, 0, array($natent)); + + // Update the separators + $a_separators = &$config['nat']['separator']; + + for ($idx=0; isset($a_separators['sep' . $idx]); $idx++ ) { + $seprow = substr($a_separators['sep' . $idx]['row']['0'], 2); + $a_separators['sep' . $idx]['row']['0'] = 'fr' . ($seprow + 1); + } } else { $a_nat[] = $natent; } diff --git a/src/usr/local/www/firewall_rules.php b/src/usr/local/www/firewall_rules.php index fc14e2c..0c2ab29 100644 --- a/src/usr/local/www/firewall_rules.php +++ b/src/usr/local/www/firewall_rules.php @@ -200,7 +200,6 @@ if (!$if || !isset($iflist[$if])) { } if ($_POST) { - $pconfig = $_POST; if ($_POST['apply']) { @@ -290,6 +289,7 @@ if (isset($_POST['del_x'])) { exit; } } else if ($_POST['order-store']) { + /* update rule order, POST[rule] is an array of ordered IDs */ if (is_array($_POST['rule']) && !empty($_POST['rule'])) { $a_filter_new = array(); @@ -469,9 +469,10 @@ $seps = 0; // There can be a separator before any rules are listed if ($config['filter']['separator'][strtolower($if)]['sep0']['row'][0] == "fr-1") { + $cellcolor = $config['filter']['separator'][strtolower($if)]['sep0']['color']; print('<tr class="ui-sortable-handle separator">' . - '<td bgcolor="#cce5ff" colspan="' . ($columns_in_table -1 ) . '">' . '<font color="#002699">' . $config['filter']['separator'][strtolower($if)]['sep0']['text'] . '</font></td>' . - '<td bgcolor="#cce5ff"><a href="#"><i class="fa fa-trash no-confirm sepdel" title="delete this separator"></i></a></td>' . + '<td class="' . $cellcolor . '" colspan="' . ($columns_in_table -1) . '">' . '<span class="' . $cellcolor . '">' . $config['filter']['separator'][strtolower($if)]['sep0']['text'] . '</span></td>' . + '<td class="' . $cellcolor . '"><a href="#"><i class="fa fa-trash no-confirm sepdel" title="delete this separator"></i></a></td>' . '</tr>' . "\n"); } @@ -875,6 +876,14 @@ for ($i = 0; isset($a_filter[$i]); $i++): <script type="text/javascript"> //<![CDATA[ + +//Need to create some variables here so that jquer/pfSenseHelpers.php can read them +iface = "<?=strtolower($if)?>"; +cncltxt = '<?=gettext("Cancel")?>'; +svtxt = '<?=gettext("Save")?>'; +svbtnplaceholder = '<?=gettext("Enter a description, Save, then drag to final location.")?>'; +configsection = "filter"; + events.push(function() { // Make rules sortable @@ -898,148 +907,6 @@ events.push(function() { saving = true; }); - // Separator bar stuff ------------------------------------------------------------------------ - - // Globals - gColor = 'bg-info'; - newSeperator = false; - saving = false; - dirty = false; - - $("#addsep").prop('type' ,'button'); - - $("#addsep").click(function() { - if (newSeperator) { - return(false); - } - - gColor = 'bg-info'; - // Inset a temporary bar in which the user can enter some optional text - sepcols = $( "#ruletable tr th" ).length - 2; - - $('#ruletable > tbody:last').append('<tr>' + - '<td class="' + gColor + '" colspan="' + sepcols + '"><input id="newsep" placeholder="<?=gettext("Enter a description, Save, then drag to final location.")?>" class="col-md-12" type="text" /></td>' + - '<td class="' + gColor + '" colspan="2"><button class="btn btn-default btn-sm" id="btnnewsep"><?=gettext("Save")?></button>' + - '<button class="btn btn-default btn-sm" id="btncncsep"><?=gettext("Cancel")?></button>' + - ' ' + - ' <a id="sepclrblue" value="bg-info"><i class="fa fa-circle text-info icon-pointer"></i></a>' + - ' <a id="sepclrred" value="bg-danger"><i class="fa fa-circle text-danger icon-pointer"></i></a>' + - ' <a id="sepclrgreen" value="bg-success"><i class="fa fa-circle text-success icon-pointer"></i></a>' + - ' <a id="sepclrorange" value="bg-warning"><i class="fa fa-circle text-warning icon-pointer"></i></button>' + - '</td></tr>'); - - $('#newsep').focus(); - newSeperator = true; - - $("#btnnewsep").prop('type' ,'button'); - - // Watch escape and enter keys - $('#newsep').keyup(function(e) { - if(e.which == 27) { - $('#btncncsep').trigger('click'); - } - }); - - $('#newsep').keypress(function(e) { - if(e.which == 13) { - $('#btnnewsep').trigger('click'); - } - }); - - handle_colors(); - - // Remove the temporary separator bar and replace it with the final version containing the - // user's text and a delete icon - $("#btnnewsep").click(function() { - var septext = escapeHtml($('#newsep').val()); - sepcols = $( "#ruletable tr th" ).length - 1; - - $('#ruletable > tbody:last >tr:last').remove(); - $('#ruletable > tbody:last').append('<tr class="ui-sortable-handle separator">' + - '<td class="' + gColor + '" colspan="' + sepcols + '">' + '<span class="' + gColor + '">' + septext + '</span></td>' + - '<td class="' + gColor + '"><a href="#"><i class="fa fa-trash sepdel"></i></a>' + - '</td></tr>'); - - $('#order-store').removeAttr('disabled'); - newSeperator = false; - dirty = true; - }); - - // Cancel button - $('#btncncsep').click(function(e) { - e.preventDefault(); - $(this).parents('tr').remove(); - newSeperator = false; - }); - }); - - // Delete a separator row - $(function(){ - $('table').on('click','tr a .sepdel',function(e){ - e.preventDefault(); - $(this).parents('tr').remove(); - $('#order-store').removeAttr('disabled'); - dirty = true; - }); - }); - - // Compose an inout array containing the row #, color and text for each separator - function save_separators() { - var seprow = 0; - var sepinput; - var sepnum = 0; - - $('#ruletable > tbody > tr').each(function() { - if ($(this).hasClass('separator')) { - seprow = $(this).prev('tr').attr("id"); - if (seprow == undefined) { - seprow = "fr-1"; - } - - sepinput = '<input type="hidden" name="separator[' + sepnum + '][row]" value="' + seprow + '"></input>'; - $('form').append(sepinput); - sepinput = '<input type="hidden" name="separator[' + sepnum + '][text]" value="' + escapeHtml($(this).find('td').text()) + '"></input>'; - $('form').append(sepinput); - sepinput = '<input type="hidden" name="separator[' + sepnum + '][color]" value="' + $(this).find('td').prop('class') + '"></input>'; - $('form').append(sepinput); - sepinput = '<input type="hidden" name="separator[' + sepnum + '][if]" value="<?=strtolower($if)?>"></input>'; - $('form').append(sepinput); - sepnum++; - } - - if ($(this).parent('tbody').hasClass('user-entries')) { - seprow++; - } - }); - } - - function reindex_rules(section) { - var row = 0; - - section.find('tr').each(function() { - if(this.id) { - $(this).attr("id", "fr" + row); - row++; - } - }) - } - - function handle_colors() { - $('[id^=sepclr]').prop("type", "button"); - - $('[id^=sepclr]').click(function () { - var color = $(this).attr('value'); - // Clear all the color classes - $(this).parent('td').prop('class', ''); - $(this).parent('td').prev('td').prop('class', ''); - // Install our new color class - $(this).parent('td').addClass(color); - $(this).parent('td').prev('td').addClass(color); - // Set the global color - gColor = color; - }); - } - // provide a warning message if the user tries to change page before saving $(window).bind('beforeunload', function(){ if ((!saving && dirty) || newSeperator) { @@ -1049,19 +916,6 @@ events.push(function() { } }); - //JS equivalent to PHP htmlspecialchars() - function escapeHtml(text) { - var map = { - '&': '&', - '<': '<', - '>': '>', - '"': '"', - "'": ''' - }; - - return text.replace(/[&<>"']/g, function(m) { return map[m]; }); - } - // -------------------------------------------------------------------------------------------- }); //]]> </script> diff --git a/src/usr/local/www/jquery/pfSenseHelpers.js b/src/usr/local/www/jquery/pfSenseHelpers.js index 476cc4f..76aaf51 100644 --- a/src/usr/local/www/jquery/pfSenseHelpers.js +++ b/src/usr/local/www/jquery/pfSenseHelpers.js @@ -465,3 +465,159 @@ $('.container .panel-heading a[data-toggle="collapse"]').each(function (idx, el) } }); }); + + // Separator bar stuff ------------------------------------------------------------------------ + + // Globals + gColor = 'bg-info'; + newSeperator = false; + saving = false; + dirty = false; + + $("#addsep").prop('type' ,'button'); + + $("#addsep").click(function() { + if (newSeperator) { + return(false); + } + + gColor = 'bg-info'; + // Inset a temporary bar in which the user can enter some optional text + sepcols = $( "#ruletable tr th" ).length - 2; + + $('#ruletable > tbody:last').append('<tr>' + + '<td class="' + gColor + '" colspan="' + sepcols + '"><input id="newsep" placeholder="' + svbtnplaceholder + '" class="col-md-12" type="text" /></td>' + + '<td class="' + gColor + '" colspan="2"><button class="btn btn-default btn-sm" id="btnnewsep">' + svtxt + '</button>' + + '<button class="btn btn-default btn-sm" id="btncncsep">' + cncltxt + '</button>' + + ' ' + + ' <a id="sepclrblue" value="bg-info"><i class="fa fa-circle text-info icon-pointer"></i></a>' + + ' <a id="sepclrred" value="bg-danger"><i class="fa fa-circle text-danger icon-pointer"></i></a>' + + ' <a id="sepclrgreen" value="bg-success"><i class="fa fa-circle text-success icon-pointer"></i></a>' + + ' <a id="sepclrorange" value="bg-warning"><i class="fa fa-circle text-warning icon-pointer"></i></button>' + + '</td></tr>'); + + $('#newsep').focus(); + newSeperator = true; + + $("#btnnewsep").prop('type' ,'button'); + + // Watch escape and enter keys + $('#newsep').keyup(function(e) { + if(e.which == 27) { + $('#btncncsep').trigger('click'); + } + }); + + $('#newsep').keypress(function(e) { + if(e.which == 13) { + $('#btnnewsep').trigger('click'); + } + }); + + handle_colors(); + + // Remove the temporary separator bar and replace it with the final version containing the + // user's text and a delete icon + $("#btnnewsep").click(function() { + var septext = escapeHtml($('#newsep').val()); + sepcols = $( "#ruletable tr th" ).length - 1; + + $('#ruletable > tbody:last >tr:last').remove(); + $('#ruletable > tbody:last').append('<tr class="ui-sortable-handle separator">' + + '<td class="' + gColor + '" colspan="' + sepcols + '">' + '<span class="' + gColor + '">' + septext + '</span></td>' + + '<td class="' + gColor + '"><a href="#"><i class="fa fa-trash sepdel"></i></a>' + + '</td></tr>'); + + $('#order-store').removeAttr('disabled'); + newSeperator = false; + dirty = true; + }); + + // Cancel button + $('#btncncsep').click(function(e) { + e.preventDefault(); + $(this).parents('tr').remove(); + newSeperator = false; + }); + }); + + // Delete a separator row + $(function(){ + $('table').on('click','tr a .sepdel',function(e){ + e.preventDefault(); + $(this).parents('tr').remove(); + $('#order-store').removeAttr('disabled'); + dirty = true; + }); + }); + + // Compose an inout array containing the row #, color and text for each separator + function save_separators() { + var seprow = 0; + var sepinput; + var sepnum = 0; + + $('#ruletable > tbody > tr').each(function() { + if ($(this).hasClass('separator')) { + seprow = $(this).prev('tr').attr("id"); + if (seprow == undefined) { + seprow = "fr-1"; + } + + sepinput = '<input type="hidden" name="separator[' + sepnum + '][row]" value="' + seprow + '"></input>'; + $('form').append(sepinput); + sepinput = '<input type="hidden" name="separator[' + sepnum + '][text]" value="' + escapeHtml($(this).find('td').text()) + '"></input>'; + $('form').append(sepinput); + sepinput = '<input type="hidden" name="separator[' + sepnum + '][color]" value="' + $(this).find('td').prop('class') + '"></input>'; + $('form').append(sepinput); + sepinput = '<input type="hidden" name="separator[' + sepnum + '][if]" value="' + iface + '"></input>'; + $('form').append(sepinput); + sepnum++; + } + + if ($(this).parent('tbody').hasClass('user-entries')) { + seprow++; + } + }); + } + + function reindex_rules(section) { + var row = 0; + + section.find('tr').each(function() { + if(this.id) { + $(this).attr("id", "fr" + row); + row++; + } + }) + } + + function handle_colors() { + $('[id^=sepclr]').prop("type", "button"); + + $('[id^=sepclr]').click(function () { + var color = $(this).attr('value'); + // Clear all the color classes + $(this).parent('td').prop('class', ''); + $(this).parent('td').prev('td').prop('class', ''); + // Install our new color class + $(this).parent('td').addClass(color); + $(this).parent('td').prev('td').addClass(color); + // Set the global color + gColor = color; + }); + } + + //JS equivalent to PHP htmlspecialchars() + function escapeHtml(text) { + var map = { + '&': '&', + '<': '<', + '>': '>', + '"': '"', + "'": ''' + }; + + return text.replace(/[&<>"']/g, function(m) { return map[m]; }); + } + // -------------------------------------------------------------------------------------------- |