Make WordPress Core

Ticket #1706: functions-formatting.php

File functions-formatting.php, 32.7 KB (added by rockinfree, 20 years ago)

Fixed version of file with line 75 in wpautop() updated (sorry, no diff on this system)

Line 
1<?php
2
3function wptexturize($text) {
4        $output = '';
5        // Capture tags and everything inside them
6        $textarr = preg_split("/(<.*>)/Us", $text, -1, PREG_SPLIT_DELIM_CAPTURE);
7        $stop = count($textarr); $next = true; // loop stuff
8        for ($i = 0; $i < $stop; $i++) {
9                $curl = $textarr[$i];
10
11                if (isset($curl{0}) && '<' != $curl{0} && $next) { // If it's not a tag
12                        $curl = str_replace('---', '&#8212;', $curl);
13                        $curl = str_replace(' -- ', ' &#8212; ', $curl);
14                        $curl = str_replace('--', '&#8211;', $curl);
15                        $curl = str_replace('xn&#8211;', 'xn--', $curl);
16                        $curl = str_replace('...', '&#8230;', $curl);
17                        $curl = str_replace('``', '&#8220;', $curl);
18
19                        // This is a hack, look at this more later. It works pretty well though.
20                        $cockney = array("'tain't","'twere","'twas","'tis","'twill","'til","'bout","'nuff","'round","'cause");
21                        $cockneyreplace = array("&#8217;tain&#8217;t","&#8217;twere","&#8217;twas","&#8217;tis","&#8217;twill","&#8217;til","&#8217;bout","&#8217;nuff","&#8217;round","&#8217;cause");
22                        $curl = str_replace($cockney, $cockneyreplace, $curl);
23
24                        $curl = preg_replace("/'s/", '&#8217;s', $curl);
25                        $curl = preg_replace("/'(\d\d(?:&#8217;|')?s)/", "&#8217;$1", $curl);
26                        $curl = preg_replace('/(\s|\A|")\'/', '$1&#8216;', $curl);
27                        $curl = preg_replace('/(\d+)"/', '$1&#8243;', $curl);
28                        $curl = preg_replace("/(\d+)'/", '$1&#8242;', $curl);
29                        $curl = preg_replace("/(\S)'([^'\s])/", "$1&#8217;$2", $curl);
30                        $curl = preg_replace('/(\s|\A)"(?!\s)/', '$1&#8220;$2', $curl);
31                        $curl = preg_replace('/"(\s|\S|\Z)/', '&#8221;$1', $curl);
32                        $curl = preg_replace("/'([\s.]|\Z)/", '&#8217;$1', $curl);
33                        $curl = preg_replace("/ \(tm\)/i", ' &#8482;', $curl);
34                        $curl = str_replace("''", '&#8221;', $curl);
35                       
36                        $curl = preg_replace('/(\d+)x(\d+)/', "$1&#215;$2", $curl);
37
38                } elseif (strstr($curl, '<code') || strstr($curl, '<pre') || strstr($curl, '<kbd' || strstr($curl, '<style') || strstr($curl, '<script'))) {
39                        // strstr is fast
40                        $next = false;
41                } else {
42                        $next = true;
43                }
44                $curl = preg_replace('/&([^#])(?![a-z12]{1,8};)/', '&#038;$1', $curl);
45                $output .= $curl;
46        }
47        return $output;
48}
49
50function clean_pre($text) {
51        $text = str_replace('<br />', '', $text);
52        $text = str_replace('<p>', "\n", $text);
53        $text = str_replace('</p>', '', $text);
54        return $text;
55}
56
57function wpautop($pee, $br = 1) {
58        $pee = $pee . "\n"; // just to make things a little easier, pad the end
59        $pee = preg_replace('|<br />\s*<br />|', "\n\n", $pee);
60        // Space things out a little
61        $pee = preg_replace('!(<(?:table|thead|tfoot|caption|colgroup|tbody|tr|td|th|div|dl|dd|dt|ul|ol|li|pre|select|form|blockquote|address|math|p|h[1-6])[^>]*>)!', "\n$1", $pee); 
62        $pee = preg_replace('!(</(?:table|thead|tfoot|caption|colgroup|tbody|tr|td|th|div|dl|dd|dt|ul|ol|li|pre|select|form|blockquote|address|math|p|h[1-6])>)!', "$1\n", $pee);
63        $pee = str_replace(array("\r\n", "\r"), "\n", $pee); // cross-platform newlines
64        $pee = preg_replace("/\n\n+/", "\n\n", $pee); // take care of duplicates
65        $pee = preg_replace('/\n?(.+?)(?:\n\s*\n|\z)/s', "\t<p>$1</p>\n", $pee); // make paragraphs, including one at the end
66        $pee = preg_replace('|<p>\s*?</p>|', '', $pee); // under certain strange conditions it could create a P of entirely whitespace
67    $pee = preg_replace('!<p>\s*(</?(?:table|thead|tfoot|caption|colgroup|tbody|tr|td|th|div|dl|dd|dt|ul|ol|li|hr|pre|select|form|blockquote|address|math|p|h[1-6])[^>]*>)\s*</p>!', "$1", $pee); // don't pee all over a tag
68        $pee = preg_replace("|<p>(<li.+?)</p>|", "$1", $pee); // problem with nested lists
69        $pee = preg_replace('|<p><blockquote([^>]*)>|i', "<blockquote$1><p>", $pee);
70        $pee = str_replace('</blockquote></p>', '</p></blockquote>', $pee);
71        $pee = preg_replace('!<p>\s*(</?(?:table|thead|tfoot|caption|colgroup|tbody|tr|td|th|div|dl|dd|dt|ul|ol|li|hr|pre|select|form|blockquote|address|math|p|h[1-6])[^>]*>)!', "$1", $pee);
72        $pee = preg_replace('!(</?(?:table|thead|tfoot|caption|colgroup|tbody|tr|td|th|div|dl|dd|dt|ul|ol|li|pre|select|form|blockquote|address|math|p|h[1-6])[^>]*>)\s*</p>!', "$1", $pee); 
73        if ($br) $pee = preg_replace('|(?<!<br />)\s*\n|', "<br />\n", $pee); // optionally make line breaks
74        $pee = preg_replace('!(</?(?:table|thead|tfoot|caption|tbody|tr|td|th|div|dl|dd|dt|ul|ol|li|pre|select|form|blockquote|address|math|p|h[1-6])[^>]*>)\s*<br />!', "$1", $pee);
75        $pee = preg_replace('!<br />(\s*</?(?:p|li|div|dl|dd|dt|th|pre|td|ul|ol)[^>]*>)!', '$1', $pee);
76        $pee = preg_replace('!(<pre.*?>)(.*?)</pre>!ise', " stripslashes('$1') .  clean_pre('$2')  . '</pre>' ", $pee);
77       
78        return $pee; 
79}
80
81function seems_utf8($Str) { # by bmorel at ssi dot fr
82        for ($i=0; $i<strlen($Str); $i++) {
83                if (ord($Str[$i]) < 0x80) continue; # 0bbbbbbb
84                elseif ((ord($Str[$i]) & 0xE0) == 0xC0) $n=1; # 110bbbbb
85                elseif ((ord($Str[$i]) & 0xF0) == 0xE0) $n=2; # 1110bbbb
86                elseif ((ord($Str[$i]) & 0xF8) == 0xF0) $n=3; # 11110bbb
87                elseif ((ord($Str[$i]) & 0xFC) == 0xF8) $n=4; # 111110bb
88                elseif ((ord($Str[$i]) & 0xFE) == 0xFC) $n=5; # 1111110b
89                else return false; # Does not match any model
90                for ($j=0; $j<$n; $j++) { # n bytes matching 10bbbbbb follow ?
91                        if ((++$i == strlen($Str)) || ((ord($Str[$i]) & 0xC0) != 0x80))
92                        return false;
93                }
94        }
95        return true;
96}
97
98function wp_specialchars( $text, $quotes = 0 ) {
99        // Like htmlspecialchars except don't double-encode HTML entities
100        $text = preg_replace('/&([^#])(?![a-z12]{1,8};)/', '&#038;$1', $text);-
101        $text = str_replace('<', '&lt;', $text);
102        $text = str_replace('>', '&gt;', $text);
103        if ( $quotes ) {
104                $text = str_replace('"', '&quot;', $text);
105                $text = str_replace("'", '&#039;', $text);
106        }
107        return $text;
108}
109
110function utf8_uri_encode( $utf8_string ) {
111  $unicode = '';       
112  $values = array();
113  $num_octets = 1;
114       
115  for ($i = 0; $i < strlen( $utf8_string ); $i++ ) {
116
117    $value = ord( $utf8_string[ $i ] );
118           
119    if ( $value < 128 ) {
120      $unicode .= chr($value);
121    } else {
122      if ( count( $values ) == 0 ) $num_octets = ( $value < 224 ) ? 2 : 3;
123               
124      $values[] = $value;
125     
126      if ( count( $values ) == $num_octets ) {
127        if ($num_octets == 3) {
128          $unicode .= '%' . dechex($values[0]) . '%' . dechex($values[1]) . '%' . dechex($values[2]);
129        } else {
130          $unicode .= '%' . dechex($values[0]) . '%' . dechex($values[1]);
131        }
132
133        $values = array();
134        $num_octets = 1;
135      }
136    }
137  }
138
139  return $unicode;   
140}
141
142function remove_accents($string) {
143        if (seems_utf8($string)) {
144                $chars = array(
145                // Decompositions for Latin-1 Supplement
146                chr(195).chr(128) => 'A', chr(195).chr(129) => 'A',
147                chr(195).chr(130) => 'A', chr(195).chr(131) => 'A',
148                chr(195).chr(132) => 'A', chr(195).chr(133) => 'A',
149                chr(195).chr(135) => 'C', chr(195).chr(136) => 'E',
150                chr(195).chr(137) => 'E', chr(195).chr(138) => 'E',
151                chr(195).chr(139) => 'E', chr(195).chr(140) => 'I',
152                chr(195).chr(141) => 'I', chr(195).chr(142) => 'I',
153                chr(195).chr(143) => 'I', chr(195).chr(145) => 'N',
154                chr(195).chr(146) => 'O', chr(195).chr(147) => 'O',
155                chr(195).chr(148) => 'O', chr(195).chr(149) => 'O',
156                chr(195).chr(150) => 'O', chr(195).chr(153) => 'U',
157                chr(195).chr(154) => 'U', chr(195).chr(155) => 'U',
158                chr(195).chr(156) => 'U', chr(195).chr(157) => 'Y',
159                chr(195).chr(159) => 's', chr(195).chr(160) => 'a',
160                chr(195).chr(161) => 'a', chr(195).chr(162) => 'a',
161                chr(195).chr(163) => 'a', chr(195).chr(164) => 'a',
162                chr(195).chr(165) => 'a', chr(195).chr(167) => 'c',
163                chr(195).chr(168) => 'e', chr(195).chr(169) => 'e',
164                chr(195).chr(170) => 'e', chr(195).chr(171) => 'e',
165                chr(195).chr(172) => 'i', chr(195).chr(173) => 'i',
166                chr(195).chr(174) => 'i', chr(195).chr(175) => 'i',
167                chr(195).chr(177) => 'n', chr(195).chr(178) => 'o',
168                chr(195).chr(179) => 'o', chr(195).chr(180) => 'o',
169                chr(195).chr(181) => 'o', chr(195).chr(182) => 'o',
170                chr(195).chr(182) => 'o', chr(195).chr(185) => 'u',
171                chr(195).chr(186) => 'u', chr(195).chr(187) => 'u',
172                chr(195).chr(188) => 'u', chr(195).chr(189) => 'y',
173                chr(195).chr(191) => 'y',
174                // Decompositions for Latin Extended-A
175                chr(196).chr(128) => 'A', chr(196).chr(129) => 'a',
176                chr(196).chr(130) => 'A', chr(196).chr(131) => 'a',
177                chr(196).chr(132) => 'A', chr(196).chr(133) => 'a',
178                chr(196).chr(134) => 'C', chr(196).chr(134) => 'c',
179                chr(196).chr(136) => 'C', chr(196).chr(137) => 'c',
180                chr(196).chr(138) => 'C', chr(196).chr(139) => 'c',
181                chr(196).chr(140) => 'C', chr(196).chr(141) => 'c',
182                chr(196).chr(142) => 'D', chr(196).chr(143) => 'd',
183                chr(196).chr(144) => 'D', chr(196).chr(145) => 'd',
184                chr(196).chr(146) => 'E', chr(196).chr(147) => 'e',
185                chr(196).chr(148) => 'E', chr(196).chr(149) => 'e',
186                chr(196).chr(150) => 'E', chr(196).chr(151) => 'e',
187                chr(196).chr(152) => 'E', chr(196).chr(153) => 'e',
188                chr(196).chr(154) => 'E', chr(196).chr(155) => 'e',
189                chr(196).chr(156) => 'G', chr(196).chr(157) => 'g',
190                chr(196).chr(158) => 'G', chr(196).chr(159) => 'g',
191                chr(196).chr(160) => 'G', chr(196).chr(161) => 'g',
192                chr(196).chr(162) => 'G', chr(196).chr(163) => 'g',
193                chr(196).chr(164) => 'H', chr(196).chr(165) => 'h',
194                chr(196).chr(166) => 'H', chr(196).chr(167) => 'h',
195                chr(196).chr(168) => 'I', chr(196).chr(169) => 'i',
196                chr(196).chr(170) => 'I', chr(196).chr(171) => 'i',
197                chr(196).chr(172) => 'I', chr(196).chr(173) => 'i',
198                chr(196).chr(174) => 'I', chr(196).chr(175) => 'i',
199                chr(196).chr(176) => 'I', chr(196).chr(177) => 'i',
200                chr(196).chr(178) => 'IJ',chr(196).chr(179) => 'ij',
201                chr(196).chr(180) => 'J', chr(196).chr(181) => 'j',
202                chr(196).chr(182) => 'K', chr(196).chr(183) => 'k',
203                chr(196).chr(184) => 'k', chr(196).chr(185) => 'L',
204                chr(196).chr(186) => 'l', chr(196).chr(187) => 'L',
205                chr(196).chr(188) => 'l', chr(196).chr(189) => 'L',
206                chr(196).chr(190) => 'l', chr(196).chr(191) => 'L',
207                chr(197).chr(128) => 'l', chr(196).chr(129) => 'L',
208                chr(197).chr(130) => 'l', chr(196).chr(131) => 'N',
209                chr(197).chr(132) => 'n', chr(196).chr(133) => 'N',
210                chr(197).chr(134) => 'n', chr(196).chr(135) => 'N',
211                chr(197).chr(136) => 'n', chr(196).chr(137) => 'N',
212                chr(197).chr(138) => 'n', chr(196).chr(139) => 'N',
213                chr(197).chr(140) => 'O', chr(196).chr(141) => 'o',
214                chr(197).chr(142) => 'O', chr(196).chr(143) => 'o',
215                chr(197).chr(144) => 'O', chr(196).chr(145) => 'o',
216                chr(197).chr(146) => 'OE',chr(197).chr(147) => 'oe',
217                chr(197).chr(148) => 'R',chr(197).chr(149) => 'r',
218                chr(197).chr(150) => 'R',chr(197).chr(151) => 'r',
219                chr(197).chr(152) => 'R',chr(197).chr(153) => 'r',
220                chr(197).chr(154) => 'S',chr(197).chr(155) => 's',
221                chr(197).chr(156) => 'S',chr(197).chr(157) => 's',
222                chr(197).chr(158) => 'S',chr(197).chr(159) => 's',
223                chr(197).chr(160) => 'S', chr(197).chr(161) => 's',
224                chr(197).chr(162) => 'T', chr(197).chr(163) => 't',
225                chr(197).chr(164) => 'T', chr(197).chr(165) => 't',
226                chr(197).chr(166) => 'T', chr(197).chr(167) => 't',
227                chr(197).chr(168) => 'U', chr(197).chr(169) => 'u',
228                chr(197).chr(170) => 'U', chr(197).chr(171) => 'u',
229                chr(197).chr(172) => 'U', chr(197).chr(173) => 'u',
230                chr(197).chr(174) => 'U', chr(197).chr(175) => 'u',
231                chr(197).chr(176) => 'U', chr(197).chr(177) => 'u',
232                chr(197).chr(178) => 'U', chr(197).chr(179) => 'u',
233                chr(197).chr(180) => 'W', chr(197).chr(181) => 'w',
234                chr(197).chr(182) => 'Y', chr(197).chr(183) => 'y',
235                chr(197).chr(184) => 'Y', chr(197).chr(185) => 'Z',
236                chr(197).chr(186) => 'z', chr(197).chr(187) => 'Z',
237                chr(197).chr(188) => 'z', chr(197).chr(189) => 'Z',
238                chr(197).chr(190) => 'z', chr(197).chr(191) => 's',
239                // Euro Sign
240                chr(226).chr(130).chr(172) => 'E');
241               
242                $string = strtr($string, $chars);
243        } else {
244                // Assume ISO-8859-1 if not UTF-8
245                $chars['in'] = chr(128).chr(131).chr(138).chr(142).chr(154).chr(158)
246                        .chr(159).chr(162).chr(165).chr(181).chr(192).chr(193).chr(194)
247                        .chr(195).chr(196).chr(197).chr(199).chr(200).chr(201).chr(202)
248                        .chr(203).chr(204).chr(205).chr(206).chr(207).chr(209).chr(210)
249                        .chr(211).chr(212).chr(213).chr(214).chr(216).chr(217).chr(218)
250                        .chr(219).chr(220).chr(221).chr(224).chr(225).chr(226).chr(227)
251                        .chr(228).chr(229).chr(231).chr(232).chr(233).chr(234).chr(235)
252                        .chr(236).chr(237).chr(238).chr(239).chr(241).chr(242).chr(243)
253                        .chr(244).chr(245).chr(246).chr(248).chr(249).chr(250).chr(251)
254                        .chr(252).chr(253).chr(255);
255
256                $chars['out'] = "EfSZszYcYuAAAAAACEEEEIIIINOOOOOOUUUUYaaaaaaceeeeiiiinoooooouuuuyy";
257
258                $string = strtr($string, $chars['in'], $chars['out']);
259                $double_chars['in'] = array(chr(140), chr(156), chr(198), chr(208), chr(222), chr(223), chr(230), chr(240), chr(254));
260                $double_chars['out'] = array('OE', 'oe', 'AE', 'DH', 'TH', 'ss', 'ae', 'dh', 'th');
261                $string = str_replace($double_chars['in'], $double_chars['out'], $string);
262        }
263
264        return $string;
265}
266
267function sanitize_title($title, $fallback_title = '') {
268        $title = strip_tags($title);
269        $title = apply_filters('sanitize_title', $title);
270
271        if (empty($title)) {
272                $title = $fallback_title;
273        }
274
275        return $title;
276}
277
278function sanitize_title_with_dashes($title) {
279        $title = strip_tags($title);
280        // Preserve escaped octets.
281        $title = preg_replace('|%([a-fA-F0-9][a-fA-F0-9])|', '---$1---', $title);
282        // Remove percent signs that are not part of an octet.
283        $title = str_replace('%', '', $title);
284        // Restore octets.
285        $title = preg_replace('|---([a-fA-F0-9][a-fA-F0-9])---|', '%$1', $title);
286
287        $title = remove_accents($title);
288        if (seems_utf8($title)) {
289                if (function_exists('mb_strtolower')) {
290                        $title = mb_strtolower($title, 'UTF-8');
291                }
292                $title = utf8_uri_encode($title);
293        }
294
295        $title = strtolower($title);
296        $title = preg_replace('/&.+?;/', '', $title); // kill entities
297        $title = preg_replace('/[^%a-z0-9 _-]/', '', $title);
298        $title = preg_replace('/\s+/', '-', $title);
299        $title = preg_replace('|-+|', '-', $title);
300        $title = trim($title, '-');
301
302        return $title;
303}
304
305function convert_chars($content, $flag = 'obsolete') { 
306        // Translation of invalid Unicode references range to valid range
307        $wp_htmltranswinuni = array(
308        '&#128;' => '&#8364;', // the Euro sign
309        '&#129;' => '',
310        '&#130;' => '&#8218;', // these are Windows CP1252 specific characters
311        '&#131;' => '&#402;',  // they would look weird on non-Windows browsers
312        '&#132;' => '&#8222;',
313        '&#133;' => '&#8230;',
314        '&#134;' => '&#8224;',
315        '&#135;' => '&#8225;',
316        '&#136;' => '&#710;',
317        '&#137;' => '&#8240;',
318        '&#138;' => '&#352;',
319        '&#139;' => '&#8249;',
320        '&#140;' => '&#338;',
321        '&#141;' => '',
322        '&#142;' => '&#382;',
323        '&#143;' => '',
324        '&#144;' => '',
325        '&#145;' => '&#8216;',
326        '&#146;' => '&#8217;',
327        '&#147;' => '&#8220;',
328        '&#148;' => '&#8221;',
329        '&#149;' => '&#8226;',
330        '&#150;' => '&#8211;',
331        '&#151;' => '&#8212;',
332        '&#152;' => '&#732;',
333        '&#153;' => '&#8482;',
334        '&#154;' => '&#353;',
335        '&#155;' => '&#8250;',
336        '&#156;' => '&#339;',
337        '&#157;' => '',
338        '&#158;' => '',
339        '&#159;' => '&#376;'
340        );
341
342        // Remove metadata tags
343        $content = preg_replace('/<title>(.+?)<\/title>/','',$content);
344        $content = preg_replace('/<category>(.+?)<\/category>/','',$content);
345
346        // Converts lone & characters into &#38; (a.k.a. &amp;)
347        $content = preg_replace('/&([^#])(?![a-z]{1,8};)/i', '&#038;$1', $content);
348
349        // Fix Word pasting
350        $content = strtr($content, $wp_htmltranswinuni);
351
352        // Just a little XHTML help
353        $content = str_replace('<br>', '<br />', $content);
354        $content = str_replace('<hr>', '<hr />', $content);
355
356        return $content;
357}
358
359function funky_javascript_fix($text) {
360        // Fixes for browsers' javascript bugs
361        global $is_macIE, $is_winIE;
362       
363        if ( $is_winIE || $is_macIE )
364                $text =  preg_replace("/\%u([0-9A-F]{4,4})/e",  "'&#'.base_convert('\\1',16,10).';'", $text);
365       
366        return $text;
367}
368
369/*
370 balanceTags
371 
372 Balances Tags of string using a modified stack.
373 
374 @param text      Text to be balanced
375 @return          Returns balanced text
376 @author          Leonard Lin (leonard@acm.org)
377 @version         v1.1
378 @date            November 4, 2001
379 @license         GPL v2.0
380 @notes           
381 @changelog       
382 ---  Modified by Scott Reilly (coffee2code) 02 Aug 2004
383             1.2  ***TODO*** Make better - change loop condition to $text
384             1.1  Fixed handling of append/stack pop order of end text
385                  Added Cleaning Hooks
386             1.0  First Version
387*/
388function balanceTags($text, $is_comment = 0) {
389       
390        if (get_settings('use_balanceTags') == 0) {
391                return $text;
392        }
393
394        $tagstack = array(); $stacksize = 0; $tagqueue = ''; $newtext = '';
395
396        # WP bug fix for comments - in case you REALLY meant to type '< !--'
397        $text = str_replace('< !--', '<    !--', $text);
398        # WP bug fix for LOVE <3 (and other situations with '<' before a number)
399        $text = preg_replace('#<([0-9]{1})#', '&lt;$1', $text);
400
401        while (preg_match("/<(\/?\w*)\s*([^>]*)>/",$text,$regex)) {
402                $newtext .= $tagqueue;
403
404                $i = strpos($text,$regex[0]);
405                $l = strlen($regex[0]);
406
407                // clear the shifter
408                $tagqueue = '';
409                // Pop or Push
410                if ($regex[1][0] == "/") { // End Tag
411                        $tag = strtolower(substr($regex[1],1));
412                        // if too many closing tags
413                        if($stacksize <= 0) { 
414                                $tag = '';
415                                //or close to be safe $tag = '/' . $tag;
416                        }
417                        // if stacktop value = tag close value then pop
418                        else if ($tagstack[$stacksize - 1] == $tag) { // found closing tag
419                                $tag = '</' . $tag . '>'; // Close Tag
420                                // Pop
421                                array_pop ($tagstack);
422                                $stacksize--;
423                        } else { // closing tag not at top, search for it
424                                for ($j=$stacksize-1;$j>=0;$j--) {
425                                        if ($tagstack[$j] == $tag) {
426                                        // add tag to tagqueue
427                                                for ($k=$stacksize-1;$k>=$j;$k--){
428                                                        $tagqueue .= '</' . array_pop ($tagstack) . '>';
429                                                        $stacksize--;
430                                                }
431                                                break;
432                                        }
433                                }
434                                $tag = '';
435                        }
436                } else { // Begin Tag
437                        $tag = strtolower($regex[1]);
438
439                        // Tag Cleaning
440
441                        // If self-closing or '', don't do anything.
442                        if((substr($regex[2],-1) == '/') || ($tag == '')) {
443                        }
444                        // ElseIf it's a known single-entity tag but it doesn't close itself, do so
445                        elseif ($tag == 'br' || $tag == 'img' || $tag == 'hr' || $tag == 'input') {
446                                $regex[2] .= '/';
447                        } else {        // Push the tag onto the stack
448                                // If the top of the stack is the same as the tag we want to push, close previous tag
449                                if (($stacksize > 0) && ($tag != 'div') && ($tagstack[$stacksize - 1] == $tag)) {
450                                        $tagqueue = '</' . array_pop ($tagstack) . '>';
451                                        $stacksize--;
452                                }
453                                $stacksize = array_push ($tagstack, $tag);
454                        }
455
456                        // Attributes
457                        $attributes = $regex[2];
458                        if($attributes) {
459                                $attributes = ' '.$attributes;
460                        }
461                        $tag = '<'.$tag.$attributes.'>';
462                        //If already queuing a close tag, then put this tag on, too
463                        if ($tagqueue) {
464                                $tagqueue .= $tag;
465                                $tag = '';
466                        }
467                }
468                $newtext .= substr($text,0,$i) . $tag;
469                $text = substr($text,$i+$l);
470        } 
471
472        // Clear Tag Queue
473        $newtext .= $tagqueue;
474
475        // Add Remaining text
476        $newtext .= $text;
477
478        // Empty Stack
479        while($x = array_pop($tagstack)) {
480                $newtext .= '</' . $x . '>'; // Add remaining tags to close
481        }
482
483        // WP fix for the bug with HTML comments
484        $newtext = str_replace("< !--","<!--",$newtext);
485        $newtext = str_replace("<    !--","< !--",$newtext);
486
487        return $newtext;
488}
489
490
491function format_to_edit($content) {
492        $content = apply_filters('format_to_edit', $content);
493        $content = htmlspecialchars($content);
494        return $content;
495}
496
497function format_to_post($content) {
498        global $wpdb;
499        $content = apply_filters('format_to_post', $content);
500        return $content;
501}
502
503function zeroise($number,$threshold) { // function to add leading zeros when necessary
504        return sprintf('%0'.$threshold.'s', $number);
505        }
506
507
508function backslashit($string) {
509        $string = preg_replace('/([a-z])/i', '\\\\\1', $string);
510        return $string;
511}
512
513function trailingslashit($string) {
514    if ( '/' != substr($string, -1)) {
515        $string .= '/';
516    }
517    return $string;
518}
519
520function addslashes_gpc($gpc) {
521        if (!get_magic_quotes_gpc()) {
522                $gpc = addslashes($gpc);
523        }
524        return $gpc;
525}
526
527function antispambot($emailaddy, $mailto=0) {
528        $emailNOSPAMaddy = '';
529        srand ((float) microtime() * 1000000);
530        for ($i = 0; $i < strlen($emailaddy); $i = $i + 1) {
531                $j = floor(rand(0, 1+$mailto));
532                if ($j==0) {
533                        $emailNOSPAMaddy .= '&#'.ord(substr($emailaddy,$i,1)).';';
534                } elseif ($j==1) {
535                        $emailNOSPAMaddy .= substr($emailaddy,$i,1);
536                } elseif ($j==2) {
537                        $emailNOSPAMaddy .= '%'.zeroise(dechex(ord(substr($emailaddy, $i, 1))), 2);
538                }
539        }
540        $emailNOSPAMaddy = str_replace('@','&#64;',$emailNOSPAMaddy);
541        return $emailNOSPAMaddy;
542}
543
544function make_clickable($ret) {
545        $ret = ' ' . $ret . ' ';
546        $ret = preg_replace("#([\s>])(https?)://([^\s<>{}()]+[^\s.,<>{}()])#i", "$1<a href='$2://$3' rel='nofollow'>$2://$3</a>", $ret);
547        $ret = preg_replace("#(\s)www\.([a-z0-9\-]+)\.([a-z0-9\-.\~]+)((?:/[^ <>{}()\n\r]*[^., <>{}()\n\r]?)?)#i", "$1<a href='http://www.$2.$3$4' rel='nofollow'>www.$2.$3$4</a>", $ret);
548        $ret = preg_replace("#(\s)([a-z0-9\-_.]+)@([^,< \n\r]+)#i", "$1<a href=\"mailto:$2@$3\">$2@$3</a>", $ret);
549        $ret = trim($ret);
550        return $ret;
551}
552
553function wp_rel_nofollow( $text ) {
554        $text = preg_replace('|<a (.+?)>|i', '<a $1 rel="nofollow">', $text);
555        return $text;
556}
557
558function convert_smilies($text) {
559        global $wp_smiliessearch, $wp_smiliesreplace;
560    $output = '';
561        if (get_settings('use_smilies')) {
562                // HTML loop taken from texturize function, could possible be consolidated
563                $textarr = preg_split("/(<.*>)/U", $text, -1, PREG_SPLIT_DELIM_CAPTURE); // capture the tags as well as in between
564                $stop = count($textarr);// loop stuff
565                for ($i = 0; $i < $stop; $i++) {
566                        $content = $textarr[$i];
567                        if ((strlen($content) > 0) && ('<' != $content{0})) { // If it's not a tag
568                                $content = str_replace($wp_smiliessearch, $wp_smiliesreplace, $content);
569                        }
570                        $output .= $content;
571                }
572        } else {
573                // return default text.
574                $output = $text;
575        }
576        return $output;
577}
578
579
580function is_email($user_email) {
581        $chars = "/^([a-z0-9+_]|\\-|\\.)+@(([a-z0-9_]|\\-)+\\.)+[a-z]{2,6}\$/i";
582        if(strstr($user_email, '@') && strstr($user_email, '.')) {
583                if (preg_match($chars, $user_email)) {
584                        return true;
585                } else {
586                        return false;
587                }
588        } else {
589                return false;
590        }
591}
592
593
594function strip_all_but_one_link($text, $mylink) {
595        $match_link = '#(<a.+?href.+?'.'>)(.+?)(</a>)#';
596        preg_match_all($match_link, $text, $matches);
597        $count = count($matches[0]);
598        for ($i=0; $i<$count; $i++) {
599                if (!strstr($matches[0][$i], $mylink)) {
600                        $text = str_replace($matches[0][$i], $matches[2][$i], $text);
601                }
602        }
603        return $text;
604}
605
606
607// used by wp-mail to handle charsets in email subjects
608function wp_iso_descrambler($string) {
609  /* this may only work with iso-8859-1, I'm afraid */
610  if (!preg_match('#\=\?(.+)\?Q\?(.+)\?\=#i', $string, $matches)) {
611    return $string;
612  } else {
613    $subject = str_replace('_', ' ', $matches[2]);
614    $subject = preg_replace('#\=([0-9a-f]{2})#ei', "chr(hexdec(strtolower('$1')))", $subject);
615    return $subject;
616  }
617}
618
619
620// give it a date, it will give you the same date as GMT
621function get_gmt_from_date($string) {
622  // note: this only substracts $time_difference from the given date
623  preg_match('#([0-9]{1,4})-([0-9]{1,2})-([0-9]{1,2}) ([0-9]{1,2}):([0-9]{1,2}):([0-9]{1,2})#', $string, $matches);
624  $string_time = gmmktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
625  $string_gmt = gmdate('Y-m-d H:i:s', $string_time - get_settings('gmt_offset') * 3600);
626  return $string_gmt;
627}
628
629// give it a GMT date, it will give you the same date with $time_difference added
630function get_date_from_gmt($string) {
631  // note: this only adds $time_difference to the given date
632  preg_match('#([0-9]{1,4})-([0-9]{1,2})-([0-9]{1,2}) ([0-9]{1,2}):([0-9]{1,2}):([0-9]{1,2})#', $string, $matches);
633  $string_time = gmmktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
634  $string_localtime = gmdate('Y-m-d H:i:s', $string_time + get_settings('gmt_offset')*3600);
635  return $string_localtime;
636}
637
638// computes an offset in seconds from an iso8601 timezone
639function iso8601_timezone_to_offset($timezone) {
640  // $timezone is either 'Z' or '[+|-]hhmm'
641  if ($timezone == 'Z') {
642    $offset = 0;
643  } else {
644    $sign    = (substr($timezone, 0, 1) == '+') ? 1 : -1;
645    $hours   = intval(substr($timezone, 1, 2));
646    $minutes = intval(substr($timezone, 3, 4)) / 60;
647    $offset  = $sign * 3600 * ($hours + $minutes);
648  }
649  return $offset;
650}
651
652// converts an iso8601 date to MySQL DateTime format used by post_date[_gmt]
653function iso8601_to_datetime($date_string, $timezone = USER) {
654  if ($timezone == GMT) {
655    preg_match('#([0-9]{4})([0-9]{2})([0-9]{2})T([0-9]{2}):([0-9]{2}):([0-9]{2})(Z|[\+|\-][0-9]{2,4}){0,1}#', $date_string, $date_bits);
656    if (!empty($date_bits[7])) { // we have a timezone, so let's compute an offset
657      $offset = iso8601_timezone_to_offset($date_bits[7]);
658    } else { // we don't have a timezone, so we assume user local timezone (not server's!)
659      $offset = 3600 * get_settings('gmt_offset');
660    }
661    $timestamp = gmmktime($date_bits[4], $date_bits[5], $date_bits[6], $date_bits[2], $date_bits[3], $date_bits[1]);
662    $timestamp -= $offset;
663    return gmdate('Y-m-d H:i:s', $timestamp);
664  } elseif ($timezone == USER) {
665    return preg_replace('#([0-9]{4})([0-9]{2})([0-9]{2})T([0-9]{2}):([0-9]{2}):([0-9]{2})(Z|[\+|\-][0-9]{2,4}){0,1}#', '$1-$2-$3 $4:$5:$6', $date_string);
666  }
667}
668
669function popuplinks($text) {
670        // Comment text in popup windows should be filtered through this.
671        // Right now it's a moderately dumb function, ideally it would detect whether
672        // a target or rel attribute was already there and adjust its actions accordingly.
673        $text = preg_replace('/<a (.+?)>/i', "<a $1 target='_blank' rel='external'>", $text);
674        return $text;
675}
676
677function sanitize_email($email) {
678        return preg_replace('/[^a-z0-9+_.@-]/i', '', $email);
679}
680
681function human_time_diff( $from, $to = '' ) {     
682        if ( empty($to) )
683                $to = time();
684        $diff = (int) abs($to - $from);
685        if ($diff <= 3600) {
686                $mins = round($diff / 60);
687                if ($mins <= 1)
688                        $since = __('1 min');
689                else
690                        $since = sprintf( __('%s mins'), $mins);
691        } else if (($diff <= 86400) && ($diff > 3600)) {
692                $hours = round($diff / 3600);
693                if ($hours <= 1)
694                        $since = __('1 hour');
695                else 
696                        $since = sprintf( __('%s hours'), $hours );
697        } elseif ($diff >= 86400) {
698                $days = round($diff / 86400);
699                if ($days <= 1)
700                        $since = __('1 day');
701                else
702                        $since = sprintf( __('%s days'), $days );
703        }
704        return $since;
705}
706
707function wp_trim_excerpt($text) { // Fakes an excerpt if needed
708        global $post;
709        if ( '' == $text ) {
710                $text = $post->post_content;
711                $text = apply_filters('the_content', $text);
712                $text = str_replace(']]>', ']]&gt;', $text);
713                $text = strip_tags($text);
714                $excerpt_length = 55;
715                $words = explode(' ', $text, $excerpt_length + 1);
716                if (count($words) > $excerpt_length) {
717                        array_pop($words);
718                        array_push($words, '[...]');
719                        $text = implode(' ', $words);
720                }
721        }
722        return $text;
723}
724
725function ent2ncr($text) {
726        $to_ncr = array(
727                        '&quot;' => '&#34;',
728                        '&amp;' => '&#38;',
729                        '&frasl;' => '&#47;',
730                        '&lt;' => '&#60;',
731                        '&gt;' => '&#62;',
732                        '&nbsp;' => '&#160;',
733                        '&iexcl;' => '&#161;',
734                        '&cent;' => '&#162;',
735                        '&pound;' => '&#163;',
736                        '&curren;' => '&#164;',
737                        '&yen;' => '&#165;',
738                        '|' => '&#166;',
739                        '&brvbar;' => '&#166;',
740                        '&brkbar;' => '&#166;',
741                        '&sect;' => '&#167;',
742                        '&uml;' => '&#168;',
743                        '&die;' => '&#168;',
744                        '&copy;' => '&#169;',
745                        '&ordf;' => '&#170;',
746                        '&laquo;' => '&#171;',
747                        '&not;' => '&#172;',
748                        '&shy;' => '&#173;',
749                        '&reg;' => '&#174;',
750                        '&macr;' => '&#175;',
751                        '&hibar;' => '&#175;',
752                        '&deg;' => '&#176;',
753                        '&plusmn;' => '&#177;',
754                        '&sup2;' => '&#178;',
755                        '&sup3;' => '&#179;',
756                        '&acute;' => '&#180;',
757                        '&micro;' => '&#181;',
758                        '&para;' => '&#182;',
759                        '&middot;' => '&#183;',
760                        '&cedil;' => '&#184;',
761                        '&sup1;' => '&#185;',
762                        '&ordm;' => '&#186;',
763                        '&raquo;' => '&#187;',
764                        '&frac14;' => '&#188;',
765                        '&frac12;' => '&#189;',
766                        '&frac34;' => '&#190;',
767                        '&iquest;' => '&#191;',
768                        '&Agrave;' => '&#192;',
769                        '&Aacute;' => '&#193;',
770                        '&Acirc;' => '&#194;',
771                        '&Atilde;' => '&#195;',
772                        '&Auml;' => '&#196;',
773                        '&Aring;' => '&#197;',
774                        '&AElig;' => '&#198;',
775                        '&Ccedil;' => '&#199;',
776                        '&Egrave;' => '&#200;',
777                        '&Eacute;' => '&#201;',
778                        '&Ecirc;' => '&#202;',
779                        '&Euml;' => '&#203;',
780                        '&Igrave;' => '&#204;',
781                        '&Iacute;' => '&#205;',
782                        '&Icirc;' => '&#206;',
783                        '&Iuml;' => '&#207;',
784                        '&ETH;' => '&#208;',
785                        '&Ntilde;' => '&#209;',
786                        '&Ograve;' => '&#210;',
787                        '&Oacute;' => '&#211;',
788                        '&Ocirc;' => '&#212;',
789                        '&Otilde;' => '&#213;',
790                        '&Ouml;' => '&#214;',
791                        '&times;' => '&#215;',
792                        '&Oslash;' => '&#216;',
793                        '&Ugrave;' => '&#217;',
794                        '&Uacute;' => '&#218;',
795                        '&Ucirc;' => '&#219;',
796                        '&Uuml;' => '&#220;',
797                        '&Yacute;' => '&#221;',
798                        '&THORN;' => '&#222;',
799                        '&szlig;' => '&#223;',
800                        '&agrave;' => '&#224;',
801                        '&aacute;' => '&#225;',
802                        '&acirc;' => '&#226;',
803                        '&atilde;' => '&#227;',
804                        '&auml;' => '&#228;',
805                        '&aring;' => '&#229;',
806                        '&aelig;' => '&#230;',
807                        '&ccedil;' => '&#231;',
808                        '&egrave;' => '&#232;',
809                        '&eacute;' => '&#233;',
810                        '&ecirc;' => '&#234;',
811                        '&euml;' => '&#235;',
812                        '&igrave;' => '&#236;',
813                        '&iacute;' => '&#237;',
814                        '&icirc;' => '&#238;',
815                        '&iuml;' => '&#239;',
816                        '&eth;' => '&#240;',
817                        '&ntilde;' => '&#241;',
818                        '&ograve;' => '&#242;',
819                        '&oacute;' => '&#243;',
820                        '&ocirc;' => '&#244;',
821                        '&otilde;' => '&#245;',
822                        '&ouml;' => '&#246;',
823                        '&divide;' => '&#247;',
824                        '&oslash;' => '&#248;',
825                        '&ugrave;' => '&#249;',
826                        '&uacute;' => '&#250;',
827                        '&ucirc;' => '&#251;',
828                        '&uuml;' => '&#252;',
829                        '&yacute;' => '&#253;',
830                        '&thorn;' => '&#254;',
831                        '&yuml;' => '&#255;',
832                        '&OElig;' => '&#338;',
833                        '&oelig;' => '&#339;',
834                        '&Scaron;' => '&#352;',
835                        '&scaron;' => '&#353;',
836                        '&Yuml;' => '&#376;',
837                        '&fnof;' => '&#402;',
838                        '&circ;' => '&#710;',
839                        '&tilde;' => '&#732;',
840                        '&Alpha;' => '&#913;',
841                        '&Beta;' => '&#914;',
842                        '&Gamma;' => '&#915;',
843                        '&Delta;' => '&#916;',
844                        '&Epsilon;' => '&#917;',
845                        '&Zeta;' => '&#918;',
846                        '&Eta;' => '&#919;',
847                        '&Theta;' => '&#920;',
848                        '&Iota;' => '&#921;',
849                        '&Kappa;' => '&#922;',
850                        '&Lambda;' => '&#923;',
851                        '&Mu;' => '&#924;',
852                        '&Nu;' => '&#925;',
853                        '&Xi;' => '&#926;',
854                        '&Omicron;' => '&#927;',
855                        '&Pi;' => '&#928;',
856                        '&Rho;' => '&#929;',
857                        '&Sigma;' => '&#931;',
858                        '&Tau;' => '&#932;',
859                        '&Upsilon;' => '&#933;',
860                        '&Phi;' => '&#934;',
861                        '&Chi;' => '&#935;',
862                        '&Psi;' => '&#936;',
863                        '&Omega;' => '&#937;',
864                        '&alpha;' => '&#945;',
865                        '&beta;' => '&#946;',
866                        '&gamma;' => '&#947;',
867                        '&delta;' => '&#948;',
868                        '&epsilon;' => '&#949;',
869                        '&zeta;' => '&#950;',
870                        '&eta;' => '&#951;',
871                        '&theta;' => '&#952;',
872                        '&iota;' => '&#953;',
873                        '&kappa;' => '&#954;',
874                        '&lambda;' => '&#955;',
875                        '&mu;' => '&#956;',
876                        '&nu;' => '&#957;',
877                        '&xi;' => '&#958;',
878                        '&omicron;' => '&#959;',
879                        '&pi;' => '&#960;',
880                        '&rho;' => '&#961;',
881                        '&sigmaf;' => '&#962;',
882                        '&sigma;' => '&#963;',
883                        '&tau;' => '&#964;',
884                        '&upsilon;' => '&#965;',
885                        '&phi;' => '&#966;',
886                        '&chi;' => '&#967;',
887                        '&psi;' => '&#968;',
888                        '&omega;' => '&#969;',
889                        '&thetasym;' => '&#977;',
890                        '&upsih;' => '&#978;',
891                        '&piv;' => '&#982;',
892                        '&ensp;' => '&#8194;',
893                        '&emsp;' => '&#8195;',
894                        '&thinsp;' => '&#8201;',
895                        '&zwnj;' => '&#8204;',
896                        '&zwj;' => '&#8205;',
897                        '&lrm;' => '&#8206;',
898                        '&rlm;' => '&#8207;',
899                        '&ndash;' => '&#8211;',
900                        '&mdash;' => '&#8212;',
901                        '&lsquo;' => '&#8216;',
902                        '&rsquo;' => '&#8217;',
903                        '&sbquo;' => '&#8218;',
904                        '&ldquo;' => '&#8220;',
905                        '&rdquo;' => '&#8221;',
906                        '&bdquo;' => '&#8222;',
907                        '&dagger;' => '&#8224;',
908                        '&Dagger;' => '&#8225;',
909                        '&bull;' => '&#8226;',
910                        '&hellip;' => '&#8230;',
911                        '&permil;' => '&#8240;',
912                        '&prime;' => '&#8242;',
913                        '&Prime;' => '&#8243;',
914                        '&lsaquo;' => '&#8249;',
915                        '&rsaquo;' => '&#8250;',
916                        '&oline;' => '&#8254;',
917                        '&frasl;' => '&#8260;',
918                        '&euro;' => '&#8364;',
919                        '&image;' => '&#8465;',
920                        '&weierp;' => '&#8472;',
921                        '&real;' => '&#8476;',
922                        '&trade;' => '&#8482;',
923                        '&alefsym;' => '&#8501;',
924                        '&crarr;' => '&#8629;',
925                        '&lArr;' => '&#8656;',
926                        '&uArr;' => '&#8657;',
927                        '&rArr;' => '&#8658;',
928                        '&dArr;' => '&#8659;',
929                        '&hArr;' => '&#8660;',
930                        '&forall;' => '&#8704;',
931                        '&part;' => '&#8706;',
932                        '&exist;' => '&#8707;',
933                        '&empty;' => '&#8709;',
934                        '&nabla;' => '&#8711;',
935                        '&isin;' => '&#8712;',
936                        '&notin;' => '&#8713;',
937                        '&ni;' => '&#8715;',
938                        '&prod;' => '&#8719;',
939                        '&sum;' => '&#8721;',
940                        '&minus;' => '&#8722;',
941                        '&lowast;' => '&#8727;',
942                        '&radic;' => '&#8730;',
943                        '&prop;' => '&#8733;',
944                        '&infin;' => '&#8734;',
945                        '&ang;' => '&#8736;',
946                        '&and;' => '&#8743;',
947                        '&or;' => '&#8744;',
948                        '&cap;' => '&#8745;',
949                        '&cup;' => '&#8746;',
950                        '&int;' => '&#8747;',
951                        '&there4;' => '&#8756;',
952                        '&sim;' => '&#8764;',
953                        '&cong;' => '&#8773;',
954                        '&asymp;' => '&#8776;',
955                        '&ne;' => '&#8800;',
956                        '&equiv;' => '&#8801;',
957                        '&le;' => '&#8804;',
958                        '&ge;' => '&#8805;',
959                        '&sub;' => '&#8834;',
960                        '&sup;' => '&#8835;',
961                        '&nsub;' => '&#8836;',
962                        '&sube;' => '&#8838;',
963                        '&supe;' => '&#8839;',
964                        '&oplus;' => '&#8853;',
965                        '&otimes;' => '&#8855;',
966                        '&perp;' => '&#8869;',
967                        '&sdot;' => '&#8901;',
968                        '&lceil;' => '&#8968;',
969                        '&rceil;' => '&#8969;',
970                        '&lfloor;' => '&#8970;',
971                        '&rfloor;' => '&#8971;',
972                        '&lang;' => '&#9001;',
973                        '&rang;' => '&#9002;',
974                        '&larr;' => '&#8592;',
975                        '&uarr;' => '&#8593;',
976                        '&rarr;' => '&#8594;',
977                        '&darr;' => '&#8595;',
978                        '&harr;' => '&#8596;',
979                        '&loz;' => '&#9674;',
980                        '&spades;' => '&#9824;',
981                        '&clubs;' => '&#9827;',
982                        '&hearts;' => '&#9829;',
983                        '&diams;' => '&#9830;'
984        );
985
986        foreach ($to_ncr as $entity => $ncr) {
987                $text = str_replace($entity, $ncr, $text);
988        }
989        return $text;
990}
991
992?>