Project

General

Profile

Download (27.2 KB) Statistics
| Branch: | Tag: | Revision:
1 04ad7c7c Scott Ullrich
<?php
2 5b237745 Scott Ullrich
/*
3 c5d81585 Renato Botelho
 * system.php
4 191cb31d Stephen Beaver
 *
5 c5d81585 Renato Botelho
 * part of pfSense (https://www.pfsense.org)
6 38809d47 Renato Botelho do Couto
 * Copyright (c) 2004-2013 BSD Perimeter
7
 * Copyright (c) 2013-2016 Electric Sheep Fencing
8 402c98a2 Reid Linnemann
 * Copyright (c) 2014-2023 Rubicon Communications, LLC (Netgate)
9 c5d81585 Renato Botelho
 * All rights reserved.
10 54c605d4 Stephen Beaver
 *
11 c5d81585 Renato Botelho
 * originally based on m0n0wall (http://m0n0.ch/wall)
12
 * Copyright (c) 2003-2004 Manuel Kasper <mk@neon1.net>.
13
 * All rights reserved.
14 54c605d4 Stephen Beaver
 *
15 b12ea3fb Renato Botelho
 * Licensed under the Apache License, Version 2.0 (the "License");
16
 * you may not use this file except in compliance with the License.
17
 * You may obtain a copy of the License at
18 54c605d4 Stephen Beaver
 *
19 b12ea3fb Renato Botelho
 * http://www.apache.org/licenses/LICENSE-2.0
20 54c605d4 Stephen Beaver
 *
21 b12ea3fb Renato Botelho
 * Unless required by applicable law or agreed to in writing, software
22
 * distributed under the License is distributed on an "AS IS" BASIS,
23
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
24
 * See the License for the specific language governing permissions and
25
 * limitations under the License.
26 54c605d4 Stephen Beaver
 */
27 5b237745 Scott Ullrich
28 6b07c15a Matthew Grooms
##|+PRIV
29
##|*IDENT=page-system-generalsetup
30 5230f468 jim-p
##|*NAME=System: General Setup
31 6b07c15a Matthew Grooms
##|*DESCR=Allow access to the 'System: General Setup' page.
32
##|*MATCH=system.php*
33
##|-PRIV
34
35 c81ef6e2 Phil Davis
require_once("guiconfig.inc");
36 7a927e67 Scott Ullrich
require_once("functions.inc");
37
require_once("filter.inc");
38
require_once("shaper.inc");
39 60ff91f1 Renato Botelho
require_once("system.inc");
40 5b237745 Scott Ullrich
41
$pconfig['hostname'] = $config['system']['hostname'];
42
$pconfig['domain'] = $config['system']['domain'];
43 a2d23e88 Phil Davis
$pconfig['dnsserver'] = $config['system']['dnsserver'];
44 0d8a219e Scott Ullrich
45 4bbbcc36 Marcos Mendoza
$arr_gateways = get_gateways();
46 d623f2da Seth Mos
47 e6367325 Phil Davis
// set default columns to two if unset
48 8f65151c Phil Davis
if (!isset($config['system']['webgui']['dashboardcolumns'])) {
49 721fafba Christian McDonald
	config_set_path('system/webgui/dashboardcolumns', 2);
50 477db933 Jared Dillard
}
51
52 27db3c75 Phil Davis
// set default language if unset
53
if (!isset($config['system']['language'])) {
54 2568e151 Christian McDonald
	config_set_path('system/language', g_get('language'));
55 27db3c75 Phil Davis
}
56
57 7e8bfed2 jim-p
$dnshost_counter = 1;
58
59
while (isset($config["system"]["dns{$dnshost_counter}host"])) {
60
	$pconfig_dnshost_counter = $dnshost_counter - 1;
61
	$pconfig["dnshost{$pconfig_dnshost_counter}"] = $config["system"]["dns{$dnshost_counter}host"];
62
	$dnshost_counter++;
63
}
64
65 a2d23e88 Phil Davis
$dnsgw_counter = 1;
66
67
while (isset($config["system"]["dns{$dnsgw_counter}gw"])) {
68
	$pconfig_dnsgw_counter = $dnsgw_counter - 1;
69
	$pconfig["dnsgw{$pconfig_dnsgw_counter}"] = $config["system"]["dns{$dnsgw_counter}gw"];
70
	$dnsgw_counter++;
71
}
72 e180a6e3 Scott Ullrich
73 5b237745 Scott Ullrich
$pconfig['dnsallowoverride'] = isset($config['system']['dnsallowoverride']);
74
$pconfig['timezone'] = $config['system']['timezone'];
75
$pconfig['timeservers'] = $config['system']['timeservers'];
76 3e139f90 Vinicius Coque
$pconfig['language'] = $config['system']['language'];
77 a5995a8e Stephen Beaver
$pconfig['webguicss'] = $config['system']['webgui']['webguicss'];
78 e79ff1ee Steve Beaver
$pconfig['logincss'] = $config['system']['webgui']['logincss'];
79 3d29d2eb Jared Dillard
$pconfig['webguifixedmenu'] = $config['system']['webgui']['webguifixedmenu'];
80 477db933 Jared Dillard
$pconfig['dashboardcolumns'] = $config['system']['webgui']['dashboardcolumns'];
81 1d3510cf Phil Davis
$pconfig['interfacessort'] = isset($config['system']['webgui']['interfacessort']);
82 24f15b3a NOYB
$pconfig['webguileftcolumnhyper'] = isset($config['system']['webgui']['webguileftcolumnhyper']);
83 d9058974 Phil Davis
$pconfig['disablealiaspopupdetail'] = isset($config['system']['webgui']['disablealiaspopupdetail']);
84 c05363c8 NOYB
$pconfig['dashboardavailablewidgetspanel'] = isset($config['system']['webgui']['dashboardavailablewidgetspanel']);
85
$pconfig['systemlogsfilterpanel'] = isset($config['system']['webgui']['systemlogsfilterpanel']);
86
$pconfig['systemlogsmanagelogpanel'] = isset($config['system']['webgui']['systemlogsmanagelogpanel']);
87 b1b8784a NOYB
$pconfig['statusmonitoringsettingspanel'] = isset($config['system']['webgui']['statusmonitoringsettingspanel']);
88 e93242eb Phil Davis
$pconfig['webguihostnamemenu'] = $config['system']['webgui']['webguihostnamemenu'];
89 f0c51530 jim-p
$pconfig['dnslocalhost'] = $config['system']['dnslocalhost'];
90 6c1f2a1c Steve Beaver
//$pconfig['dashboardperiod'] = isset($config['widgets']['period']) ? $config['widgets']['period']:"10";
91 52e91f70 PiBa-NL
$pconfig['roworderdragging'] = isset($config['system']['webgui']['roworderdragging']);
92 a22947a4 Steve Beaver
$pconfig['loginshowhost'] = isset($config['system']['webgui']['loginshowhost']);
93 88081ea2 derelict-pf
$pconfig['requirestatefilter'] = isset($config['system']['webgui']['requirestatefilter']);
94 c4518538 jim-p
$pconfig['requirefirewallinterface'] = isset($config['system']['webgui']['requirefirewallinterface']);
95 8ca95ed8 jim-p
96 2ee8dea1 Phil Davis
if (!$pconfig['timezone']) {
97 2568e151 Christian McDonald
	if (isset($g['default_timezone']) && !empty(g_get('default_timezone'))) {
98
		$pconfig['timezone'] = g_get('default_timezone');
99 ecaca752 Renato Botelho
	} else {
100
		$pconfig['timezone'] = "Etc/UTC";
101
	}
102 2ee8dea1 Phil Davis
}
103 ecaca752 Renato Botelho
104 2ee8dea1 Phil Davis
if (!$pconfig['timeservers']) {
105 5b237745 Scott Ullrich
	$pconfig['timeservers'] = "pool.ntp.org";
106 2ee8dea1 Phil Davis
}
107 04ad7c7c Scott Ullrich
108 79eaddf4 Renato Botelho
$changedesc = gettext("System") . ": ";
109 62d01225 Bill Marquette
$changecount = 0;
110 417c6042 Bill Marquette
111 5b237745 Scott Ullrich
function is_timezone($elt) {
112
	return !preg_match("/\/$/", $elt);
113
}
114
115 2ee8dea1 Phil Davis
if ($pconfig['timezone'] <> $_POST['timezone']) {
116 c6188970 Reid Linnemann
	filter_pflog_start();
117 aa1ab1da Scott Ullrich
}
118
119 60ff91f1 Renato Botelho
$timezonelist = system_get_timezone_list();
120 e5f4c829 Renato Botelho
$timezonedesc = $timezonelist;
121
122
/*
123
 * Etc/GMT entries work the opposite way to what people expect.
124
 * Ref: https://github.com/eggert/tz/blob/master/etcetera and Redmine issue 7089
125
 * Add explanatory text to entries like:
126
 * Etc/GMT+1 and Etc/GMT-1
127
 * but not:
128
 * Etc/GMT or Etc/GMT+0
129
 */
130
foreach ($timezonedesc as $idx => $desc) {
131
	if (substr($desc, 0, 7) != "Etc/GMT" || substr($desc, 8, 1) == "0") {
132
		continue;
133
	}
134
135
	$direction = substr($desc, 7, 1);
136
137
	switch ($direction) {
138
	case '-':
139 88de4ab0 Phil Davis
		$direction_str = gettext('AHEAD of');
140 e5f4c829 Renato Botelho
		break;
141
	case '+':
142
		$direction_str = gettext('BEHIND');
143
		break;
144
	default:
145 86ec819a jim-p
		continue 2;
146 e5f4c829 Renato Botelho
	}
147
148
	$hr_offset = substr($desc, 8);
149 88de4ab0 Phil Davis
	$timezonedesc[$idx] = $desc . " " .
150 d93d8c9c Steve Beaver
	    sprintf(ngettext('(%1$s hour %2$s GMT)', '(%1$s hours %2$s GMT)', intval($hr_offset)), $hr_offset, $direction_str);
151 e5f4c829 Renato Botelho
}
152 5b237745 Scott Ullrich
153 f211d7c0 luckman212
$multiwan = 0;
154 47e079f6 Viktor G
$multiwan6 = 0;
155
foreach ($arr_gateways as $gw) {
156
	if ($gw['ipprotocol'] == 'inet') {
157 f211d7c0 luckman212
		$multiwan++;
158 6038cba7 luckman212
		if ($multiwan > 1) {
159
			break;
160
		}
161 47e079f6 Viktor G
	} else {
162
		$multiwan6++;
163
		if ($multiwan6 > 1) {
164
			break;
165
		}
166 7922db8a Seth Mos
	}
167
}
168 77446beb Matthew Grooms
169 5b237745 Scott Ullrich
if ($_POST) {
170
171 c668c964 Scott Ullrich
	$changecount++;
172 1180e4f0 Sjon Hortensius
173 5b237745 Scott Ullrich
	unset($input_errors);
174
	$pconfig = $_POST;
175
176
	/* input validation */
177 cfbfd941 smos
	$reqdfields = explode(" ", "hostname domain");
178 2ee8dea1 Phil Davis
	$reqdfieldsn = array(gettext("Hostname"), gettext("Domain"));
179 04ad7c7c Scott Ullrich
180 1e9b4611 Renato Botelho
	do_input_validation($_POST, $reqdfields, $reqdfieldsn, $input_errors);
181 04ad7c7c Scott Ullrich
182 2d86ee95 Phil Davis
	if ($_POST['hostname']) {
183
		if (!is_hostname($_POST['hostname'])) {
184
			$input_errors[] = gettext("The hostname can only contain the characters A-Z, 0-9 and '-'. It may not start or end with '-'.");
185
		} else {
186
			if (!is_unqualified_hostname($_POST['hostname'])) {
187
				$input_errors[] = gettext("A valid hostname is specified, but the domain name part should be omitted");
188
			}
189
		}
190 5b237745 Scott Ullrich
	}
191 8ee5aa03 Viktor Gurov
	if ($_POST['domain'] && (!is_domain($_POST['domain'], false, false))) {
192 41e0d95f jim-p
		$input_errors[] = gettext("The domain may only contain the characters a-z, 0-9, '-' and '.', and it cannot start with '.' or '-'.");
193 5b237745 Scott Ullrich
	}
194 9ceace25 jim-p
	validate_webguicss_field($input_errors, $_POST['webguicss']);
195
	validate_webguifixedmenu_field($input_errors, $_POST['webguifixedmenu']);
196
	validate_webguihostnamemenu_field($input_errors, $_POST['webguihostnamemenu']);
197
	validate_dashboardcolumns_field($input_errors, $_POST['dashboardcolumns']);
198 d623f2da Seth Mos
199 58b07c57 NewEraCracker
	$dnslist = $ignore_posted_dnsgw = array();
200 df4471e2 Phil Davis
201 a2d23e88 Phil Davis
	$dnscounter = 0;
202
	$dnsname = "dns{$dnscounter}";
203
204
	while (isset($_POST[$dnsname])) {
205
		$dnsgwname = "dnsgw{$dnscounter}";
206 7e8bfed2 jim-p
		$dnshostname = "dnshost{$dnscounter}";
207 a936104b Stephen Beaver
		$dnslist[] = $_POST[$dnsname];
208
209 d623f2da Seth Mos
		if (($_POST[$dnsname] && !is_ipaddr($_POST[$dnsname]))) {
210 a2d23e88 Phil Davis
			$input_errors[] = sprintf(gettext("A valid IP address must be specified for DNS server %s."), $dnscounter+1);
211 52acb1ff Phil Davis
		} else {
212 7e8bfed2 jim-p
			if (!empty($_POST[$dnshostname]) && !is_hostname($_POST[$dnshostname])) {
213
				$input_errors[] = sprintf(gettext('The hostname provided for DNS server "%1$s" is not valid.'), $_POST[$dnsname]);
214
			}
215 2ee8dea1 Phil Davis
			if (($_POST[$dnsgwname] <> "") && ($_POST[$dnsgwname] <> "none")) {
216 52acb1ff Phil Davis
				// A real gateway has been selected.
217
				if (is_ipaddr($_POST[$dnsname])) {
218 2ee8dea1 Phil Davis
					if ((is_ipaddrv4($_POST[$dnsname])) && (validate_address_family($_POST[$dnsname], $_POST[$dnsgwname]) === false)) {
219 1bab4a10 NOYB
						$input_errors[] = sprintf(gettext('The IPv6 gateway "%1$s" can not be specified for IPv4 DNS server "%2$s".'), $_POST[$dnsgwname], $_POST[$dnsname]);
220 52acb1ff Phil Davis
					}
221 2ee8dea1 Phil Davis
					if ((is_ipaddrv6($_POST[$dnsname])) && (validate_address_family($_POST[$dnsname], $_POST[$dnsgwname]) === false)) {
222 1bab4a10 NOYB
						$input_errors[] = sprintf(gettext('The IPv4 gateway "%1$s" can not be specified for IPv6 DNS server "%2$s".'), $_POST[$dnsgwname], $_POST[$dnsname]);
223 52acb1ff Phil Davis
					}
224
				} else {
225 df4471e2 Phil Davis
					// The user selected a gateway but did not provide a DNS address. Be nice and set the gateway back to "none".
226
					$ignore_posted_dnsgw[$dnsgwname] = true;
227 52acb1ff Phil Davis
				}
228 13ea7caa smos
			}
229 d623f2da Seth Mos
		}
230 a2d23e88 Phil Davis
		$dnscounter++;
231
		$dnsname = "dns{$dnscounter}";
232 5b237745 Scott Ullrich
	}
233 d623f2da Seth Mos
234 c25e42c8 Mark Furneaux
	if (count(array_filter($dnslist)) != count(array_unique(array_filter($dnslist)))) {
235 f700dc99 Chris Buechler
		$input_errors[] = gettext('Each configured DNS server must have a unique IP address. Remove the duplicated IP.');
236
	}
237
238 a2d23e88 Phil Davis
	$dnscounter = 0;
239
	$dnsname = "dns{$dnscounter}";
240
241 985fc0fb Ermal Lu?i
	$direct_networks_list = explode(" ", filter_get_direct_networks_list());
242 a2d23e88 Phil Davis
	while (isset($_POST[$dnsname])) {
243
		$dnsgwname = "dnsgw{$dnscounter}";
244
		if ($_POST[$dnsgwname] && ($_POST[$dnsgwname] <> "none")) {
245 d8587952 Phil Davis
			foreach ($direct_networks_list as $direct_network) {
246 a2d23e88 Phil Davis
				if (ip_in_subnet($_POST[$dnsname], $direct_network)) {
247 86212d70 luckman212
					$input_errors[] = sprintf(gettext("A gateway cannot be specified for %s because that IP address is part of a directly connected subnet %s. To use that nameserver, change its Gateway to `none`."), $_POST[$dnsname], $direct_network);
248 c98d28e1 Seth Mos
				}
249
			}
250
		}
251 a2d23e88 Phil Davis
		$dnscounter++;
252
		$dnsname = "dns{$dnscounter}";
253 c98d28e1 Seth Mos
	}
254
255 8adb814b David P Hilton
	# it's easy to have a little too much whitespace in the field, clean it up for the user before processing.
256
	$_POST['timeservers'] = preg_replace('/[[:blank:]]+/', ' ', $_POST['timeservers']);
257
	$_POST['timeservers'] = trim($_POST['timeservers']);
258 5b237745 Scott Ullrich
	foreach (explode(' ', $_POST['timeservers']) as $ts) {
259 518fa664 kiokoman
		if (!is_domain($ts) && (!is_ipaddr($ts))) {
260
			$input_errors[] = gettext("NTP Time Server names must be valid domain names, IPv4 addresses, or IPv6 addresses");
261 5b237745 Scott Ullrich
		}
262
	}
263
264 a2d23e88 Phil Davis
	if ($input_errors) {
265
		// Put the user-entered list back into place so it will be redisplayed for correction.
266
		$pconfig['dnsserver'] = $dnslist;
267
	} else {
268 f211d7c0 luckman212
		// input validation passed, so we can proceed with removing static routes for dead DNS gateways
269
		if (is_array($config['system']['dnsserver'])) {
270
		  	$dns_servers_arr = $config['system']['dnsserver'];
271
	 		foreach ($dns_servers_arr as $arr_index => $this_dnsserver) {
272 829322b3 Christian McDonald
				$i = (int)$arr_index + 1;
273
				$this_dnsgw = config_get_path("system/dns{$i}gw");
274 f211d7c0 luckman212
				unset($gatewayip);
275
				unset($inet6);
276
				if ((!empty($this_dnsgw)) && ($this_dnsgw != 'none') && (!empty($this_dnsserver))) {
277
					$gatewayip = lookup_gateway_ip_by_name($this_dnsgw);
278
					$inet6 = is_ipaddrv6($gatewayip) ? '-inet6 ' : '';
279 ded361f5 Viktor G
					mwexec("/sbin/route -q delete -host {$inet6}{$this_dnsserver} " . escapeshellarg($gatewayip));
280 f211d7c0 luckman212
				}
281
			}
282
		}
283
284 f1a34790 N0YB
		update_if_changed("hostname", $config['system']['hostname'], $_POST['hostname']);
285
		update_if_changed("domain", $config['system']['domain'], $_POST['domain']);
286 9eab73da Bill Marquette
		update_if_changed("timezone", $config['system']['timezone'], $_POST['timezone']);
287
		update_if_changed("NTP servers", $config['system']['timeservers'], strtolower($_POST['timeservers']));
288 04ad7c7c Scott Ullrich
289 2ee8dea1 Phil Davis
		if ($_POST['language'] && $_POST['language'] != $config['system']['language']) {
290 721fafba Christian McDonald
			config_set_path('system/language', $_POST['language']);
291 ceecd29b Renato Botelho
			set_language();
292 3e139f90 Vinicius Coque
		}
293
294 6e081414 Christian McDonald
		config_del_path('system/webgui/interfacessort');
295 721fafba Christian McDonald
		config_set_path('system/webgui/interfacessort', $_POST['interfacessort'] ? true : false);
296 1d3510cf Phil Davis
297 6e081414 Christian McDonald
		config_del_path('system/webgui/webguileftcolumnhyper');
298 721fafba Christian McDonald
		config_set_path('system/webgui/webguileftcolumnhyper', $_POST['webguileftcolumnhyper'] ? true : false);
299 24f15b3a NOYB
300 6e081414 Christian McDonald
		config_del_path('system/webgui/disablealiaspopupdetail');
301 721fafba Christian McDonald
		config_set_path('system/webgui/disablealiaspopupdetail', $_POST['disablealiaspopupdetail'] ? true : false);
302 d9058974 Phil Davis
303 6e081414 Christian McDonald
		config_del_path('system/webgui/dashboardavailablewidgetspanel');
304 721fafba Christian McDonald
		config_set_path('system/webgui/dashboardavailablewidgetspanel', $_POST['dashboardavailablewidgetspanel'] ? true : false);
305 c05363c8 NOYB
306 6e081414 Christian McDonald
		config_del_path('system/webgui/systemlogsfilterpanel');
307 721fafba Christian McDonald
		config_set_path('system/webgui/systemlogsfilterpanel', $_POST['systemlogsfilterpanel'] ? true : false);
308 c05363c8 NOYB
309 6e081414 Christian McDonald
		config_del_path('system/webgui/systemlogsmanagelogpanel');
310 721fafba Christian McDonald
		config_set_path('system/webgui/systemlogsmanagelogpanel', $_POST['systemlogsmanagelogpanel'] ? true : false);
311 c05363c8 NOYB
312 6e081414 Christian McDonald
		config_del_path('system/webgui/statusmonitoringsettingspanel');
313 721fafba Christian McDonald
		config_set_path('system/webgui/statusmonitoringsettingspanel', $_POST['statusmonitoringsettingspanel'] ? true : false);
314 b1b8784a NOYB
315 9ceace25 jim-p
//		if ($_POST['dashboardperiod']) {
316
//			$config['widgets']['period'] = $_POST['dashboardperiod'];
317
//		}
318
319
		if ($_POST['webguicss']) {
320 721fafba Christian McDonald
			config_set_path('system/webgui/webguicss', $_POST['webguicss']);
321 9ceace25 jim-p
		} else {
322 6e081414 Christian McDonald
			config_del_path('system/webgui/webguicss');
323 9ceace25 jim-p
		}
324
325 721fafba Christian McDonald
		config_set_path('system/webgui/roworderdragging', $_POST['roworderdragging'] ? true:false);
326 9ceace25 jim-p
327
		if ($_POST['logincss']) {
328 721fafba Christian McDonald
			config_set_path('system/webgui/logincss', $_POST['logincss']);
329 9ceace25 jim-p
		} else {
330 6e081414 Christian McDonald
			config_del_path('system/webgui/logincss');
331 9ceace25 jim-p
		}
332
333 721fafba Christian McDonald
		config_set_path('system/webgui/loginshowhost', $_POST['loginshowhost'] ? true:false);
334 9ceace25 jim-p
335
		if ($_POST['webguifixedmenu']) {
336 721fafba Christian McDonald
			config_set_path('system/webgui/webguifixedmenu', $_POST['webguifixedmenu']);
337 9ceace25 jim-p
		} else {
338 6e081414 Christian McDonald
			config_del_path('system/webgui/webguifixedmenu');
339 9ceace25 jim-p
		}
340
341
		if ($_POST['webguihostnamemenu']) {
342 721fafba Christian McDonald
			config_set_path('system/webgui/webguihostnamemenu', $_POST['webguihostnamemenu']);
343 9ceace25 jim-p
		} else {
344 6e081414 Christian McDonald
			config_del_path('system/webgui/webguihostnamemenu');
345 9ceace25 jim-p
		}
346
347
		if ($_POST['dashboardcolumns']) {
348 721fafba Christian McDonald
			config_set_path('system/webgui/dashboardcolumns', $_POST['dashboardcolumns']);
349 9ceace25 jim-p
		} else {
350 6e081414 Christian McDonald
			config_del_path('system/webgui/dashboardcolumns');
351 9ceace25 jim-p
		}
352
353 721fafba Christian McDonald
		config_set_path('system/webgui/requirestatefilter', $_POST['requirestatefilter'] ? true : false);
354 c4518538 jim-p
		config_set_path('system/webgui/requirefirewallinterface', $_POST['requirefirewallinterface'] ? true : false);
355 9ceace25 jim-p
356 4fbf63aa Bill Marquette
		/* XXX - billm: these still need updating after figuring out how to check if they actually changed */
357 52acb1ff Phil Davis
		$olddnsservers = $config['system']['dnsserver'];
358 6e081414 Christian McDonald
		config_del_path('system/dnsserver');
359 a2d23e88 Phil Davis
360
		$dnscounter = 0;
361
		$dnsname = "dns{$dnscounter}";
362
363
		while (isset($_POST[$dnsname])) {
364
			if ($_POST[$dnsname]) {
365
				$config['system']['dnsserver'][] = $_POST[$dnsname];
366
			}
367
			$dnscounter++;
368
			$dnsname = "dns{$dnscounter}";
369 2ee8dea1 Phil Davis
		}
370 04ad7c7c Scott Ullrich
371 a2d23e88 Phil Davis
		// Remember the new list for display also.
372
		$pconfig['dnsserver'] = $config['system']['dnsserver'];
373
374 07bd3f83 Scott Ullrich
		$olddnsallowoverride = $config['system']['dnsallowoverride'];
375 20b90e0a Scott Ullrich
376 6e081414 Christian McDonald
		config_del_path('system/dnsallowoverride');
377 721fafba Christian McDonald
		config_set_path('system/dnsallowoverride', $_POST['dnsallowoverride'] ? true : false);
378 e180a6e3 Scott Ullrich
379 f0c51530 jim-p
		if ($_POST['dnslocalhost']) {
380 721fafba Christian McDonald
			config_set_path('system/dnslocalhost', $_POST['dnslocalhost']);
381 2ee8dea1 Phil Davis
		} else {
382 6e081414 Christian McDonald
			config_del_path('system/dnslocalhost');
383 2ee8dea1 Phil Davis
		}
384 8ca95ed8 jim-p
385 e180a6e3 Scott Ullrich
		/* which interface should the dns servers resolve through? */
386 a2d23e88 Phil Davis
		$dnscounter = 0;
387
		// The $_POST array key of the DNS IP (starts from 0)
388
		$dnsname = "dns{$dnscounter}";
389 df4471e2 Phil Davis
		$outdnscounter = 0;
390 a2d23e88 Phil Davis
		while (isset($_POST[$dnsname])) {
391
			// The $_POST array key of the corresponding gateway (starts from 0)
392
			$dnsgwname = "dnsgw{$dnscounter}";
393 7e8bfed2 jim-p
			$dnshostname = "dnshost{$dnscounter}";
394
			// The numbering of DNS GW/host entries in the config starts from 1
395 a2d23e88 Phil Davis
			$dnsgwconfigcounter = $dnscounter + 1;
396 7e8bfed2 jim-p
			$dnshostconfigcounter = $dnscounter + 1;
397 a2d23e88 Phil Davis
			// So this is the array key of the DNS GW entry in $config['system']
398
			$dnsgwconfigname = "dns{$dnsgwconfigcounter}gw";
399 7e8bfed2 jim-p
			$dnshostconfigname = "dns{$dnshostconfigcounter}host";
400 a2d23e88 Phil Davis
401 829322b3 Christian McDonald
			$olddnsgwname = config_get_path("system/{$dnsgwconfigname}");
402
			$olddnshostname = config_get_path("system/{$dnshostconfigname}");
403 df4471e2 Phil Davis
404 2ee8dea1 Phil Davis
			if ($ignore_posted_dnsgw[$dnsgwname]) {
405 df4471e2 Phil Davis
				$thisdnsgwname = "none";
406 2ee8dea1 Phil Davis
			} else {
407 df4471e2 Phil Davis
				$thisdnsgwname = $pconfig[$dnsgwname];
408 2ee8dea1 Phil Davis
			}
409 7e8bfed2 jim-p
			$thisdnshostname = $pconfig[$dnshostname];
410 df4471e2 Phil Davis
411
			// "Blank" out the settings for this index, then we set them below using the "outdnscounter" index.
412 a2d23e88 Phil Davis
			$config['system'][$dnsgwconfigname] = "none";
413 df4471e2 Phil Davis
			$pconfig[$dnsgwname] = "none";
414 7e8bfed2 jim-p
			$config['system'][$dnshostconfigname] = "";
415
			$pconfig[$dnshostname] = "";
416 df4471e2 Phil Davis
			$pconfig[$dnsname] = "";
417
418
			if ($_POST[$dnsname]) {
419
				// Only the non-blank DNS servers were put into the config above.
420
				// So we similarly only add the corresponding gateways sequentially to the config (and to pconfig), as we find non-blank DNS servers.
421
				// This keeps the DNS server IP and corresponding gateway "lined up" when the user blanks out a DNS server IP in the middle of the list.
422 a2d23e88 Phil Davis
423
				// The $pconfig array key of the DNS IP (starts from 0)
424
				$outdnsname = "dns{$outdnscounter}";
425
				// The $pconfig array key of the corresponding gateway (starts from 0)
426
				$outdnsgwname = "dnsgw{$outdnscounter}";
427 7e8bfed2 jim-p
				// The $pconfig array key of the corresponding hostname (starts from 0)
428
				$outdnshostname = "dnshost{$outdnscounter}";
429
430
				// The numbering of DNS GW/host entries in the config starts from 1
431 a2d23e88 Phil Davis
				$outdnsgwconfigcounter = $outdnscounter + 1;
432 7e8bfed2 jim-p
				$outdnshostconfigcounter = $outdnscounter + 1;
433 a2d23e88 Phil Davis
				// So this is the array key of the output DNS GW entry in $config['system']
434
				$outdnsgwconfigname = "dns{$outdnsgwconfigcounter}gw";
435 7e8bfed2 jim-p
				$outdnshostconfigname = "dns{$outdnshostconfigcounter}host";
436 a2d23e88 Phil Davis
437 df4471e2 Phil Davis
				$pconfig[$outdnsname] = $_POST[$dnsname];
438 2ee8dea1 Phil Davis
				if ($_POST[$dnsgwname]) {
439 a2d23e88 Phil Davis
					$config['system'][$outdnsgwconfigname] = $thisdnsgwname;
440 df4471e2 Phil Davis
					$pconfig[$outdnsgwname] = $thisdnsgwname;
441
				} else {
442
					// Note: when no DNS GW name is chosen, the entry is set to "none", so actually this case never happens.
443 7e3ea4a8 Christian McDonald
					config_del_path("system/{$outdnsgwconfigname}");
444 df4471e2 Phil Davis
					$pconfig[$outdnsgwname] = "";
445 0d192133 jim-p
				}
446
				if ($_POST[$dnshostname]) {
447
					$config['system'][$outdnshostconfigname] = $thisdnshostname;
448
					$pconfig[$outdnshostname] = $thisdnshostname;
449
				} else {
450
					// Note: when no DNS hostname is chosen, unset the value.
451 7e3ea4a8 Christian McDonald
					config_del_path("system/{$outdnshostconfigname}");
452 7e8bfed2 jim-p
					$pconfig[$outdnshostname] = "";
453 df4471e2 Phil Davis
				}
454 a2d23e88 Phil Davis
				$outdnscounter++;
455 d623f2da Seth Mos
			}
456 a2d23e88 Phil Davis
457
			$dnscounter++;
458
			// The $_POST array key of the DNS IP (starts from 0)
459
			$dnsname = "dns{$dnscounter}";
460 d623f2da Seth Mos
		}
461 04ad7c7c Scott Ullrich
462 f211d7c0 luckman212
		// clean up dnsgw orphans
463
		$oldgwcounter = 1;
464
		$olddnsgwconfigname = "dns{$oldgwcounter}gw";
465
		while (isset($config['system'][$olddnsgwconfigname])) {
466
			if (empty($config['system']['dnsserver'][$oldgwcounter - 1])) {
467 7e3ea4a8 Christian McDonald
				config_del_path("system/{$olddnsgwconfigname}");
468 f211d7c0 luckman212
			}
469
			$oldgwcounter++;
470
			$olddnsgwconfigname = "dns{$oldgwcounter}gw";
471
		}
472
		unset($oldgwcounter);
473
		unset($olddnsgwconfigname);
474
475 2ee8dea1 Phil Davis
		if ($changecount > 0) {
476 62d01225 Bill Marquette
			write_config($changedesc);
477 2ee8dea1 Phil Davis
		}
478 04ad7c7c Scott Ullrich
479 44c42356 Phil Davis
		$changes_applied = true;
480 5b237745 Scott Ullrich
		$retval = 0;
481 44c42356 Phil Davis
		$retval |= system_hostname_configure();
482 3cfdba5f Scott Ullrich
		$retval |= system_hosts_generate();
483
		$retval |= system_resolvconf_generate();
484 2ee8dea1 Phil Davis
		if (isset($config['dnsmasq']['enable'])) {
485 1e2c8821 Warren Baker
			$retval |= services_dnsmasq_configure();
486 2ee8dea1 Phil Davis
		} elseif (isset($config['unbound']['enable'])) {
487 1e2c8821 Warren Baker
			$retval |= services_unbound_configure();
488 2ee8dea1 Phil Davis
		}
489 3cfdba5f Scott Ullrich
		$retval |= system_timezone_configure();
490
		$retval |= system_ntp_configure();
491
492 2ee8dea1 Phil Davis
		if ($olddnsallowoverride != $config['system']['dnsallowoverride']) {
493 b8292903 Ermal
			$retval |= send_event("service reload dns");
494 2ee8dea1 Phil Davis
		}
495 3cfdba5f Scott Ullrich
496 e7d967d8 Scott Ullrich
		// Reload the filter - plugins might need to be run.
497 0027de0a Ermal Lu?i
		$retval |= filter_configure();
498 5b237745 Scott Ullrich
	}
499 df4471e2 Phil Davis
500
	unset($ignore_posted_dnsgw);
501 5b237745 Scott Ullrich
}
502 4df96eff Scott Ullrich
503 2ee8dea1 Phil Davis
$pgtitle = array(gettext("System"), gettext("General Setup"));
504 4df96eff Scott Ullrich
include("head.inc");
505
506 8f65151c Phil Davis
if ($input_errors) {
507 41ea4cf3 Sjon Hortensius
	print_input_errors($input_errors);
508 8f65151c Phil Davis
}
509 ddb84143 Stephen Beaver
510 44c42356 Phil Davis
if ($changes_applied) {
511
	print_apply_result_box($retval);
512 8f65151c Phil Davis
}
513 5b237745 Scott Ullrich
?>
514 41ea4cf3 Sjon Hortensius
<div id="container">
515 b40bcb23 Sjon Hortensius
<?php
516 1180e4f0 Sjon Hortensius
517 b40bcb23 Sjon Hortensius
$form = new Form;
518 a32c0623 Sjon Hortensius
$section = new Form_Section('System');
519
$section->addInput(new Form_Input(
520 a97531c5 Sjon Hortensius
	'hostname',
521 153c3aa6 Phil Davis
	'*Hostname',
522 a32c0623 Sjon Hortensius
	'text',
523
	$pconfig['hostname'],
524
	['placeholder' => 'pfSense']
525 4b34ebd2 jim-p
))->setHelp('Name of the firewall host, without domain part.');
526 512f2c10 Stephen Beaver
527 a32c0623 Sjon Hortensius
$section->addInput(new Form_Input(
528 a97531c5 Sjon Hortensius
	'domain',
529 153c3aa6 Phil Davis
	'*Domain',
530 a32c0623 Sjon Hortensius
	'text',
531
	$pconfig['domain'],
532 4b34ebd2 jim-p
	['placeholder' => 'home.arpa, example.com, home, office, private, etc.']
533
))->setHelp('Domain name for the firewall.%1$s%1$s' .
534
	'Do not end the domain name with \'.local\' as the final part (Top Level Domain, TLD). ' .
535
	'The \'local\' TLD is %2$swidely used%3$s by mDNS (e.g. Avahi, Bonjour, Rendezvous, Airprint, Airplay) ' .
536 41e0d95f jim-p
	'and some Windows systems and networked devices. ' .
537
	'These will not network correctly if the router uses \'local\' as its TLD. ' .
538 4b34ebd2 jim-p
	'Alternatives such as \'home.arpa\', \'local.lan\', or \'mylocal\' are safe.',
539
	'<br/>',
540 41e0d95f jim-p
	'<a target="_blank" href="https://www.unbound.net/pipermail/unbound-users/2011-March/001735.html">',
541
	'</a>'
542 ef77e40e stilez
);
543 512f2c10 Stephen Beaver
544 b40bcb23 Sjon Hortensius
$form->add($section);
545
546 70dc5cd6 Phil Davis
$section = new Form_Section('DNS Server Settings');
547 b40bcb23 Sjon Hortensius
548 a2d23e88 Phil Davis
if (!is_array($pconfig['dnsserver'])) {
549
	$pconfig['dnsserver'] = array();
550
}
551
552
$dnsserver_count = count($pconfig['dnsserver']);
553
$dnsserver_num = 0;
554
$dnsserver_help = gettext("Address") . '<br/>' . gettext("Enter IP addresses to be used by the system for DNS resolution.") . " " .
555
	gettext("These are also used for the DHCP service, DNS Forwarder and DNS Resolver when it has DNS Query Forwarding enabled.");
556 7e8bfed2 jim-p
$dnshost_help = gettext("Hostname") . '<br/>' . gettext("Enter the DNS Server Hostname for TLS Verification in the DNS Resolver (optional).");
557 a2d23e88 Phil Davis
$dnsgw_help = gettext("Gateway") . '<br/>'. gettext("Optionally select the gateway for each DNS server.") . " " .
558
	gettext("When using multiple WAN connections there should be at least one unique DNS server per gateway.");
559
560
// If there are no DNS servers, make an empty entry for initial display.
561
if ($dnsserver_count == 0) {
562
	$pconfig['dnsserver'][] = '';
563
}
564
565
foreach ($pconfig['dnsserver'] as $dnsserver) {
566 54c605d4 Stephen Beaver
567 05025e63 Steve Beaver
	$is_last_dnsserver = (($dnsserver_num == $dnsserver_count - 1) || $dnsserver_count == 0);
568 a2d23e88 Phil Davis
	$group = new Form_Group($dnsserver_num == 0 ? 'DNS Servers':'');
569
	$group->addClass('repeatable');
570 54c605d4 Stephen Beaver
571
	$group->add(new Form_Input(
572 a2d23e88 Phil Davis
		'dns' . $dnsserver_num,
573 54c605d4 Stephen Beaver
		'DNS Server',
574
		'text',
575 a2d23e88 Phil Davis
		$dnsserver
576
	))->setHelp(($is_last_dnsserver) ? $dnsserver_help:null);
577 b40bcb23 Sjon Hortensius
578 7e8bfed2 jim-p
	$group->add(new Form_Input(
579
		'dnshost' . $dnsserver_num,
580
		'DNS Hostname',
581
		'text',
582
		$pconfig['dnshost' . $dnsserver_num]
583
	))->setHelp(($is_last_dnsserver) ? $dnshost_help:null);
584
585 47e079f6 Viktor G
	if (($multiwan > 1) || ($multiwan6 > 1)) {
586 b40bcb23 Sjon Hortensius
		$options = array('none' => 'none');
587
588 8f65151c Phil Davis
		foreach ($arr_gateways as $gwname => $gwitem) {
589
			if ((is_ipaddrv4(lookup_gateway_ip_by_name($pconfig[$dnsgw])) && (is_ipaddrv6($gwitem['gateway'])))) {
590 b40bcb23 Sjon Hortensius
				continue;
591
			}
592 54c605d4 Stephen Beaver
593 8f65151c Phil Davis
			if ((is_ipaddrv6(lookup_gateway_ip_by_name($pconfig[$dnsgw])) && (is_ipaddrv4($gwitem['gateway'])))) {
594 b40bcb23 Sjon Hortensius
				continue;
595
			}
596 1180e4f0 Sjon Hortensius
597 b40bcb23 Sjon Hortensius
			$options[$gwname] = $gwname.' - '.$gwitem['friendlyiface'].' - '.$gwitem['gateway'];
598
		}
599 1180e4f0 Sjon Hortensius
600 a97531c5 Sjon Hortensius
		$group->add(new Form_Select(
601 a2d23e88 Phil Davis
			'dnsgw' . $dnsserver_num,
602 e4dd8be4 NOYB
			'Gateway',
603 a2d23e88 Phil Davis
			$pconfig['dnsgw' . $dnsserver_num],
604 a97531c5 Sjon Hortensius
			$options
605 f211d7c0 luckman212
		))->setWidth(4)->setHelp(($is_last_dnsserver) ? $dnsgw_help:null);
606 b40bcb23 Sjon Hortensius
	}
607 1180e4f0 Sjon Hortensius
608 a2d23e88 Phil Davis
	$group->add(new Form_Button(
609
		'deleterow' . $dnsserver_num,
610
		'Delete',
611
		null,
612 e6f78714 Marcos Mendoza
		'fa-solid fa-trash-can'
613 f211d7c0 luckman212
	))->setWidth(2)->addClass('btn-warning');
614 54c605d4 Stephen Beaver
615 b40bcb23 Sjon Hortensius
	$section->add($group);
616 a2d23e88 Phil Davis
	$dnsserver_num++;
617 b40bcb23 Sjon Hortensius
}
618 1180e4f0 Sjon Hortensius
619 a2d23e88 Phil Davis
$section->addInput(new Form_Button(
620
	'addrow',
621
	'Add DNS Server',
622
	null,
623 e6f78714 Marcos Mendoza
	'fa-solid fa-plus'
624 a2d23e88 Phil Davis
))->addClass('btn-success addbtn');
625
626 a005a836 Sjon Hortensius
$section->addInput(new Form_Checkbox(
627 a97531c5 Sjon Hortensius
	'dnsallowoverride',
628 70dc5cd6 Phil Davis
	'DNS Server Override',
629 349e7c67 Viktor G
	'Allow DNS server list to be overridden by DHCP/PPP on WAN or remote OpenVPN server',
630 b40bcb23 Sjon Hortensius
	$pconfig['dnsallowoverride']
631 314a088a Phil Davis
))->setHelp('If this option is set, %s will use DNS servers '.
632 349e7c67 Viktor G
	'assigned by a DHCP/PPP server on WAN or a remote OpenVPN server (if Pull DNS ' .
633
	'option is enabled) for its own purposes (including the DNS Forwarder/DNS Resolver). '.
634 2568e151 Christian McDonald
        'However, they will not be assigned to DHCP clients.', g_get('product_label'));
635 b40bcb23 Sjon Hortensius
636 f0c51530 jim-p
$section->addInput(new Form_Select(
637 a97531c5 Sjon Hortensius
	'dnslocalhost',
638 f0c51530 jim-p
	'DNS Resolution Behavior',
639
	$pconfig['dnslocalhost'],
640
	array(
641
		''       => 'Use local DNS (127.0.0.1), fall back to remote DNS Servers (Default)',
642
		'local'  => 'Use local DNS (127.0.0.1), ignore remote DNS Servers',
643
		'remote' => 'Use remote DNS Servers, ignore local DNS',
644
	)
645
))->setHelp('By default the firewall will use local DNS service (127.0.0.1, DNS '.
646
	'Resolver or Forwarder) as the first DNS server when possible, and it '.
647
	'will fall back to remote DNS servers otherwise. Use this option to '.
648
	'choose alternate behaviors.');
649 b40bcb23 Sjon Hortensius
650
$form->add($section);
651
652 a005a836 Sjon Hortensius
$section = new Form_Section('Localization');
653 512f2c10 Stephen Beaver
654 a005a836 Sjon Hortensius
$section->addInput(new Form_Select(
655 a97531c5 Sjon Hortensius
	'timezone',
656 153c3aa6 Phil Davis
	'*Timezone',
657 a32c0623 Sjon Hortensius
	$pconfig['timezone'],
658 e5f4c829 Renato Botelho
	array_combine($timezonelist, $timezonedesc)
659 781d9ce4 Phil Davis
))->setHelp('Select a geographic region name (Continent/Location) to determine the timezone for the firewall. %1$s' .
660
	'Choose a special or "Etc" zone only in cases where the geographic zones do not properly handle the clock offset required for this firewall.', '<br/>');
661 512f2c10 Stephen Beaver
662 a005a836 Sjon Hortensius
$section->addInput(new Form_Input(
663 a97531c5 Sjon Hortensius
	'timeservers',
664 a32c0623 Sjon Hortensius
	'Timeservers',
665
	'text',
666
	$pconfig['timeservers']
667
))->setHelp('Use a space to separate multiple hosts (only one required). '.
668 1bab4a10 NOYB
	'Remember to set up at least one DNS server if a host name is entered here!');
669 512f2c10 Stephen Beaver
670 a005a836 Sjon Hortensius
$section->addInput(new Form_Select(
671 a97531c5 Sjon Hortensius
	'language',
672 153c3aa6 Phil Davis
	'*Language',
673 a32c0623 Sjon Hortensius
	$pconfig['language'],
674
	get_locale_list()
675
))->setHelp('Choose a language for the webConfigurator');
676 b40bcb23 Sjon Hortensius
677
$form->add($section);
678
679 1176360c k-paulius
$section = new Form_Section('webConfigurator');
680 a5995a8e Stephen Beaver
681 8bab524e Phil Davis
gen_webguicss_field($section, $pconfig['webguicss']);
682
gen_webguifixedmenu_field($section, $pconfig['webguifixedmenu']);
683
gen_webguihostnamemenu_field($section, $pconfig['webguihostnamemenu']);
684
gen_dashboardcolumns_field($section, $pconfig['dashboardcolumns']);
685 1d3510cf Phil Davis
gen_interfacessort_field($section, $pconfig['interfacessort']);
686 8bab524e Phil Davis
gen_associatedpanels_fields(
687
	$section,
688
	$pconfig['dashboardavailablewidgetspanel'],
689
	$pconfig['systemlogsfilterpanel'],
690
	$pconfig['systemlogsmanagelogpanel'],
691
	$pconfig['statusmonitoringsettingspanel']);
692 88081ea2 derelict-pf
gen_requirestatefilter_field($section, $pconfig['requirestatefilter']);
693 c4518538 jim-p
gen_requirefirewallinterface_field($section, $pconfig['requirefirewallinterface']);
694 8bab524e Phil Davis
gen_webguileftcolumnhyper_field($section, $pconfig['webguileftcolumnhyper']);
695 d9058974 Phil Davis
gen_disablealiaspopupdetail_field($section, $pconfig['disablealiaspopupdetail']);
696 24f15b3a NOYB
697 52e91f70 PiBa-NL
$section->addInput(new Form_Checkbox(
698
	'roworderdragging',
699
	'Disable dragging',
700 86212d70 luckman212
	'Disable dragging of firewall/NAT rules',
701 52e91f70 PiBa-NL
	$pconfig['roworderdragging']
702
))->setHelp('Disables dragging rows to allow selecting and copying row contents and avoid accidental changes.');
703
704 e79ff1ee Steve Beaver
$section->addInput(new Form_Select(
705
	'logincss',
706 d58a7378 Steve Beaver
	'Login page color',
707 e79ff1ee Steve Beaver
	$pconfig['logincss'],
708 1fe82d1d Administrator
	["1e3f75;" => gettext("Dark Blue"), "003300" => gettext("Dark green"), "770101" => gettext("Crimson red"),
709 626aefbe Steve Beaver
	 "4b1263" => gettext("Purple"), "424142" => gettext("Gray"), "333333" => gettext("Dark gray"),
710 1fe82d1d Administrator
	 "000000" => gettext("Black"), "633215" => gettext("Dark brown"), "bf7703" => gettext("Brown"), 
711
	 "008000" => gettext("Green"), "007faa" => gettext("Light Blue"), "dc2a2a" => gettext("Red"),
712
	 "9b59b6" => gettext("Violet")]
713 d58a7378 Steve Beaver
))->setHelp('Choose a color for the login page');
714 e79ff1ee Steve Beaver
715 a22947a4 Steve Beaver
$section->addInput(new Form_Checkbox(
716
	'loginshowhost',
717
	'Login hostname',
718
	'Show hostname on login banner',
719
	$pconfig['loginshowhost']
720
));
721 6c1f2a1c Steve Beaver
/*
722 512f2c10 Stephen Beaver
$section->addInput(new Form_Input(
723
	'dashboardperiod',
724
	'Dashboard update period',
725
	'number',
726
	$pconfig['dashboardperiod'],
727 134ee13d Stephen Beaver
	['min' => '5', 'max' => '600']
728 512f2c10 Stephen Beaver
))->setHelp('Time in seconds between dashboard widget updates. Small values cause ' .
729
			'more frequent updates but increase the load on the web server. ' .
730
			'Minimum is 5 seconds, maximum 600 seconds');
731 6c1f2a1c Steve Beaver
*/
732 a5995a8e Stephen Beaver
$form->add($section);
733
734 b40bcb23 Sjon Hortensius
print $form;
735 7bb301eb Stephen Beaver
736
$csswarning = sprintf(gettext("%sUser-created themes are unsupported, use at your own risk."), "<br />");
737
738 8c4ef875 NOYB
?>
739
</div>
740 7bb301eb Stephen Beaver
741 46345696 Colin Fleming
<script type="text/javascript">
742 7bb301eb Stephen Beaver
//<![CDATA[
743
events.push(function() {
744
745
	function setThemeWarning() {
746
		if ($('#webguicss').val().startsWith("pfSense")) {
747
			$('#csstxt').html("").addClass("text-default");
748
		} else {
749
			$('#csstxt').html("<?=$csswarning?>").addClass("text-danger");
750
		}
751
	}
752
753
	$('#webguicss').change(function() {
754
		setThemeWarning();
755
	});
756
757
	setThemeWarning();
758 a2d23e88 Phil Davis
759
	// Suppress "Delete row" button if there are fewer than two rows
760
	checkLastRow();
761 7bb301eb Stephen Beaver
});
762
//]]>
763
</script>
764
765 8c4ef875 NOYB
<?php
766 60ff91f1 Renato Botelho
include("foot.inc");
767 8c4ef875 NOYB
?>