Project

General

Profile

Download (39.7 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
	if (!preg_match("/[^a-zA-Z0-9_]/", $name) && (strlen($name) < 32))
477
		return true;
478
	else
479
		return false;
480
}
481

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

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

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

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

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

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

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

    
531
	$iflist = array();
532

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

    
546
	return $iflist;
547
}
548

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

    
553
        $alias_list=array();
554

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

    
564
        return $alias_list;
565
}
566

    
567

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

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

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

    
588
	$iflist = array();
589

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

    
598
	return $iflist;
599
}
600

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

    
605
	$iflist = array();
606

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

    
618
	return $iflist;
619
}
620

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

    
625
	$iflist = array();
626

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

    
639
	return $iflist;
640
}
641

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

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

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

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

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

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

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

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

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

    
849
	global $g;
850

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

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

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

    
872
	global $aliastable;
873

    
874
	$aliastable = array();
875

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

    
886
	global $aliastable;
887

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

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

    
894
	global $aliastable;
895

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
984
	return false;
985
}
986

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

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

    
999
    global $config;
1000

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

    
1003
    switch($mac_format) {
1004

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

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

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

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

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

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

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

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

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

    
1035
               sleep(1);
1036
       }
1037

    
1038
       return false;
1039
}
1040

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

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

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

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

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

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

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

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

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

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

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

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

    
1154
	return $values;
1155
}
1156

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

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

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

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

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

    
1187
	return $ret;
1188
}
1189

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

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

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

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

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

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

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

    
1249
	return false;
1250
}
1251

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

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

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

    
1275
        return $do_assign;
1276
}
1277

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1500
?>
(49-49/61)