1 : <?php
2 :
3 : /**
4 : * PHPDevShell is a RAD Framework aimed at developing administrative applications.
5 : *
6 : * @package PHPDevShell
7 : * @link http://www.phpdevshell.org
8 : * @copyright Copyright (C) 2007 Jason Schoeman, All rights reserved.
9 : * @license GNU/LGPL, see readme/licensed_under_lgpl or http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html
10 : *
11 : * Copyright notice: See readme/notice
12 : * By using PHPDevShell you agree to notice and license, if you dont agree to terms you are not allowed to use PHPDevShell.
13 : */
14 :
15 : /**
16 : * Build array from get url.
17 : *
18 : * TODO: it's probably faster to use PHP build-in function (array_merge...)
19 : *
20 : * @param array $myGET
21 : * @param array $includeInGet
22 : * @param array $excludeFromGet
23 : * @return array
24 : *
25 : * @date 20110809 (v1.0.1) (greg) fixed a typo with $includeInGet
26 : * @author greg
27 : */
28 : function PU_BuildGETArray(array $myGET, $includeInGet = null, $excludeFromGet = null)
29 : {
30 4 : if (!is_null($includeInGet)) {
31 4 : if (!is_array($includeInGet)) $includeInGet = array($includeInGet);
32 4 : foreach ($includeInGet as $index => $value)
33 4 : $myGET[$index] = $value;
34 4 : }
35 4 : if (!is_null($excludeFromGet)) {
36 3 : if (!is_array($excludeFromGet)) $excludeFromGet = array($excludeFromGet);
37 3 : foreach ($excludeFromGet as $param)
38 3 : unset($myGET[$param]);
39 3 : }
40 4 : return $myGET;
41 : }
42 :
43 : /**
44 : * Creates a (string) url to be used with GET, including encoding
45 : *
46 : * @param array $myGET
47 : * @param string $glue
48 : * @return string
49 : */
50 : function PU_BuildGETString(array $myGET, $glue = '&')
51 : {
52 4 : $url = '';
53 4 : if (count($myGET)) {
54 4 : $params = array();
55 4 : foreach ($myGET as $index => $value)
56 4 : $params[] .= rawurlencode($index) . '=' . rawurlencode($value);
57 4 : $url = '?' . implode($glue, $params);
58 4 : }
59 4 : return $url;
60 : }
61 :
62 : /**
63 : * Build GET part of a url
64 : *
65 : * @param $includeInGet (optional) array of pairs: parameters to add as GET in the url
66 : * @param $excludeFromGet (optional) array of strings: parameters to remove from GET in the url
67 : * @return string the whole parameter part of the url (including '?') ; maybe empty if there are no parameters
68 : */
69 : function PU_BuildGET($includeInGet = null, $excludeFromGet = null, $glue = '&')
70 : {
71 2 : return PU_BuildGETString(PU_BuildGETArray($_GET, $includeInGet, $excludeFromGet), $glue);
72 : }
73 :
74 : /**
75 : * Build a xml-style attributes string based on an array
76 : *
77 : * @version 1.1
78 : * @date 20091203
79 : * @date 20110203 (v1.1) (greg) added the glue parameter
80 : * @param $attributes array, the attribute array to compile
81 : * @param $glue string, a piece of string to insert between the values
82 : * @return string
83 : */
84 : function PU_BuildAttrString(array $attributes = null, $glue = '')
85 : {
86 1 : $result = '';
87 1 : if (is_array($attributes))
88 1 : foreach ($attributes as $key => $value) {
89 1 : if ($result && $glue) $result .= $glue;
90 1 : $result .= " $key=\"$value\"";
91 1 : }
92 1 : return $result;
93 : }
94 :
95 : /**
96 : * Builds a parsed url.
97 : *
98 : * @param array $p
99 : * @return string
100 : */
101 : function PU_buildParsedURL($p)
102 : {
103 1 : if (!is_array($p)) return $p;
104 :
105 1 : if (empty($p['scheme'])) $p['scheme'] = 'http';
106 1 : if (empty($p['host'])) $p['host'] = $_SERVER["HTTP_HOST"];
107 1 : if (empty($p['port'])) $p['port'] = ''; else $p['port'] = ':' . $p['port'];
108 1 : if (empty($p['user'])) $p['user'] = '';
109 1 : if (empty($p['pass'])) $p['pass'] = '';
110 1 : if (empty($p['path'])) $p['path'] = $_SERVER["PHP_SELF"];
111 1 : if (empty($p['query'])) $p['query'] = '';
112 1 : if (empty($p['fragment'])) $p['fragment'] = ''; else
113 0 : $p['fragment'] = '#' . $p['fragment'];
114 :
115 1 : $auth = ($p['user'] || $p['pass']) ? $p['user'] . ':' . $p['pass'] . '@' : '';
116 :
117 1 : if ($p['query'] && ('?' != substr($p['query'], 0, 1)))
118 1 : $p['query'] = '?' . $p['query'];
119 :
120 1 : if ('/' == substr($p['path'], 0, 1))
121 1 : $url = $p['scheme'] . '://' . $auth . $p['host'] . $p['port'] . $p['path'] . $p['query'] . $p['fragment'];
122 1 : else $url = $p['path'] . $p['query'] . $p['fragment'];
123 :
124 1 : return $url;
125 : }
126 :
127 : /**
128 : * Build a url with GET parameters
129 : *
130 : * @param string|array $target (optional) string: the target script url (current script if missing)
131 : * @param array $includeInGet (optional) array of pairs: parameters to add as GET in the url
132 : * @param array $excludeFromGet (optional) array of strings: parameters to remove from GET in the url
133 : * @return string the built url
134 : *
135 : * @version 1.1
136 : * @author greg
137 : *
138 : * @date 20100930 (v1.1) (greg) $target parameter can now be an array resulting from php's parse_url function
139 : */
140 : function PU_BuildURL($target = null, $includeInGet = null, $excludeFromGet = null, $glue = '&')
141 : {
142 1 : if (is_null($target)) $target = $_SERVER["REQUEST_URI"];
143 1 : if (!is_array($target)) $target = parse_url($target);
144 :
145 1 : if (empty($target['query'])) $tarGET = $_GET;
146 : else {
147 1 : parse_str($target['query'], $tarGET);
148 1 : $tarGET = array_merge($_GET, $tarGET);
149 : }
150 1 : $myGET = PU_BuildGETArray($tarGET, $includeInGet, $excludeFromGet);
151 1 : $target['query'] = PU_BuildGETString($myGET, $glue);
152 1 : $target = PU_buildParsedURL($target);
153 1 : return $target;
154 : }
155 :
156 : /**
157 : * Build a html link (A+HREF html tag) with label and url and GET parameters
158 : *
159 : * @version 1.0.1
160 : * @date 20091203: added $attrs parameter
161 : * @param $label string: the text of the link
162 : * @param $includeInGet (optional) array of pairs: parameters to add as GET in the url
163 : * @param $excludeFromGet (optional) array of strings: parameters to remove from GET in the url
164 : * @param $target (optional) string: the target script url (current script if missing)
165 : * @return string the complete html link
166 : */
167 : function PU_BuildHREF($label, $includeInGet = null, $excludeFromGet = null, $target = null, array $attrs = null)
168 : {
169 0 : $url = PU_BuildURL($target, $includeInGet, $excludeFromGet);
170 0 : $href = '<a href="' . $url . '">' . $label . '</a>';
171 0 : return $href;
172 : }
173 :
174 : /**
175 : * Clean a string from possibly harmful chars
176 : *
177 : * These are removed: single and double quotes, backslashes, optionnaly html tags (everything between < and >)
178 : *
179 : * A cleaned string should be safe to include in an html output
180 : *
181 : * @param $string the string to clean
182 : * @param $clean_htlm if true, HTML tags are deleted too
183 : *
184 : * @return string
185 : */
186 : function PU_CleanString($string, $clean_htlm = false)
187 : {
188 1 : $string = preg_replace('/["\'\\\\]/', '', $string);
189 1 : if ($clean_htlm) $string = preg_replace('/<.+>/', '', $string);
190 1 : return $string;
191 : }
192 :
193 : /**
194 : * Convert a string to UTF8 (default) or to HTML
195 : *
196 : * @param $string the string to convert
197 : * @param $htmlize if true the string is converted to HTML, otherwise to UTF8
198 : *
199 : * @return string
200 : */
201 : function PU_MakeString($string, $htmlize = false)
202 : {
203 0 : if (!empty($string)) {
204 0 : $from = mb_detect_encoding($string, "UTF-8, ISO-8859-1, ISO-8859-15", true);
205 0 : $to = ($htmlize ? 'HTML-ENTITIES' : 'UTF-8');
206 0 : $string = mb_convert_encoding($string, $to, $from);
207 0 : }
208 0 : return $string;
209 : }
210 :
211 : /**
212 : * Search for array values inside array and returns key.
213 : *
214 : * @param array $needle
215 : * @param array $haystack
216 : * @return mixed
217 : */
218 : function PU_ArraySearch($needle, $haystack)
219 : {
220 0 : if (empty($needle) || empty($haystack)) {
221 0 : return false;
222 : }
223 :
224 0 : foreach ($haystack as $key => $value) {
225 0 : $exists = 0;
226 0 : foreach ($needle as $nkey => $nvalue) {
227 0 : if (!empty($value[$nkey]) && $value[$nkey] == $nvalue) {
228 0 : $exists = 1;
229 0 : } else {
230 0 : $exists = 0;
231 : }
232 0 : }
233 0 : if ($exists) return $key;
234 0 : }
235 :
236 0 : return false;
237 : }
238 :
239 : /**
240 : * Create gettext functions.
241 : */
242 : if (function_exists('gettext')) {
243 :
244 : /**
245 : * Wrapper for $core->__() method.
246 : * Converts text to use gettext PO system. Does the same as $core->__();
247 : *
248 : * @param string $say_what The string required to output or convert.
249 : * @param string $domain Override textdomain that should be looked under for this text string.
250 : * @return string Will return converted string or same string if not available.
251 : * @author Jason Schoeman
252 : */
253 : function __($gettext, $domain = false)
254 : {
255 : // Do we have a textdomain override value?
256 0 : if (empty($domain)) {
257 : // Normal gettext in current domain.
258 0 : return gettext("$gettext");
259 : } else {
260 : // Lets handle text inside a different domain.
261 0 : return dgettext("$domain", "$gettext");
262 : }
263 : }
264 :
265 : /**
266 : * Specifically meant for core translation domain.
267 : *
268 : * @param string $say_what The string required to output or convert.
269 : * @return string
270 : */
271 : function ___($gettext)
272 : {
273 2 : return dgettext('core.lang', "$gettext");
274 : }
275 :
276 : /**
277 : * This function echos the returning text.
278 : *
279 : * @param text $text
280 : */
281 : function _e($text)
282 : {
283 0 : echo gettext($text);
284 0 : }
285 :
286 : /**
287 : * This function echos the returning text inside a domain.
288 : *
289 : * @param text $text
290 : */
291 : function __e($text, $domain)
292 : {
293 0 : echo dgettext($domain, $text);
294 0 : }
295 : } else {
296 :
297 : /**
298 : * Specifically meant for core translation domain.
299 : *
300 : * @param string $say_what The string required to output or convert.
301 : * @return string
302 : */
303 : function ___($gettext)
304 : {
305 0 : return dgettext('core.lang', "$gettext");
306 : }
307 :
308 : // Create dummy functions.
309 : function gettext($text)
310 : {
311 0 : return $text;
312 : }
313 :
314 : function dgettext($domain, $text)
315 : {
316 0 : return $text;
317 : }
318 :
319 : function _($text)
320 : {
321 0 : return $text;
322 : }
323 :
324 : function __($gettext, $domain = false)
325 : {
326 0 : return $gettext;
327 : }
328 :
329 : function _e($text)
330 : {
331 0 : echo $text;
332 0 : }
333 :
334 : function __e($text)
335 : {
336 0 : echo $text;
337 0 : }
338 :
339 : function textdomain ($textdomain)
340 : {
341 0 : return '';
342 : }
343 : }
344 :
345 : /**
346 : * Outputs an array in html
347 : *
348 : * A slightly better version of print_r()
349 : *
350 : * @version 1.2
351 : * @author greg
352 : *
353 : * @date 20100825 (greg) (v1.1) updated to deal with associative arrays
354 : * @date 20110211 (greg) (v1.2) added $htmlize parameter
355 : *
356 : * @param array $a
357 : * @param string $title
358 : * @param boolean $htmlize (default to false) if true html is escaped to be displayed as source
359 : */
360 : function PU_dumpArray($a, $title = null, $htmlize = false)
361 : {
362 21 : if (!is_array($a)) $a = array($a);
363 21 : $s = '';
364 21 : if ($title) $s .= "<p>$title</p>";
365 :
366 21 : if (count($a) == 0) $s .= '<p>Empty array</p>';
367 : else {
368 21 : $s .= '<ul>';
369 21 : foreach ($a as $k => $e) {
370 21 : if ($htmlize) $e = htmlentities($e);
371 21 : $s .= "<li><i>[ $k ] =></i> $e</li>";
372 21 : }
373 21 : $s .= '</ul>';
374 : }
375 21 : return $s;
376 : }
377 :
378 : /**
379 : * Get rid of all buffer, optionaly flushing (i.e. writing to the browser)
380 : * Default behavior is to ignore.
381 : *
382 : * @param boolean $flush do we flush or ignore?
383 : */
384 : function PU_cleanBuffers($flush = false)
385 : {
386 : try {
387 2 : for ($loop = ob_get_level(); $loop; $loop--) {
388 1 : $flush ? ob_end_flush() : ob_end_clean();
389 1 : }
390 2 : } catch (Exception $e) {
391 : // only mask the exception and prevent it from bubbling
392 0 : $a = 0;
393 0 : } catch (ErrorException $e) {
394 : // only mask the exception and prevent it from bubbling
395 0 : $a = 0;
396 0 : } catch (PHPDS_fatalError $e) {
397 : // only mask the exception and prevent it from bubbling
398 0 : $a = 0;
399 : }
400 2 : }
401 :
402 : /**
403 : * Add a header if and only if headers have not been sent yet
404 : *
405 : * @param string $header the header string to add
406 : * @return nothing
407 : *
408 : * @version 1.0
409 : * @since 3.0.6
410 : * @date 20110809 (v1.0) (greg) added
411 : * @author greg <greg@phpdevshell.org>
412 : */
413 : function PU_silentHeader($header)
414 : {
415 2 : if (!headers_sent()) {
416 0 : header($header);
417 0 : }
418 2 : }
419 :
420 : /**
421 : * Determines if the current request has been made by some kind of ajax call (i.e. XMLHttpRequest)
422 : *
423 : * @param boolean $json set to true if you want to force the request's result as json
424 : * @return boolean
425 : *
426 : * @version 1.0.1
427 : * @date 20110809 (v1.0.1) (greg) use PU_silentHeader to prevent unit tests from failing
428 : * @author greg <greg@phpdevshell.org>
429 : */
430 : function PU_isAJAX($json = false)
431 : {
432 4 : $ajax = isset($_SERVER["HTTP_X_REQUESTED_WITH"]) && ($_SERVER["HTTP_X_REQUESTED_WITH"] == 'XMLHttpRequest');
433 4 : if ($ajax && $json) {
434 2 : PU_cleanBuffers();
435 2 : PU_silentHeader('Content-Type: application/json');
436 2 : }
437 4 : return $ajax;
438 : }
439 :
440 : /**
441 : * Checks for a json context and if so, outputs data
442 : *
443 : * @author greg <greg@phpdevshell.org>
444 : * @version 1.1
445 : * @since v3.0.1
446 : * @date 20110309 (v1.0) (greg) added
447 : * @date 20110316 (v1.1) (greg) returns instead of printing (for buffering)
448 : *
449 : * @param $data mixed, the data to be encoded and sent
450 : * @param $force boolean, (optionnal) do we pretend it's json context even if it's not?
451 : * @return boolean, false if it's not JSON, or the encoded data
452 : */
453 : function PU_isJSON($data, $force = false)
454 : {
455 5 : $json = $force || (isset($_SERVER["HTTP_X_REQUESTED_TYPE"]) && ($_SERVER["HTTP_X_REQUESTED_TYPE"] == 'json'));
456 5 : if ($json && PU_isAJAX(true)) {
457 2 : return json_encode($data);
458 : }
459 4 : return false;
460 : }
461 :
462 : /**
463 : * OBSOLETE don't use
464 : *
465 : * @param $data
466 : */
467 : function PU_exitToAJAX($data)
468 : {
469 0 : PU_isAJAX(true);
470 0 : print json_encode($data);
471 0 : exit;
472 : }
473 :
474 : /**
475 : * Get rid of null values inside an array
476 : *
477 : * All values which are null in the array are remove, shortening the array
478 : *
479 : * @param array $a the array to compact
480 : */
481 : function PU_array_compact(array $a)
482 : {
483 21 : array_walk($a, create_function('&$v,$k,$a', 'if (is_null($a[$k])) unset($a[$k]);'), $a);
484 21 : return $a;
485 : }
486 :
487 :
488 :
489 :
490 :
491 :
492 :
493 : /**
494 : * version of sprintf for cases where named arguments are desired (python syntax)
495 : *
496 : * with sprintf: sprintf('second: %2$s ; first: %1$s', '1st', '2nd');
497 : *
498 : * with sprintfn: sprintfn('second: %(second)s ; first: %(first)s', array(
499 : * 'first' => '1st',
500 : * 'second'=> '2nd'
501 : * ));
502 : * @author nate at frickenate dot com
503 : * @param string $format sprintf format string, with any number of named arguments
504 : * @param array $args array of [ 'arg_name' => 'arg value', ... ] replacements to be made
505 : * @return string|false result of sprintf call, or bool false on error
506 : */
507 : function PU_sprintfn($format, array $args = array())
508 : {
509 : try {
510 : // map of argument names to their corresponding sprintf numeric argument value
511 21 : $arg_nums = array_slice(array_flip(array_keys(array(0 => 0) + $args)), 1);
512 :
513 : // find the next named argument. each search starts at the end of the previous replacement.
514 21 : for ($pos = 0; preg_match('/(?<=%)\(([a-zA-Z_]\w*)\)/', $format, $match, PREG_OFFSET_CAPTURE, $pos);) {
515 21 : $arg_pos = $match[0][1];
516 21 : $arg_len = strlen($match[0][0]);
517 21 : $arg_key = $match[1][0];
518 :
519 : // programmer did not supply a value for the named argument found in the format string
520 21 : if (!array_key_exists($arg_key, $arg_nums)) {
521 0 : throw new PHPDS_Exception("Missing named argument '${arg_key}'");
522 : }
523 :
524 : // replace the named argument with the corresponding numeric one
525 21 : $format = substr_replace($format, $replace = $arg_nums[$arg_key] . '$', $arg_pos, $arg_len);
526 21 : $pos = $arg_pos + strlen($replace); // skip to end of replacement for next iteration
527 21 : }
528 :
529 21 : $result = vsprintf($format, array_values($args));
530 21 : return $result;
531 1 : } catch (Exception $e) {
532 1 : throw new PHPDS_sprintfnException($format, $args, $e);
533 : }
534 : }
535 :
536 :
537 : /**
538 : * Create a html string of <options> from an associative array
539 : *
540 : * @version 1.0.1
541 : * @date 20101021 (v1.0.1) (greg) added checks on $a ; removed htmlentities
542 : * @author greg
543 : *
544 : * @param array $a
545 : * @param string|array $selected which key(s) should be marked as "selected" (optional)
546 : * @return string the html to display
547 : */
548 : function PU_buildHTMLoptions($a, $selected = null)
549 : {
550 0 : $options = '';
551 0 : if (is_array($a) && (count($a) > 0))
552 0 : foreach ($a as $key => $value) {
553 0 : $options .= '<option value="' . htmlspecialchars($key) . '"';
554 0 : if (($key == $selected) || (is_array($selected) && in_array($key, $selected)))
555 0 : $options .=' selected ';
556 0 : $options .= '>' . ($value) . '</option>';
557 0 : }
558 0 : return $options;
559 : }
560 :
561 : /**
562 : * Add an include path to check in for classes.
563 : * @param string $path
564 : */
565 : function PU_addIncludePath($path)
566 : {
567 0 : if (!empty($path) && is_string($path)) {
568 0 : set_include_path(get_include_path() . PATH_SEPARATOR . $path);
569 0 : }
570 0 : }
571 :
572 : /**
573 : * A class to deal with tree-structured data (such as groups)
574 : *
575 : * Usage:
576 : * $tree = new PU_tree
577 : * $tree->add(1, 0); // add a root node
578 : * $tree->add(2, 1, 'leaf'); // add a named leaf to the root node
579 : * $tree->climb(); // study the tree YOU HAVE TO DO THAT BEFORE ACTUALLY USING THE TREE
580 : *
581 : * @author greg
582 : * @date 20100514
583 : * @version 1.0
584 : *
585 : */
586 : class PU_tree
587 : {
588 : /**
589 : * Associative array of the nodes (element ref => element, usually a label)
590 : *
591 : * @var array
592 : */
593 : protected $elements = array(0);
594 : /**
595 : * Associative array: for each node (by ref), what are the nodes upper in the tree
596 : *
597 : * @var array
598 : */
599 : protected $ascendants = array();
600 : /**
601 : * Associative array: for each node (by ref), what are the nodes lower in the tree
602 : *
603 : * @var array
604 : */
605 : protected $descendants = array();
606 :
607 : /**
608 : * Add an element to the tree. When all elements are added, you MUST call climb()
609 : *
610 : * @param mixed $leaf the new element ref
611 : * @param mixed $node the element onto this new element is stuck
612 : * @param mixed $label an optional label to display
613 : * @return this
614 : */
615 : public function add($leaf, $node, $label = '')
616 : {
617 0 : $this->elements[$leaf] = $label;
618 0 : $this->descendants[$node][] = $leaf;
619 :
620 0 : return $this;
621 : }
622 :
623 : /**
624 : * Climb the tree in order to fill the descendant array.
625 : * Don't call it with parameter
626 : *
627 : * @param unknown_type $branch
628 : * @return this
629 : */
630 : public function climb($branch = 0)
631 : {
632 0 : if (! empty($this->descendants[$branch]) && is_array($this->descendants[$branch])) {
633 0 : foreach ($this->descendants[$branch] as $leaf) {
634 0 : $this->ascendants[$leaf] = (empty($branch)) ? array() : $this->ascendants[$branch];
635 0 : if ($branch) $this->ascendants[$leaf][] = $branch;
636 0 : $this->climb($leaf);
637 0 : }
638 0 : }
639 0 : return $this;
640 : }
641 :
642 : /**
643 : * Returns the ascendants of the given node, either as array or as a string for sql
644 : *
645 : * @param $node the node which ascendants are asked
646 : * @param $as_array boolean, do you want an array (true) or a string (false)
647 : * @return array or string
648 : */
649 : public function ascendants($node, $as_array = false)
650 : {
651 : if ($as_array)
652 0 : return (isset($this->ascendants[$node]) ? $this->ascendants[$node] : array());
653 : else
654 0 : return (isset($this->ascendants[$node]) ? implode(',', $this->ascendants[$node]) : '');
655 : }
656 :
657 : /**
658 : * Returns the descendants of the given node, either as array or as a string for sql
659 : *
660 : * @param $node the node which ascendants are asked
661 : * @param $as_array boolean, do you want an array (true) or a string (false)
662 : * @return array or string
663 : */
664 : public function descendants($node, $as_array = false)
665 : {
666 : if ($as_array)
667 0 : return (isset($this->descendants[$node]) ? $this->descendants[$node] : array());
668 : else
669 0 : return (isset($this->descendants[$node]) ? implode(',', $this->descendants[$node]) : '');
670 : }
671 :
672 : /**
673 : * Returns an array of nodes, either the whole tree, or only the nodes listed in the filter
674 : *
675 : * @param array $filter
676 : * @return array
677 : */
678 : public function nodes(array $filter = null)
679 : {
680 0 : if ($filter) return array_intersect_key($this->elements, $filter);
681 0 : else return $this->elements;
682 : }
683 : }
684 :
685 :
686 :
687 :
688 :
689 :
690 :
691 :
692 :
693 :
694 :
695 :
696 :
697 :
698 :
699 :
700 :
701 :
702 :
703 :
704 :
705 :
706 :
707 :
708 :
709 : ///////////////////////// WINDOWS COMPATIBILITY FUNCTIONS //////////////////////////////
710 :
711 :
712 : // thanks to me at rowanlewis dot com (http://fr2.php.net/manual/en/function.fnmatch.php)
713 :
714 : if (!function_exists('fnmatch')) {
715 : define('FNM_PATHNAME', 1);
716 : define('FNM_NOESCAPE', 2);
717 : define('FNM_PERIOD', 4);
718 : define('FNM_CASEFOLD', 16);
719 :
720 : function fnmatch($pattern, $string, $flags = 0) {
721 0 : return pcre_fnmatch($pattern, $string, $flags);
722 : }
723 : }
724 :
725 : function pcre_fnmatch($pattern, $string, $flags = 0) {
726 0 : $modifiers = null;
727 : $transforms = array(
728 0 : '\*' => '.*',
729 0 : '\?' => '.',
730 0 : '\[\!' => '[^',
731 0 : '\[' => '[',
732 0 : '\]' => ']',
733 0 : '\.' => '\.',
734 : '\\' => '\\\\'
735 0 : );
736 :
737 : // Forward slash in string must be in pattern:
738 0 : if ($flags & FNM_PATHNAME) {
739 0 : $transforms['\*'] = '[^/]*';
740 0 : }
741 :
742 : // Back slash should not be escaped:
743 0 : if ($flags & FNM_NOESCAPE) {
744 0 : unset($transforms['\\']);
745 0 : }
746 :
747 : // Perform case insensitive match:
748 0 : if ($flags & FNM_CASEFOLD) {
749 0 : $modifiers .= 'i';
750 0 : }
751 :
752 : // Period at start must be the same as pattern:
753 0 : if ($flags & FNM_PERIOD) {
754 0 : if (strpos($string, '.') === 0 && strpos($pattern, '.') !== 0) return false;
755 0 : }
756 :
757 : $pattern = '#^'
758 0 : . strtr(preg_quote($pattern, '#'), $transforms)
759 0 : . '$#'
760 0 : . $modifiers;
761 :
762 0 : return (boolean)preg_match($pattern, $string);
763 : }
764 :
765 :
766 :
767 :
768 :
|