Project

General

Profile

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

    
158
function send_multiple_events($cmds) {
159
        global $g;
160

    
161
	if (!is_array($cmds))
162
		return;
163
        $fd = fsockopen($g['event_address']);
164
        if ($fd) {
165
		foreach ($cmds as $cmd) {
166
                	fwrite($fd, $cmd);
167
                	$resp = fread($fd, 4096);
168
                	if ($resp != "OK\n")
169
                        	log_error("send_event: sent {$cmd} got {$resp}");
170
		}
171
                fclose($fd);
172
        }
173
}
174

    
175
function refcount_init($reference) {
176
	$shmid = shmop_open($reference, "c", 0644, 10);
177
	shmop_write($shmid, 0, 0);
178
	shmop_close($shmid);
179
}
180

    
181
function refcount_reference($reference) {
182
	$shmid = @shmop_open($reference, "w", 0644, 10);
183
	if (!$shmid) {
184
		refcount_init($reference);
185
		$shmid = shmop_open($reference, "w", 0644, 10);
186
	}
187
	$shm_data = shmop_read($shmid, 0, 10);
188
	$shm_data = intval($shm_data) + 1;
189
	shmop_write($shmid, $shm_data, 0);
190
	shmop_close($shmid);
191
	
192
	return $shm_data;
193
}
194

    
195
function refcount_unreference($reference) {
196
	/* We assume that the shared memory exists. */
197
	$shmid = shmop_open($reference, "w", 0644, 10);
198
	$shm_data = shmop_read($shmid, 0, 10);
199
	$shm_data = intval($shm_data) - 1;
200
	if ($shm_data < 0) {
201
		//debug_backtrace();
202
		log_error("Reference {$reference} is going negative, not doing unreference.");
203
	} else
204
		shmop_write($shmid, $shm_data, 0);
205
	shmop_close($shmid);
206
	
207
	return $shm_data;
208
}
209

    
210
function is_module_loaded($module_name) {
211
	$running = `/sbin/kldstat | grep {$module_name} | /usr/bin/grep -v grep | /usr/bin/wc -l`;
212
	if (intval($running) >= 1)
213
		return true;
214
	else
215
		return false;
216
}
217

    
218
/* return the subnet address given a host address and a subnet bit count */
219
function gen_subnet($ipaddr, $bits) {
220
	if (!is_ipaddr($ipaddr) || !is_numeric($bits))
221
		return "";
222

    
223
	return long2ip(ip2long($ipaddr) & gen_subnet_mask_long($bits));
224
}
225

    
226
/* return the highest (broadcast) address in the subnet given a host address and a subnet bit count */
227
function gen_subnet_max($ipaddr, $bits) {
228
	if (!is_ipaddr($ipaddr) || !is_numeric($bits))
229
		return "";
230

    
231
	return long2ip32(ip2long($ipaddr) | ~gen_subnet_mask_long($bits));
232
}
233

    
234
/* returns a subnet mask (long given a bit count) */
235
function gen_subnet_mask_long($bits) {
236
	$sm = 0;
237
	for ($i = 0; $i < $bits; $i++) {
238
		$sm >>= 1;
239
		$sm |= 0x80000000;
240
	}
241
	return $sm;
242
}
243

    
244
/* same as above but returns a string */
245
function gen_subnet_mask($bits) {
246
	return long2ip(gen_subnet_mask_long($bits));
247
}
248

    
249
/* Convert long int to IP address, truncating to 32-bits. */
250
function long2ip32($ip) {
251
	return long2ip($ip & 0xFFFFFFFF);
252
}
253

    
254
/* Convert IP address to long int, truncated to 32-bits to avoid sign extension on 64-bit platforms. */
255
function ip2long32($ip) {
256
	return ( ip2long($ip) & 0xFFFFFFFF );
257
}
258

    
259
/* Convert IP address to unsigned long int. */
260
function ip2ulong($ip) {
261
	return sprintf("%u", ip2long32($ip));
262
}
263

    
264
/* Find out how many IPs are contained within a given IP range
265
 *  e.g. 192.168.0.0 to 192.168.0.255 returns 256
266
 */
267
function ip_range_size($startip, $endip) {
268
	if (is_ipaddr($startip) && is_ipaddr($endip)) {
269
		// Operate as unsigned long because otherwise it wouldn't work
270
		//   when crossing over from 127.255.255.255 / 128.0.0.0 barrier
271
		return abs(ip2ulong($startip) - ip2ulong($endip)) + 1;
272
	}
273
	return -1;
274
}
275

    
276
/* Find the smallest possible subnet mask which can contain a given number of IPs
277
 *  e.g. 512 IPs can fit in a /23, but 513 IPs need a /22
278
 */
279
function find_smallest_cidr($number) {
280
	$smallest = 1;
281
	for ($b=32; $b > 0; $b--) {
282
		$smallest = ($number <= pow(2,$b)) ? $b : $smallest;
283
	}
284
	return (32-$smallest);
285
}
286

    
287
/* Return the previous IP address before the given address */
288
function ip_before($ip) {
289
	return long2ip32(ip2long($ip)-1);
290
}
291

    
292
/* Return the next IP address after the given address */
293
function ip_after($ip) {
294
	return long2ip32(ip2long($ip)+1);
295
}
296

    
297
/* Return true if the first IP is 'before' the second */
298
function ip_less_than($ip1, $ip2) {
299
	// Compare as unsigned long because otherwise it wouldn't work when
300
	//   crossing over from 127.255.255.255 / 128.0.0.0 barrier
301
	return ip2ulong($ip1) < ip2ulong($ip2);
302
}
303

    
304
/* Return true if the first IP is 'after' the second */
305
function ip_greater_than($ip1, $ip2) {
306
	// Compare as unsigned long because otherwise it wouldn't work
307
	//   when crossing over from 127.255.255.255 / 128.0.0.0 barrier
308
	return ip2ulong($ip1) > ip2ulong($ip2);
309
}
310

    
311
/* Convert a range of IPs to an array of subnets which can contain the range. */
312
function ip_range_to_subnet_array($startip, $endip) {
313
	if (!is_ipaddr($startip) || !is_ipaddr($endip)) {
314
		return array();
315
	}
316

    
317
	// Container for subnets within this range.
318
	$rangesubnets = array();
319

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

    
323
	// Loop here to reduce subnet size and retest as needed. We need to make sure
324
	//   that the target subnet is wholly contained between $startip and $endip.
325
	for ($cidr; $cidr <= 32; $cidr++) {
326
		// Find the network and broadcast addresses for the subnet being tested.
327
		$targetsub_min = gen_subnet($startip, $cidr);
328
		$targetsub_max = gen_subnet_max($startip, $cidr);
329

    
330
		// Check best case where the range is exactly one subnet.
331
		if (($targetsub_min == $startip) && ($targetsub_max == $endip)) {
332
			// Hooray, the range is exactly this subnet!
333
			return array("{$startip}/{$cidr}");
334
		}
335

    
336
		// These remaining scenarios will find a subnet that uses the largest
337
		//  chunk possible of the range being tested, and leave the rest to be
338
		//  tested recursively after the loop.
339

    
340
		// Check if the subnet begins with $startip and ends before $endip
341
		if (($targetsub_min == $startip) && ip_less_than($targetsub_max, $endip)) {
342
			break;
343
		}
344

    
345
		// Check if the subnet ends at $endip and starts after $startip
346
		if (ip_greater_than($targetsub_min, $startip) && ($targetsub_max == $endip)) {
347
			break;
348
		}
349

    
350
		// Check if the subnet is between $startip and $endip
351
		if (ip_greater_than($targetsub_min, $startip) && ip_less_than($targetsub_max, $endip)) {
352
			break;
353
		}
354
	}
355

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

    
362
	// Add in the subnet we found before, to preserve ordering
363
	$rangesubnets[] = "{$targetsub_min}/{$cidr}";
364

    
365
	// And some more logic that will search after the subnet we found to fill in to the end of the range.
366
	if ($endip != $targetsub_max) {
367
		$rangesubnets = array_merge($rangesubnets, ip_range_to_subnet_array(ip_after($targetsub_max), $endip));
368
	}
369
	return $rangesubnets;
370
}
371

    
372
function is_iprange($range) {
373
	if (substr_count($range, '-') != 1) {
374
		return false;
375
	}
376
	list($ip1, $ip2) = explode ('-', $range);
377
	return (is_ipaddr($ip1) && is_ipaddr($ip2));
378
}
379

    
380
function is_numericint($arg) {
381
	return (preg_match("/[^0-9]/", $arg) ? false : true);
382
}
383

    
384
/* returns true if $ipaddr is a valid dotted IPv4 address */
385
function is_ipaddr($ipaddr) {
386
	if (!is_string($ipaddr))
387
		return false;
388

    
389
	$ip_long = ip2long($ipaddr);
390
	$ip_reverse = long2ip32($ip_long);
391

    
392
	if ($ipaddr == $ip_reverse)
393
		return true;
394
	else
395
		return false;
396
}
397

    
398
/* returns true if $ipaddr is a valid dotted IPv4 address or an alias thereof */
399
function is_ipaddroralias($ipaddr) {
400
	global $config;
401

    
402
	if (is_alias($ipaddr)) {
403
		if (is_array($config['aliases']['alias'])) {
404
			foreach ($config['aliases']['alias'] as $alias) {
405
                        	if ($alias['name'] == $ipaddr && $alias['type'] != "port")
406
					return true;
407
			}
408
                }
409
		return false;
410
	} else
411
		return is_ipaddr($ipaddr);
412

    
413
}
414

    
415
/* returns true if $subnet is a valid subnet in CIDR format */
416
function is_subnet($subnet) {
417
	if (!is_string($subnet))
418
		return false;
419

    
420
	list($hp,$np) = explode('/', $subnet);
421

    
422
	if (!is_ipaddr($hp))
423
		return false;
424

    
425
	if (!is_numeric($np) || ($np < 1) || ($np > 32))
426
		return false;
427

    
428
	return true;
429
}
430

    
431
/* returns true if $subnet is a valid subnet in CIDR format or an alias thereof */
432
function is_subnetoralias($subnet) {
433

    
434
	global $aliastable;
435

    
436
	if (isset($aliastable[$subnet]) && is_subnet($aliastable[$subnet]))
437
		return true;
438
	else
439
		return is_subnet($subnet);
440
}
441

    
442
/* returns true if $hostname is a valid hostname */
443
function is_hostname($hostname) {
444
	if (!is_string($hostname))
445
		return false;
446

    
447
	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))
448
		return true;
449
	else
450
		return false;
451
}
452

    
453
/* returns true if $domain is a valid domain name */
454
function is_domain($domain) {
455
	if (!is_string($domain))
456
		return false;
457

    
458
	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))
459
		return true;
460
	else
461
		return false;
462
}
463

    
464
/* returns true if $macaddr is a valid MAC address */
465
function is_macaddr($macaddr) {
466
	return preg_match('/^[0-9A-F]{2}(?:[:][0-9A-F]{2}){5}$/i', $macaddr) == 1 ? true : false;
467
}
468

    
469
/* returns true if $name is a valid name for an alias */
470
/* returns NULL if a reserved word is used */
471
function is_validaliasname($name) {
472
	/* Array of reserved words */
473
	$reserved = array("port", "pass");
474
	if (in_array($name, $reserved, true))
475
		return; /* return NULL */
476

    
477
	if (!preg_match("/[^a-zA-Z0-9_]/", $name))
478
		return true;
479
	else
480
		return false;
481
}
482

    
483
/* returns true if $port is a valid TCP/UDP port */
484
function is_port($port) {
485
	$tmpports = explode(":", $port);
486
	foreach($tmpports as $tmpport) {
487
		if (getservbyname($tmpport, "tcp") || getservbyname($tmpport, "udp"))
488
                	continue;
489
		if (!ctype_digit($tmpport))
490
			return false;
491
		else if ((intval($tmpport) < 1) || (intval($tmpport) > 65535))
492
			return false;
493
	}
494
	return true;
495
}
496

    
497
/* returns true if $portrange is a valid TCP/UDP portrange ("<port>:<port>") */
498
function is_portrange($portrange) {
499
        $ports = explode(":", $portrange);
500

    
501
        if(count($ports) == 2 && is_port($ports[0]) && is_port($ports[1]))
502
                return true;
503
        else
504
                return false;
505
}
506

    
507
/* returns true if $port is a valid port number or an alias thereof */
508
function is_portoralias($port) {
509
	global $config;
510

    
511
        if (is_alias($port)) {
512
                if (is_array($config['aliases']['alias'])) {
513
                        foreach ($config['aliases']['alias'] as $alias) {
514
                                if ($alias['name'] == $port && $alias['type'] == "port")
515
                                        return true;
516
                        }
517
                }
518
                return false;
519
        } else
520
                return is_port($port);
521
}
522

    
523
/* returns true if $val is a valid shaper bandwidth value */
524
function is_valid_shaperbw($val) {
525
	return (preg_match("/^(\d+(?:\.\d+)?)([MKG]?b|%)$/", $val));
526
}
527

    
528
/* return the configured carp interface list */
529
function get_configured_carp_interface_list() {
530
	global $config;
531

    
532
	$iflist = array();
533

    
534
	if(is_array($config['virtualip']['vip'])) {
535
                $viparr = &$config['virtualip']['vip'];
536
                foreach ($viparr as $vip) {
537
                        switch ($vip['mode']) {
538
                        case "carp":
539
                        case "carpdev-dhcp":
540
				$vipif = "vip" . $vip['vhid'];
541
                        	$iflist[$vipif] = $vip['subnet'];
542
                                break;
543
                        }
544
                }
545
        }
546

    
547
	return $iflist;
548
}
549

    
550
/* return the configured IP aliases list */
551
function get_configured_ip_aliases_list() {
552
        global $config;
553

    
554
        $alias_list=array();
555

    
556
        if(is_array($config['virtualip']['vip'])) {
557
                $viparr = &$config['virtualip']['vip'];
558
                foreach ($viparr as $vip) {
559
                        if ($vip['mode']=="ipalias") {
560
                                $alias_list[$vip['subnet']] = $vip['interface'];
561
                        }
562
                }
563
        }
564

    
565
        return $alias_list;
566
}
567

    
568

    
569
/* comparison function for sorting by the order in which interfaces are normally created */
570
function compare_interface_friendly_names($a, $b) {
571
	if ($a == $b)
572
		return 0;
573
	else if ($a == 'wan')
574
		return -1;
575
	else if ($b == 'wan')
576
		return 1;
577
	else if ($a == 'lan')
578
		return -1;
579
	else if ($b == 'lan')
580
		return 1;
581

    
582
	return strnatcmp($a, $b);
583
}
584

    
585
/* return the configured interfaces list. */
586
function get_configured_interface_list($only_opt = false, $withdisabled = false) {
587
	global $config;
588

    
589
	$iflist = array();
590

    
591
	/* if list */
592
	foreach($config['interfaces'] as $if => $ifdetail) {
593
		if ($only_opt && ($if == "wan" || $if == "lan"))
594
			continue;
595
		if (isset($ifdetail['enable']) || $withdisabled == true)
596
			$iflist[$if] = $if;
597
	}
598

    
599
	return $iflist;
600
}
601

    
602
/* return the configured interfaces list. */
603
function get_configured_interface_list_by_realif($only_opt = false, $withdisabled = false) {
604
	global $config;
605

    
606
	$iflist = array();
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
			$tmpif = get_real_interface($if);
614
			if (!empty($tmpif))
615
				$iflist[$tmpif] = $if;
616
		}
617
	}
618

    
619
	return $iflist;
620
}
621

    
622
/* return the configured interfaces list with their description. */
623
function get_configured_interface_with_descr($only_opt = false, $withdisabled = false) {
624
	global $config;
625

    
626
	$iflist = array();
627

    
628
	/* if list */
629
	foreach($config['interfaces'] as $if => $ifdetail) {
630
		if ($only_opt && ($if == "wan" || $if == "lan"))
631
			continue;
632
		if (isset($ifdetail['enable']) || $withdisabled == true) {
633
			if(empty($ifdetail['descr']))
634
				$iflist[$if] = strtoupper($if);
635
			else
636
				$iflist[$if] = strtoupper($ifdetail['descr']);
637
		}
638
	}
639

    
640
	return $iflist;
641
}
642

    
643
/*
644
 *   get_configured_ip_addresses() - Return a list of all configured
645
 *   interfaces IP Addresses
646
 *
647
 */
648
function get_configured_ip_addresses() {
649
	require_once("interfaces.inc");
650
	$ip_array = array();
651
	$interfaces = get_configured_interface_list();
652
	if(is_array($interfaces)) {
653
		foreach($interfaces as $int) {
654
			$ipaddr = get_interface_ip($int);
655
			$ip_array[$int] = $ipaddr;
656
		}
657
	}
658
	$interfaces = get_configured_carp_interface_list();
659
	if(is_array($interfaces)) 
660
		foreach($interfaces as $int => $ipaddr) 
661
			$ip_array[$int] = $ipaddr;
662
	return $ip_array;
663
}
664

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

    
776
/****f* util/log_error
777
* NAME
778
*   log_error  - Sends a string to syslog.
779
* INPUTS
780
*   $error     - string containing the syslog message.
781
* RESULT
782
*   null
783
******/
784
function log_error($error) {
785
        global $g;
786
        $page = $_SERVER['SCRIPT_NAME'];
787
        syslog(LOG_WARNING, "$page: $error");
788
        if ($g['debug'])
789
                syslog(LOG_WARNING, var_dump(debug_backtrace()));
790
        return;
791
}
792

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

    
810
/****f* util/exec_command
811
 * NAME
812
 *   exec_command - Execute a command and return a string of the result.
813
 * INPUTS
814
 *   $command   - String of the command to be executed.
815
 * RESULT
816
 *   String containing the command's result.
817
 * NOTES
818
 *   This function returns the command's stdout and stderr.
819
 ******/
820
function exec_command($command) {
821
        $output = array();
822
        exec($command . ' 2>&1 ', $output);
823
        return(implode("\n", $output));
824
}
825

    
826
/* wrapper for exec() */
827
function mwexec($command, $mute = false) {
828
	global $g;
829

    
830
	if ($g['debug']) {
831
		if (!$_SERVER['REMOTE_ADDR'])
832
			echo "mwexec(): $command\n";
833
	}
834
	$oarr = array();
835
	$retval = 0;
836
	$garbage = exec("$command 2>&1", $oarr, $retval);
837

    
838
	if(isset($config['system']['developerspew']))
839
                $mute = false;
840
	if(($retval <> 0) && ($mute === false)) {
841
		$output = implode(" ", $oarr);
842
		log_error("The command '$command' returned exit code '$retval', the output was '$output' ");
843
	}
844
	return $retval;
845
}
846

    
847
/* wrapper for exec() in background */
848
function mwexec_bg($command) {
849

    
850
	global $g;
851

    
852
	if ($g['debug']) {
853
		if (!$_SERVER['REMOTE_ADDR'])
854
			echo "mwexec(): $command\n";
855
	}
856

    
857
	exec("nohup $command > /dev/null 2>&1 &");
858
}
859

    
860
/* unlink a file, if it exists */
861
function unlink_if_exists($fn) {
862
	$to_do = glob($fn);
863
	if(is_array($to_do)) {
864
		foreach($to_do as $filename)
865
			@unlink($filename);
866
	} else {
867
		@unlink($fn);
868
	}
869
}
870
/* make a global alias table (for faster lookups) */
871
function alias_make_table($config) {
872

    
873
	global $aliastable;
874

    
875
	$aliastable = array();
876

    
877
	if (is_array($config['aliases']['alias'])) {
878
		foreach ($config['aliases']['alias'] as $alias) {
879
			if ($alias['name'])
880
				$aliastable[$alias['name']] = $alias['address'];
881
		}
882
	}
883
}
884
/* check if an alias exists */
885
function is_alias($name) {
886

    
887
	global $aliastable;
888

    
889
	return isset($aliastable[$name]);
890
}
891

    
892
/* expand a host or network alias, if necessary */
893
function alias_expand($name) {
894

    
895
	global $aliastable;
896

    
897
	if (isset($aliastable[$name]))
898
		return "\${$name}";
899
	else if (is_ipaddr($name) || is_subnet($name) || is_port($name))
900
		return "{$name}";
901
	else
902
		return null;
903
}
904

    
905
function alias_expand_urltable($name) {
906
	global $config;
907
	$urltable_prefix = "/var/db/aliastables/";
908
	$urltable_filename = $urltable_prefix . $name . ".txt";
909

    
910
	foreach ($config['aliases']['alias'] as $alias) {
911
		if (($alias['type'] == 'urltable') && ($alias['name'] == $name)) {
912
			if (is_URL($alias["url"]) && file_exists($urltable_filename) && filesize($urltable_filename))
913
				return $urltable_filename;
914
			else if (process_alias_urltable($name, $alias["url"], 0, true))
915
				return $urltable_filename;
916
		}
917
	}
918
	return null;
919
}
920

    
921
/* find out whether two subnets overlap */
922
function check_subnets_overlap($subnet1, $bits1, $subnet2, $bits2) {
923

    
924
	if (!is_numeric($bits1))
925
		$bits1 = 32;
926
	if (!is_numeric($bits2))
927
		$bits2 = 32;
928

    
929
	if ($bits1 < $bits2)
930
		$relbits = $bits1;
931
	else
932
		$relbits = $bits2;
933

    
934
	$sn1 = gen_subnet_mask_long($relbits) & ip2long($subnet1);
935
	$sn2 = gen_subnet_mask_long($relbits) & ip2long($subnet2);
936

    
937
	if ($sn1 == $sn2)
938
		return true;
939
	else
940
		return false;
941
}
942

    
943
/* compare two IP addresses */
944
function ipcmp($a, $b) {
945
	if (ip_less_than($a, $b))
946
		return -1;
947
	else if (ip_greater_than($a, $b))
948
		return 1;
949
	else
950
		return 0;
951
}
952

    
953
/* return true if $addr is in $subnet, false if not */
954
function ip_in_subnet($addr,$subnet) {
955
	list($ip, $mask) = explode('/', $subnet);
956
	$mask = (0xffffffff << (32 - $mask)) & 0xffffffff;
957
	return ((ip2long($addr) & $mask) == (ip2long($ip) & $mask));
958
}
959

    
960
/* verify (and remove) the digital signature on a file - returns 0 if OK */
961
function verify_digital_signature($fname) {
962
	global $g;
963

    
964
	if(!file_exists("/usr/local/sbin/gzsig"))
965
		return 4;
966

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

    
970
/* obtain MAC address given an IP address by looking at the ARP table */
971
function arp_get_mac_by_ip($ip) {
972
	mwexec("/sbin/ping -c 1 -t 1 {$ip}", true);
973
	$arpoutput = "";
974
	exec("/usr/sbin/arp -n {$ip}", $arpoutput);
975

    
976
	if ($arpoutput[0]) {
977
		$arpi = explode(" ", $arpoutput[0]);
978
		$macaddr = $arpi[3];
979
		if (is_macaddr($macaddr))
980
			return $macaddr;
981
		else
982
			return false;
983
	}
984

    
985
	return false;
986
}
987

    
988
/* return a fieldname that is safe for xml usage */
989
function xml_safe_fieldname($fieldname) {
990
	$replace = array('/', '-', ' ', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')',
991
			 '_', '+', '=', '{', '}', '[', ']', '|', '/', '<', '>', '?',
992
			 ':', ',', '.', '\'', '\\'
993
		);
994
	return strtolower(str_replace($replace, "", $fieldname));
995
}
996

    
997
function mac_format($clientmac) {
998
    $mac =explode(":", $clientmac);
999

    
1000
    global $config;
1001

    
1002
    $mac_format = $config['captiveportal']['radmac_format'] ? $config['captiveportal']['radmac_format'] : false;
1003

    
1004
    switch($mac_format) {
1005

    
1006
        case 'singledash':
1007
        return "$mac[0]$mac[1]$mac[2]-$mac[3]$mac[4]$mac[5]";
1008

    
1009
        case 'ietf':
1010
        return "$mac[0]-$mac[1]-$mac[2]-$mac[3]-$mac[4]-$mac[5]";
1011

    
1012
        case 'cisco':
1013
        return "$mac[0]$mac[1].$mac[2]$mac[3].$mac[4]$mac[5]";
1014

    
1015
        case 'unformatted':
1016
        return "$mac[0]$mac[1]$mac[2]$mac[3]$mac[4]$mac[5]";
1017

    
1018
        default:
1019
        return $clientmac;
1020
    }
1021
}
1022

    
1023
function resolve_retry($hostname, $retries = 5) {
1024

    
1025
       if (is_ipaddr($hostname))
1026
               return $hostname;
1027

    
1028
       for ($i = 0; $i < $retries; $i++) {
1029
               $ip = gethostbyname($hostname);
1030

    
1031
               if ($ip && $ip != $hostname) {
1032
                       /* success */
1033
                       return $ip;
1034
               }
1035

    
1036
               sleep(1);
1037
       }
1038

    
1039
       return false;
1040
}
1041

    
1042
function format_bytes($bytes) {
1043
	if ($bytes >= 1073741824) {
1044
		return sprintf("%.2f GB", $bytes/1073741824);
1045
	} else if ($bytes >= 1048576) {
1046
		return sprintf("%.2f MB", $bytes/1048576);
1047
	} else if ($bytes >= 1024) {
1048
		return sprintf("%.0f KB", $bytes/1024);
1049
	} else {
1050
		return sprintf("%d bytes", $bytes);
1051
	}
1052
}
1053

    
1054
function update_filter_reload_status($text) {
1055
        global $g;
1056

    
1057
        file_put_contents("{$g['varrun_path']}/filter_reload_status", $text);
1058
}
1059

    
1060
/****f* util/return_dir_as_array
1061
 * NAME
1062
 *   return_dir_as_array - Return a directory's contents as an array.
1063
 * INPUTS
1064
 *   $dir       - string containing the path to the desired directory.
1065
 * RESULT
1066
 *   $dir_array - array containing the directory's contents. This array will be empty if the path specified is invalid.
1067
 ******/
1068
function return_dir_as_array($dir) {
1069
        $dir_array = array();
1070
        if (is_dir($dir)) {
1071
                if ($dh = opendir($dir)) {
1072
                        while (($file = readdir($dh)) !== false) {
1073
                                $canadd = 0;
1074
                                if($file == ".") $canadd = 1;
1075
                                if($file == "..") $canadd = 1;
1076
                                if($canadd == 0)
1077
                                        array_push($dir_array, $file);
1078
                        }
1079
                        closedir($dh);
1080
                }
1081
        }
1082
        return $dir_array;
1083
}
1084

    
1085
function run_plugins($directory) {
1086
        global $config, $g;
1087

    
1088
		/* process packager manager custom rules */
1089
		$files = return_dir_as_array($directory);
1090
		if (is_array($files)) {
1091
			foreach ($files as $file) {
1092
				if (stristr($file, ".sh") == true)
1093
					mwexec($directory . $file . " start");
1094
				else if (!is_dir($directory . "/" . $file) && stristr($file,".inc")) 
1095
					require_once($directory . "/" . $file);
1096
			}
1097
		}
1098
}
1099

    
1100
/*
1101
 *    safe_mkdir($path, $mode = 0755)
1102
 *    create directory if it doesn't already exist and isn't a file!
1103
 */
1104
function safe_mkdir($path, $mode=0755) {
1105
        global $g;
1106

    
1107
        if (!is_file($path) && !is_dir($path)) {
1108
                return @mkdir($path, $mode, true);
1109
        } else {
1110
                return false;
1111
        }
1112
}
1113

    
1114
/*
1115
 * make_dirs($path, $mode = 0755)
1116
 * create directory tree recursively (mkdir -p)
1117
 */
1118
function make_dirs($path, $mode = 0755) {
1119
        $base = '';
1120
        foreach (explode('/', $path) as $dir) {
1121
                $base .= "/$dir";
1122
                if (!is_dir($base)) {
1123
                        if (!@mkdir($base, $mode))
1124
                                return false;
1125
                }
1126
        }
1127
        return true;
1128
}
1129

    
1130
/*
1131
 * get_sysctl($names)
1132
 * Get values of sysctl OID's listed in $names (accepts an array or a single
1133
 * name) and return an array of key/value pairs set for those that exist
1134
 */
1135
function get_sysctl($names) {
1136
	if (empty($names))
1137
		return array();
1138

    
1139
	if (is_array($names)) {
1140
		$name_list = array();
1141
		foreach ($names as $name) {
1142
			$name_list[] = escapeshellarg($name);
1143
		}
1144
	} else
1145
		$name_list = array(escapeshellarg($names));
1146

    
1147
	exec("/sbin/sysctl -i " . implode(" ", $name_list), $output);
1148
	$values = array();
1149
	foreach ($output as $line) {
1150
		$line = explode(": ", $line, 2);
1151
		if (count($line) == 2)
1152
			$values[$line[0]] = $line[1];
1153
	}
1154

    
1155
	return $values;
1156
}
1157

    
1158
/*
1159
 * set_sysctl($value_list)
1160
 * Set sysctl OID's listed as key/value pairs and return
1161
 * an array with keys set for those that succeeded
1162
 */
1163
function set_sysctl($values) {
1164
	if (empty($values))
1165
		return array();
1166

    
1167
	$value_list = array();
1168
	foreach ($values as $key => $value) {
1169
		$value_list[] = escapeshellarg($key) . "=" . escapeshellarg($value);
1170
	}
1171

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

    
1174
	/* Retry individually if failed (one or more read-only) */
1175
	if ($success <> 0 && count($value_list) > 1) {
1176
		foreach ($value_list as $value) {
1177
			exec("/sbin/sysctl -i " . $value, $output);
1178
		}
1179
	}
1180

    
1181
	$ret = array();
1182
	foreach ($output as $line) {
1183
		$line = explode(": ", $line, 2);
1184
		if (count($line) == 2)
1185
			$ret[$line[0]] = true;
1186
	}
1187

    
1188
	return $ret;
1189
}
1190

    
1191
/*
1192
 *     get_memory()
1193
 *     returns an array listing the amount of
1194
 *     memory installed in the hardware
1195
 *     [0]real and [1]available
1196
 */
1197
function get_memory() {
1198
		$matches = "";
1199
        if(file_exists("/var/log/dmesg.boot"))
1200
			$mem = `cat /var/log/dmesg.boot | grep memory`;
1201
		else
1202
			$mem = `dmesg -a | grep memory`;			
1203
		if (preg_match_all("/avail memory.* \((.*)MB\)/", $mem, $matches)) 
1204
			return array($matches[1][0], $matches[1][0]);
1205
		if(!$real && !$avail) {
1206
			$real = trim(`sysctl hw.physmem | cut -d' ' -f2`);
1207
			$avail = trim(`sysctl hw.realmem | cut -d' ' -f2`);
1208
			/* convert from bytes to megabytes */
1209
			return array(($real/1048576),($avail/1048576));
1210
		}
1211
}
1212

    
1213
function mute_kernel_msgs() {
1214
		global $config;
1215
		// Do not mute serial console.  The kernel gets very very cranky
1216
		// and will start dishing you cannot control tty errors.
1217
		if(trim(file_get_contents("/etc/platform")) == "nanobsd") 
1218
			return;
1219
		if($config['system']['enableserial']) 
1220
			return;			
1221
		exec("/sbin/conscontrol mute on");
1222
}
1223

    
1224
function unmute_kernel_msgs() {
1225
		global $config;
1226
		// Do not mute serial console.  The kernel gets very very cranky
1227
		// and will start dishing you cannot control tty errors.
1228
		if(trim(file_get_contents("/etc/platform")) == "nanobsd") 
1229
			return;
1230
		exec("/sbin/conscontrol mute off");
1231
}
1232

    
1233
function start_devd() {
1234
	global $g;
1235

    
1236
        exec("/sbin/devd");
1237
        sleep(1);
1238
}
1239

    
1240
function is_interface_vlan_mismatch() {
1241
        global $config, $g;
1242

    
1243
        if (is_array($config['vlans']['vlan'])) {
1244
                foreach ($config['vlans']['vlan'] as $vlan) {
1245
                        if (does_interface_exist($vlan['if']) == false)
1246
				return true;
1247
                }
1248
        }
1249

    
1250
	return false;
1251
}
1252

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

    
1256
        /* XXX: Should we process only enabled interfaces?! */
1257
        $do_assign = false;
1258
        $i = 0;
1259
	if (is_array($config['interfaces'])) {
1260
        	foreach ($config['interfaces'] as $ifname => $ifcfg) {
1261
                	if (preg_match("/^enc|^cua|^tun|^l2tp|^pptp|^ppp|^ovpn|^gif|^gre|^lagg|^bridge|vlan|_wlan/i", $ifcfg['if'])) {
1262
                        	$i++;
1263
                	}
1264
                	else if (does_interface_exist($ifcfg['if']) == false) {
1265
				$do_assign = true;
1266
                	} else
1267
                        	$i++;
1268
        	}
1269
	}
1270

    
1271
        if ($g['minimum_nic_count'] > $i) {
1272
                $do_assign = true;
1273
        } else if (file_exists("{$g['tmp_path']}/assign_complete"))
1274
                $do_assign = false;
1275

    
1276
        return $do_assign;
1277
}
1278

    
1279
/* sync carp entries to other firewalls */
1280
function carp_sync_client() {
1281
	global $g;
1282
	send_event("filter sync");
1283
}
1284

    
1285
/****f* util/isAjax
1286
 * NAME
1287
 *   isAjax - reports if the request is driven from prototype
1288
 * INPUTS
1289
 *   none
1290
 * RESULT
1291
 *   true/false
1292
 ******/
1293
function isAjax() {
1294
        return isset ($_SERVER['HTTP_X_REQUESTED_WITH']) && $_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest';
1295
}
1296

    
1297
/****f* util/timeout
1298
 * NAME
1299
 *   timeout - console input with timeout countdown. Note: erases 2 char of screen for timer. Leave space.
1300
 * INPUTS
1301
 *   optional, seconds to wait before timeout. Default 9 seconds.
1302
 * RESULT
1303
 *   returns 1 char of user input or null if no input.
1304
 ******/
1305
function timeout($timer = 9) {
1306
	while(!isset($key)) {
1307
		if ($timer >= 9) { echo chr(8) . chr(8) . ($timer==9 ? chr(32) : null)  . "{$timer}";  }
1308
		else { echo chr(8). "{$timer}"; }
1309
		`/bin/stty -icanon min 0 time 25`;
1310
		$key = trim(`KEY=\`dd count=1 2>/dev/null\`; echo \$KEY`);
1311
		`/bin/stty icanon`;
1312
		if ($key == '')
1313
			unset($key);
1314
		$timer--;
1315
		if ($timer == 0)
1316
			break;
1317
	}
1318
	return $key;	
1319
}
1320

    
1321
/****f* util/msort
1322
 * NAME
1323
 *   msort - sort array
1324
 * INPUTS
1325
 *   $array to be sorted, field to sort by, direction of sort
1326
 * RESULT
1327
 *   returns newly sorted array
1328
 ******/
1329
function msort($array, $id="id", $sort_ascending=true) {
1330
	$temp_array = array();
1331
	while(count($array)>0) {
1332
		$lowest_id = 0;
1333
		$index=0;
1334
		foreach ($array as $item) {
1335
			if (isset($item[$id])) {
1336
				if ($array[$lowest_id][$id]) {
1337
					if (strtolower($item[$id]) < strtolower($array[$lowest_id][$id])) {
1338
						$lowest_id = $index;
1339
					}
1340
				}
1341
			}
1342
			$index++;
1343
		}
1344
		$temp_array[] = $array[$lowest_id];
1345
		$array = array_merge(array_slice($array, 0,$lowest_id), array_slice($array, $lowest_id+1));
1346
	}
1347
	if ($sort_ascending) {
1348
		return $temp_array;
1349
	} else {
1350
    	return array_reverse($temp_array);
1351
	}
1352
}
1353

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

    
1427
/****f* util/is_URL
1428
 * NAME
1429
 *   is_URL
1430
 * INPUTS
1431
 *   string to check
1432
 * RESULT
1433
 *   Returns true if item is a URL
1434
 ******/
1435
function is_URL($url) {
1436
	$match = preg_match("'\b(([\w-]+://?|www[.])[^\s()<>]+(?:\([\w\d]+\)|([^[:punct:]\s]|/)))'", $url);
1437
	if($match)
1438
		return true;	
1439
	return false;
1440
}
1441

    
1442
function is_file_included($file = "") {
1443
	$files = get_included_files();
1444
	if (in_array($file, $files))
1445
		return true;
1446
	
1447
	return false;
1448
}
1449

    
1450
/*
1451
	This function was borrowed from a comment on PHP.net at the following URL:
1452
	http://www.php.net/manual/en/function.array-merge-recursive.php#73843
1453
 */
1454
function array_merge_recursive_unique($array0, $array1)
1455
{
1456
    $arrays = func_get_args();
1457
    $remains = $arrays;
1458

    
1459
    // We walk through each arrays and put value in the results (without
1460
    // considering previous value).
1461
    $result = array();
1462

    
1463
    // loop available array
1464
    foreach($arrays as $array) {
1465

    
1466
        // The first remaining array is $array. We are processing it. So
1467
        // we remove it from remaing arrays.
1468
        array_shift($remains);
1469

    
1470
        // We don't care non array param, like array_merge since PHP 5.0.
1471
        if(is_array($array)) {
1472
            // Loop values
1473
            foreach($array as $key => $value) {
1474
                if(is_array($value)) {
1475
                    // we gather all remaining arrays that have such key available
1476
                    $args = array();
1477
                    foreach($remains as $remain) {
1478
                        if(array_key_exists($key, $remain)) {
1479
                            array_push($args, $remain[$key]);
1480
                        }
1481
                    }
1482

    
1483
                    if(count($args) > 2) {
1484
                        // put the recursion
1485
                        $result[$key] = call_user_func_array(__FUNCTION__, $args);
1486
                    } else {
1487
                        foreach($value as $vkey => $vval) {
1488
                            $result[$key][$vkey] = $vval;
1489
                        }
1490
                    }
1491
                } else {
1492
                    // simply put the value
1493
                    $result[$key] = $value;
1494
                }
1495
            }
1496
        }
1497
    }
1498
    return $result;
1499
}
1500

    
1501
?>
(49-49/61)