summaryrefslogtreecommitdiffstats
path: root/src/usr/local/www/services_ntpd.php
diff options
context:
space:
mode:
authorStephen Beaver <sbeaver@netgate.com>2015-09-22 13:49:53 -0400
committerStephen Beaver <sbeaver@netgate.com>2015-09-22 13:50:31 -0400
commitf4439c0066f188b7b56e8322ed0b43d1742810f5 (patch)
treed4b3b4c8cb1aa43c03a80d376ff8ecf41a55e130 /src/usr/local/www/services_ntpd.php
parent6ed6941d91d4ebc25e574c0bd5e8053179e3d13e (diff)
downloadpfsense-f4439c0066f188b7b56e8322ed0b43d1742810f5.zip
pfsense-f4439c0066f188b7b56e8322ed0b43d1742810f5.tar.gz
Fixed #5183 by converting to PHP table library
Diffstat (limited to 'src/usr/local/www/services_ntpd.php')
-rw-r--r--src/usr/local/www/services_ntpd.php306
1 files changed, 243 insertions, 63 deletions
diff --git a/src/usr/local/www/services_ntpd.php b/src/usr/local/www/services_ntpd.php
index 8dbac22..506ff4b 100644
--- a/src/usr/local/www/services_ntpd.php
+++ b/src/usr/local/www/services_ntpd.php
@@ -1,33 +1,59 @@
<?php
/*
services_ntpd.php
-
- Copyright (C) 2013 Dagorlad
- Copyright (C) 2012 Jim Pingle
- Copyright (C) 2013-2015 Electric Sheep Fencing, LP
- All rights reserved.
-
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions are met:
-
- 1. Redistributions of source code must retain the above copyright notice,
- this list of conditions and the following disclaimer.
-
- 2. Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
-
- THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
- INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
- AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
- OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- POSSIBILITY OF SUCH DAMAGE.
*/
+/* ====================================================================
+ * Copyright (c) 2004-2015 Electric Sheep Fencing, LLC. All rights reserved.
+ * Copyright (c) 2004, 2005 Scott Ullrich
+ * Copyright (c) 2013 Dagorlad
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgment:
+ * "This product includes software developed by the pfSense Project
+ * for use in the pfSense software distribution. (http://www.pfsense.org/).
+ *
+ * 4. The names "pfSense" and "pfSense Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * coreteam@pfsense.org.
+ *
+ * 5. Products derived from this software may not be called "pfSense"
+ * nor may "pfSense" appear in their names without prior written
+ * permission of the Electric Sheep Fencing, LLC.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ *
+ * "This product includes software developed by the pfSense Project
+ * for use in the pfSense software distribution (http://www.pfsense.org/).
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE pfSense PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE pfSense PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * ====================================================================
+ *
+ */
/*
pfSense_MODULE: ntpd
*/
@@ -61,11 +87,6 @@ if (empty($config['ntpd']['interface'])) {
$pconfig['interface'] = explode(",", $config['ntpd']['interface']);
}
-if($_GET['addrow'])
- $maxrows = $_GET['addrow'] + 1;
-else
- $maxrows = 3;
-
if ($_POST) {
unset($input_errors);
$pconfig = $_POST;
@@ -281,53 +302,46 @@ $section->addInput(new Form_Select(
'Selecting no interfaces will listen on all interfaces with a wildcard.' . '<br />' .
'Selecting all interfaces will explicitly listen on only the interfaces/IPs specified.');
-// NUMTIMESERVERS time servers are always available, but we only display a smaller number of these ($maxrows)
-// Clicking the 'Add Row' button increments $maxrows so you can see more of time servers
+$maxrows = 3;
$timeservers = explode( ' ', $config['system']['timeservers']);
-for ($i = $j = 0; $i < NUMTIMESERVERS; $i++) {
-
- if($i >= $maxrows)
- continue;
-
- $group = new Form_Group($i == 0 ? 'Time servers':'');
+for ($counter=0; $counter < $maxrows; $counter++) {
+ $group = new Form_Group($counter == 0 ? 'Time servers':'');
+ $group->addClass('repeatable');
$group->add(new Form_Input(
- 'server' . $i,
+ 'server' . $counter,
null,
'text',
- $timeservers[$i]
- ));
+ $timeservers[$counter],
+ ['placeholder' => 'Hostname']
+ ))->setWidth(3);
$group->add(new Form_Checkbox(
- 'servprefer' . $i,
+ 'servprefer' . $counter,
null,
- 'Prefer',
- isset($config['ntpd']['prefer']) && isset($timeservers[$i]) && substr_count($config['ntpd']['prefer'], $timeservers[$i])
- ));
+ null,
+ isset($config['ntpd']['prefer']) && isset($timeservers[$counter]) && substr_count($config['ntpd']['prefer'], $timeservers[$counter])
+ ))->sethelp('Prefer');
$group->add(new Form_Checkbox(
- 'servselect' . $i,
+ 'servselect' . $counter,
+ null,
null,
- 'NoSelect',
- isset($config['ntpd']['noselect']) && isset($timeservers[$i]) && substr_count($config['ntpd']['noselect'], $timeservers[$i])
- ));
+ isset($config['ntpd']['noselect']) && isset($timeservers[$counter]) && substr_count($config['ntpd']['noselect'], $timeservers[$counter])
+ ))->sethelp('No Select');
+
+ $group->add(new Form_Button(
+ 'deleterow' . $counter,
+ 'Delete'
+ ))->removeClass('btn-primary')->addClass('btn-warning');
$section->add($group);
}
-// Show the 'Add Rows' button only if we are currently displaying less than the maximum
-// number of configured servers
-if($maxrows < NUMTIMESERVERS) {
- $btnaddrow = new Form_Button(
- 'btnaddrow',
- 'Add Server',
- 'services_ntpd.php?addrow=' . $maxrows
- );
-
- $btnaddrow->removeClass('btn-primary')->addClass('btn-success btn-sm');
-} else {
- $btnaddrow = false;
-}
+$section->addInput(new Form_Button(
+ 'addrow',
+ 'Add'
+))->removeClass('btn-primary')->addClass('btn-success');
$section->addInput(new Form_StaticText(
null,
@@ -507,6 +521,172 @@ events.push(function(){
$('#' + id).parent().parent().parent('div').removeClass('hidden');
}
+ function setMasks() {
+ // Find all ipaddress masks and make dynamic based on address family of input
+ $('span.pfIpMask + select').each(function (idx, select){
+ var input = $(select).prevAll('input[type=text]');
+
+ input.on('change', function(e){
+ var isV6 = (input.val().indexOf(':') != -1), min = 0, max = 128;
+ if (!isV6)
+ max = 32;
+
+ if (input.val() == "")
+ return;
+
+ while (select.options.length > max)
+ select.remove(0);
+
+ if (select.options.length < max)
+ {
+ for (var i=select.options.length; i<=max; i++)
+ select.options.add(new Option(i, i), 0);
+ }
+ });
+
+ // Fire immediately
+ input.change();
+ });
+ }
+
+ // Complicated function to move all help text associated with this input id to the same id
+ // on the row above. That way if you delete the last row, you don't lose the help
+ function moveHelpText(id) {
+ $('#' + id).parent('div').parent('div').find('input').each(function() { // For each <span></span>
+ var fromId = this.id;
+ var toId = decrStringInt(fromId);
+ var helpSpan;
+
+ if(!$(this).hasClass('pfIpMask') && !$(this).hasClass('btn')) {
+
+ helpSpan = $('#' + fromId).parent('div').parent('div').find('span:last').clone();
+ if($(helpSpan).hasClass('help-block')) {
+ if($('#' + decrStringInt(fromId)).parent('div').hasClass('input-group'))
+ $('#' + decrStringInt(fromId)).parent('div').after(helpSpan);
+ else
+ $('#' + decrStringInt(fromId)).after(helpSpan);
+ }
+ }
+ });
+ }
+
+ // Increment the number at the end of the string
+ function bumpStringInt( str ) {
+ var data = str.match(/(\D*)(\d+)(\D*)/), newStr = "";
+
+ if( data )
+ newStr = data[ 1 ] + ( Number( data[ 2 ] ) + 1 ) + data[ 3 ];
+
+ return newStr || str;
+ }
+
+ // Decrement the number at the end of the string
+ function decrStringInt( str ) {
+ var data = str.match(/(\D*)(\d+)(\D*)/), newStr = "";
+
+ if( data )
+ newStr = data[ 1 ] + ( Number( data[ 2 ] ) - 1 ) + data[ 3 ];
+
+ return newStr || str;
+ }
+
+ // Called after a delete so that there are no gaps in the numbering. Most of the time the config system doesn't care about
+ // gaps, but I do :)
+ function renumber() {
+ var idx = 0;
+
+ $('.repeatable').each(function() {
+
+ $(this).find('input').each(function() {
+ $(this).prop("id", this.id.replace(/\d+$/, "") + idx);
+ $(this).prop("name", this.name.replace(/\d+$/, "") + idx);
+ });
+
+ $(this).find('select').each(function() {
+ $(this).prop("id", this.id.replace(/\d+$/, "") + idx);
+ $(this).prop("name", this.name.replace(/\d+$/, "") + idx);
+ });
+
+ $(this).find('label').attr('for', $(this).find('label').attr('for').replace(/\d+$/, "") + idx);
+
+ idx++;
+ });
+ }
+
+ function delete_row(row) {
+ $('#' + row).parent('div').parent('div').remove();
+ renumber();
+ }
+
+ function add_row() {
+ // Find the lst repeatable group
+ var lastRepeatableGroup = $('.repeatable:last');
+
+ // Clone it
+ var newGroup = lastRepeatableGroup.clone(true);
+
+ // Increment the suffix number for each input elemnt in the new group
+ $(newGroup).find('input').each(function() {
+ $(this).prop("id", bumpStringInt(this.id));
+ $(this).prop("name", bumpStringInt(this.name));
+ if(!$(this).is('[id^=delete]'))
+ $(this).val('');
+ });
+
+ // Do the same for selectors
+ $(newGroup).find('select').each(function() {
+ $(this).prop("id", bumpStringInt(this.id));
+ $(this).prop("name", bumpStringInt(this.name));
+ // If this selector lists mask bits, we need it to be reset to all 128 options
+ // and no items selected, so that automatic v4/v6 selection still works
+ if($(this).is('[id^=address_subnet]')) {
+ $(this).empty();
+ for(idx=128; idx>0; idx--) {
+ $(this).append($('<option>', {
+ value: idx,
+ text: idx
+ }));
+ }
+ }
+ });
+
+ // And for "for" tags
+ $(newGroup).find('label').attr('for', bumpStringInt($(newGroup).find('label').attr('for')));
+ $(newGroup).find('label').text(""); // Clear the label. We only want it on the very first row
+
+ // Insert the updated/cloned row
+ $(lastRepeatableGroup).after(newGroup);
+/*
+ // Delete any help text from the group we have cloned
+ $(lastRepeatableGroup).find('.help-block').each(function() {
+ $(this).remove();
+ });
+*/
+ setMasks();
+
+ $('[id^=address]').autocomplete({
+ source: addressarray
+ });
+ }
+
+ // These are action buttons, not submit buttons
+ $('[id^=addrow]').prop('type','button');
+ $('[id^=delete]').prop('type','button');
+
+ // on click . .
+ $('[id^=addrow]').click(function() {
+ add_row();
+ });
+
+ $('[id^=delete]').click(function(event) {
+ if($('.repeatable').length > 1) {
+ // moveHelpText(event.target.id);
+ delete_row(event.target.id);
+ }
+ else
+ alert('<?php echo gettext("You may not delete the last one!")?>');
+ });
+
// Make the ‘clear’ button a plain button, not a submit button
$('#btnadvstats').prop('type','button');
OpenPOWER on IntegriCloud