+// Destructive normalize of URI array
+// NOTE: Give me the uri_pickup() result with chunks
+function uri_array_normalize(& $pickups, $preserve = TRUE)
+{
+ if (! is_array($pickups)) return $pickups;
+
+ foreach (array_keys($pickups) as $key) {
+ $_key = & $pickups[$key];
+ $_key['path'] = isset($_key['path']) ? strtolower($_key['path']) : '';
+ $_key['file'] = isset($_key['file']) ? file_normalize($_key['file']) : '';
+ $_key['query'] = isset($_key['query']) ? query_normalize(strtolower($_key['query']), TRUE) : '';
+ $_key['fragment'] = (isset($_key['fragment']) && $preserve) ?
+ strtolower($_key['fragment']) : ''; // Just ignore
+ }
+
+ return $pickups;
+}
+
+// An URI array => An URI (See uri_pickup())
+function uri_array_implode($uri = array())
+{
+ if (empty($uri) || ! is_array($uri)) return NULL;
+
+ $tmp = array();
+ if (isset($uri['scheme']) && $uri['scheme'] !== '') {
+ $tmp[] = & $uri['scheme'];
+ $tmp[] = '://';
+ }
+ if (isset($uri['userinfo']) && $uri['userinfo'] !== '') {
+ $tmp[] = & $uri['userinfo'];
+ $tmp[] = '@';
+ }
+ if (isset($uri['host']) && $uri['host'] !== '') {
+ $tmp[] = & $uri['host'];
+ }
+ if (isset($uri['port']) && $uri['port'] !== '') {
+ $tmp[] = ':';
+ $tmp[] = & $uri['port'];
+ }
+ if (isset($uri['path']) && $uri['path'] !== '') {
+ $tmp[] = & $uri['path'];
+ }
+ if (isset($uri['file']) && $uri['file'] !== '') {
+ $tmp[] = & $uri['file'];
+ }
+ if (isset($uri['query']) && $uri['query'] !== '') {
+ $tmp[] = '?';
+ $tmp[] = & $uri['query'];
+ }
+ if (isset($uri['fragment']) && $uri['fragment'] !== '') {
+ $tmp[] = '#';
+ $tmp[] = & $uri['fragment'];
+ }
+
+ return implode('', $tmp);
+}
+
+// $array['something'] => $array['wanted']
+function array_rename_keys(& $array, $keys = array('from' => 'to'), $force = FALSE, $default = '')
+{
+ if (! is_array($array) || ! is_array($keys)) return FALSE;
+
+ // Nondestructive test
+ if (! $force)
+ foreach(array_keys($keys) as $from)
+ if (! isset($array[$from]))
+ return FALSE;
+
+ foreach($keys as $from => $to) {
+ if ($from === $to) continue;
+ if (! $force || isset($array[$from])) {
+ $array[$to] = & $array[$from];
+ unset($array[$from]);
+ } else {
+ $array[$to] = $default;
+ }
+ }
+
+ return TRUE;
+}
+
+// ---------------------
+// Area pickup
+
+// Pickup all of markup areas
+function area_pickup($string = '', $method = array())
+{
+ $area = array();
+ if (empty($method)) return $area;
+
+ // Anchor tag pair by preg_match and preg_match_all()
+ // [OK] <a href></a>
+ // [OK] <a href= >Good site!</a>
+ // [OK] <a href= "#" >test</a>
+ // [OK] <a href="http://nasty.example.com">visit http://nasty.example.com/</a>
+ // [OK] <a href=\'http://nasty.example.com/\' >discount foobar</a>
+ // [NG] <a href="http://ng.example.com">visit http://ng.example.com _not_ended_
+ $regex = '#<a\b[^>]*\bhref\b[^>]*>.*?</a\b[^>]*(>)#i';
+ if (isset($method['area_anchor'])) {
+ $areas = array();
+ $count = isset($method['asap']) ?
+ preg_match($regex, $string) :
+ preg_match_all($regex, $string, $areas);
+ if (! empty($count)) $area['area_anchor'] = $count;
+ }
+ if (isset($method['uri_anchor'])) {
+ $areas = array();
+ preg_match_all($regex, $string, $areas, PREG_SET_ORDER | PREG_OFFSET_CAPTURE);
+ foreach(array_keys($areas) as $_area) {
+ $areas[$_area] = array(
+ $areas[$_area][0][1], // Area start (<a href>)
+ $areas[$_area][1][1], // Area end (</a>)
+ );
+ }
+ if (! empty($areas)) $area['uri_anchor'] = $areas;
+ }
+
+ // phpBB's "BBCode" pair by preg_match and preg_match_all()
+ // [OK] [url][/url]
+ // [OK] [url]http://nasty.example.com/[/url]
+ // [OK] [link]http://nasty.example.com/[/link]
+ // [OK] [url=http://nasty.example.com]visit http://nasty.example.com/[/url]
+ // [OK] [link http://nasty.example.com/]buy something[/link]
+ $regex = '#\[(url|link)\b[^\]]*\].*?\[/\1\b[^\]]*(\])#i';
+ if (isset($method['area_bbcode'])) {
+ $areas = array();
+ $count = isset($method['asap']) ?
+ preg_match($regex, $string) :
+ preg_match_all($regex, $string, $areas, PREG_SET_ORDER);
+ if (! empty($count)) $area['area_bbcode'] = $count;
+ }
+ if (isset($method['uri_bbcode'])) {
+ $areas = array();
+ preg_match_all($regex, $string, $areas, PREG_SET_ORDER | PREG_OFFSET_CAPTURE);
+ foreach(array_keys($areas) as $_area) {
+ $areas[$_area] = array(
+ $areas[$_area][0][1], // Area start ([url])
+ $areas[$_area][2][1], // Area end ([/url])
+ );
+ }
+ if (! empty($areas)) $area['uri_bbcode'] = $areas;
+ }
+
+ // Various Wiki syntax
+ // [text_or_uri>text_or_uri]
+ // [text_or_uri:text_or_uri]
+ // [text_or_uri|text_or_uri]
+ // [text_or_uri->text_or_uri]
+ // [text_or_uri text_or_uri] // MediaWiki
+ // MediaWiki: [http://nasty.example.com/ visit http://nasty.example.com/]
+
+ return $area;
+}
+
+// If in doubt, it's a little doubtful
+// if (Area => inside <= Area) $brief += -1
+function area_measure($areas, & $array, $belief = -1, $a_key = 'area', $o_key = 'offset')
+{
+ if (! is_array($areas) || ! is_array($array)) return;
+
+ $areas_keys = array_keys($areas);
+ foreach(array_keys($array) as $u_index) {
+ $offset = isset($array[$u_index][$o_key]) ?
+ intval($array[$u_index][$o_key]) : 0;
+ foreach($areas_keys as $a_index) {
+ if (isset($array[$u_index][$a_key])) {
+ $offset_s = intval($areas[$a_index][0]);
+ $offset_e = intval($areas[$a_index][1]);
+ // [Area => inside <= Area]
+ if ($offset_s < $offset && $offset < $offset_e) {
+ $array[$u_index][$a_key] += $belief;
+ }
+ }
+ }
+ }
+}
+
+// ---------------------
+// Spam-uri pickup
+