Project

General

Profile

Download (33.8 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
	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="' . $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-solid 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, $specialnet_flags = []) {
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
		$specialnets = get_specialnet('', $specialnet_flags);
412
		if (array_key_exists($adr['network'], $specialnets)) {
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['tagged']) {
514
		if (array_key_exists('nottagged', $item)) {
515
			$item_set .= '!';
516
		}
517
		$item_set .= "tagged " . htmlspecialchars($item['tagged']) . " ";
518
	}
519
	if ($item['tag']) {
520
		$item_set .= "tag " . htmlspecialchars($item['tag']) . " ";
521
	}
522
	if (isset($item['allowopts'])) {
523
		$item_set .= "allowopts ";
524
	}
525
	if (isset($item['disablereplyto'])) {
526
		$item_set .= "disable reply-to ";
527
	}
528
	if ($item['tcpflags_any'] || $item['tcpflags1'] || $item['tcpflags2']) {
529
		$item_set .= "tcpflags set";
530
	}
531

    
532
	return $item_set;
533
}
534

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

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

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

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

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

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

    
589
	return $bc;
590
}
591

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

    
600
	return $divstr;
601
}
602

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
921
function system_alias_info_popup($friendly_interface) {
922
	if (empty($friendly_interface)) {
923
		return '';
924
	}
925

    
926
	$content = [];
927
	$alias = escapeshellarg(strtoupper($friendly_interface) . '__NETWORK');
928
	exec("/sbin/pfctl -t {$alias} -T show 2>/dev/null", $content);
929

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

    
935
	$content = "<h5>{$alias}</h5>";
936
	if (empty($alias_items)) {
937
		return $content;
938
	}
939

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

    
944
function alias_info_popup($alias_id) {
945
	global $user_settings;
946

    
947
	$alias = config_get_path("aliases/alias/{$alias_id}");
948
	if (!is_array($alias)) {
949
		return;
950
	}
951

    
952
	$maxlength = 60;
953
	$content = "";
954

    
955
	if ($user_settings['webgui']['disablealiaspopupdetail']) {
956
		if (strlen($alias['descr']) >= $maxlength) {
957
			$alias['descr'] = substr($alias['descr'], 0, $maxlength) . '&hellip;';
958
		}
959

    
960
		$content .= $alias['descr'];
961
	} else if ($alias['url']) {
962
		// TODO: Change it when pf supports tables with ports
963
		if ($alias['type'] == "urltable") {
964
			exec("/sbin/pfctl -t {$alias['name']} -T show | wc -l", $total_entries);
965
			$counter=preg_replace("/\D/", "", $total_entries[0]);
966
			exec("/sbin/pfctl -t {$alias['name']} -T show | head -10002", $alias_addresses);
967
		} else {
968
			$urlfn = alias_expand_urltable($alias['name']);
969
			$alias_addresses = empty($urlfn) ? [] : explode("\n", file_get_contents($urlfn));
970
			$counter = count($alias_addresses);
971
		}
972

    
973
		$content .= '<h5>'. htmlspecialchars($alias['url']) .'</h5><ul><li>'. implode('</li><li>', $alias_addresses) .'</li></ul>';
974
		if ($counter > 10002) {
975
			$content .= '<i>'. gettext("listing only first 10k items") .'</i>';
976
		}
977
	} else {
978
		$alias_addresses = explode (" ", $alias['address']);
979
		$alias_details = explode ("||", $alias['detail']);
980
		$idx = 0;
981

    
982
		$content .= "<table>\n";
983
		$content .= "<thead>\n";
984
		$content .= "<tr>\n";
985
		$content .= "<th>" . gettext("Value") . "</th><th  style='padding-left: 10px;'>" . gettext("Description") . "</th></tr>\n";
986
		$content .= "</thead>\n";
987
		$content .= "<tbody>\n";
988

    
989
		foreach ($alias_addresses as $ap) {
990
			$content .= "	<tr>\n";
991
			$content .= "		<td>\n";
992
			$content .= 			alias_idn_to_utf8($ap);
993
			$content .=	"		</td>\n";
994
			$content .= "		<td style='padding-left: 10px;'>\n";
995
			$content .= 			htmlspecialchars($alias_details[$idx]);
996
			$content .=	"		</td>\n";
997
			$content .= "	</tr>\n";
998
			$idx++;
999
		}
1000

    
1001
		$content .= "</tbody>\n";
1002
		$content .= "</table>\n";
1003
	}
1004

    
1005
	return $content;
1006
}
1007

    
1008
function gateway_info_popup($showgw, $gateways_status = false) {
1009
	config_init_path('gateways/gateway_group');
1010
	/* Get groups indexed by name so we can avoid re-scanning the array
1011
	 * multiple times later unnecessarily. */
1012
	$a_gateways = get_gateways(GW_CACHE_DISABLED | GW_CACHE_INACTIVE);
1013

    
1014
	/* Use cached gateway status if available.
1015
	 * See https://redmine.pfsense.org/issues/12174 */
1016
	if (!is_array($gateways_status)) {
1017
		$gateways_status = return_gateways_status(true);
1018
	}
1019

    
1020
	$content = "";
1021
	$gws = array();
1022
	$bgdanger = array('force_down', 'down', 'highloss', 'highdelay');
1023
	$bgwarning = array('loss', 'delay');
1024
	$bgsuccess = array('online', 'none');
1025
	$bgcolor = "bg-info";
1026
	$link = "";
1027

    
1028
	if (is_array($a_gateways)) {
1029
		/* Since gw array is hashed by name, we need to count the
1030
		 * index number manually for links since those are by position.
1031
		 */
1032
		$i = 0;
1033
		foreach ($a_gateways as $gateway) {
1034
			if ($gateway['name'] == $showgw) {
1035
				$gws[] = $gateway['name'];
1036
				$link = "/system_gateways_edit.php?id={$i}";
1037
				break;
1038
			}
1039
			$i++;
1040
		}
1041
	}
1042
	$grouptiermap = [];
1043
	foreach(config_get_path('gateways/gateway_group', []) as $i => $gwgroup) {
1044
		if ($gwgroup['name'] == $showgw) {
1045
			$groupinfo = [];
1046
			foreach ($gwgroup['item'] as $member) {
1047
				$membersplit = explode("|", $member);
1048
				$groupinfo[] = [
1049
					'gw' => $membersplit[0],
1050
					'tier' => $membersplit[1],
1051
					'type' => $membersplit[2]
1052
				];
1053
				/* Store tier separately */
1054
				$grouptiermap[$membersplit[0]] = $membersplit[1];
1055
			}
1056
			/* Sort group info array by tier (number) and then by
1057
			 * name (natural) */
1058
			$gws = array_column($groupinfo, 'gw');
1059
			$tiers = array_column($groupinfo, 'tier');
1060
			array_multisort($tiers, SORT_NUMERIC,
1061
					$gws, SORT_NATURAL,
1062
					$groupinfo);
1063
			/* Re-slice member gateways which are now sorted */
1064
			$gws = array_column($groupinfo, 'gw');
1065
			$link = "/system_gateway_groups_edit.php?id={$i}";
1066
			break;
1067
		}
1068
	}
1069

    
1070
	if (!empty($gws)) {
1071
		$content .= "<table>\n";
1072
		$content .= "<thead>\n";
1073
		$content .= "<tr>\n";
1074
		/* Only add Tier column if this is a group */
1075
		if (!empty($grouptiermap)) {
1076
			$content .= "<th>" . gettext("Tier") . "</th>";
1077
			$content .= "<th style='padding-left: 10px;'>";
1078
		} else {
1079
			$content .= "<th>";
1080
		}
1081
		$content .= gettext("Name") . "</th>";
1082
		$content .= "<th style='padding-left: 10px;'>" . gettext("Interface") . "</th>";
1083
		$content .= "<th style='padding-left: 10px;'>" . gettext("Gateway") . "</th></tr>\n";
1084
		$content .= "</thead>\n";
1085
		$content .= "<tbody>\n";
1086
		foreach ($gws as $gw) {
1087
			foreach ($gateways_status as $gwstatus) {
1088
				if ($gwstatus['name'] != $gw) {
1089
					continue;
1090
				}
1091
				/* Distinguish between online/offline in general */
1092
				if (stristr($gwstatus['status'], "online")) {
1093
					/* Use substatus to indicate warnings as needed */
1094
					if (in_array($gwstatus['substatus'], $bgdanger)) {
1095
						$bgcolor = "bg-danger";
1096
					} elseif (in_array($gwstatus['substatus'], $bgwarning)) {
1097
						$bgcolor = "bg-warning";
1098
					} elseif (in_array($gwstatus['substatus'], $bgsuccess)) {
1099
						$bgcolor = "bg-success";
1100
					}
1101
				} elseif (stristr($gwstatus['status'], "down")) {
1102
					/* Anything down is danger, no need to check substatus. */
1103
					$bgcolor = "bg-danger";
1104
				} else {
1105
					/* Unknown status */
1106
					$bgcolor = "bg-info";
1107
				}
1108
			}
1109
			$content .= "	<tr class='{$bgcolor}'>\n";
1110
			/* Only print Tier if this is a group */
1111
			if (!empty($grouptiermap)) {
1112
				$content .= "		<td>\n";
1113
				$content .= 			$grouptiermap[$gw];
1114
				$content .= "		</td>\n";
1115
			}
1116
			$content .= "		<td>\n";
1117
			$content .= 			$gw;
1118
			$content .= "		</td>\n";
1119
			$content .= "		<td style='padding-left: 10px;'>\n";
1120
			$content .= 			$a_gateways[$gw]['friendlyifdescr'];
1121
			$content .= "		</td>\n";
1122
			$content .= "		<td style='padding-left: 10px;'>\n";
1123
			$content .= 			$a_gateways[$gw]['gateway'];
1124
			$content .= "		</td>\n";
1125
			$content .= "	</tr>\n";
1126
		}
1127
		$content .= "</tbody>\n";
1128
		$content .= "</table>\n";
1129
	} else {
1130
		return;
1131
	}
1132

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

    
1136
function rule_columns_with_alias($src, $srcport, $dst, $dstport, $target="", $targetport="") {
1137
	$columns = array();
1138
	foreach (config_get_path('aliases/alias', []) as $alias_id => $alias_name) {
1139
		if ($alias_name['name'] == $src) {
1140
			$columns['src'] = $alias_id;
1141
		}
1142
		if ($alias_name['name'] == $srcport) {
1143
			$columns['srcport'] = $alias_id;
1144
		}
1145
		if ($alias_name['name'] == $dst) {
1146
			$columns['dst'] = $alias_id;
1147
		}
1148
		if ($alias_name['name'] == $dstport) {
1149
			$columns['dstport'] = $alias_id;
1150
		}
1151
		if ($alias_name['name'] == $target) {
1152
			$columns['target'] = $alias_id;
1153
		}
1154
		if ($alias_name['name'] == $targetport) {
1155
			$columns['targetport'] = $alias_id;
1156
		}
1157
	}
1158

    
1159
	return $columns;
1160
}
1161

    
1162
function form_output_row($name, $label, $content) {
1163
var_dump($content);die;
1164
?>
1165
<div class="form-group">
1166
	<label for="<?=$name?>" class="col-sm-2 control-label"><?=gettext($label); ?></label>
1167
	<div class="col-sm-10">
1168
		<?=$content?>
1169
	</div>
1170
</div>
1171
<?php
1172
}
1173

    
1174
function set_flash_message($class, $msg) {
1175
	@phpsession_begin();
1176
	$_SESSION['flash_messages'][$class][] = $msg;
1177
	@phpsession_end(true);
1178
}
1179

    
1180
function get_flash_message() {
1181
	@phpsession_begin();
1182
	if (isset($_SESSION['flash_messages']) && !empty($_SESSION['flash_messages'])) {
1183
		foreach ($_SESSION['flash_messages'] as $class => $flash_message) {
1184
			print_info_box(implode("<br />", $flash_message), $class);
1185
		}
1186
		unset($_SESSION['flash_messages']);
1187
	}
1188
	@phpsession_end(true);
1189
}
1190

    
1191
/* Retrieve GET or POST Value/State
1192
 * Example Usage:
1193
 * $value = getGETPOSTsettingvalue('get/post parameter name', "");
1194
 * $value = getGETPOSTsettingvalue('get/post parameter name', null);
1195
 * $state = getGETPOSTsettingvalue('get/post parameter name', null);
1196
 * $state = getGETPOSTsettingvalue('get/post parameter name', false);
1197
 */
1198
function getGETPOSTsettingvalue($settingname, $default) {
1199
	$settingvalue = $default;
1200
	if ($_GET[$settingname]) {
1201
		$settingvalue = $_GET[$settingname];
1202
	}
1203
	if ($_POST[$settingname]) {
1204
		$settingvalue = $_POST[$settingname];
1205
	}
1206
	return $settingvalue;
1207
}
1208

    
1209
/* set timezone */
1210
$cfgtz = config_get_path('system/timezone');
1211
if ($cfgtz) {
1212
	$timezone = $cfgtz;
1213
} elseif (isset($g['default_timezone']) && !empty(g_get('default_timezone'))) {
1214
	$timezone = g_get('default_timezone');
1215
} else {
1216
	$timezone = "Etc/UTC";
1217
}
1218

    
1219
/* Remove files we do not want to see in a crash report */
1220
function cleanup_crash_file_list() {
1221
	$files = glob("/var/crash/*");
1222
	if (!is_array($files) || empty($files)) {
1223
		return array();
1224
	}
1225

    
1226
	$exclude_patterns = array(
1227
		'.*.last',
1228
		'bounds',
1229
		'minfree'
1230
	);
1231

    
1232
	foreach ($files as $idx => $fb) {
1233
		if (preg_match('/' . implode('|', $exclude_patterns) . '/', basename($fb)) == 1) {
1234
			unset($files[$idx]);
1235
		}
1236
	}
1237

    
1238
	return $files;
1239
}
1240

    
1241
function system_has_crash_data() {
1242
	/* Test if there are any crash data files present */
1243
	return count(cleanup_crash_file_list()) > 0;
1244
}
1245

    
1246
function system_has_php_errors() {
1247
	/* Check if the PHP error log is empty. Cast to int in case the file
1248
	 * does not exist and filesize() returns false. */
1249
	return (int) @filesize("/tmp/PHP_errors.log") > 0;
1250
}
1251

    
1252
date_default_timezone_set($timezone);
1253

    
1254
?>
(68-68/232)