Project

General

Profile

Download (38 KB) Statistics
| Branch: | Tag: | Revision:
1
<?php 
2
/*
3
	util.inc
4
	part of the pfSense project (http://www.pfsense.com)
5

    
6
	originally part of m0n0wall (http://m0n0.ch/wall)
7
	Copyright (C) 2003-2004 Manuel Kasper <mk@neon1.net>.
8
	All rights reserved.
9

    
10
	Redistribution and use in source and binary forms, with or without
11
	modification, are permitted provided that the following conditions are met:
12

    
13
	1. Redistributions of source code must retain the above copyright notice,
14
	   this list of conditions and the following disclaimer.
15

    
16
	2. Redistributions in binary form must reproduce the above copyright
17
	   notice, this list of conditions and the following disclaimer in the
18
	   documentation and/or other materials provided with the distribution.
19

    
20
	THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
21
	INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
22
	AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
23
	AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
24
	OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25
	SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26
	INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27
	CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28
	ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29
	POSSIBILITY OF SUCH DAMAGE.
30
*/
31

    
32
/*
33
	pfSense_BUILDER_BINARIES:	/bin/ps	/bin/kill	/usr/bin/killall	/sbin/ifconfig	/usr/bin/netstat
34
	pfSense_BUILDER_BINARIES:	/usr/bin/awk	/sbin/dmesg		/sbin/ping /usr/local/sbin/gzsig	/usr/sbin/arp
35
	pfSense_BUILDER_BINARIES:	/sbin/conscontrol	/sbin/devd	/bin/ps
36
	pfSense_MODULE:	utils
37
*/
38

    
39
/* kill a process by pid file */
40
function killbypid($pidfile) {
41
	return sigkillbypid($pidfile, "TERM");
42
}
43

    
44
function isvalidpid($pid) {
45
	$output = "";
46
	exec("/bin/pgrep -F {$pid}", $output, $retval);
47

    
48
	return (intval($retval) == 0);
49
}
50

    
51
function is_process_running($process) {
52
	$output = "";
53
	exec("/bin/pgrep -ax {$process}", $output, $retval);
54

    
55
	return (intval($retval) == 0);
56
}
57

    
58
function isvalidproc($proc) {
59
	return is_process_running($proc);
60
}
61

    
62
/* sigkill a process by pid file */
63
/* return 1 for success and 0 for a failure */
64
function sigkillbypid($pidfile, $sig) {
65
	if (is_file($pidfile))
66
		return mwexec("/bin/pkill -{$sig} -F {$pidfile}", true);
67

    
68
	return 0;
69
}
70

    
71
/* kill a process by name */
72
function sigkillbyname($procname, $sig) {
73
	if(isvalidproc($procname))
74
		return mwexec("/usr/bin/killall -{$sig} " . escapeshellarg($procname), true);
75
}
76

    
77
/* kill a process by name */
78
function killbyname($procname) {
79
	if(isvalidproc($procname)) 
80
		mwexec("/usr/bin/killall " . escapeshellarg($procname));
81
}
82

    
83
function is_subsystem_dirty($subsystem = "") {
84
	global $g;
85

    
86
	if ($subsystem == "")
87
		return false;
88

    
89
	if (file_exists("{$g['varrun_path']}/{$subsystem}.dirty"))
90
		return true;
91

    
92
	return false;
93
}
94

    
95
function mark_subsystem_dirty($subsystem = "") {
96
	global $g;
97

    
98
	if (!file_put_contents("{$g['varrun_path']}/{$subsystem}.dirty", "DIRTY"))
99
		log_error("WARNING: Could not mark subsystem: {$subsytem} dirty");
100
}
101

    
102
function clear_subsystem_dirty($subsystem = "") {
103
	global $g;
104

    
105
	@unlink("{$g['varrun_path']}/{$subsystem}.dirty");
106
}
107

    
108
function config_lock() {
109
	return;
110
}
111
function config_unlock() {
112
	return;
113
}
114

    
115
/* lock configuration file */
116
function lock($lock, $op = LOCK_SH) {
117
	global $g, $cfglckkeyconsumers;
118
	if (!$lock)
119
		die("WARNING: You must give a name as parameter to lock() function.");
120
	if (!file_exists("{$g['tmp_path']}/{$lock}.lock"))
121
		@touch("{$g['tmp_path']}/{$lock}.lock");
122
	$cfglckkeyconsumers++;
123
	if ($fp = fopen("{$g['tmp_path']}/{$lock}.lock", "w")) {
124
		if (flock($fp, $op))
125
			return $fp;
126
		else
127
			fclose($fp);
128
	}
129
}
130

    
131
/* unlock configuration file */
132
function unlock($cfglckkey = 0) {
133
	global $g, $cfglckkeyconsumers;
134
	flock($cfglckkey, LOCK_UN);
135
	fclose($cfglckkey);
136
	return;
137
}
138

    
139
function send_event($cmd) {
140
	global $g;
141

    
142
	if(!isset($g['event_address']))
143
		$g['event_address'] = "unix:///var/run/check_reload_status";
144
		
145
	$try = 0;
146
	while ($try < 3) {
147
		$fd = @fsockopen($g['event_address']);
148
		if ($fd) {
149
			fwrite($fd, $cmd);
150
			$resp = fread($fd, 4096);
151
			if ($resp != "OK\n")
152
				log_error("send_event: sent {$cmd} got {$resp}");
153
			fclose($fd);
154
			$try = 3;
155
		} else
156
			mwexec_bg("/usr/bin/nice -n20 /usr/local/sbin/check_reload_status");
157
		$try++;
158
	}
159
}
160

    
161
function send_multiple_events($cmds) {
162
	global $g;
163

    
164
	if(!isset($g['event_address']))
165
		$g['event_address'] = "unix:///var/run/check_reload_status";
166
			
167
	if (!is_array($cmds))
168
		return;
169
	$fd = fsockopen($g['event_address']);
170
	if ($fd) {
171
		foreach ($cmds as $cmd) {
172
			fwrite($fd, $cmd);
173
			$resp = fread($fd, 4096);
174
			if ($resp != "OK\n")
175
				log_error("send_event: sent {$cmd} got {$resp}");
176
		}
177
		fclose($fd);
178
	}
179
}
180

    
181
function refcount_init($reference) {
182
	$shmid = @shmop_open($reference, "c", 0644, 10);
183
	@shmop_write($shmid, 0, 0);
184
	@shmop_close($shmid);
185
}
186

    
187
function refcount_reference($reference) {
188
	try {
189
		$shmid = @shmop_open($reference, "w", 0, 0);
190
		if (!$shmid) {
191
			refcount_init($reference);
192
			$shmid = @shmop_open($reference, "w", 0, 0);
193
		}
194
		$shm_data = @shmop_read($shmid, 0, 10);
195
		if (intval($shm_data) < 0)
196
			$shm_data = 0;
197
		$shm_data = intval($shm_data) + 1;
198
		@shmop_write($shmid, $shm_data, 0);
199
		@shmop_close($shmid);
200
	} catch (Exception $e) {
201
		log_error($e->getMessage());
202
	}
203
		
204
	return $shm_data;
205
}
206

    
207
function refcount_unreference($reference) {
208
	try {
209
		/* We assume that the shared memory exists. */
210
		$shmid = @shmop_open($reference, "w", 0, 0);
211
		$shm_data = @shmop_read($shmid, 0, 10);
212
		$shm_data = intval($shm_data) - 1;
213
		if ($shm_data < 0) {
214
			//log_error("MISUAGE OF REFCOUNT_API: trace " . print_r(debug_backtrace(), true));
215
			log_error("Reference {$reference} is going negative, not doing unreference.");
216
		} else
217
			@shmop_write($shmid, $shm_data, 0);
218
		@shmop_close($shmid);
219
	} catch (Exception $e) {
220
		log_error($e->getMessage());
221
	}
222
	
223
	return $shm_data;
224
}
225

    
226
function is_module_loaded($module_name) {
227
	$running = `/sbin/kldstat | grep {$module_name} | /usr/bin/grep -v grep | /usr/bin/wc -l`;
228
	if (intval($running) >= 1)
229
		return true;
230
	else
231
		return false;
232
}
233

    
234
/* return the subnet address given a host address and a subnet bit count */
235
function gen_subnet($ipaddr, $bits) {
236
	if (!is_ipaddr($ipaddr) || !is_numeric($bits))
237
		return "";
238

    
239
	return long2ip(ip2long($ipaddr) & gen_subnet_mask_long($bits));
240
}
241

    
242
/* return the highest (broadcast) address in the subnet given a host address and a subnet bit count */
243
function gen_subnet_max($ipaddr, $bits) {
244
	if (!is_ipaddr($ipaddr) || !is_numeric($bits))
245
		return "";
246

    
247
	return long2ip32(ip2long($ipaddr) | ~gen_subnet_mask_long($bits));
248
}
249

    
250
/* returns a subnet mask (long given a bit count) */
251
function gen_subnet_mask_long($bits) {
252
	$sm = 0;
253
	for ($i = 0; $i < $bits; $i++) {
254
		$sm >>= 1;
255
		$sm |= 0x80000000;
256
	}
257
	return $sm;
258
}
259

    
260
/* same as above but returns a string */
261
function gen_subnet_mask($bits) {
262
	return long2ip(gen_subnet_mask_long($bits));
263
}
264

    
265
/* Convert long int to IP address, truncating to 32-bits. */
266
function long2ip32($ip) {
267
	return long2ip($ip & 0xFFFFFFFF);
268
}
269

    
270
/* Convert IP address to long int, truncated to 32-bits to avoid sign extension on 64-bit platforms. */
271
function ip2long32($ip) {
272
	return ( ip2long($ip) & 0xFFFFFFFF );
273
}
274

    
275
/* Convert IP address to unsigned long int. */
276
function ip2ulong($ip) {
277
	return sprintf("%u", ip2long32($ip));
278
}
279

    
280
/* Find out how many IPs are contained within a given IP range
281
 *  e.g. 192.168.0.0 to 192.168.0.255 returns 256
282
 */
283
function ip_range_size($startip, $endip) {
284
	if (is_ipaddr($startip) && is_ipaddr($endip)) {
285
		// Operate as unsigned long because otherwise it wouldn't work
286
		//   when crossing over from 127.255.255.255 / 128.0.0.0 barrier
287
		return abs(ip2ulong($startip) - ip2ulong($endip)) + 1;
288
	}
289
	return -1;
290
}
291

    
292
/* Find the smallest possible subnet mask which can contain a given number of IPs
293
 *  e.g. 512 IPs can fit in a /23, but 513 IPs need a /22
294
 */
295
function find_smallest_cidr($number) {
296
	$smallest = 1;
297
	for ($b=32; $b > 0; $b--) {
298
		$smallest = ($number <= pow(2,$b)) ? $b : $smallest;
299
	}
300
	return (32-$smallest);
301
}
302

    
303
/* Return the previous IP address before the given address */
304
function ip_before($ip) {
305
	return long2ip32(ip2long($ip)-1);
306
}
307

    
308
/* Return the next IP address after the given address */
309
function ip_after($ip) {
310
	return long2ip32(ip2long($ip)+1);
311
}
312

    
313
/* Return true if the first IP is 'before' the second */
314
function ip_less_than($ip1, $ip2) {
315
	// Compare as unsigned long because otherwise it wouldn't work when
316
	//   crossing over from 127.255.255.255 / 128.0.0.0 barrier
317
	return ip2ulong($ip1) < ip2ulong($ip2);
318
}
319

    
320
/* Return true if the first IP is 'after' the second */
321
function ip_greater_than($ip1, $ip2) {
322
	// Compare as unsigned long because otherwise it wouldn't work
323
	//   when crossing over from 127.255.255.255 / 128.0.0.0 barrier
324
	return ip2ulong($ip1) > ip2ulong($ip2);
325
}
326

    
327
/* Convert a range of IPs to an array of subnets which can contain the range. */
328
function ip_range_to_subnet_array($startip, $endip) {
329
	if (!is_ipaddr($startip) || !is_ipaddr($endip)) {
330
		return array();
331
	}
332

    
333
	// Container for subnets within this range.
334
	$rangesubnets = array();
335

    
336
	// Figure out what the smallest subnet is that holds the number of IPs in the given range.
337
	$cidr = find_smallest_cidr(ip_range_size($startip, $endip));
338

    
339
	// Loop here to reduce subnet size and retest as needed. We need to make sure
340
	//   that the target subnet is wholly contained between $startip and $endip.
341
	for ($cidr; $cidr <= 32; $cidr++) {
342
		// Find the network and broadcast addresses for the subnet being tested.
343
		$targetsub_min = gen_subnet($startip, $cidr);
344
		$targetsub_max = gen_subnet_max($startip, $cidr);
345

    
346
		// Check best case where the range is exactly one subnet.
347
		if (($targetsub_min == $startip) && ($targetsub_max == $endip)) {
348
			// Hooray, the range is exactly this subnet!
349
			return array("{$startip}/{$cidr}");
350
		}
351

    
352
		// These remaining scenarios will find a subnet that uses the largest
353
		//  chunk possible of the range being tested, and leave the rest to be
354
		//  tested recursively after the loop.
355

    
356
		// Check if the subnet begins with $startip and ends before $endip
357
		if (($targetsub_min == $startip) && ip_less_than($targetsub_max, $endip)) {
358
			break;
359
		}
360

    
361
		// Check if the subnet ends at $endip and starts after $startip
362
		if (ip_greater_than($targetsub_min, $startip) && ($targetsub_max == $endip)) {
363
			break;
364
		}
365

    
366
		// Check if the subnet is between $startip and $endip
367
		if (ip_greater_than($targetsub_min, $startip) && ip_less_than($targetsub_max, $endip)) {
368
			break;
369
		}
370
	}
371

    
372
	// Some logic that will recursivly search from $startip to the first IP before the start of the subnet we just found.
373
	// NOTE: This may never be hit, the way the above algo turned out, but is left for completeness.
374
	if ($startip != $targetsub_min) {
375
		$rangesubnets = array_merge($rangesubnets, ip_range_to_subnet_array($startip, ip_before($targetsub_min)));
376
	}
377

    
378
	// Add in the subnet we found before, to preserve ordering
379
	$rangesubnets[] = "{$targetsub_min}/{$cidr}";
380

    
381
	// And some more logic that will search after the subnet we found to fill in to the end of the range.
382
	if ($endip != $targetsub_max) {
383
		$rangesubnets = array_merge($rangesubnets, ip_range_to_subnet_array(ip_after($targetsub_max), $endip));
384
	}
385
	return $rangesubnets;
386
}
387

    
388
function is_iprange($range) {
389
	if (substr_count($range, '-') != 1) {
390
		return false;
391
	}
392
	list($ip1, $ip2) = explode ('-', $range);
393
	return (is_ipaddr($ip1) && is_ipaddr($ip2));
394
}
395

    
396
function is_numericint($arg) {
397
	return (preg_match("/[^0-9]/", $arg) ? false : true);
398
}
399

    
400
/* returns true if $ipaddr is a valid dotted IPv4 address */
401
function is_ipaddr($ipaddr) {
402
	if (!is_string($ipaddr))
403
		return false;
404

    
405
	$ip_long = ip2long($ipaddr);
406
	$ip_reverse = long2ip32($ip_long);
407

    
408
	if ($ipaddr == $ip_reverse)
409
		return true;
410
	else
411
		return false;
412
}
413

    
414
/* returns true if $ipaddr is a valid dotted IPv4 address or an alias thereof */
415
function is_ipaddroralias($ipaddr) {
416
	global $config;
417

    
418
	if (is_alias($ipaddr)) {
419
		if (is_array($config['aliases']['alias'])) {
420
			foreach ($config['aliases']['alias'] as $alias) {
421
				if ($alias['name'] == $ipaddr && $alias['type'] != "port")
422
					return true;
423
			}
424
		}
425
		return false;
426
	} else
427
		return is_ipaddr($ipaddr);
428

    
429
}
430

    
431
/* returns true if $subnet is a valid subnet in CIDR format */
432
function is_subnet($subnet) {
433
	if (!is_string($subnet))
434
		return false;
435

    
436
	list($hp,$np) = explode('/', $subnet);
437

    
438
	if (!is_ipaddr($hp))
439
		return false;
440

    
441
	if (!is_numeric($np) || ($np < 1) || ($np > 32))
442
		return false;
443

    
444
	return true;
445
}
446

    
447
/* returns true if $subnet is a valid subnet in CIDR format or an alias thereof */
448
function is_subnetoralias($subnet) {
449
	global $aliastable;
450

    
451
	if (isset($aliastable[$subnet]) && is_subnet($aliastable[$subnet]))
452
		return true;
453
	else
454
		return is_subnet($subnet);
455
}
456

    
457
/* returns true if $hostname is a valid hostname */
458
function is_hostname($hostname) {
459
	if (!is_string($hostname))
460
		return false;
461

    
462
	if (preg_match('/^(?:(?:[a-z0-9_]|[a-z0-9_][a-z0-9_\-]*[a-z0-9_])\.)*(?:[a-z0-9_]|[a-z0-9_][a-z0-9_\-]*[a-z0-9_])$/i', $hostname))
463
		return true;
464
	else
465
		return false;
466
}
467

    
468
/* returns true if $domain is a valid domain name */
469
function is_domain($domain) {
470
	if (!is_string($domain))
471
		return false;
472

    
473
	if (preg_match('/^(?:(?:[a-z0-9]|[a-z0-9][a-z0-9\-]*[a-z0-9])\.)*(?:[a-z0-9]|[a-z0-9][a-z0-9\-]*[a-z0-9])$/i', $domain))
474
		return true;
475
	else
476
		return false;
477
}
478

    
479
/* returns true if $macaddr is a valid MAC address */
480
function is_macaddr($macaddr) {
481
	return preg_match('/^[0-9A-F]{2}(?:[:][0-9A-F]{2}){5}$/i', $macaddr) == 1 ? true : false;
482
}
483

    
484
/* returns true if $name is a valid name for an alias */
485
/* returns NULL if a reserved word is used */
486
function is_validaliasname($name) {
487
	/* Array of reserved words */
488
	$reserved = array("port", "pass");
489
	if (in_array($name, $reserved, true))
490
		return; /* return NULL */
491
	if (!preg_match("/[^a-zA-Z0-9_]/", $name) && (strlen($name) < 32))
492
		return true;
493
	else
494
		return false;
495
}
496

    
497
/* returns true if $port is a valid TCP/UDP port */
498
function is_port($port) {
499
	$tmpports = explode(":", $port);
500
	foreach($tmpports as $tmpport) {
501
		if (getservbyname($tmpport, "tcp") || getservbyname($tmpport, "udp"))
502
			continue;
503
		if (!ctype_digit($tmpport))
504
			return false;
505
		else if ((intval($tmpport) < 1) || (intval($tmpport) > 65535))
506
			return false;
507
	}
508
	return true;
509
}
510

    
511
/* returns true if $portrange is a valid TCP/UDP portrange ("<port>:<port>") */
512
function is_portrange($portrange) {
513
	$ports = explode(":", $portrange);
514

    
515
	if(count($ports) == 2 && is_port($ports[0]) && is_port($ports[1]))
516
		return true;
517
	else
518
		return false;
519
}
520

    
521
/* returns true if $port is a valid port number or an alias thereof */
522
function is_portoralias($port) {
523
	global $config;
524

    
525
	if (is_alias($port)) {
526
		if (is_array($config['aliases']['alias'])) {
527
			foreach ($config['aliases']['alias'] as $alias) {
528
				if ($alias['name'] == $port && $alias['type'] == "port")
529
					return true;
530
				}
531
			}
532
			return false;
533
	} else
534
		return is_port($port);
535
}
536

    
537
/* returns true if $val is a valid shaper bandwidth value */
538
function is_valid_shaperbw($val) {
539
	return (preg_match("/^(\d+(?:\.\d+)?)([MKG]?b|%)$/", $val));
540
}
541

    
542
/* return the configured carp interface list */
543
function get_configured_carp_interface_list() {
544
	global $config;
545

    
546
	$iflist = array();
547

    
548
	if(is_array($config['virtualip']['vip'])) {
549
		$viparr = &$config['virtualip']['vip'];
550
		foreach ($viparr as $vip) {
551
			switch ($vip['mode']) {
552
				case "carp":
553
				case "carpdev-dhcp":
554
					$vipif = "vip" . $vip['vhid'];
555
					$iflist[$vipif] = $vip['subnet'];
556
					break;
557
			}
558
		}
559
	}
560

    
561
	return $iflist;
562
}
563

    
564
/* return the configured IP aliases list */
565
function get_configured_ip_aliases_list() {
566
	global $config;
567

    
568
	$alias_list=array();
569

    
570
	if(is_array($config['virtualip']['vip'])) {
571
		$viparr = &$config['virtualip']['vip'];
572
		foreach ($viparr as $vip) {
573
			if ($vip['mode']=="ipalias") {
574
				$alias_list[$vip['subnet']] = $vip['interface'];
575
			}
576
		}
577
	}
578

    
579
	return $alias_list;
580
}
581

    
582

    
583
/* comparison function for sorting by the order in which interfaces are normally created */
584
function compare_interface_friendly_names($a, $b) {
585
	if ($a == $b)
586
		return 0;
587
	else if ($a == 'wan')
588
		return -1;
589
	else if ($b == 'wan')
590
		return 1;
591
	else if ($a == 'lan')
592
		return -1;
593
	else if ($b == 'lan')
594
		return 1;
595

    
596
	return strnatcmp($a, $b);
597
}
598

    
599
/* return the configured interfaces list. */
600
function get_configured_interface_list($only_opt = false, $withdisabled = false) {
601
	global $config;
602

    
603
	$iflist = array();
604

    
605
	if(!is_array($config['interfaces']))
606
		$config = parse_config(true);
607

    
608
	/* if list */
609
	foreach($config['interfaces'] as $if => $ifdetail) {
610
		if ($only_opt && ($if == "wan" || $if == "lan"))
611
			continue;
612
		if (isset($ifdetail['enable']) || $withdisabled == true)
613
			$iflist[$if] = $if;
614
	}
615

    
616
	return $iflist;
617
}
618

    
619
/* return the configured interfaces list. */
620
function get_configured_interface_list_by_realif($only_opt = false, $withdisabled = false) {
621
	global $config;
622

    
623
	$iflist = array();
624

    
625
	/* if list */
626
	foreach($config['interfaces'] as $if => $ifdetail) {
627
		if ($only_opt && ($if == "wan" || $if == "lan"))
628
			continue;
629
		if (isset($ifdetail['enable']) || $withdisabled == true) {
630
			$tmpif = get_real_interface($if);
631
			if (!empty($tmpif))
632
				$iflist[$tmpif] = $if;
633
		}
634
	}
635

    
636
	return $iflist;
637
}
638

    
639
/* return the configured interfaces list with their description. */
640
function get_configured_interface_with_descr($only_opt = false, $withdisabled = false) {
641
	global $config;
642

    
643
	$iflist = array();
644

    
645
	/* if list */
646
	foreach($config['interfaces'] as $if => $ifdetail) {
647
		if ($only_opt && ($if == "wan" || $if == "lan"))
648
			continue;
649
		if (isset($ifdetail['enable']) || $withdisabled == true) {
650
			if(empty($ifdetail['descr']))
651
				$iflist[$if] = strtoupper($if);
652
			else
653
				$iflist[$if] = strtoupper($ifdetail['descr']);
654
		}
655
	}
656

    
657
	return $iflist;
658
}
659

    
660
/*
661
 *   get_configured_ip_addresses() - Return a list of all configured
662
 *   interfaces IP Addresses
663
 *
664
 */
665
function get_configured_ip_addresses() {
666
	require_once("interfaces.inc");
667
	$ip_array = array();
668
	$interfaces = get_configured_interface_list();
669
	if(is_array($interfaces)) {
670
		foreach($interfaces as $int) {
671
			$ipaddr = get_interface_ip($int);
672
			$ip_array[$int] = $ipaddr;
673
		}
674
	}
675
	$interfaces = get_configured_carp_interface_list();
676
	if(is_array($interfaces)) 
677
		foreach($interfaces as $int => $ipaddr) 
678
			$ip_array[$int] = $ipaddr;
679
	return $ip_array;
680
}
681

    
682
/*
683
 *   get_interface_list() - Return a list of all physical interfaces
684
 *   along with MAC and status.
685
 *
686
 *   $mode = "active" - use ifconfig -lu
687
 *           "media"  - use ifconfig to check physical connection
688
 *			status (much slower)
689
 */
690
function get_interface_list($mode = "active", $keyby = "physical", $vfaces = "") {
691
        global $config;
692
	$upints = array();
693
        /* get a list of virtual interface types */
694
        if(!$vfaces) {
695
		$vfaces = array (
696
				'bridge',
697
				'ppp',
698
				'pppoe',
699
				'pptp',
700
				'l2tp',
701
				'sl',
702
				'gif',
703
				'gre',
704
				'faith',
705
				'lo',
706
				'ng',
707
				'_vlan',
708
				'_wlan',
709
				'pflog',
710
				'plip',
711
				'pfsync',
712
				'enc',
713
				'tun',
714
				'carp',
715
				'lagg',
716
				'vip',
717
				'ipfw'
718
		);
719
	}
720
	switch($mode) {
721
	case "active":
722
                $upints = explode(" ", trim(shell_exec("/sbin/ifconfig -lu")));
723
        	break;
724
	case "media":
725
                $intlist = explode(" ", trim(shell_exec("/sbin/ifconfig -l")));
726
                $ifconfig = "";
727
                exec("/sbin/ifconfig -a", $ifconfig);
728
                $regexp = '/(' . implode('|', $intlist) . '):\s/';
729
                $ifstatus = preg_grep('/status:/', $ifconfig);
730
		foreach($ifstatus as $status) {
731
			$int = array_shift($intlist);
732
			if(stristr($status, "active")) $upints[] = $int;
733
		}
734
		break;
735
	default:
736
		$upints = explode(" ", trim(shell_exec("/sbin/ifconfig -l")));
737
		break;
738
	}
739
        /* build interface list with netstat */
740
        $linkinfo = "";
741
        exec("/usr/bin/netstat -inW -f link | awk '{ print $1, $4 }'", $linkinfo);
742
        array_shift($linkinfo);
743
	/* build ip address list with netstat */
744
	$ipinfo = "";
745
	exec("/usr/bin/netstat -inW -f inet | awk '{ print $1, $4 }'", $ipinfo);
746
	array_shift($ipinfo);
747
	foreach($linkinfo as $link) {
748
		$friendly = "";
749
		$alink = explode(" ", $link);
750
		$ifname = rtrim(trim($alink[0]), '*');
751
		/* trim out all numbers before checking for vfaces */
752
		if (!in_array(array_shift(preg_split('/\d/', $ifname)), $vfaces) &&
753
			!stristr($ifname, "_vlan") && !stristr($ifname, "_wlan")) {
754
			$toput = array(
755
					"mac" => trim($alink[1]),
756
					"up" => in_array($ifname, $upints)
757
				);
758
			foreach($ipinfo as $ip) {
759
				$aip = explode(" ", $ip);
760
				if($aip[0] == $ifname) {
761
					$toput['ipaddr'] = $aip[1];
762
				}
763
			}
764
			if (is_array($config['interfaces'])) {
765
				foreach($config['interfaces'] as $name => $int)
766
					if($int['if'] == $ifname) $friendly = $name;
767
			}
768
			switch($keyby) {
769
			case "physical":
770
				if($friendly != "") {
771
					$toput['friendly'] = $friendly;
772
				}
773
				$dmesg_arr = array();
774
				exec("/sbin/dmesg |grep $ifname | head -n1", $dmesg_arr);
775
				preg_match_all("/<(.*?)>/i", $dmesg_arr[0], $dmesg);
776
				$toput['dmesg'] = $dmesg[1][0];
777
				$iflist[$ifname] = $toput;
778
				break;
779
			case "ppp":
780
				
781
			case "friendly":
782
				if($friendly != "") {
783
					$toput['if'] = $ifname;
784
					$iflist[$friendly] = $toput;
785
				}
786
				break;
787
			}
788
		}
789
	}
790
	return $iflist;
791
}
792

    
793
/****f* util/log_error
794
* NAME
795
*   log_error  - Sends a string to syslog.
796
* INPUTS
797
*   $error     - string containing the syslog message.
798
* RESULT
799
*   null
800
******/
801
function log_error($error) {
802
	global $g;
803
	$page = $_SERVER['SCRIPT_NAME'];
804
	syslog(LOG_WARNING, "$page: $error");
805
	if ($g['debug'])
806
		syslog(LOG_WARNING, var_dump(debug_backtrace()));
807
	return;
808
}
809

    
810
/****f* util/log_auth
811
* NAME
812
*   log_error  - Sends a string to syslog as LOG_AUTH facility
813
* INPUTS
814
*   $error     - string containing the syslog message.
815
* RESULT
816
*   null
817
******/
818
function log_auth($error) {
819
	global $g;
820
	$page = $_SERVER['SCRIPT_NAME'];
821
	syslog(LOG_AUTH, "$page: $error");
822
	if ($g['debug'])
823
		syslog(LOG_WARNING, var_dump(debug_backtrace()));
824
	return;
825
}
826

    
827
/****f* util/exec_command
828
 * NAME
829
 *   exec_command - Execute a command and return a string of the result.
830
 * INPUTS
831
 *   $command   - String of the command to be executed.
832
 * RESULT
833
 *   String containing the command's result.
834
 * NOTES
835
 *   This function returns the command's stdout and stderr.
836
 ******/
837
function exec_command($command) {
838
	$output = array();
839
	exec($command . ' 2>&1 ', $output);
840
	return(implode("\n", $output));
841
}
842

    
843
/* wrapper for exec() */
844
function mwexec($command, $mute = false) {
845
	global $g;
846

    
847
	if ($g['debug']) {
848
		if (!$_SERVER['REMOTE_ADDR'])
849
			echo "mwexec(): $command\n";
850
	}
851
	$oarr = array();
852
	$retval = 0;
853
	$garbage = exec("$command 2>&1", $oarr, $retval);
854

    
855
	if(isset($config['system']['developerspew']))
856
		$mute = false;
857
	if(($retval <> 0) && ($mute === false)) {
858
		$output = implode(" ", $oarr);
859
		log_error("The command '$command' returned exit code '$retval', the output was '$output' ");
860
	}
861
	return $retval;
862
}
863

    
864
/* wrapper for exec() in background */
865
function mwexec_bg($command) {
866
	global $g;
867

    
868
	if ($g['debug']) {
869
		if (!$_SERVER['REMOTE_ADDR'])
870
			echo "mwexec(): $command\n";
871
	}
872

    
873
	exec("nohup $command > /dev/null 2>&1 &");
874
}
875

    
876
/* unlink a file, if it exists */
877
function unlink_if_exists($fn) {
878
	$to_do = glob($fn);
879
	if(is_array($to_do)) {
880
		foreach($to_do as $filename)
881
			@unlink($filename);
882
	} else {
883
		@unlink($fn);
884
	}
885
}
886
/* make a global alias table (for faster lookups) */
887
function alias_make_table($config) {
888
	global $aliastable;
889

    
890
	$aliastable = array();
891

    
892
	if (is_array($config['aliases']['alias'])) {
893
		foreach ($config['aliases']['alias'] as $alias) {
894
			if ($alias['name'])
895
				$aliastable[$alias['name']] = $alias['address'];
896
		}
897
	}
898
}
899
/* check if an alias exists */
900
function is_alias($name) {
901
	global $aliastable;
902

    
903
	return isset($aliastable[$name]);
904
}
905

    
906
/* expand a host or network alias, if necessary */
907
function alias_expand($name) {
908
	global $aliastable;
909

    
910
	if (isset($aliastable[$name]))
911
		return "\${$name}";
912
	else if (is_ipaddr($name) || is_subnet($name) || is_port($name))
913
		return "{$name}";
914
	else
915
		return null;
916
}
917

    
918
function alias_expand_urltable($name) {
919
	global $config;
920
	$urltable_prefix = "/var/db/aliastables/";
921
	$urltable_filename = $urltable_prefix . $name . ".txt";
922

    
923
	foreach ($config['aliases']['alias'] as $alias) {
924
		if (($alias['type'] == 'urltable') && ($alias['name'] == $name)) {
925
			if (is_URL($alias["url"]) && file_exists($urltable_filename) && filesize($urltable_filename))
926
				return $urltable_filename;
927
			else if (process_alias_urltable($name, $alias["url"], 0, true))
928
				return $urltable_filename;
929
		}
930
	}
931
	return null;
932
}
933

    
934
/* find out whether two subnets overlap */
935
function check_subnets_overlap($subnet1, $bits1, $subnet2, $bits2) {
936

    
937
	if (!is_numeric($bits1))
938
		$bits1 = 32;
939
	if (!is_numeric($bits2))
940
		$bits2 = 32;
941

    
942
	if ($bits1 < $bits2)
943
		$relbits = $bits1;
944
	else
945
		$relbits = $bits2;
946

    
947
	$sn1 = gen_subnet_mask_long($relbits) & ip2long($subnet1);
948
	$sn2 = gen_subnet_mask_long($relbits) & ip2long($subnet2);
949

    
950
	if ($sn1 == $sn2)
951
		return true;
952
	else
953
		return false;
954
}
955

    
956
/* compare two IP addresses */
957
function ipcmp($a, $b) {
958
	if (ip_less_than($a, $b))
959
		return -1;
960
	else if (ip_greater_than($a, $b))
961
		return 1;
962
	else
963
		return 0;
964
}
965

    
966
/* return true if $addr is in $subnet, false if not */
967
function ip_in_subnet($addr,$subnet) {
968
	list($ip, $mask) = explode('/', $subnet);
969
	$mask = (0xffffffff << (32 - $mask)) & 0xffffffff;
970
	return ((ip2long($addr) & $mask) == (ip2long($ip) & $mask));
971
}
972

    
973
/* verify (and remove) the digital signature on a file - returns 0 if OK */
974
function verify_digital_signature($fname) {
975
	global $g;
976

    
977
	if(!file_exists("/usr/local/sbin/gzsig"))
978
		return 4;
979

    
980
	return mwexec("/usr/local/sbin/gzsig verify {$g['etc_path']}/pubkey.pem < " . escapeshellarg($fname));
981
}
982

    
983
/* obtain MAC address given an IP address by looking at the ARP table */
984
function arp_get_mac_by_ip($ip) {
985
	mwexec("/sbin/ping -c 1 -t 1 {$ip}", true);
986
	$arpoutput = "";
987
	exec("/usr/sbin/arp -n {$ip}", $arpoutput);
988

    
989
	if ($arpoutput[0]) {
990
		$arpi = explode(" ", $arpoutput[0]);
991
		$macaddr = $arpi[3];
992
		if (is_macaddr($macaddr))
993
			return $macaddr;
994
		else
995
			return false;
996
	}
997

    
998
	return false;
999
}
1000

    
1001
/* return a fieldname that is safe for xml usage */
1002
function xml_safe_fieldname($fieldname) {
1003
	$replace = array('/', '-', ' ', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')',
1004
			 '_', '+', '=', '{', '}', '[', ']', '|', '/', '<', '>', '?',
1005
			 ':', ',', '.', '\'', '\\'
1006
		);
1007
	return strtolower(str_replace($replace, "", $fieldname));
1008
}
1009

    
1010
function mac_format($clientmac) {
1011
    $mac =explode(":", $clientmac);
1012

    
1013
    global $config;
1014

    
1015
    $mac_format = $config['captiveportal']['radmac_format'] ? $config['captiveportal']['radmac_format'] : false;
1016

    
1017
    switch($mac_format) {
1018

    
1019
        case 'singledash':
1020
        return "$mac[0]$mac[1]$mac[2]-$mac[3]$mac[4]$mac[5]";
1021

    
1022
        case 'ietf':
1023
        return "$mac[0]-$mac[1]-$mac[2]-$mac[3]-$mac[4]-$mac[5]";
1024

    
1025
        case 'cisco':
1026
        return "$mac[0]$mac[1].$mac[2]$mac[3].$mac[4]$mac[5]";
1027

    
1028
        case 'unformatted':
1029
        return "$mac[0]$mac[1]$mac[2]$mac[3]$mac[4]$mac[5]";
1030

    
1031
        default:
1032
        return $clientmac;
1033
    }
1034
}
1035

    
1036
function resolve_retry($hostname, $retries = 5) {
1037

    
1038
	if (is_ipaddr($hostname))
1039
		return $hostname;
1040

    
1041
	for ($i = 0; $i < $retries; $i++) {
1042
		$ip = gethostbyname($hostname);
1043

    
1044
		if ($ip && $ip != $hostname) {
1045
			/* success */
1046
			return $ip;
1047
		}
1048

    
1049
		sleep(1);
1050
	}
1051

    
1052
	return false;
1053
}
1054

    
1055
function format_bytes($bytes) {
1056
	if ($bytes >= 1073741824) {
1057
		return sprintf("%.2f GB", $bytes/1073741824);
1058
	} else if ($bytes >= 1048576) {
1059
		return sprintf("%.2f MB", $bytes/1048576);
1060
	} else if ($bytes >= 1024) {
1061
		return sprintf("%.0f KB", $bytes/1024);
1062
	} else {
1063
		return sprintf("%d bytes", $bytes);
1064
	}
1065
}
1066

    
1067
function update_filter_reload_status($text) {
1068
	global $g;
1069

    
1070
	file_put_contents("{$g['varrun_path']}/filter_reload_status", $text);
1071
}
1072

    
1073
/****f* util/return_dir_as_array
1074
 * NAME
1075
 *   return_dir_as_array - Return a directory's contents as an array.
1076
 * INPUTS
1077
 *   $dir       - string containing the path to the desired directory.
1078
 * RESULT
1079
 *   $dir_array - array containing the directory's contents. This array will be empty if the path specified is invalid.
1080
 ******/
1081
function return_dir_as_array($dir) {
1082
	$dir_array = array();
1083
	if (is_dir($dir)) {
1084
		if ($dh = opendir($dir)) {
1085
			while (($file = readdir($dh)) !== false) {
1086
				$canadd = 0;
1087
				if($file == ".") $canadd = 1;
1088
				if($file == "..") $canadd = 1;
1089
				if($canadd == 0)
1090
					array_push($dir_array, $file);
1091
			}
1092
			closedir($dh);
1093
		}
1094
	}
1095
	return $dir_array;
1096
}
1097

    
1098
function run_plugins($directory) {
1099
	global $config, $g;
1100

    
1101
	/* process packager manager custom rules */
1102
	$files = return_dir_as_array($directory);
1103
	if (is_array($files)) {
1104
		foreach ($files as $file) {
1105
			if (stristr($file, ".sh") == true)
1106
				mwexec($directory . $file . " start");
1107
			else if (!is_dir($directory . "/" . $file) && stristr($file,".inc")) 
1108
				require_once($directory . "/" . $file);
1109
		}
1110
	}
1111
}
1112

    
1113
/*
1114
 *    safe_mkdir($path, $mode = 0755)
1115
 *    create directory if it doesn't already exist and isn't a file!
1116
 */
1117
function safe_mkdir($path, $mode=0755) {
1118
	global $g;
1119

    
1120
	if (!is_file($path) && !is_dir($path)) {
1121
		return @mkdir($path, $mode, true);
1122
	} else {
1123
		return false;
1124
	}
1125
}
1126

    
1127
/*
1128
 * make_dirs($path, $mode = 0755)
1129
 * create directory tree recursively (mkdir -p)
1130
 */
1131
function make_dirs($path, $mode = 0755) {
1132
	$base = '';
1133
	foreach (explode('/', $path) as $dir) {
1134
		$base .= "/$dir";
1135
		if (!is_dir($base)) {
1136
			if (!@mkdir($base, $mode))
1137
				return false;
1138
		}
1139
	}
1140
	return true;
1141
}
1142

    
1143
/*
1144
 * get_sysctl($names)
1145
 * Get values of sysctl OID's listed in $names (accepts an array or a single
1146
 * name) and return an array of key/value pairs set for those that exist
1147
 */
1148
function get_sysctl($names) {
1149
	if (empty($names))
1150
		return array();
1151

    
1152
	if (is_array($names)) {
1153
		$name_list = array();
1154
		foreach ($names as $name) {
1155
			$name_list[] = escapeshellarg($name);
1156
		}
1157
	} else
1158
		$name_list = array(escapeshellarg($names));
1159

    
1160
	exec("/sbin/sysctl -i " . implode(" ", $name_list), $output);
1161
	$values = array();
1162
	foreach ($output as $line) {
1163
		$line = explode(": ", $line, 2);
1164
		if (count($line) == 2)
1165
			$values[$line[0]] = $line[1];
1166
	}
1167

    
1168
	return $values;
1169
}
1170

    
1171
/*
1172
 * set_sysctl($value_list)
1173
 * Set sysctl OID's listed as key/value pairs and return
1174
 * an array with keys set for those that succeeded
1175
 */
1176
function set_sysctl($values) {
1177
	if (empty($values))
1178
		return array();
1179

    
1180
	$value_list = array();
1181
	foreach ($values as $key => $value) {
1182
		$value_list[] = escapeshellarg($key) . "=" . escapeshellarg($value);
1183
	}
1184

    
1185
	exec("/sbin/sysctl -i " . implode(" ", $value_list), $output, $success);
1186

    
1187
	/* Retry individually if failed (one or more read-only) */
1188
	if ($success <> 0 && count($value_list) > 1) {
1189
		foreach ($value_list as $value) {
1190
			exec("/sbin/sysctl -i " . $value, $output);
1191
		}
1192
	}
1193

    
1194
	$ret = array();
1195
	foreach ($output as $line) {
1196
		$line = explode(": ", $line, 2);
1197
		if (count($line) == 2)
1198
			$ret[$line[0]] = true;
1199
	}
1200

    
1201
	return $ret;
1202
}
1203

    
1204
/*
1205
 *     get_memory()
1206
 *     returns an array listing the amount of
1207
 *     memory installed in the hardware
1208
 *     [0]real and [1]available
1209
 */
1210
function get_memory() {
1211
	$matches = "";
1212
	if(file_exists("/var/log/dmesg.boot"))
1213
		$mem = `cat /var/log/dmesg.boot | grep memory`;
1214
	else
1215
		$mem = `dmesg -a | grep memory`;			
1216
	if (preg_match_all("/avail memory.* \((.*)MB\)/", $mem, $matches)) 
1217
		return array($matches[1][0], $matches[1][0]);
1218
	if(!$real && !$avail) {
1219
		$real = trim(`sysctl hw.physmem | cut -d' ' -f2`);
1220
		$avail = trim(`sysctl hw.realmem | cut -d' ' -f2`);
1221
		/* convert from bytes to megabytes */
1222
		return array(($real/1048576),($avail/1048576));
1223
	}
1224
}
1225

    
1226
function mute_kernel_msgs() {
1227
	global $config;
1228
	// Do not mute serial console.  The kernel gets very very cranky
1229
	// and will start dishing you cannot control tty errors.
1230
	if(trim(file_get_contents("/etc/platform")) == "nanobsd") 
1231
		return;
1232
	if($config['system']['enableserial']) 
1233
		return;			
1234
	exec("/sbin/conscontrol mute on");
1235
}
1236

    
1237
function unmute_kernel_msgs() {
1238
	global $config;
1239
	// Do not mute serial console.  The kernel gets very very cranky
1240
	// and will start dishing you cannot control tty errors.
1241
	if(trim(file_get_contents("/etc/platform")) == "nanobsd") 
1242
		return;
1243
	exec("/sbin/conscontrol mute off");
1244
}
1245

    
1246
function start_devd() {
1247
	global $g;
1248

    
1249
	exec("/sbin/devd");
1250
	sleep(1);
1251
}
1252

    
1253
function is_interface_vlan_mismatch() {
1254
	global $config, $g;
1255

    
1256
	if (is_array($config['vlans']['vlan'])) {
1257
		foreach ($config['vlans']['vlan'] as $vlan) {
1258
			if (does_interface_exist($vlan['if']) == false)
1259
				return true;
1260
		}
1261
	}
1262

    
1263
	return false;
1264
}
1265

    
1266
function is_interface_mismatch() {
1267
	global $config, $g;
1268

    
1269
	$do_assign = false;
1270
	$i = 0;
1271
	if (is_array($config['interfaces'])) {
1272
		foreach ($config['interfaces'] as $ifname => $ifcfg) {
1273
			if (preg_match("/^enc|^cua|^tun|^l2tp|^pptp|^ppp|^ovpn|^gif|^gre|^lagg|^bridge|vlan|_wlan/i", $ifcfg['if'])) {
1274
				// Do not check these interfaces.
1275
				$i++;
1276
				continue;
1277
			}
1278
			else if (does_interface_exist($ifcfg['if']) == false) {
1279
				$do_assign = true;
1280
			} else
1281
				$i++;
1282
		}
1283
	}
1284

    
1285
	if ($g['minimum_nic_count'] > $i) {
1286
		$do_assign = true;
1287
	} else if (file_exists("{$g['tmp_path']}/assign_complete"))
1288
	$do_assign = false;
1289

    
1290
	return $do_assign;
1291
}
1292

    
1293
/* sync carp entries to other firewalls */
1294
function carp_sync_client() {
1295
	global $g;
1296
	send_event("filter sync");
1297
}
1298

    
1299
/****f* util/isAjax
1300
 * NAME
1301
 *   isAjax - reports if the request is driven from prototype
1302
 * INPUTS
1303
 *   none
1304
 * RESULT
1305
 *   true/false
1306
 ******/
1307
function isAjax() {
1308
	return isset ($_SERVER['HTTP_X_REQUESTED_WITH']) && $_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest';
1309
}
1310

    
1311
/****f* util/timeout
1312
 * NAME
1313
 *   timeout - console input with timeout countdown. Note: erases 2 char of screen for timer. Leave space.
1314
 * INPUTS
1315
 *   optional, seconds to wait before timeout. Default 9 seconds.
1316
 * RESULT
1317
 *   returns 1 char of user input or null if no input.
1318
 ******/
1319
function timeout($timer = 9) {
1320
	while(!isset($key)) {
1321
		if ($timer >= 9) { echo chr(8) . chr(8) . ($timer==9 ? chr(32) : null)  . "{$timer}";  }
1322
		else { echo chr(8). "{$timer}"; }
1323
		`/bin/stty -icanon min 0 time 25`;
1324
		$key = trim(`KEY=\`dd count=1 2>/dev/null\`; echo \$KEY`);
1325
		`/bin/stty icanon`;
1326
		if ($key == '')
1327
			unset($key);
1328
		$timer--;
1329
		if ($timer == 0)
1330
			break;
1331
	}
1332
	return $key;	
1333
}
1334

    
1335
/****f* util/msort
1336
 * NAME
1337
 *   msort - sort array
1338
 * INPUTS
1339
 *   $array to be sorted, field to sort by, direction of sort
1340
 * RESULT
1341
 *   returns newly sorted array
1342
 ******/
1343
function msort($array, $id="id", $sort_ascending=true) {
1344
	$temp_array = array();
1345
	while(count($array)>0) {
1346
		$lowest_id = 0;
1347
		$index=0;
1348
		foreach ($array as $item) {
1349
			if (isset($item[$id])) {
1350
				if ($array[$lowest_id][$id]) {
1351
					if (strtolower($item[$id]) < strtolower($array[$lowest_id][$id])) {
1352
						$lowest_id = $index;
1353
					}
1354
				}
1355
			}
1356
			$index++;
1357
		}
1358
		$temp_array[] = $array[$lowest_id];
1359
		$array = array_merge(array_slice($array, 0,$lowest_id), array_slice($array, $lowest_id+1));
1360
	}
1361
	if ($sort_ascending) {
1362
		return $temp_array;
1363
	} else {
1364
    	return array_reverse($temp_array);
1365
	}
1366
}
1367

    
1368
/****f* util/color
1369
 * NAME
1370
 *   color - outputs a color code to the ansi terminal if supported
1371
 * INPUTS
1372
 *   color code or color name
1373
 * RESULT
1374
 *   Outputs the ansi color sequence for the color specified.  Default resets terminal.
1375
 ******/
1376
function color($color = "0m") {
1377
	/*
1378
		Color codes available:
1379
		 0m reset; clears all colors and styles (to white on black)
1380
		 1m bold on (see below)
1381
		 3m italics on
1382
		 4m underline on
1383
		 7m inverse on; reverses foreground & background colors
1384
		 9m strikethrough on
1385
		 22m bold off (see below)
1386
		 23m italics off
1387
		 24m underline off
1388
		 27m inverse off
1389
		 29m strikethrough off
1390
		 30m set foreground color to black
1391
		 31m set foreground color to red
1392
		 32m set foreground color to green
1393
		 33m set foreground color to yellow
1394
		 34m set foreground color to blue
1395
		 35m set foreground color to magenta (purple)
1396
		 36m set foreground color to cyan
1397
		 37m set foreground color to white
1398
		 40m  set background color to black
1399
		 41m set background color to red
1400
		 42m set background color to green
1401
		 43m set background color to yellow
1402
		 44m set background color to blue
1403
		 45m set background color to magenta (purple)
1404
		 46m set background color to cyan
1405
		 47m set background color to white
1406
		 49m set background color to default (black)
1407
	*/	
1408
	// Allow caching of TERM to 
1409
	// speedup subequence requests.
1410
	global $TERM;
1411
	if(!$TERM) 
1412
		$TERM=`/usr/bin/env | grep color`;
1413
	if(!$TERM)
1414
		$TERM=`/usr/bin/env | grep cons25`;
1415
	if($TERM) {
1416
		$ESCAPE=chr(27);
1417
		switch ($color) {
1418
			case "black":
1419
				return "{$ESCAPE}[30m"; 
1420
			case "red":
1421
				return "{$ESCAPE}[31m"; 
1422
			case "green":
1423
				return "{$ESCAPE}[32m"; 
1424
			case "yellow":
1425
				return "{$ESCAPE}[33m"; 
1426
			case "blue":
1427
				return "{$ESCAPE}[34m"; 
1428
			case "magenta":
1429
				return "{$ESCAPE}[35m"; 
1430
			case "cyan":
1431
				return "{$ESCAPE}[36m"; 
1432
			case "white":
1433
				return "{$ESCAPE}[37m"; 
1434
			case "default":
1435
				return "{$ESCAPE}[39m"; 
1436
		}
1437
		return "{$ESCAPE}[{$color}";
1438
	}
1439
}
1440

    
1441
/****f* util/is_URL
1442
 * NAME
1443
 *   is_URL
1444
 * INPUTS
1445
 *   string to check
1446
 * RESULT
1447
 *   Returns true if item is a URL
1448
 ******/
1449
function is_URL($url) {
1450
	$match = preg_match("'\b(([\w-]+://?|www[.])[^\s()<>]+(?:\([\w\d]+\)|([^[:punct:]\s]|/)))'", $url);
1451
	if($match)
1452
		return true;	
1453
	return false;
1454
}
1455

    
1456
function is_file_included($file = "") {
1457
	$files = get_included_files();
1458
	if (in_array($file, $files))
1459
		return true;
1460
	
1461
	return false;
1462
}
1463

    
1464
/*
1465
	This function was borrowed from a comment on PHP.net at the following URL:
1466
	http://www.php.net/manual/en/function.array-merge-recursive.php#73843
1467
 */
1468
function array_merge_recursive_unique($array0, $array1) {
1469

    
1470
	$arrays = func_get_args();
1471
	$remains = $arrays;
1472

    
1473
	// We walk through each arrays and put value in the results (without
1474
	// considering previous value).
1475
	$result = array();
1476

    
1477
	// loop available array
1478
	foreach($arrays as $array) {
1479

    
1480
		// The first remaining array is $array. We are processing it. So
1481
		// we remove it from remaing arrays.
1482
        array_shift($remains);
1483

    
1484
		// We don't care non array param, like array_merge since PHP 5.0.
1485
		if(is_array($array)) {
1486
			// Loop values
1487
			foreach($array as $key => $value) {
1488
				if(is_array($value)) {
1489
					// we gather all remaining arrays that have such key available
1490
					$args = array();
1491
					foreach($remains as $remain) {
1492
						if(array_key_exists($key, $remain)) {
1493
							array_push($args, $remain[$key]);
1494
						}
1495
					}
1496

    
1497
					if(count($args) > 2) {
1498
						// put the recursion
1499
						$result[$key] = call_user_func_array(__FUNCTION__, $args);
1500
					} else {
1501
						foreach($value as $vkey => $vval) {
1502
							$result[$key][$vkey] = $vval;
1503
						}
1504
					}
1505
				} else {
1506
					// simply put the value
1507
					$result[$key] = $value;
1508
				}
1509
			}
1510
		}
1511
	}
1512
	return $result;
1513
}
1514

    
1515
?>
(49-49/61)