Project

General

Profile

Download (33.1 KB) Statistics
| Branch: | Tag: | Revision:
1
<?php
2
/*
3
 * guiconfig.inc
4
 *
5
 * part of pfSense (https://www.pfsense.org)
6
 * Copyright (c) 2004-2013 BSD Perimeter
7
 * Copyright (c) 2013-2016 Electric Sheep Fencing
8
 * Copyright (c) 2014-2023 Rubicon Communications, LLC (Netgate)
9
 * All rights reserved.
10
 *
11
 * originally based on m0n0wall (http://m0n0.ch/wall)
12
 * Copyright (c) 2003-2004 Manuel Kasper <mk@neon1.net>.
13
 * All rights reserved.
14
 *
15
 * 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
 *
19
 * http://www.apache.org/licenses/LICENSE-2.0
20
 *
21
 * 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
 */
27

    
28
/* Include authentication routines */
29
/* THIS MUST BE ABOVE ALL OTHER CODE */
30
header("X-Frame-Options: SAMEORIGIN");
31
include_once('phpsessionmanager.inc');
32
include_once("util.inc");
33

    
34
function pfSense_csrf_callback() {
35
	include "csrf_error.php";
36
}
37

    
38
if (!$nocsrf) {
39
	function csrf_startup() {
40
		csrf_conf('rewrite-js', '/csrf/csrf-magic.js');
41
		/* Loading the configuration to get this value breaks other
42
		 * functions. See https://redmine.pfsense.org/issues/13757 */
43
		// $timeout_minutes = config_get_path('system/webgui/session_timeout', 240);
44
		$timeout_minutes = 240;
45
		csrf_conf('expires', $timeout_minutes * 60);
46
		csrf_conf('callback', 'pfSense_csrf_callback');
47
	}
48
	require_once("csrf/csrf-magic.php");
49
	if ($_SERVER['REQUEST_METHOD'] == 'POST') {
50
		phpsession_end(true);
51
	}
52
}
53

    
54
/* make sure nothing is cached */
55
if (!$omit_nocacheheaders) {
56
	header("Expires: 0");
57
	header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
58
	header("Cache-Control: no-cache, no-store, must-revalidate");
59
	header("Pragma: no-cache");
60
}
61

    
62
require_once("authgui.inc");
63
/* Load config.inc after authgui.inc
64
 * See https://redmine.pfsense.org/issues/13757 */
65
include_once('config.inc');
66
include_once('config.lib.inc');
67

    
68
/* parse the configuration and include all configuration functions */
69
require_once("functions.inc");
70

    
71
/* Include the autoloader for all the GUI display classes */
72
require_once("classes/autoload.inc.php");
73

    
74
/* used by progress bar */
75
$lastseen = "-1";
76

    
77
$navlevelsep = ": ";	/* navigation level separator string */
78
$mandfldhtml = "";		/* display this before mandatory input fields */
79
$mandfldhtmlspc = "";	/* same as above, but with spacing */
80

    
81
if (!function_exists('set_language')) {
82
	require_once("pfsense-utils.inc");
83
}
84

    
85
set_language();
86

    
87
/* Some ajax scripts still need access to GUI */
88
if (!$ignorefirmwarelock) {
89
	if (is_subsystem_dirty('firmwarelock')) {
90
		if (!$d_isfwfile) {
91
			header("Location: system_update.php");
92
			exit;
93
		} else {
94
			return;
95
		}
96
	}
97
}
98

    
99
$firewall_rules_dscp_types = array(
100
	"af11",
101
	"af12",
102
	"af13",
103
	"af21",
104
	"af22",
105
	"af23",
106
	"af31",
107
	"af32",
108
	"af33",
109
	"af41",
110
	"af42",
111
	"af43",
112
	"VA",
113
	"EF",
114
	"cs1",
115
	"cs2",
116
	"cs3",
117
	"cs4",
118
	"cs5",
119
	"cs6",
120
	"cs7",
121
	"0x01",
122
	"0x02",
123
	"0x04");
124

    
125
$auth_server_types = array(
126
	'ldap' => "LDAP",
127
	'radius' => "RADIUS");
128

    
129
$ldap_urltypes = array(
130
	'Standard TCP' => 389,
131
	'STARTTLS Encrypted' => 389,
132
	'SSL/TLS Encrypted' => 636);
133

    
134
$ldap_scopes = array(
135
	'one' => gettext("One Level"),
136
	'subtree' => gettext("Entire Subtree"));
137

    
138
$ldap_protvers = array(
139
	2,
140
	3);
141

    
142
$ldap_templates = array(
143

    
144
	'open' => array(
145
		'desc' => "OpenLDAP",
146
		'attr_user' => "cn",
147
		'attr_group' => "cn",
148
		'attr_member' => "member",
149
		'allow_unauthenticated' => "true"),
150

    
151
	'msad' => array(
152
		'desc' => "Microsoft AD",
153
		'attr_user' => "samAccountName",
154
		'attr_group' => "cn",
155
		'attr_member' => "memberOf",
156
		'allow_unauthenticated' => "false"),
157

    
158
	'edir' => array(
159
		'desc' => "Novell eDirectory",
160
		'attr_user' => "cn",
161
		'attr_group' => "cn",
162
		'attr_member' => "uniqueMember",
163
		'allow_unauthenticated' => "false"));
164

    
165
$radius_srvcs = array(
166
	'both' => gettext("Authentication and Accounting"),
167
	'auth' => gettext("Authentication"),
168
	'acct' => gettext("Accounting"));
169

    
170
$radius_protocol = array(
171
	'PAP' => "PAP",
172
	'CHAP_MD5' => "MD5-CHAP",
173
	'MSCHAPv1' => "MS-CHAPv1",
174
	'MSCHAPv2' => "MS-CHAPv2");
175

    
176
$netbios_nodetypes = array(
177
	'0' => "none",
178
	'1' => "b-node",
179
	'2' => "p-node",
180
	'4' => "m-node",
181
	'8' => "h-node");
182

    
183
/* some well known ports */
184
$wkports = array(
185
	179 => "BGP",
186
	5999 => "CVSup",
187
	53 => "DNS",
188
	853 => "DNS over TLS",
189
	21 => "FTP",
190
	3000 => "HBCI",
191
	80 => "HTTP",
192
	443 => "HTTPS",
193
	5190 => "ICQ",
194
	113 => "IDENT/AUTH",
195
	143 => "IMAP",
196
	993 => "IMAP/S",
197
	4500 => "IPsec NAT-T",
198
	500 => "ISAKMP",
199
	1701 => "L2TP",
200
	389 => "LDAP",
201
	636 => "LDAP/S",
202
	1755 => "MMS/TCP",
203
	7000 => "MMS/UDP",
204
	445 => "MS DS",
205
	3389 => "MS RDP",
206
	1512 => "MS WINS",
207
	1863 => "MSN",
208
	119 => "NNTP",
209
	123 => "NTP",
210
	138 => "NetBIOS-DGM",
211
	137 => "NetBIOS-NS",
212
	139 => "NetBIOS-SSN",
213
	1194 => "OpenVPN",
214
	110 => "POP3",
215
	995 => "POP3/S",
216
	1723 => "PPTP",
217
	1812 => "RADIUS",
218
	1813 => "RADIUS accounting",
219
	5004 => "RTP",
220
	5060 => "SIP",
221
	25 => "SMTP",
222
	465 => "SMTP/S",
223
	161 => "SNMP",
224
	162 => "SNMP-Trap",
225
	22 => "SSH",
226
	3478 => "STUN",
227
	587 => "SUBMISSION",
228
	514 => "Syslog",
229
	3544 => "Teredo",
230
	23 => "Telnet",
231
	69 => "TFTP",
232
	5900 => "VNC");
233

    
234
/* TCP flags */
235
$tcpflags = array("fin", "syn", "rst", "psh", "ack", "urg", "ece", "cwr");
236

    
237
$medias = array(
238
	"auto" => gettext("autoselect"),
239
	"100full" => gettext("100BASE-TX full-duplex"),
240
	"100half" => gettext("100BASE-TX half-duplex"),
241
	"10full" => gettext("10BASE-T full-duplex"),
242
	"10half" => gettext("10BASE-T half-duplex"));
243

    
244
$wlan_modes = array(
245
	"bss" => gettext("Infrastructure (BSS)"),
246
	"adhoc" => gettext("Ad-hoc (IBSS)"),
247
	"hostap" => gettext("Access Point"));
248

    
249
function do_input_validation($postdata, $reqdfields, $reqdfieldsn, &$input_errors) {
250

    
251
	/* check for bad control characters */
252
	foreach ($postdata as $pn => $pd) {
253
		if (is_string($pd) && preg_match("/[\\x00-\\x08\\x0b\\x0c\\x0e-\\x1f]/", $pd)) {
254
			$input_errors[] = sprintf(gettext("The field %s contains invalid characters."), $pn);
255
		}
256
	}
257

    
258
	if (is_array($reqdfields)) {
259
		for ($i = 0; $i < count($reqdfields); $i++) {
260
			if ($postdata[$reqdfields[$i]] == "") {
261
				$input_errors[] = sprintf(gettext("The field %s is required."), $reqdfieldsn[$i]);
262
			}
263
		}
264
	}
265
}
266

    
267
function print_input_errors($input_errors) {
268
	echo '<div class="alert alert-danger input-errors">';
269
	echo '<p>' . gettext('The following input errors were detected:') . '</p>';
270
	echo '<ul>';
271

    
272
	foreach ($input_errors as $ierr) {
273
		echo '<li>' . htmlspecialchars($ierr) . '</li>';
274
	}
275

    
276
	echo '</ul>';
277
	echo '</div>';
278
}
279

    
280
function verify_gzip_file($fname) {
281
	$returnvar = mwexec("/usr/bin/gzip -t " . escapeshellarg($fname));
282
	if ($returnvar != 0) {
283
		return 0;
284
	} else {
285
		return 1;
286
	}
287
}
288

    
289
// sprint_info_box() returns a string with a formatted informational box, it does not print the box.
290
// To format and print in one step, call print_info_box() as usual.
291
// Any required button is explicitly created, rather than relying on the detection of certain
292
// strings in the message (such as "apply"). print_info_box_np() has been exterminated.
293
// $class = the bootstrap style class (default, info, warning, success, danger)
294
// $btnname and btntext describe the optional button and its display text, the default is an 'x' Close button.
295
// Note that there is also a shortcut function print_apply_box here that creates a standard "apply" box for you.
296
// In many cases just substitute that for print_info_box_np() to easily get a warning style "Apply changes" box.
297
function sprint_info_box($msg, $class="alert-warning", $btnname = "close", $btntext = "", $btnicon = "", $btnclass = "default") {
298

    
299
	if (strpos($class, "alert-") !== 0) {
300
		$class = 'alert-' . $class;
301
	}
302

    
303
	$msg = '<div class="pull-left">' . $msg . '</div>';
304

    
305
	if ($btnname === "close") {
306
		$msg = '<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">&times;</span></button>' . $msg;
307
	} else if ($btnname != "") {
308
		if (empty($btntext)) {
309
			$btntext = $btnname;
310
		}
311
		if (!empty($btnicon)) {
312
			$btnicon = '<i class="fa ' . $btnicon . ' icon-embed-btn"></i>';
313
		}
314

    
315
		$msg .= '<form method="post" class="pull-right"><button type="submit" class="btn btn-' . $btnclass . '" name="'. $btnname . '" value="' . $btntext . '">' . $btnicon . $btntext . '</button>';
316

    
317
		if ( isset($_POST['if']) && !empty($_POST['if'])) {
318
			$msg .= "<input type=\"hidden\" name=\"if\" value=\"" . htmlspecialchars($_POST['if']) . "\" />";
319
		}
320

    
321
		$msg .= '</form>';
322
	}
323

    
324
	return '<div class="alert ' . $class . ' clearfix" role="alert">' . $msg . '</div>';
325
}
326

    
327
// Format and print an info box. See sprint_info_box() for details.
328
function print_info_box($msg, $class="alert-warning", $btnname = "close", $btntext = "", $btnicon = "", $btnclass = "default") {
329
	echo sprint_info_box($msg, $class, $btnname, $btntext, $btnicon, $btnclass);
330
}
331

    
332
function print_apply_box($msg) {
333
	print_info_box($msg, "warning", "apply", gettext("Apply Changes"), 'fa-check', 'success');
334
}
335

    
336
// Format and print a box reporting that changes have been applied
337
// $retval = status value from the functions called to apply the changes
338
// 0 is good
339
// non-zero is a problem
340
// $extra_text = optional extra text to display after the standard message
341
function print_apply_result_box($retval, $extra_text="") {
342
	$result_msg = get_std_save_message($retval);
343
	if ($retval === 0) {
344
		// 0 is success
345
		$severity = "success";
346
	} else {
347
		// non-zero means there was some problem
348
		$severity = "warning";
349
	}
350

    
351
	if (strlen($extra_text) > 0) {
352
		$result_msg .= " " . $extra_text;
353
	}
354
	print_info_box($result_msg, $severity);
355
}
356

    
357
/*
358
 * Print Bootstrap callout
359
 *
360
 * @param string $msg     message to display
361
 * @param string $class   contextual class, defaults to info (default | danger | warning | info)
362
 * @param string $heading optional callout heading
363
 */
364
function print_callout($msg, $class = 'info', $heading = '') {
365

    
366
	if ('' == $msg) {
367
		return;
368
	}
369
	$class = strtolower($class);
370
	$callout = '';
371

    
372
	if ($class != 'default' && $class != 'danger' && $class != 'warning' && $class != 'info') {
373
		$class = 'info';
374
	}
375
	$callout .= '<div class="bs-callout bs-callout-' . $class . '">';
376

    
377
	if ('' != $heading) {
378
		$callout .= '<h4>' . $heading . '</h4>';
379
	}
380
	$callout .= $msg . '</div>';
381
	echo $callout;
382
}
383

    
384
function get_std_save_message($retval) {
385
	$filter_related = false;
386
	$filter_pages = array("firewall_aliases", "firewall_nat", "firewall_rules", "status_logs_filter");
387
	if ($retval === 0) {
388
		// 0 is success
389
		$to_return = gettext("The changes have been applied successfully.");
390
	} else {
391
		// non-zero means there was some problem
392
		$to_return = sprintf(gettext('There was a problem applying the changes. See the %1$sSystem Logs%2$s.'), '<a href="status_logs.php">', '</a>');
393
	}
394
	foreach ($filter_pages as $fp) {
395
		if (stristr($_SERVER['SCRIPT_FILENAME'], $fp)) {
396
			$filter_related = true;
397
		}
398
	}
399
	if ($filter_related) {
400
		$to_return .= " " . gettext("The firewall rules are now reloading in the background.") . "<br />" .
401
		    sprintf(gettext('%1$sMonitor%2$s the filter reload progress.'), "<a href='status_filter_reload.php'>", "</a>");
402
	}
403
	return $to_return;
404
}
405

    
406
function pprint_address($adr) {
407
	// outbound NAT rules use a value of 'any' rather than a key
408
	if (isset($adr['any']) || $adr['network'] == 'any') {
409
		$padr = "*";
410
	} else if ($adr['network']) {
411
		if (get_specialnet($adr['network'])) {
412
			$specialnets = get_specialnet();
413
			$padr = $specialnets[$adr['network']];
414
		} else {
415
			$padr = $adr['network'];
416
		}
417
	} else {
418
		$padr = $adr['address'];
419
	}
420

    
421
	if (isset($adr['not'])) {
422
		$padr = "! " . $padr;
423
	}
424

    
425
	return $padr;
426
}
427

    
428
function pprint_port($port) {
429
	global $wkports;
430

    
431
	$pport = "";
432

    
433
	if (!$port) {
434
		return "*";
435
	} else {
436
		$srcport = explode("-", $port);
437
		if ((!$srcport[1]) || ($srcport[0] == $srcport[1])) {
438
			$pport = $srcport[0];
439
			if ($wkports[$srcport[0]]) {
440
				$pport .= " (" . $wkports[$srcport[0]] . ")";
441
			}
442
		} else {
443
			$pport .= $srcport[0] . " - " . $srcport[1];
444
		}
445
	}
446

    
447
	return $pport;
448
}
449

    
450
function insert_word_breaks_in_domain_name($domain_name) {
451
	return str_replace('.', '<wbr>.', $domain_name);
452
}
453

    
454
function firewall_check_for_advanced_options(&$item) {
455
	$item_set = "";
456
	if ($item['os']) {
457
			$item_set .= "os " . htmlspecialchars($item['os']) . " ";
458
	}
459
	if ($item['dscp']) {
460
		$item_set .= "dscp " . htmlspecialchars($item['dscp']) . " ";
461
	}
462
	if ($item['max']) {
463
		$item_set .= "max " . htmlspecialchars($item['max']) . " ";
464
	}
465
	if ($item['max-src-nodes']) {
466
		$item_set .= "max-src-nodes " . htmlspecialchars($item['max-src-nodes']) . " ";
467
	}
468
	if ($item['max-src-conn']) {
469
		$item_set .= "max-src-conn " . htmlspecialchars($item['max-src-conn']) . " ";
470
	}
471
	if ($item['max-src-states']) {
472
		$item_set .= "max-src-states " . htmlspecialchars($item['max-src-states']) . " ";
473
	}
474
	if (isset($item['nopfsync'])) {
475
		$item_set .= "nopfsync ";
476
	}
477
	if ($item['statetype'] != "keep state" && $item['statetype'] != "") {
478
		$item_set .= "statetype " . htmlspecialchars($item['statetype']) . " ";
479
	}
480
	if ($item['statetimeout']) {
481
		$item_set .= "statetimeout " . htmlspecialchars($item['statetimeout']) . " ";
482
	}
483
	if (isset($item['nosync'])) {
484
		$item_set .= "no XMLRPC Sync ";
485
	}
486
	if ($item['max-src-conn-rate']) {
487
		$item_set .= "max-src-conn-rate " . htmlspecialchars($item['max-src-conn-rate']) . " ";
488
	}
489
	if ($item['max-src-conn-rates']) {
490
		$item_set .= "max-src-conn-rates " . htmlspecialchars($item['max-src-conn-rates']) . " ";
491
	}
492
	if ($item['vlanprio']) {
493
		$item_set .= "vlanprio " . htmlspecialchars($item['vlanprio']) . " ";
494
	}
495
	if ($item['vlanprioset']) {
496
		$item_set .= "vlanprioset " . htmlspecialchars($item['vlanprioset']) . " ";
497
	}
498
	if ($item['gateway']) {
499
		$item_set .= "gateway " . htmlspecialchars($item['gateway']) . " ";
500
	}
501
	if ($item['dnpipe']) {
502
		$item_set .= "limiter " . htmlspecialchars($item['dnpipe']) . " ";
503
	}
504
	if ($item['pdnpipe']) {
505
		$item_set .= "limiter " . htmlspecialchars($item['pdnpipe']) . " ";
506
	}
507
	if ($item['ackqueue']) {
508
		$item_set .= "ackqueue " . htmlspecialchars($item['ackqueue']) . " ";
509
	}
510
	if ($item['defaultqueue']) {
511
		$item_set .= "defaultqueue " . htmlspecialchars($item['defaultqueue']) . " ";
512
	}
513
	if ($item['tag']) {
514
		$item_set .= "tag " . htmlspecialchars($item['tag']) . " ";
515
	}
516
	if ($item['tagged']) {
517
		$item_set .= "tagged " . htmlspecialchars($item['tagged']) . " ";
518
	}
519
	if (isset($item['allowopts'])) {
520
		$item_set .= "allowopts ";
521
	}
522
	if (isset($item['disablereplyto'])) {
523
		$item_set .= "disable reply-to ";
524
	}
525
	if ($item['tcpflags_any'] || $item['tcpflags1'] || $item['tcpflags2']) {
526
		$item_set .= "tcpflags set";
527
	}
528

    
529
	return $item_set;
530
}
531

    
532
function gentitle($title) {
533
	global $navlevelsep;
534
	if (!is_array($title)) {
535
		return $title;
536
	} else {
537
		return join($navlevelsep, $title);
538
	}
539
}
540

    
541
function genhtmltitle($title, $links=true) {
542
	if (is_array($title)) {
543
		$num_crumbs = count($title);
544
	} else if ($title != NULL) {
545
		$num_crumbs = 1;
546
	} else {
547
		$num_crumbs = 0;
548
	}
549

    
550
	// If the array contains only one element, there are no breadcrumbs, so don't
551
	// add anything else
552
	if ($num_crumbs > 1) {
553
		$bc = '<ol class="breadcrumb">';
554

    
555
		if (!is_array($links)) {
556
			$gen_default = ($links === true);
557
			$links = array_fill(0, $num_crumbs, '');
558
			// If no links passed, then default to a link to self on the last entry.
559
			if ($gen_default) {
560
				$links[$num_crumbs-1] = '@self';
561
			}
562
		}
563

    
564
		foreach ($title as $idx => $el) {
565
			$href = $links[$idx];
566
			if (strlen($href) > 0) {
567
				// For convenience, if the caller specifies '@self' then make a link
568
				// to the current page, including any query string.
569
				if ($href == '@self') {
570
					$href = $_SERVER['REQUEST_URI'];
571
				}
572
				if (substr($href, 0, 1) != '/') {
573
					$href = '/' . $href;
574
				}
575
				$bc .= '<li><a href="' . htmlentities($href) . '">' . $el . '</a></li>';
576
			} else {
577
				$bc .= '<li>' . $el . '</li>';
578
			}
579
		}
580

    
581
		$bc .= '</ol>';
582
	} else {
583
		$bc = "";
584
	}
585

    
586
	return $bc;
587
}
588

    
589
function gen_customwidgettitle_div($widgettitle) {
590
	$divstr = '<div class="form-group">';
591
	$divstr .= '  <label for="descr" class="col-sm-4 control-label">' . gettext('Widget title'). '</label>';
592
	$divstr .= '  <div class="col-sm-4">';
593
	$divstr .= '    <input type="text" name="descr" id="descr" value="'. $widgettitle . '" class="form-control" />';
594
	$divstr .= '  </div>';
595
	$divstr .= '</div>';
596

    
597
	return $divstr;
598
}
599

    
600
function set_customwidgettitle(& $user_settings) {
601
	if ($_POST['descr']) {
602
		$user_settings['widgets'][$_POST['widgetkey']]['descr'] = trim($_POST['descr']);
603
	} else {
604
		unset($user_settings['widgets'][$_POST['widgetkey']]['descr']);
605
	}
606
}
607

    
608
/* update the changedesc and changecount(er) variables */
609
function update_changedesc($update) {
610
	global $changedesc;
611
	global $changecount;
612

    
613
	$changedesc .= " {$update}";
614
	$changecount++;
615
}
616

    
617
/* Check if variable has changed, update and log if it has
618
 * returns true if var changed
619
 * varname = variable name in plain text
620
 * orig = original value
621
 * new = new value
622
 */
623
function update_if_changed($varname, & $orig, $new) {
624
	if (is_array($orig) && is_array($new)) {
625
		$a_diff = array_diff($orig, $new);
626
		foreach ($a_diff as $diff) {
627
			update_changedesc("removed {$varname}: \"{$diff}\"");
628
		}
629
		$a_diff = array_diff($new, $orig);
630
		foreach ($a_diff as $diff) {
631
			update_changedesc("added {$varname}: \"{$diff}\"");
632
		}
633
		$orig = $new;
634
		return true;
635

    
636
	} else {
637
		if ($orig != $new) {
638
			update_changedesc("{$varname}: \"{$orig}\" -> \"{$new}\"");
639
			$orig = $new;
640
			return true;
641
		}
642
	}
643
	return false;
644
}
645

    
646
//function to create widget tabs when called
647
function display_widget_tabs(& $tab_array) {
648
	echo "<div id=\"tabs\">";
649
	foreach ($tab_array as $ta) {
650
		$dashpos = strpos($ta[2], '-');
651
		$tabclass = substr($ta[2], 0, $dashpos);
652
		$tabclass = $tabclass . "-class";
653
		if ($ta[1] == true) {
654
			$tabActive = "table-cell";
655
			$tabNonActive = "none";
656
		} else {
657
			$tabActive = "none";
658
			$tabNonActive = "table-cell";
659
		}
660
		echo "<div id=\"{$ta[2]}-active\" class=\"{$tabclass}-tabactive\" style=\"display:{$tabActive}; background-color:#EEEEEE; color:black;\">";
661
		echo "<b>&nbsp;&nbsp;&nbsp;{$ta[0]}";
662
		echo "&nbsp;&nbsp;&nbsp;</b>";
663
		echo "</div>";
664

    
665
		echo "<div id=\"{$ta[2]}-deactive\" class=\"{$tabclass}-tabdeactive\" style=\"display:{$tabNonActive}; background-color:#777777; color:white; cursor: pointer;\" onclick=\"return changeTabDIV('{$ta[2]}')\">";
666
		echo "<b>&nbsp;&nbsp;&nbsp;{$ta[0]}";
667
		echo "&nbsp;&nbsp;&nbsp;</b>";
668
		echo "</div>";
669
	}
670
	echo "</div>";
671
}
672

    
673
// Return inline javascript file or CSS to minimize
674
// request count going back to server.
675
function outputJavaScriptFileInline($javascript) {
676
	if (file_exists($javascript)) {
677
		echo "\n<script type=\"text/javascript\">\n";
678
		include_once($javascript);
679
		echo "\n</script>\n";
680
	} else {
681
		echo "\n\n<!-- Could not locate file:  {$javascript} -->\n\n";
682
	}
683
}
684

    
685
function outputCSSPrintFileInline($css) {
686
	if (file_exists($css)) {
687
		echo "\n<style media=\"print\" type=\"text/css\">\n";
688
		include_once($css);
689
		echo "\n</style>\n";
690
	} else {
691
		echo "\n\n<!-- Could not locate file:  {$css} -->\n\n";
692
	}
693
}
694

    
695
function outputCSSFileInline($css) {
696
	if (file_exists($css)) {
697
		echo "\n<style type=\"text/css\">\n";
698
		include_once($css);
699
		echo "\n</style>\n";
700
	} else {
701
		echo "\n\n<!-- Could not locate file:  {$css} -->\n\n";
702
	}
703
}
704

    
705
$rfc2616 = array(
706
	100 => "100 Continue",
707
	101 => "101 Switching Protocols",
708
	200 => "200 OK",
709
	201 => "201 Created",
710
	202 => "202 Accepted",
711
	203 => "203 Non-Authoritative Information",
712
	204 => "204 No Content",
713
	205 => "205 Reset Content",
714
	206 => "206 Partial Content",
715
	300 => "300 Multiple Choices",
716
	301 => "301 Moved Permanently",
717
	302 => "302 Found",
718
	303 => "303 See Other",
719
	304 => "304 Not Modified",
720
	305 => "305 Use Proxy",
721
	306 => "306 (Unused)",
722
	307 => "307 Temporary Redirect",
723
	400 => "400 Bad Request",
724
	401 => "401 Unauthorized",
725
	402 => "402 Payment Required",
726
	403 => "403 Forbidden",
727
	404 => "404 Not Found",
728
	405 => "405 Method Not Allowed",
729
	406 => "406 Not Acceptable",
730
	407 => "407 Proxy Authentication Required",
731
	408 => "408 Request Timeout",
732
	409 => "409 Conflict",
733
	410 => "410 Gone",
734
	411 => "411 Length Required",
735
	412 => "412 Precondition Failed",
736
	413 => "413 Request Entity Too Large",
737
	414 => "414 Request-URI Too Long",
738
	415 => "415 Unsupported Media Type",
739
	416 => "416 Requested Range Not Satisfiable",
740
	417 => "417 Expectation Failed",
741
	500 => "500 Internal Server Error",
742
	501 => "501 Not Implemented",
743
	502 => "502 Bad Gateway",
744
	503 => "503 Service Unavailable",
745
	504 => "504 Gateway Timeout",
746
	505 => "505 HTTP Version Not Supported"
747
);
748

    
749
function is_rfc2616_code($code) {
750
	global $rfc2616;
751
	if (isset($rfc2616[$code])) {
752
		return true;
753
	} else {
754
		return false;
755
	}
756
}
757

    
758
function print_rfc2616_select($tag, $current) {
759
	global $rfc2616;
760

    
761
	/* Default to 200 OK if not set */
762
	if ($current == "") {
763
		$current = 200;
764
	}
765

    
766
	echo "<select id=\"{$tag}\" name=\"{$tag}\">\n";
767
	foreach ($rfc2616 as $code => $message) {
768
		if ($code == $current) {
769
			$sel = " selected";
770
		} else {
771
			$sel = "";
772
		}
773
		echo "<option value=\"{$code}\"{$sel}>{$message}</option>\n";
774
	}
775
	echo "</select>\n";
776
}
777

    
778
// Useful debugging function, much cleaner than print_r
779
function echo_array($array, $return_me = false) {
780
	$return = "";
781
	if (is_array($array) == false) {
782
		$return = "The provided variable is not an array.";
783
	} else {
784
		foreach ($array as $name=>$value) {
785
			if (is_array($value)) {
786
				$return .= "";
787
				$return .= "['<b>$name</b>'] {<div style=\"margin-left:10px;\">\n";
788
				$return .= echo_array($value, true);
789
				$return .= "</div>}";
790
				$return .= "\n\n";
791
			} else {
792
				if (is_string($value)) {
793
					$value = "\"$value\"";
794
				}
795
				$return .= "['<b>$name</b>'] = $value\n\n";
796
			}
797
		}
798
	}
799
	if ($return_me == true) {
800
		return $return;
801
	} else {
802
		echo "<pre>".$return."</pre>";
803
	}
804
}
805

    
806
/****f* pfsense-utils/display_top_tabs
807
 * NAME
808
 *	 display_top_tabs - display tabs with rounded edges
809
 * INPUTS
810
 *	 $text	  - array of tabs
811
 * RESULT
812
 *	 null
813
 ******/
814
function display_top_tabs(& $tab_array, $no_drop_down = false, $type = 'pills', $usepost = "") {
815
	global $tab_array_indent;
816
	global $tab_array_space;
817
	global $tab_array_char_limit;
818

    
819
	/*	does the user have access to this tab?
820
	 *	master user has access to everything.
821
	 *	if the user does not have access, simply
822
	 *	unset the tab item.
823
	 */
824

    
825
	/* empty string code */
826
	if ($tab_array_indent == '') {
827
		$tab_array_indent = 0;
828
	}
829

    
830
	if ($tab_array_space == '') {
831
		$tab_array_space = 1;
832
	}
833

    
834
	if ($tab_array_char_limit == '') {
835
		$tab_array_char_limit = 256;
836
	}
837

    
838
	foreach ($tab_array as $tab_id => $ta) {
839
		if (!isAllowedPage($ta[2])) {
840
			unset ($tab_array[$tab_id]);
841
		}
842
	}
843

    
844
	$tabcharcount = 0;
845
	foreach ($tab_array as $ta) {
846
		$tabcharcount = $tabcharcount + strlen($ta[0]);
847
	}
848

    
849
	if ($no_drop_down == true) {
850
		$tabcharcount = 0;
851
		unset($tab_array_char_limit);
852
	}
853

    
854
	// If the character count of the tab names is > 670
855
	// then show a select item dropdown menubox.
856
	if ($tabcharcount > $tab_array_char_limit) {
857
		echo gettext("Currently viewing: ");
858
		echo "<select name=\"TabSelect\" onchange=\"tabs_will_go(this)\">\n";
859

    
860
		foreach ($tab_array as $ta) {
861
			if ($ta[1] == "true") {
862
				$selected = " selected";
863
			} else {
864
				$selected = "";
865
			}
866
			// Onclick in option will not work in some browser
867
			// echo "<option onclick=\"document.location='{$ta[2]}';\"{$selected}>{$ta['0']}</option>\n";
868
			echo "<option value=\"{$ta[2]}\"{$selected}>{$ta['0']}</option>\n";
869
		}
870

    
871
		echo "</select>\n<p>&nbsp;</p>";
872
		echo "<script type=\"text/javascript\">";
873
		echo "\n//<![CDATA[\n";
874
		if ($usepost == 'usepost') {
875
			echo " function tabs_will_go(obj){ var target = obj.value.split(\"?\"); postSubmit(get2post(target[1]),target[0]); }\n";
876
		} else {
877
			echo " function tabs_will_go(obj){ document.location = obj.value; }\n";
878
		}
879
		echo "//]]>\n";
880
		echo "</script>";
881
	} else {
882
		echo '<ul class="nav nav-' . $type . '">';
883

    
884
		foreach ($tab_array as $ta) {
885
			echo '<li role="presentation"';
886
			if ($ta[1]) {
887
				echo ' class="active"';
888
			}
889

    
890
			echo '><a href="' . $ta[2] . '" ' . $usepost . '>' . $ta[0] . '</a></li>';
891
		}
892

    
893
		echo '</ul>';
894
	}
895
}
896

    
897
function add_package_tabs($tabgroup, &$tab_array) {
898
	foreach (config_get_path('installedpackages/package', []) as $pkg) {
899
		if (!is_array($pkg['tabs']['tab'])) {
900
			continue;
901
		}
902

    
903
		foreach ($pkg['tabs']['tab'] as $tab) {
904
			if ($tab['tabgroup'] != $tabgroup) {
905
				continue;
906
			}
907
			$tab_entry = array();
908
			if ($tab['name']) {
909
				$tab_entry[] = $tab['name'];
910
				$tab_entry[] = false;
911
				$tab_entry[] = $tab['url'];
912
				$tab_array[] = $tab_entry;
913
			}
914
		}
915
	}
916
}
917

    
918
function alias_info_popup($alias_id) {
919
	global $user_settings;
920

    
921
	$alias = config_get_path("aliases/alias/{$alias_id}");
922
	if (!is_array($alias)) {
923
		return;
924
	}
925

    
926
	$maxlength = 60;
927
	$content = "";
928

    
929
	if ($user_settings['webgui']['disablealiaspopupdetail']) {
930
		if (strlen($alias['descr']) >= $maxlength) {
931
			$alias['descr'] = substr($alias['descr'], 0, $maxlength) . '&hellip;';
932
		}
933

    
934
		$content .= $alias['descr'];
935
	} else if ($alias['url']) {
936
		// TODO: Change it when pf supports tables with ports
937
		if ($alias['type'] == "urltable") {
938
			exec("/sbin/pfctl -t {$alias['name']} -T show | wc -l", $total_entries);
939
			$counter=preg_replace("/\D/", "", $total_entries[0]);
940
			exec("/sbin/pfctl -t {$alias['name']} -T show | head -10002", $alias_addresses);
941
		} else {
942
			$urlfn = alias_expand_urltable($alias['name']);
943
			$alias_addresses = empty($urlfn) ? [] : explode("\n", file_get_contents($urlfn));
944
			$counter = count($alias_addresses);
945
		}
946

    
947
		$content .= '<h5>'. htmlspecialchars($alias['url']) .'</h5><ul><li>'. implode('</li><li>', $alias_addresses) .'</li></ul>';
948
		if ($counter > 10002) {
949
			$content .= '<i>'. gettext("listing only first 10k items") .'</i>';
950
		}
951
	} else {
952
		$alias_addresses = explode (" ", $alias['address']);
953
		$alias_details = explode ("||", $alias['detail']);
954
		$idx = 0;
955

    
956
		$content .= "<table>\n";
957
		$content .= "<thead>\n";
958
		$content .= "<tr>\n";
959
		$content .= "<th>" . gettext("Value") . "</th><th  style='padding-left: 10px;'>" . gettext("Description") . "</th></tr>\n";
960
		$content .= "</thead>\n";
961
		$content .= "<tbody>\n";
962

    
963
		foreach ($alias_addresses as $ap) {
964
			$content .= "	<tr>\n";
965
			$content .= "		<td>\n";
966
			$content .= 			alias_idn_to_utf8($ap);
967
			$content .=	"		</td>\n";
968
			$content .= "		<td style='padding-left: 10px;'>\n";
969
			$content .= 			htmlspecialchars($alias_details[$idx]);
970
			$content .=	"		</td>\n";
971
			$content .= "	</tr>\n";
972
			$idx++;
973
		}
974

    
975
		$content .= "</tbody>\n";
976
		$content .= "</table>\n";
977
	}
978

    
979
	return $content;
980
}
981

    
982
function gateway_info_popup($showgw, $gateways_status = false) {
983
	init_config_arr(array('gateways', 'gateway_group'));
984
	/* Get groups indexed by name so we can avoid re-scanning the array
985
	 * multiple times later unnecessarily. */
986
	$a_gateways = return_gateways_array(true, false, true, false);
987

    
988
	/* Use cached gateway status if available.
989
	 * See https://redmine.pfsense.org/issues/12174 */
990
	if (!is_array($gateways_status)) {
991
		$gateways_status = return_gateways_status(true);
992
	}
993

    
994
	$content = "";
995
	$gws = array();
996
	$bgdanger = array('force_down', 'down', 'highloss', 'highdelay');
997
	$bgwarning = array('loss', 'delay');
998
	$bgsuccess = array('online', 'none');
999
	$bgcolor = "bg-info";
1000
	$link = "";
1001

    
1002
	if (is_array($a_gateways)) {
1003
		/* Since gw array is hashed by name, we need to count the
1004
		 * index number manually for links since those are by position.
1005
		 */
1006
		$i = 0;
1007
		foreach ($a_gateways as $gateway) {
1008
			if ($gateway['name'] == $showgw) {
1009
				$gws[] = $gateway['name'];
1010
				$link = "/system_gateways_edit.php?id={$i}";
1011
				break;
1012
			}
1013
			$i++;
1014
		}
1015
	}
1016
	$grouptiermap = [];
1017
	foreach(config_get_path('gateways/gateway_group') as $i => $gwgroup) {
1018
		if ($gwgroup['name'] == $showgw) {
1019
			$groupinfo = [];
1020
			foreach ($gwgroup['item'] as $member) {
1021
				$membersplit = explode("|", $member);
1022
				$groupinfo[] = [
1023
					'gw' => $membersplit[0],
1024
					'tier' => $membersplit[1],
1025
					'type' => $membersplit[2]
1026
				];
1027
				/* Store tier separately */
1028
				$grouptiermap[$membersplit[0]] = $membersplit[1];
1029
			}
1030
			/* Sort group info array by tier (number) and then by
1031
			 * name (natural) */
1032
			$gws = array_column($groupinfo, 'gw');
1033
			$tiers = array_column($groupinfo, 'tier');
1034
			array_multisort($tiers, SORT_NUMERIC,
1035
					$gws, SORT_NATURAL,
1036
					$groupinfo);
1037
			/* Re-slice member gateways which are now sorted */
1038
			$gws = array_column($groupinfo, 'gw');
1039
			$link = "system_gateway_groups_edit.php?id={$i}";
1040
			break;
1041
		}
1042
	}
1043

    
1044
	if (!empty($gws)) {
1045
		$content .= "<table>\n";
1046
		$content .= "<thead>\n";
1047
		$content .= "<tr>\n";
1048
		/* Only add Tier column if this is a group */
1049
		if (!empty($grouptiermap)) {
1050
			$content .= "<th>" . gettext("Tier") . "</th>";
1051
			$content .= "<th style='padding-left: 10px;'>";
1052
		} else {
1053
			$content .= "<th>";
1054
		}
1055
		$content .= gettext("Name") . "</th>";
1056
		$content .= "<th style='padding-left: 10px;'>" . gettext("Interface") . "</th>";
1057
		$content .= "<th style='padding-left: 10px;'>" . gettext("Gateway") . "</th></tr>\n";
1058
		$content .= "</thead>\n";
1059
		$content .= "<tbody>\n";
1060
		foreach ($gws as $gw) {
1061
			foreach ($gateways_status as $gwstatus) {
1062
				if ($gwstatus['name'] != $gw) {
1063
					continue;
1064
				}
1065
				/* Distinguish between online/offline in general */
1066
				if (stristr($gwstatus['status'], "online")) {
1067
					/* Use substatus to indicate warnings as needed */
1068
					if (in_array($gwstatus['substatus'], $bgdanger)) {
1069
						$bgcolor = "bg-danger";
1070
					} elseif (in_array($gwstatus['substatus'], $bgwarning)) {
1071
						$bgcolor = "bg-warning";
1072
					} elseif (in_array($gwstatus['substatus'], $bgsuccess)) {
1073
						$bgcolor = "bg-success";
1074
					}
1075
				} elseif (stristr($gwstatus['status'], "down")) {
1076
					/* Anything down is danger, no need to check substatus. */
1077
					$bgcolor = "bg-danger";
1078
				} else {
1079
					/* Unknown status */
1080
					$bgcolor = "bg-info";
1081
				}
1082
			}
1083
			$content .= "	<tr class='{$bgcolor}'>\n";
1084
			/* Only print Tier if this is a group */
1085
			if (!empty($grouptiermap)) {
1086
				$content .= "		<td>\n";
1087
				$content .= 			$grouptiermap[$gw];
1088
				$content .= "		</td>\n";
1089
			}
1090
			$content .= "		<td>\n";
1091
			$content .= 			$gw;
1092
			$content .= "		</td>\n";
1093
			$content .= "		<td style='padding-left: 10px;'>\n";
1094
			$content .= 			$a_gateways[$gw]['friendlyifdescr'];
1095
			$content .= "		</td>\n";
1096
			$content .= "		<td style='padding-left: 10px;'>\n";
1097
			$content .= 			$a_gateways[$gw]['gateway'];
1098
			$content .= "		</td>\n";
1099
			$content .= "	</tr>\n";
1100
		}
1101
		$content .= "</tbody>\n";
1102
		$content .= "</table>\n";
1103
	} else {
1104
		return;
1105
	}
1106

    
1107
	return "<a href=\"{$link}\" data-toggle=\"popover\" data-trigger=\"hover focus\" title=\"" . gettext('Gateway details') . "\" data-content=\"{$content}\" data-html=\"true\">";
1108
}
1109

    
1110
function rule_columns_with_alias($src, $srcport, $dst, $dstport, $target="", $targetport="") {
1111
	$columns = array();
1112
	foreach (config_get_path('aliases/alias', []) as $alias_id => $alias_name) {
1113
		if ($alias_name['name'] == $src) {
1114
			$columns['src'] = $alias_id;
1115
		}
1116
		if ($alias_name['name'] == $srcport) {
1117
			$columns['srcport'] = $alias_id;
1118
		}
1119
		if ($alias_name['name'] == $dst) {
1120
			$columns['dst'] = $alias_id;
1121
		}
1122
		if ($alias_name['name'] == $dstport) {
1123
			$columns['dstport'] = $alias_id;
1124
		}
1125
		if ($alias_name['name'] == $target) {
1126
			$columns['target'] = $alias_id;
1127
		}
1128
		if ($alias_name['name'] == $targetport) {
1129
			$columns['targetport'] = $alias_id;
1130
		}
1131
	}
1132

    
1133
	return $columns;
1134
}
1135

    
1136
function form_output_row($name, $label, $content) {
1137
var_dump($content);die;
1138
?>
1139
<div class="form-group">
1140
	<label for="<?=$name?>" class="col-sm-2 control-label"><?=gettext($label); ?></label>
1141
	<div class="col-sm-10">
1142
		<?=$content?>
1143
	</div>
1144
</div>
1145
<?php
1146
}
1147

    
1148
function set_flash_message($class, $msg) {
1149
	@phpsession_begin();
1150
	$_SESSION['flash_messages'][$class][] = $msg;
1151
	@phpsession_end(true);
1152
}
1153

    
1154
function get_flash_message() {
1155
	@phpsession_begin();
1156
	if (isset($_SESSION['flash_messages']) && !empty($_SESSION['flash_messages'])) {
1157
		foreach ($_SESSION['flash_messages'] as $class => $flash_message) {
1158
			print_info_box(implode("<br />", $flash_message), $class);
1159
		}
1160
		unset($_SESSION['flash_messages']);
1161
	}
1162
	@phpsession_end(true);
1163
}
1164

    
1165
/* Retrieve GET or POST Value/State
1166
 * Example Usage:
1167
 * $value = getGETPOSTsettingvalue('get/post parameter name', "");
1168
 * $value = getGETPOSTsettingvalue('get/post parameter name', null);
1169
 * $state = getGETPOSTsettingvalue('get/post parameter name', null);
1170
 * $state = getGETPOSTsettingvalue('get/post parameter name', false);
1171
 */
1172
function getGETPOSTsettingvalue($settingname, $default) {
1173
	$settingvalue = $default;
1174
	if ($_GET[$settingname]) {
1175
		$settingvalue = $_GET[$settingname];
1176
	}
1177
	if ($_POST[$settingname]) {
1178
		$settingvalue = $_POST[$settingname];
1179
	}
1180
	return $settingvalue;
1181
}
1182

    
1183
/* set timezone */
1184
$cfgtz = config_get_path('system/timezone');
1185
if ($cfgtz) {
1186
	$timezone = $cfgtz;
1187
} elseif (isset($g['default_timezone']) && !empty(g_get('default_timezone'))) {
1188
	$timezone = g_get('default_timezone');
1189
} else {
1190
	$timezone = "Etc/UTC";
1191
}
1192

    
1193
/* Remove files we do not want to see in a crash report */
1194
function cleanup_crash_file_list() {
1195
	$files = glob("/var/crash/*");
1196
	if (!is_array($files) || empty($files)) {
1197
		return array();
1198
	}
1199

    
1200
	$exclude_patterns = array(
1201
		'.*.last',
1202
		'bounds',
1203
		'minfree'
1204
	);
1205

    
1206
	foreach ($files as $idx => $fb) {
1207
		if (preg_match('/' . implode('|', $exclude_patterns) . '/', basename($fb)) == 1) {
1208
			unset($files[$idx]);
1209
		}
1210
	}
1211

    
1212
	return $files;
1213
}
1214

    
1215
function system_has_crash_data() {
1216
	/* Test if there are any crash data files present */
1217
	return count(cleanup_crash_file_list()) > 0;
1218
}
1219

    
1220
function system_has_php_errors() {
1221
	/* Check if the PHP error log is empty. Cast to int in case the file
1222
	 * does not exist and filesize() returns false. */
1223
	return (int) @filesize("/tmp/PHP_errors.log") > 0;
1224
}
1225

    
1226
date_default_timezone_set($timezone);
1227

    
1228
?>
(66-66/228)