Project

General

Profile

Download (34.6 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-2024 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
}
60

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

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

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

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

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

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

    
84
set_language();
85

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

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

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

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

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

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

    
141
$ldap_templates = array(
142

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
424
	return $padr;
425
}
426

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

    
430
	$pport = "";
431

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

    
446
	return $pport;
447
}
448

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

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

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

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

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

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

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

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

    
587
	return $bc;
588
}
589

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

    
598
	return $divstr;
599
}
600

    
601
function set_customwidgettitle(& $user_settings) {
602
	if (!is_valid_widgetkey($_POST['widgetkey'], $user_settings)) {
603
		return false;
604
	}
605
	if ($_POST['descr']) {
606
		$user_settings['widgets'][$_POST['widgetkey']]['descr'] = trim($_POST['descr']);
607
	} else {
608
		unset($user_settings['widgets'][$_POST['widgetkey']]['descr']);
609
	}
610
}
611

    
612
/* update the changedesc and changecount(er) variables */
613
function update_changedesc($update) {
614
	global $changedesc;
615
	global $changecount;
616

    
617
	$changedesc .= " {$update}";
618
	$changecount++;
619
}
620

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

    
640
	} else {
641
		if ($orig != $new) {
642
			update_changedesc("{$varname}: \"{$orig}\" -> \"{$new}\"");
643
			$orig = $new;
644
			return true;
645
		}
646
	}
647
	return false;
648
}
649

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

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

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

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

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

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

    
753
function is_rfc2616_code($code) {
754
	global $rfc2616;
755
	if (isset($rfc2616[$code])) {
756
		return true;
757
	} else {
758
		return false;
759
	}
760
}
761

    
762
function print_rfc2616_select($tag, $current) {
763
	global $rfc2616;
764

    
765
	/* Default to 200 OK if not set */
766
	if ($current == "") {
767
		$current = 200;
768
	}
769

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

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

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

    
823
	/*	does the user have access to this tab?
824
	 *	master user has access to everything.
825
	 *	if the user does not have access, simply
826
	 *	unset the tab item.
827
	 */
828

    
829
	/* empty string code */
830
	if ($tab_array_indent == '') {
831
		$tab_array_indent = 0;
832
	}
833

    
834
	if ($tab_array_space == '') {
835
		$tab_array_space = 1;
836
	}
837

    
838
	if ($tab_array_char_limit == '') {
839
		$tab_array_char_limit = 256;
840
	}
841

    
842
	foreach ($tab_array as $tab_id => $ta) {
843
		if (!isAllowedPage($ta[2])) {
844
			unset ($tab_array[$tab_id]);
845
		}
846
	}
847

    
848
	$tabcharcount = 0;
849
	foreach ($tab_array as $ta) {
850
		$tabcharcount = $tabcharcount + strlen($ta[0]);
851
	}
852

    
853
	if ($no_drop_down == true) {
854
		$tabcharcount = 0;
855
		unset($tab_array_char_limit);
856
	}
857

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

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

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

    
888
		foreach ($tab_array as $ta) {
889
			echo '<li role="presentation"';
890
			if ($ta[1]) {
891
				echo ' class="active"';
892
			}
893

    
894
			echo '><a href="' . $ta[2] . '" ' . $usepost . '>' . $ta[0] . '</a></li>';
895
		}
896

    
897
		echo '</ul>';
898
	}
899
}
900

    
901
function add_package_tabs($tabgroup, &$tab_array) {
902
	foreach (config_get_path('installedpackages/package', []) as $pkg) {
903
		if (!is_array($pkg['tabs']['tab'])) {
904
			continue;
905
		}
906

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

    
922
function system_alias_info_popup($name, $description = null) {
923
	if (empty($name)) {
924
		return '';
925
	}
926

    
927
	$content = [];
928
	$alias = escapeshellarg($name);
929
	exec("/sbin/pfctl -t {$alias} -T show 2>/dev/null", $content);
930

    
931
	$alias_items = [];
932
	foreach ($content as $address) {
933
		$alias_items[] = htmlspecialchars(trim($address));
934
	}
935

    
936
	$content = '<h5>' . ($description ?? htmlspecialchars($name)) . '</h5>';
937
	if (empty($alias_items)) {
938
		return $content;
939
	}
940

    
941
	$content .= '<ul><li>' . implode('</li><li>', $alias_items) . '</li></ul>';
942
	return $content;
943
}
944

    
945
function alias_info_popup($alias_id, $is_system_alias = false) {
946
	global $user_settings;
947

    
948
	$alias = null;
949

    
950
	if ($is_system_alias) {
951
		// Reserved aliases take precedence.
952
		$reserved_alias = get_reserved_table_names($alias_id);
953
		if (empty($reserved_alias)) {
954
			return system_alias_info_popup($alias_id);
955
		} elseif (in_array($reserved_alias[array_key_first($reserved_alias)]['type'], ['network', 'host']) && empty($reserved_alias[array_key_first($reserved_alias)]['address'])) {
956
			return system_alias_info_popup($alias_id, $reserved_alias[array_key_first($reserved_alias)]['descr']);
957
		}
958
		$alias = $reserved_alias[array_key_first($reserved_alias)];
959
	} else {
960
		$alias = config_get_path("aliases/alias/{$alias_id}");
961
	}
962

    
963
	if (!isset($alias)) {
964
		return '';
965
	}
966

    
967
	$maxlength = 60;
968
	$content = "";
969

    
970
	if ($user_settings['webgui']['disablealiaspopupdetail']) {
971
		if (strlen($alias['descr']) >= $maxlength) {
972
			$alias['descr'] = substr($alias['descr'], 0, $maxlength) . '&hellip;';
973
		}
974

    
975
		return htmlspecialchars($alias['descr']);
976
	} else if ($alias['url']) {
977
		// TODO: Change it when pf supports tables with ports
978
		if ($alias['type'] == "urltable") {
979
			exec("/sbin/pfctl -t {$alias['name']} -T show | wc -l", $total_entries);
980
			$counter=preg_replace("/\D/", "", $total_entries[0]);
981
			exec("/sbin/pfctl -t {$alias['name']} -T show | head -10002", $alias_addresses);
982
		} else {
983
			$urlfn = alias_expand_urltable($alias['name']);
984
			$alias_addresses = empty($urlfn) ? [] : explode("\n", file_get_contents($urlfn));
985
			$counter = count($alias_addresses);
986
		}
987

    
988
		$content .= '<h5>'. htmlspecialchars($alias['url']) .'</h5><ul><li>'. implode('</li><li>', $alias_addresses) .'</li></ul>';
989
		if ($counter > 10002) {
990
			$content .= '<i>'. gettext("listing only first 10k items") .'</i>';
991
		}
992
	} else {
993
		if (empty($alias['address'])) {
994
			if (strlen($alias['descr']) >= $maxlength) {
995
				$alias['descr'] = substr($alias['descr'], 0, $maxlength) . '&hellip;';
996
			}
997
			return htmlspecialchars($alias['descr']);
998
		}
999
		$alias_addresses = explode (" ", $alias['address']);
1000
		$alias_details = explode ("||", $alias['detail']);
1001
		$idx = 0;
1002

    
1003
		$content .= "<table>\n";
1004
		$content .= "<thead>\n";
1005
		$content .= "<tr>\n";
1006
		$content .= "<th>" . gettext("Value") . "</th><th  style='padding-left: 10px;'>" . gettext("Description") . "</th></tr>\n";
1007
		$content .= "</thead>\n";
1008
		$content .= "<tbody>\n";
1009

    
1010
		foreach ($alias_addresses as $ap) {
1011
			$content .= "	<tr>\n";
1012
			$content .= "		<td>\n";
1013
			$content .= 			alias_idn_to_utf8($ap);
1014
			$content .=	"		</td>\n";
1015
			$content .= "		<td style='padding-left: 10px;'>\n";
1016
			$content .= 			htmlspecialchars($alias_details[$idx]);
1017
			$content .=	"		</td>\n";
1018
			$content .= "	</tr>\n";
1019
			$idx++;
1020
		}
1021

    
1022
		$content .= "</tbody>\n";
1023
		$content .= "</table>\n";
1024
	}
1025

    
1026
	return $content;
1027
}
1028

    
1029
function gateway_info_popup($showgw, $gateways_status = false) {
1030
	/* Get groups indexed by name so we can avoid re-scanning the array
1031
	 * multiple times later unnecessarily. */
1032
	$a_gateways = get_gateways(GW_CACHE_DISABLED | GW_CACHE_INACTIVE);
1033

    
1034
	/* Use cached gateway status if available.
1035
	 * See https://redmine.pfsense.org/issues/12174 */
1036
	if (!is_array($gateways_status)) {
1037
		$gateways_status = return_gateways_status(true);
1038
	}
1039

    
1040
	$content = "";
1041
	$gws = array();
1042
	$bgdanger = array('force_down', 'down', 'highloss', 'highdelay');
1043
	$bgwarning = array('loss', 'delay');
1044
	$bgsuccess = array('online', 'none');
1045
	$bgcolor = "bg-info";
1046
	$link = "";
1047

    
1048
	if (is_array($a_gateways)) {
1049
		/* Since gw array is hashed by name, we need to count the
1050
		 * index number manually for links since those are by position.
1051
		 */
1052
		$i = 0;
1053
		foreach ($a_gateways as $gateway) {
1054
			if ($gateway['name'] == $showgw) {
1055
				$gws[] = $gateway['name'];
1056
				$link = "/system_gateways_edit.php?id={$i}";
1057
				break;
1058
			}
1059
			$i++;
1060
		}
1061
	}
1062
	$grouptiermap = [];
1063
	foreach(config_get_path('gateways/gateway_group', []) as $i => $gwgroup) {
1064
		if ($gwgroup['name'] == $showgw) {
1065
			$groupinfo = [];
1066
			foreach ($gwgroup['item'] as $member) {
1067
				$membersplit = explode("|", $member);
1068
				$groupinfo[] = [
1069
					'gw' => $membersplit[0],
1070
					'tier' => $membersplit[1],
1071
					'type' => $membersplit[2]
1072
				];
1073
				/* Store tier separately */
1074
				$grouptiermap[$membersplit[0]] = $membersplit[1];
1075
			}
1076
			/* Sort group info array by tier (number) and then by
1077
			 * name (natural) */
1078
			$gws = array_column($groupinfo, 'gw');
1079
			$tiers = array_column($groupinfo, 'tier');
1080
			array_multisort($tiers, SORT_NUMERIC,
1081
					$gws, SORT_NATURAL,
1082
					$groupinfo);
1083
			/* Re-slice member gateways which are now sorted */
1084
			$gws = array_column($groupinfo, 'gw');
1085
			$link = "/system_gateway_groups_edit.php?id={$i}";
1086
			break;
1087
		}
1088
	}
1089

    
1090
	if (!empty($gws)) {
1091
		$content .= "<table>\n";
1092
		$content .= "<thead>\n";
1093
		$content .= "<tr>\n";
1094
		/* Only add Tier column if this is a group */
1095
		if (!empty($grouptiermap)) {
1096
			$content .= "<th>" . gettext("Tier") . "</th>";
1097
			$content .= "<th style='padding-left: 10px;'>";
1098
		} else {
1099
			$content .= "<th>";
1100
		}
1101
		$content .= gettext("Name") . "</th>";
1102
		$content .= "<th style='padding-left: 10px;'>" . gettext("Interface") . "</th>";
1103
		$content .= "<th style='padding-left: 10px;'>" . gettext("Gateway") . "</th></tr>\n";
1104
		$content .= "</thead>\n";
1105
		$content .= "<tbody>\n";
1106
		foreach ($gws as $gw) {
1107
			foreach ($gateways_status as $gwstatus) {
1108
				if ($gwstatus['name'] != $gw) {
1109
					continue;
1110
				}
1111
				/* Distinguish between online/offline in general */
1112
				if (stristr($gwstatus['status'], "online")) {
1113
					/* Use substatus to indicate warnings as needed */
1114
					if (in_array($gwstatus['substatus'], $bgdanger)) {
1115
						$bgcolor = "bg-danger";
1116
					} elseif (in_array($gwstatus['substatus'], $bgwarning)) {
1117
						$bgcolor = "bg-warning";
1118
					} elseif (in_array($gwstatus['substatus'], $bgsuccess)) {
1119
						$bgcolor = "bg-success";
1120
					}
1121
				} elseif (stristr($gwstatus['status'], "down")) {
1122
					/* Anything down is danger, no need to check substatus. */
1123
					$bgcolor = "bg-danger";
1124
				} else {
1125
					/* Unknown status */
1126
					$bgcolor = "bg-info";
1127
				}
1128
			}
1129
			$content .= "	<tr class='{$bgcolor}'>\n";
1130
			/* Only print Tier if this is a group */
1131
			if (!empty($grouptiermap)) {
1132
				$content .= "		<td>\n";
1133
				$content .= 			$grouptiermap[$gw];
1134
				$content .= "		</td>\n";
1135
			}
1136
			$content .= "		<td>\n";
1137
			$content .= 			$gw;
1138
			$content .= "		</td>\n";
1139
			$content .= "		<td style='padding-left: 10px;'>\n";
1140
			$content .= 			$a_gateways[$gw]['friendlyifdescr'];
1141
			$content .= "		</td>\n";
1142
			$content .= "		<td style='padding-left: 10px;'>\n";
1143
			$content .= 			$a_gateways[$gw]['gateway'];
1144
			$content .= "		</td>\n";
1145
			$content .= "	</tr>\n";
1146
		}
1147
		$content .= "</tbody>\n";
1148
		$content .= "</table>\n";
1149
	} else {
1150
		return;
1151
	}
1152

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

    
1156
function rule_columns_with_alias($src, $srcport, $dst, $dstport, $target="", $targetport="") {
1157
	$columns = array();
1158
	foreach (config_get_path('aliases/alias', []) as $alias_id => $alias_name) {
1159
		if ($alias_name['name'] == $src) {
1160
			$columns['src'] = $alias_id;
1161
		}
1162
		if ($alias_name['name'] == $srcport) {
1163
			$columns['srcport'] = $alias_id;
1164
		}
1165
		if ($alias_name['name'] == $dst) {
1166
			$columns['dst'] = $alias_id;
1167
		}
1168
		if ($alias_name['name'] == $dstport) {
1169
			$columns['dstport'] = $alias_id;
1170
		}
1171
		if ($alias_name['name'] == $target) {
1172
			$columns['target'] = $alias_id;
1173
		}
1174
		if ($alias_name['name'] == $targetport) {
1175
			$columns['targetport'] = $alias_id;
1176
		}
1177
	}
1178

    
1179
	return $columns;
1180
}
1181

    
1182
function form_output_row($name, $label, $content) {
1183
var_dump($content);die;
1184
?>
1185
<div class="form-group">
1186
	<label for="<?=$name?>" class="col-sm-2 control-label"><?=gettext($label); ?></label>
1187
	<div class="col-sm-10">
1188
		<?=$content?>
1189
	</div>
1190
</div>
1191
<?php
1192
}
1193

    
1194
function set_flash_message($class, $msg) {
1195
	@phpsession_begin();
1196
	$_SESSION['flash_messages'][$class][] = $msg;
1197
	@phpsession_end(true);
1198
}
1199

    
1200
function get_flash_message() {
1201
	@phpsession_begin();
1202
	if (isset($_SESSION['flash_messages']) && !empty($_SESSION['flash_messages'])) {
1203
		foreach ($_SESSION['flash_messages'] as $class => $flash_message) {
1204
			print_info_box(implode("<br />", $flash_message), $class);
1205
		}
1206
		unset($_SESSION['flash_messages']);
1207
	}
1208
	@phpsession_end(true);
1209
}
1210

    
1211
/* Retrieve GET or POST Value/State
1212
 * Example Usage:
1213
 * $value = getGETPOSTsettingvalue('get/post parameter name', "");
1214
 * $value = getGETPOSTsettingvalue('get/post parameter name', null);
1215
 * $state = getGETPOSTsettingvalue('get/post parameter name', null);
1216
 * $state = getGETPOSTsettingvalue('get/post parameter name', false);
1217
 */
1218
function getGETPOSTsettingvalue($settingname, $default) {
1219
	$settingvalue = $default;
1220
	if ($_GET[$settingname]) {
1221
		$settingvalue = $_GET[$settingname];
1222
	}
1223
	if ($_POST[$settingname]) {
1224
		$settingvalue = $_POST[$settingname];
1225
	}
1226
	return $settingvalue;
1227
}
1228

    
1229
/* set timezone */
1230
$cfgtz = config_get_path('system/timezone');
1231
if ($cfgtz) {
1232
	$timezone = $cfgtz;
1233
} elseif (isset($g['default_timezone']) && !empty(g_get('default_timezone'))) {
1234
	$timezone = g_get('default_timezone');
1235
} else {
1236
	$timezone = "Etc/UTC";
1237
}
1238

    
1239
/* Remove files we do not want to see in a crash report */
1240
function cleanup_crash_file_list() {
1241
	$files = glob("/var/crash/*");
1242
	if (!is_array($files) || empty($files)) {
1243
		return array();
1244
	}
1245

    
1246
	$exclude_patterns = array(
1247
		'.*.last',
1248
		'bounds',
1249
		'minfree'
1250
	);
1251

    
1252
	foreach ($files as $idx => $fb) {
1253
		if (preg_match('/' . implode('|', $exclude_patterns) . '/', basename($fb)) == 1) {
1254
			unset($files[$idx]);
1255
		}
1256
	}
1257

    
1258
	return $files;
1259
}
1260

    
1261
function system_has_crash_data() {
1262
	/* Test if there are any crash data files present */
1263
	return count(cleanup_crash_file_list()) > 0;
1264
}
1265

    
1266
function system_has_php_errors() {
1267
	/* Check if the PHP error log is empty. Cast to int in case the file
1268
	 * does not exist and filesize() returns false. */
1269
	return (int) @filesize("/tmp/PHP_errors.log") > 0;
1270
}
1271

    
1272
date_default_timezone_set($timezone);
1273

    
1274
?>
(68-68/232)