home *** CD-ROM | disk | FTP | other *** search
/ MacAddict 108 / MacAddict108.iso / Software / Internet & Communication / WordPress 1.5.1.dmg / wordpress / wp-includes / functions-formatting.php < prev    next >
Encoding:
PHP Script  |  2005-05-04  |  32.7 KB  |  994 lines

  1. <?php
  2.  
  3. function 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('---', '—', $curl);
  13.             $curl = str_replace(' -- ', ' — ', $curl);
  14.             $curl = str_replace('--', '–', $curl);
  15.             $curl = str_replace('xn–', 'xn--', $curl);
  16.             $curl = str_replace('...', '…', $curl);
  17.             $curl = str_replace('``', '“', $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("’tain’t","’twere","’twas","’tis","’twill","’til","’bout","’nuff","’round","’cause");
  22.             $curl = str_replace($cockney, $cockneyreplace, $curl);
  23.  
  24.             $curl = preg_replace("/'s/", '’s', $curl);
  25.             $curl = preg_replace("/'(\d\d(?:’|')?s)/", "’$1", $curl);
  26.             $curl = preg_replace('/(\s|\A|")\'/', '$1‘', $curl);
  27.             $curl = preg_replace('/(\d+)"/', '$1″', $curl);
  28.             $curl = preg_replace("/(\d+)'/", '$1′', $curl);
  29.             $curl = preg_replace("/(\S)'([^'\s])/", "$1’$2", $curl);
  30.             $curl = preg_replace('/(\s|\A)"(?!\s)/', '$1“$2', $curl);
  31.             $curl = preg_replace('/"(\s|\S|\Z)/', '”$1', $curl);
  32.             $curl = preg_replace("/'([\s.]|\Z)/", '’$1', $curl);
  33.             $curl = preg_replace("/ \(tm\)/i", ' ™', $curl);
  34.             $curl = str_replace("''", '”', $curl);
  35.             
  36.             $curl = preg_replace('/(\d+)x(\d+)/', "$1×$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};)/', '&$1', $curl);
  45.         $output .= $curl;
  46.     }
  47.     return $output;
  48. }
  49.  
  50. function 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.  
  57. function 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.  
  81.  
  82. function seems_utf8($Str) { # by bmorel at ssi dot fr
  83.     for ($i=0; $i<strlen($Str); $i++) {
  84.         if (ord($Str[$i]) < 0x80) continue; # 0bbbbbbb
  85.         elseif ((ord($Str[$i]) & 0xE0) == 0xC0) $n=1; # 110bbbbb
  86.         elseif ((ord($Str[$i]) & 0xF0) == 0xE0) $n=2; # 1110bbbb
  87.         elseif ((ord($Str[$i]) & 0xF8) == 0xF0) $n=3; # 11110bbb
  88.         elseif ((ord($Str[$i]) & 0xFC) == 0xF8) $n=4; # 111110bb
  89.         elseif ((ord($Str[$i]) & 0xFE) == 0xFC) $n=5; # 1111110b
  90.         else return false; # Does not match any model
  91.         for ($j=0; $j<$n; $j++) { # n bytes matching 10bbbbbb follow ?
  92.             if ((++$i == strlen($Str)) || ((ord($Str[$i]) & 0xC0) != 0x80))
  93.             return false;
  94.         }
  95.     }
  96.     return true;
  97. }
  98.  
  99. function wp_specialchars( $text, $quotes = 0 ) {
  100.     // Like htmlspecialchars except don't double-encode HTML entities
  101.     $text = preg_replace('/&([^#])(?![a-z12]{1,8};)/', '&$1', $text);-
  102.     $text = str_replace('<', '<', $text);
  103.     $text = str_replace('>', '>', $text);
  104.     if ( $quotes ) {
  105.         $text = str_replace('"', '"', $text);
  106.         $text = str_replace("'", ''', $text);
  107.     }
  108.     return $text;
  109. }
  110.  
  111. function utf8_uri_encode( $utf8_string ) {
  112.   $unicode = '';        
  113.   $values = array();
  114.   $num_octets = 1;
  115.         
  116.   for ($i = 0; $i < strlen( $utf8_string ); $i++ ) {
  117.  
  118.     $value = ord( $utf8_string[ $i ] );
  119.             
  120.     if ( $value < 128 ) {
  121.       $unicode .= chr($value);
  122.     } else {
  123.       if ( count( $values ) == 0 ) $num_octets = ( $value < 224 ) ? 2 : 3;
  124.                 
  125.       $values[] = $value;
  126.       
  127.       if ( count( $values ) == $num_octets ) {
  128.     if ($num_octets == 3) {
  129.       $unicode .= '%' . dechex($values[0]) . '%' . dechex($values[1]) . '%' . dechex($values[2]);
  130.     } else {
  131.       $unicode .= '%' . dechex($values[0]) . '%' . dechex($values[1]);
  132.     }
  133.  
  134.     $values = array();
  135.     $num_octets = 1;
  136.       }
  137.     }
  138.   }
  139.  
  140.   return $unicode;    
  141. }
  142.  
  143. function remove_accents($string) {
  144.     if (seems_utf8($string)) {
  145.         $chars = array(
  146.         // Decompositions for Latin-1 Supplement
  147.         chr(195).chr(128) => 'A', chr(195).chr(129) => 'A',
  148.         chr(195).chr(130) => 'A', chr(195).chr(131) => 'A',
  149.         chr(195).chr(132) => 'A', chr(195).chr(133) => 'A',
  150.         chr(195).chr(135) => 'C', chr(195).chr(136) => 'E',
  151.         chr(195).chr(137) => 'E', chr(195).chr(138) => 'E',
  152.         chr(195).chr(139) => 'E', chr(195).chr(140) => 'I',
  153.         chr(195).chr(141) => 'I', chr(195).chr(142) => 'I',
  154.         chr(195).chr(143) => 'I', chr(195).chr(145) => 'N',
  155.         chr(195).chr(146) => 'O', chr(195).chr(147) => 'O',
  156.         chr(195).chr(148) => 'O', chr(195).chr(149) => 'O',
  157.         chr(195).chr(150) => 'O', chr(195).chr(153) => 'U',
  158.         chr(195).chr(154) => 'U', chr(195).chr(155) => 'U',
  159.         chr(195).chr(156) => 'U', chr(195).chr(157) => 'Y',
  160.         chr(195).chr(159) => 's', chr(195).chr(160) => 'a',
  161.         chr(195).chr(161) => 'a', chr(195).chr(162) => 'a',
  162.         chr(195).chr(163) => 'a', chr(195).chr(164) => 'a',
  163.         chr(195).chr(165) => 'a', chr(195).chr(167) => 'c',
  164.         chr(195).chr(168) => 'e', chr(195).chr(169) => 'e',
  165.         chr(195).chr(170) => 'e', chr(195).chr(171) => 'e',
  166.         chr(195).chr(172) => 'i', chr(195).chr(173) => 'i',
  167.         chr(195).chr(174) => 'i', chr(195).chr(175) => 'i',
  168.         chr(195).chr(177) => 'n', chr(195).chr(178) => 'o',
  169.         chr(195).chr(179) => 'o', chr(195).chr(180) => 'o',
  170.         chr(195).chr(181) => 'o', chr(195).chr(182) => 'o',
  171.         chr(195).chr(182) => 'o', chr(195).chr(185) => 'u',
  172.         chr(195).chr(186) => 'u', chr(195).chr(187) => 'u',
  173.         chr(195).chr(188) => 'u', chr(195).chr(189) => 'y',
  174.         chr(195).chr(191) => 'y',
  175.         // Decompositions for Latin Extended-A
  176.         chr(196).chr(128) => 'A', chr(196).chr(129) => 'a',
  177.         chr(196).chr(130) => 'A', chr(196).chr(131) => 'a',
  178.         chr(196).chr(132) => 'A', chr(196).chr(133) => 'a',
  179.         chr(196).chr(134) => 'C', chr(196).chr(134) => 'c',
  180.         chr(196).chr(136) => 'C', chr(196).chr(137) => 'c',
  181.         chr(196).chr(138) => 'C', chr(196).chr(139) => 'c',
  182.         chr(196).chr(140) => 'C', chr(196).chr(141) => 'c',
  183.         chr(196).chr(142) => 'D', chr(196).chr(143) => 'd',
  184.         chr(196).chr(144) => 'D', chr(196).chr(145) => 'd',
  185.         chr(196).chr(146) => 'E', chr(196).chr(147) => 'e',
  186.         chr(196).chr(148) => 'E', chr(196).chr(149) => 'e',
  187.         chr(196).chr(150) => 'E', chr(196).chr(151) => 'e',
  188.         chr(196).chr(152) => 'E', chr(196).chr(153) => 'e',
  189.         chr(196).chr(154) => 'E', chr(196).chr(155) => 'e',
  190.         chr(196).chr(156) => 'G', chr(196).chr(157) => 'g',
  191.         chr(196).chr(158) => 'G', chr(196).chr(159) => 'g',
  192.         chr(196).chr(160) => 'G', chr(196).chr(161) => 'g',
  193.         chr(196).chr(162) => 'G', chr(196).chr(163) => 'g',
  194.         chr(196).chr(164) => 'H', chr(196).chr(165) => 'h',
  195.         chr(196).chr(166) => 'H', chr(196).chr(167) => 'h',
  196.         chr(196).chr(168) => 'I', chr(196).chr(169) => 'i',
  197.         chr(196).chr(170) => 'I', chr(196).chr(171) => 'i',
  198.         chr(196).chr(172) => 'I', chr(196).chr(173) => 'i',
  199.         chr(196).chr(174) => 'I', chr(196).chr(175) => 'i',
  200.         chr(196).chr(176) => 'I', chr(196).chr(177) => 'i',
  201.         chr(196).chr(178) => 'IJ',chr(196).chr(179) => 'ij',
  202.         chr(196).chr(180) => 'J', chr(196).chr(181) => 'j',
  203.         chr(196).chr(182) => 'K', chr(196).chr(183) => 'k',
  204.         chr(196).chr(184) => 'k', chr(196).chr(185) => 'L',
  205.         chr(196).chr(186) => 'l', chr(196).chr(187) => 'L',
  206.         chr(196).chr(188) => 'l', chr(196).chr(189) => 'L',
  207.         chr(196).chr(190) => 'l', chr(196).chr(191) => 'L',
  208.         chr(197).chr(128) => 'l', chr(196).chr(129) => 'L',
  209.         chr(197).chr(130) => 'l', chr(196).chr(131) => 'N',
  210.         chr(197).chr(132) => 'n', chr(196).chr(133) => 'N',
  211.         chr(197).chr(134) => 'n', chr(196).chr(135) => 'N',
  212.         chr(197).chr(136) => 'n', chr(196).chr(137) => 'N',
  213.         chr(197).chr(138) => 'n', chr(196).chr(139) => 'N',
  214.         chr(197).chr(140) => 'O', chr(196).chr(141) => 'o',
  215.         chr(197).chr(142) => 'O', chr(196).chr(143) => 'o',
  216.         chr(197).chr(144) => 'O', chr(196).chr(145) => 'o',
  217.         chr(197).chr(146) => 'OE',chr(197).chr(147) => 'oe',
  218.         chr(197).chr(148) => 'R',chr(197).chr(149) => 'r',
  219.         chr(197).chr(150) => 'R',chr(197).chr(151) => 'r',
  220.         chr(197).chr(152) => 'R',chr(197).chr(153) => 'r',
  221.         chr(197).chr(154) => 'S',chr(197).chr(155) => 's',
  222.         chr(197).chr(156) => 'S',chr(197).chr(157) => 's',
  223.         chr(197).chr(158) => 'S',chr(197).chr(159) => 's',
  224.         chr(197).chr(160) => 'S', chr(197).chr(161) => 's',
  225.         chr(197).chr(162) => 'T', chr(197).chr(163) => 't',
  226.         chr(197).chr(164) => 'T', chr(197).chr(165) => 't',
  227.         chr(197).chr(166) => 'T', chr(197).chr(167) => 't',
  228.         chr(197).chr(168) => 'U', chr(197).chr(169) => 'u',
  229.         chr(197).chr(170) => 'U', chr(197).chr(171) => 'u',
  230.         chr(197).chr(172) => 'U', chr(197).chr(173) => 'u',
  231.         chr(197).chr(174) => 'U', chr(197).chr(175) => 'u',
  232.         chr(197).chr(176) => 'U', chr(197).chr(177) => 'u',
  233.         chr(197).chr(178) => 'U', chr(197).chr(179) => 'u',
  234.         chr(197).chr(180) => 'W', chr(197).chr(181) => 'w',
  235.         chr(197).chr(182) => 'Y', chr(197).chr(183) => 'y',
  236.         chr(197).chr(184) => 'Y', chr(197).chr(185) => 'Z',
  237.         chr(197).chr(186) => 'z', chr(197).chr(187) => 'Z',
  238.         chr(197).chr(188) => 'z', chr(197).chr(189) => 'Z',
  239.         chr(197).chr(190) => 'z', chr(197).chr(191) => 's',
  240.         // Euro Sign
  241.         chr(226).chr(130).chr(172) => 'E');
  242.         
  243.         $string = strtr($string, $chars);
  244.     } else {
  245.         // Assume ISO-8859-1 if not UTF-8
  246.         $chars['in'] = chr(128).chr(131).chr(138).chr(142).chr(154).chr(158)
  247.             .chr(159).chr(162).chr(165).chr(181).chr(192).chr(193).chr(194)
  248.             .chr(195).chr(196).chr(197).chr(199).chr(200).chr(201).chr(202)
  249.             .chr(203).chr(204).chr(205).chr(206).chr(207).chr(209).chr(210)
  250.             .chr(211).chr(212).chr(213).chr(214).chr(216).chr(217).chr(218)
  251.             .chr(219).chr(220).chr(221).chr(224).chr(225).chr(226).chr(227)
  252.             .chr(228).chr(229).chr(231).chr(232).chr(233).chr(234).chr(235)
  253.             .chr(236).chr(237).chr(238).chr(239).chr(241).chr(242).chr(243)
  254.             .chr(244).chr(245).chr(246).chr(248).chr(249).chr(250).chr(251)
  255.             .chr(252).chr(253).chr(255);
  256.  
  257.         $chars['out'] = "EfSZszYcYuAAAAAACEEEEIIIINOOOOOOUUUUYaaaaaaceeeeiiiinoooooouuuuyy";
  258.  
  259.         $string = strtr($string, $chars['in'], $chars['out']);
  260.         $double_chars['in'] = array(chr(140), chr(156), chr(198), chr(208), chr(222), chr(223), chr(230), chr(240), chr(254));
  261.         $double_chars['out'] = array('OE', 'oe', 'AE', 'DH', 'TH', 'ss', 'ae', 'dh', 'th');
  262.         $string = str_replace($double_chars['in'], $double_chars['out'], $string);
  263.     }
  264.  
  265.     return $string;
  266. }
  267.  
  268. function sanitize_title($title, $fallback_title = '') {
  269.     $title = strip_tags($title);
  270.     $title = apply_filters('sanitize_title', $title);
  271.  
  272.     if (empty($title)) {
  273.         $title = $fallback_title;
  274.     }
  275.  
  276.     return $title;
  277. }
  278.  
  279. function sanitize_title_with_dashes($title) {
  280.     $title = strip_tags($title);
  281.     // Preserve escaped octets.
  282.     $title = preg_replace('|%([a-fA-F0-9][a-fA-F0-9])|', '---$1---', $title);
  283.     // Remove percent signs that are not part of an octet.
  284.     $title = str_replace('%', '', $title);
  285.     // Restore octets.
  286.     $title = preg_replace('|---([a-fA-F0-9][a-fA-F0-9])---|', '%$1', $title);
  287.  
  288.     $title = remove_accents($title);
  289.     if (seems_utf8($title)) {
  290.         if (function_exists('mb_strtolower')) {
  291.             $title = mb_strtolower($title, 'UTF-8');
  292.         }
  293.         $title = utf8_uri_encode($title);
  294.     }
  295.  
  296.     $title = strtolower($title);
  297.     $title = preg_replace('/&.+?;/', '', $title); // kill entities
  298.     $title = preg_replace('/[^%a-z0-9 _-]/', '', $title);
  299.     $title = preg_replace('/\s+/', '-', $title);
  300.     $title = preg_replace('|-+|', '-', $title);
  301.     $title = trim($title, '-');
  302.  
  303.     return $title;
  304. }
  305.  
  306. function convert_chars($content, $flag = 'obsolete') { 
  307.     // Translation of invalid Unicode references range to valid range
  308.     $wp_htmltranswinuni = array(
  309.     '€' => '€', // the Euro sign
  310.     '' => '',
  311.     '‚' => '‚', // these are Windows CP1252 specific characters
  312.     'ƒ' => 'ƒ',  // they would look weird on non-Windows browsers
  313.     '„' => '„',
  314.     '…' => '…',
  315.     '†' => '†',
  316.     '‡' => '‡',
  317.     'ˆ' => 'ˆ',
  318.     '‰' => '‰',
  319.     'Š' => 'Š',
  320.     '‹' => '‹',
  321.     'Œ' => 'Œ',
  322.     '' => '',
  323.     'Ž' => 'ž',
  324.     '' => '',
  325.     '' => '',
  326.     '‘' => '‘',
  327.     '’' => '’',
  328.     '“' => '“',
  329.     '”' => '”',
  330.     '•' => '•',
  331.     '–' => '–',
  332.     '—' => '—',
  333.     '˜' => '˜',
  334.     '™' => '™',
  335.     'š' => 'š',
  336.     '›' => '›',
  337.     'œ' => 'œ',
  338.     '' => '',
  339.     'ž' => '',
  340.     'Ÿ' => 'Ÿ'
  341.     );
  342.  
  343.     // Remove metadata tags
  344.     $content = preg_replace('/<title>(.+?)<\/title>/','',$content);
  345.     $content = preg_replace('/<category>(.+?)<\/category>/','',$content);
  346.  
  347.     // Converts lone & characters into & (a.k.a. &)
  348.     $content = preg_replace('/&([^#])(?![a-z]{1,8};)/i', '&$1', $content);
  349.  
  350.     // Fix Word pasting
  351.     $content = strtr($content, $wp_htmltranswinuni);
  352.  
  353.     // Just a little XHTML help
  354.     $content = str_replace('<br>', '<br />', $content);
  355.     $content = str_replace('<hr>', '<hr />', $content);
  356.  
  357.     return $content;
  358. }
  359.  
  360. function funky_javascript_fix($text) {
  361.     // Fixes for browsers' javascript bugs
  362.     global $is_macIE, $is_winIE;
  363.     
  364.     if ( $is_winIE || $is_macIE )
  365.         $text =  preg_replace("/\%u([0-9A-F]{4,4})/e",  "'&#'.base_convert('\\1',16,10).';'", $text);
  366.     
  367.     return $text;
  368. }
  369.  
  370. /*
  371.  balanceTags
  372.  
  373.  Balances Tags of string using a modified stack.
  374.  
  375.  @param text      Text to be balanced
  376.  @return          Returns balanced text
  377.  @author          Leonard Lin (leonard@acm.org)
  378.  @version         v1.1
  379.  @date            November 4, 2001
  380.  @license         GPL v2.0
  381.  @notes           
  382.  @changelog       
  383.  ---  Modified by Scott Reilly (coffee2code) 02 Aug 2004
  384.              1.2  ***TODO*** Make better - change loop condition to $text
  385.              1.1  Fixed handling of append/stack pop order of end text
  386.                   Added Cleaning Hooks
  387.              1.0  First Version
  388. */
  389. function balanceTags($text, $is_comment = 0) {
  390.     
  391.     if (get_settings('use_balanceTags') == 0) {
  392.         return $text;
  393.     }
  394.  
  395.     $tagstack = array(); $stacksize = 0; $tagqueue = ''; $newtext = '';
  396.  
  397.     # WP bug fix for comments - in case you REALLY meant to type '< !--'
  398.     $text = str_replace('< !--', '<    !--', $text);
  399.     # WP bug fix for LOVE <3 (and other situations with '<' before a number)
  400.     $text = preg_replace('#<([0-9]{1})#', '<$1', $text);
  401.  
  402.     while (preg_match("/<(\/?\w*)\s*([^>]*)>/",$text,$regex)) {
  403.         $newtext .= $tagqueue;
  404.  
  405.         $i = strpos($text,$regex[0]);
  406.         $l = strlen($regex[0]);
  407.  
  408.         // clear the shifter
  409.         $tagqueue = '';
  410.         // Pop or Push
  411.         if ($regex[1][0] == "/") { // End Tag
  412.             $tag = strtolower(substr($regex[1],1));
  413.             // if too many closing tags
  414.             if($stacksize <= 0) { 
  415.                 $tag = '';
  416.                 //or close to be safe $tag = '/' . $tag;
  417.             }
  418.             // if stacktop value = tag close value then pop
  419.             else if ($tagstack[$stacksize - 1] == $tag) { // found closing tag
  420.                 $tag = '</' . $tag . '>'; // Close Tag
  421.                 // Pop
  422.                 array_pop ($tagstack);
  423.                 $stacksize--;
  424.             } else { // closing tag not at top, search for it
  425.                 for ($j=$stacksize-1;$j>=0;$j--) {
  426.                     if ($tagstack[$j] == $tag) {
  427.                     // add tag to tagqueue
  428.                         for ($k=$stacksize-1;$k>=$j;$k--){
  429.                             $tagqueue .= '</' . array_pop ($tagstack) . '>';
  430.                             $stacksize--;
  431.                         }
  432.                         break;
  433.                     }
  434.                 }
  435.                 $tag = '';
  436.             }
  437.         } else { // Begin Tag
  438.             $tag = strtolower($regex[1]);
  439.  
  440.             // Tag Cleaning
  441.  
  442.             // If self-closing or '', don't do anything.
  443.             if((substr($regex[2],-1) == '/') || ($tag == '')) {
  444.             }
  445.             // ElseIf it's a known single-entity tag but it doesn't close itself, do so
  446.             elseif ($tag == 'br' || $tag == 'img' || $tag == 'hr' || $tag == 'input') {
  447.                 $regex[2] .= '/';
  448.             } else {    // Push the tag onto the stack
  449.                 // If the top of the stack is the same as the tag we want to push, close previous tag
  450.                 if (($stacksize > 0) && ($tag != 'div') && ($tagstack[$stacksize - 1] == $tag)) {
  451.                     $tagqueue = '</' . array_pop ($tagstack) . '>';
  452.                     $stacksize--;
  453.                 }
  454.                 $stacksize = array_push ($tagstack, $tag);
  455.             }
  456.  
  457.             // Attributes
  458.             $attributes = $regex[2];
  459.             if($attributes) {
  460.                 $attributes = ' '.$attributes;
  461.             }
  462.             $tag = '<'.$tag.$attributes.'>';
  463.             //If already queuing a close tag, then put this tag on, too
  464.             if ($tagqueue) {
  465.                 $tagqueue .= $tag;
  466.                 $tag = '';
  467.             }
  468.         }
  469.         $newtext .= substr($text,0,$i) . $tag;
  470.         $text = substr($text,$i+$l);
  471.     }  
  472.  
  473.     // Clear Tag Queue
  474.     $newtext .= $tagqueue;
  475.  
  476.     // Add Remaining text
  477.     $newtext .= $text;
  478.  
  479.     // Empty Stack
  480.     while($x = array_pop($tagstack)) {
  481.         $newtext .= '</' . $x . '>'; // Add remaining tags to close
  482.     }
  483.  
  484.     // WP fix for the bug with HTML comments
  485.     $newtext = str_replace("< !--","<!--",$newtext);
  486.     $newtext = str_replace("<    !--","< !--",$newtext);
  487.  
  488.     return $newtext;
  489. }
  490.  
  491.  
  492. function format_to_edit($content) {
  493.     $content = apply_filters('format_to_edit', $content);
  494.     $content = htmlspecialchars($content);
  495.     return $content;
  496. }
  497.  
  498. function format_to_post($content) {
  499.     global $wpdb;
  500.     $content = apply_filters('format_to_post', $content);
  501.     return $content;
  502. }
  503.  
  504. function zeroise($number,$threshold) { // function to add leading zeros when necessary
  505.     return sprintf('%0'.$threshold.'s', $number);
  506.     }
  507.  
  508.  
  509. function backslashit($string) {
  510.     $string = preg_replace('/([a-z])/i', '\\\\\1', $string);
  511.     return $string;
  512. }
  513.  
  514. function trailingslashit($string) {
  515.     if ( '/' != substr($string, -1)) {
  516.         $string .= '/';
  517.     }
  518.     return $string;
  519. }
  520.  
  521. function addslashes_gpc($gpc) {
  522.     if (!get_magic_quotes_gpc()) {
  523.         $gpc = addslashes($gpc);
  524.     }
  525.     return $gpc;
  526. }
  527.  
  528. function antispambot($emailaddy, $mailto=0) {
  529.     $emailNOSPAMaddy = '';
  530.     srand ((float) microtime() * 1000000);
  531.     for ($i = 0; $i < strlen($emailaddy); $i = $i + 1) {
  532.         $j = floor(rand(0, 1+$mailto));
  533.         if ($j==0) {
  534.             $emailNOSPAMaddy .= '&#'.ord(substr($emailaddy,$i,1)).';';
  535.         } elseif ($j==1) {
  536.             $emailNOSPAMaddy .= substr($emailaddy,$i,1);
  537.         } elseif ($j==2) {
  538.             $emailNOSPAMaddy .= '%'.zeroise(dechex(ord(substr($emailaddy, $i, 1))), 2);
  539.         }
  540.     }
  541.     $emailNOSPAMaddy = str_replace('@','@',$emailNOSPAMaddy);
  542.     return $emailNOSPAMaddy;
  543. }
  544.  
  545. function make_clickable($ret) {
  546.     $ret = ' ' . $ret . ' ';
  547.     $ret = preg_replace("#([\s>])(https?)://([^\s<>{}()]+[^\s.,<>{}()])#i", "$1<a href='$2://$3' rel='nofollow'>$2://$3</a>", $ret);
  548.     $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);
  549.     $ret = preg_replace("#(\s)([a-z0-9\-_.]+)@([^,< \n\r]+)#i", "$1<a href=\"mailto:$2@$3\">$2@$3</a>", $ret);
  550.     $ret = trim($ret);
  551.     return $ret;
  552. }
  553.  
  554. function wp_rel_nofollow( $text ) {
  555.     $text = preg_replace('|<a (.+?)>|i', '<a $1 rel="nofollow">', $text);
  556.     return $text;
  557. }
  558.  
  559. function convert_smilies($text) {
  560.     global $wp_smiliessearch, $wp_smiliesreplace;
  561.     $output = '';
  562.     if (get_settings('use_smilies')) {
  563.         // HTML loop taken from texturize function, could possible be consolidated
  564.         $textarr = preg_split("/(<.*>)/U", $text, -1, PREG_SPLIT_DELIM_CAPTURE); // capture the tags as well as in between
  565.         $stop = count($textarr);// loop stuff
  566.         for ($i = 0; $i < $stop; $i++) {
  567.             $content = $textarr[$i];
  568.             if ((strlen($content) > 0) && ('<' != $content{0})) { // If it's not a tag
  569.                 $content = str_replace($wp_smiliessearch, $wp_smiliesreplace, $content);
  570.             }
  571.             $output .= $content;
  572.         }
  573.     } else {
  574.         // return default text.
  575.         $output = $text;
  576.     }
  577.     return $output;
  578. }
  579.  
  580.  
  581. function is_email($user_email) {
  582.     $chars = "/^([a-z0-9+_]|\\-|\\.)+@(([a-z0-9_]|\\-)+\\.)+[a-z]{2,6}\$/i";
  583.     if(strstr($user_email, '@') && strstr($user_email, '.')) {
  584.         if (preg_match($chars, $user_email)) {
  585.             return true;
  586.         } else {
  587.             return false;
  588.         }
  589.     } else {
  590.         return false;
  591.     }
  592. }
  593.  
  594.  
  595. function strip_all_but_one_link($text, $mylink) {
  596.     $match_link = '#(<a.+?href.+?'.'>)(.+?)(</a>)#';
  597.     preg_match_all($match_link, $text, $matches);
  598.     $count = count($matches[0]);
  599.     for ($i=0; $i<$count; $i++) {
  600.         if (!strstr($matches[0][$i], $mylink)) {
  601.             $text = str_replace($matches[0][$i], $matches[2][$i], $text);
  602.         }
  603.     }
  604.     return $text;
  605. }
  606.  
  607.  
  608. // used by wp-mail to handle charsets in email subjects
  609. function wp_iso_descrambler($string) {
  610.   /* this may only work with iso-8859-1, I'm afraid */
  611.   if (!preg_match('#\=\?(.+)\?Q\?(.+)\?\=#i', $string, $matches)) {
  612.     return $string;
  613.   } else {
  614.     $subject = str_replace('_', ' ', $matches[2]);
  615.     $subject = preg_replace('#\=([0-9a-f]{2})#ei', "chr(hexdec(strtolower('$1')))", $subject);
  616.     return $subject;
  617.   }
  618. }
  619.  
  620.  
  621. // give it a date, it will give you the same date as GMT
  622. function get_gmt_from_date($string) {
  623.   // note: this only substracts $time_difference from the given date
  624.   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);
  625.   $string_time = gmmktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
  626.   $string_gmt = gmdate('Y-m-d H:i:s', $string_time - get_settings('gmt_offset') * 3600);
  627.   return $string_gmt;
  628. }
  629.  
  630. // give it a GMT date, it will give you the same date with $time_difference added
  631. function get_date_from_gmt($string) {
  632.   // note: this only adds $time_difference to the given date
  633.   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);
  634.   $string_time = gmmktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]);
  635.   $string_localtime = gmdate('Y-m-d H:i:s', $string_time + get_settings('gmt_offset')*3600);
  636.   return $string_localtime;
  637. }
  638.  
  639. // computes an offset in seconds from an iso8601 timezone
  640. function iso8601_timezone_to_offset($timezone) {
  641.   // $timezone is either 'Z' or '[+|-]hhmm'
  642.   if ($timezone == 'Z') {
  643.     $offset = 0;
  644.   } else {
  645.     $sign    = (substr($timezone, 0, 1) == '+') ? 1 : -1;
  646.     $hours   = intval(substr($timezone, 1, 2));
  647.     $minutes = intval(substr($timezone, 3, 4)) / 60;
  648.     $offset  = $sign * 3600 * ($hours + $minutes);
  649.   }
  650.   return $offset;
  651. }
  652.  
  653. // converts an iso8601 date to MySQL DateTime format used by post_date[_gmt]
  654. function iso8601_to_datetime($date_string, $timezone = USER) {
  655.   if ($timezone == GMT) {
  656.     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);
  657.     if (!empty($date_bits[7])) { // we have a timezone, so let's compute an offset
  658.       $offset = iso8601_timezone_to_offset($date_bits[7]);
  659.     } else { // we don't have a timezone, so we assume user local timezone (not server's!)
  660.       $offset = 3600 * get_settings('gmt_offset');
  661.     }
  662.     $timestamp = gmmktime($date_bits[4], $date_bits[5], $date_bits[6], $date_bits[2], $date_bits[3], $date_bits[1]);
  663.     $timestamp -= $offset;
  664.     return gmdate('Y-m-d H:i:s', $timestamp);
  665.   } elseif ($timezone == USER) {
  666.     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);
  667.   }
  668. }
  669.  
  670. function popuplinks($text) {
  671.     // Comment text in popup windows should be filtered through this.
  672.     // Right now it's a moderately dumb function, ideally it would detect whether
  673.     // a target or rel attribute was already there and adjust its actions accordingly.
  674.     $text = preg_replace('/<a (.+?)>/i', "<a $1 target='_blank' rel='external'>", $text);
  675.     return $text;
  676. }
  677.  
  678. function sanitize_email($email) {
  679.     return preg_replace('/[^a-z0-9+_.@-]/i', '', $email);
  680. }
  681.  
  682. function human_time_diff( $from, $to = '' ) {     
  683.     if ( empty($to) )
  684.         $to = time();
  685.     $diff = (int) abs($to - $from);
  686.     if ($diff <= 3600) {
  687.         $mins = round($diff / 60);
  688.         if ($mins <= 1)
  689.             $since = __('1 min');
  690.         else
  691.             $since = sprintf( __('%s mins'), $mins);
  692.     } else if (($diff <= 86400) && ($diff > 3600)) {
  693.         $hours = round($diff / 3600);
  694.         if ($hours <= 1)
  695.             $since = __('1 hour');
  696.         else 
  697.             $since = sprintf( __('%s hours'), $hours );
  698.     } elseif ($diff >= 86400) {
  699.         $days = round($diff / 86400);
  700.         if ($days <= 1)
  701.             $since = __('1 day');
  702.         else
  703.             $since = sprintf( __('%s days'), $days );
  704.     }
  705.     return $since;
  706. }
  707.  
  708. function wp_trim_excerpt($text) { // Fakes an excerpt if needed
  709.     global $post;
  710.     if ( '' == $text ) {
  711.         $text = $post->post_content;
  712.         $text = apply_filters('the_content', $text);
  713.         $text = str_replace(']]>', ']]>', $text);
  714.         $text = strip_tags($text);
  715.         $excerpt_length = 55;
  716.         $words = explode(' ', $text, $excerpt_length + 1);
  717.         if (count($words) > $excerpt_length) {
  718.             array_pop($words);
  719.             array_push($words, '[...]');
  720.             $text = implode(' ', $words);
  721.         }
  722.     }
  723.     return $text;
  724. }
  725.  
  726. function ent2ncr($text) {
  727.     $to_ncr = array(
  728.             '"' => '"',
  729.             '&' => '&',
  730.             '⁄' => '/',
  731.             '<' => '<',
  732.             '>' => '>',
  733.             ' ' => ' ',
  734.             '¡' => '¡',
  735.             '¢' => '¢',
  736.             '£' => '£',
  737.             '¤' => '¤',
  738.             '¥' => '¥',
  739.             '|' => '¦',
  740.             '¦' => '¦',
  741.             '&brkbar;' => '¦',
  742.             '§' => '§',
  743.             '¨' => '¨',
  744.             '¨' => '¨',
  745.             '©' => '©',
  746.             'ª' => 'ª',
  747.             '«' => '«',
  748.             '¬' => '¬',
  749.             '­' => '­',
  750.             '®' => '®',
  751.             '¯' => '¯',
  752.             '&hibar;' => '¯',
  753.             '°' => '°',
  754.             '±' => '±',
  755.             '²' => '²',
  756.             '³' => '³',
  757.             '´' => '´',
  758.             'µ' => 'µ',
  759.             '¶' => '¶',
  760.             '·' => '·',
  761.             '¸' => '¸',
  762.             '¹' => '¹',
  763.             'º' => 'º',
  764.             '»' => '»',
  765.             '¼' => '¼',
  766.             '½' => '½',
  767.             '¾' => '¾',
  768.             '¿' => '¿',
  769.             'À' => 'À',
  770.             'Á' => 'Á',
  771.             'Â' => 'Â',
  772.             'Ã' => 'Ã',
  773.             'Ä' => 'Ä',
  774.             'Å' => 'Å',
  775.             'Æ' => 'Æ',
  776.             'Ç' => 'Ç',
  777.             'È' => 'È',
  778.             'É' => 'É',
  779.             'Ê' => 'Ê',
  780.             'Ë' => 'Ë',
  781.             'Ì' => 'Ì',
  782.             'Í' => 'Í',
  783.             'Î' => 'Î',
  784.             'Ï' => 'Ï',
  785.             'Ð' => 'Ð',
  786.             'Ñ' => 'Ñ',
  787.             'Ò' => 'Ò',
  788.             'Ó' => 'Ó',
  789.             'Ô' => 'Ô',
  790.             'Õ' => 'Õ',
  791.             'Ö' => 'Ö',
  792.             '×' => '×',
  793.             'Ø' => 'Ø',
  794.             'Ù' => 'Ù',
  795.             'Ú' => 'Ú',
  796.             'Û' => 'Û',
  797.             'Ü' => 'Ü',
  798.             'Ý' => 'Ý',
  799.             'Þ' => 'Þ',
  800.             'ß' => 'ß',
  801.             'à' => 'à',
  802.             'á' => 'á',
  803.             'â' => 'â',
  804.             'ã' => 'ã',
  805.             'ä' => 'ä',
  806.             'å' => 'å',
  807.             'æ' => 'æ',
  808.             'ç' => 'ç',
  809.             'è' => 'è',
  810.             'é' => 'é',
  811.             'ê' => 'ê',
  812.             'ë' => 'ë',
  813.             'ì' => 'ì',
  814.             'í' => 'í',
  815.             'î' => 'î',
  816.             'ï' => 'ï',
  817.             'ð' => 'ð',
  818.             'ñ' => 'ñ',
  819.             'ò' => 'ò',
  820.             'ó' => 'ó',
  821.             'ô' => 'ô',
  822.             'õ' => 'õ',
  823.             'ö' => 'ö',
  824.             '÷' => '÷',
  825.             'ø' => 'ø',
  826.             'ù' => 'ù',
  827.             'ú' => 'ú',
  828.             'û' => 'û',
  829.             'ü' => 'ü',
  830.             'ý' => 'ý',
  831.             'þ' => 'þ',
  832.             'ÿ' => 'ÿ',
  833.             'Œ' => 'Œ',
  834.             'œ' => 'œ',
  835.             'Š' => 'Š',
  836.             'š' => 'š',
  837.             'Ÿ' => 'Ÿ',
  838.             'ƒ' => 'ƒ',
  839.             'ˆ' => 'ˆ',
  840.             '˜' => '˜',
  841.             'Α' => 'Α',
  842.             'Β' => 'Β',
  843.             'Γ' => 'Γ',
  844.             'Δ' => 'Δ',
  845.             'Ε' => 'Ε',
  846.             'Ζ' => 'Ζ',
  847.             'Η' => 'Η',
  848.             'Θ' => 'Θ',
  849.             'Ι' => 'Ι',
  850.             'Κ' => 'Κ',
  851.             'Λ' => 'Λ',
  852.             'Μ' => 'Μ',
  853.             'Ν' => 'Ν',
  854.             'Ξ' => 'Ξ',
  855.             'Ο' => 'Ο',
  856.             'Π' => 'Π',
  857.             'Ρ' => 'Ρ',
  858.             'Σ' => 'Σ',
  859.             'Τ' => 'Τ',
  860.             'Υ' => 'Υ',
  861.             'Φ' => 'Φ',
  862.             'Χ' => 'Χ',
  863.             'Ψ' => 'Ψ',
  864.             'Ω' => 'Ω',
  865.             'α' => 'α',
  866.             'β' => 'β',
  867.             'γ' => 'γ',
  868.             'δ' => 'δ',
  869.             'ε' => 'ε',
  870.             'ζ' => 'ζ',
  871.             'η' => 'η',
  872.             'θ' => 'θ',
  873.             'ι' => 'ι',
  874.             'κ' => 'κ',
  875.             'λ' => 'λ',
  876.             'μ' => 'μ',
  877.             'ν' => 'ν',
  878.             'ξ' => 'ξ',
  879.             'ο' => 'ο',
  880.             'π' => 'π',
  881.             'ρ' => 'ρ',
  882.             'ς' => 'ς',
  883.             'σ' => 'σ',
  884.             'τ' => 'τ',
  885.             'υ' => 'υ',
  886.             'φ' => 'φ',
  887.             'χ' => 'χ',
  888.             'ψ' => 'ψ',
  889.             'ω' => 'ω',
  890.             'ϑ' => 'ϑ',
  891.             'ϒ' => 'ϒ',
  892.             'ϖ' => 'ϖ',
  893.             ' ' => ' ',
  894.             ' ' => ' ',
  895.             ' ' => ' ',
  896.             '‌' => '‌',
  897.             '‍' => '‍',
  898.             '‎' => '‎',
  899.             '‏' => '‏',
  900.             '–' => '–',
  901.             '—' => '—',
  902.             '‘' => '‘',
  903.             '’' => '’',
  904.             '‚' => '‚',
  905.             '“' => '“',
  906.             '”' => '”',
  907.             '„' => '„',
  908.             '†' => '†',
  909.             '‡' => '‡',
  910.             '•' => '•',
  911.             '…' => '…',
  912.             '‰' => '‰',
  913.             '′' => '′',
  914.             '″' => '″',
  915.             '‹' => '‹',
  916.             '›' => '›',
  917.             '‾' => '‾',
  918.             '⁄' => '⁄',
  919.             '€' => '€',
  920.             'ℑ' => 'ℑ',
  921.             '℘' => '℘',
  922.             'ℜ' => 'ℜ',
  923.             '™' => '™',
  924.             'ℵ' => 'ℵ',
  925.             '↵' => '↵',
  926.             '⇐' => '⇐',
  927.             '⇑' => '⇑',
  928.             '⇒' => '⇒',
  929.             '⇓' => '⇓',
  930.             '⇔' => '⇔',
  931.             '∀' => '∀',
  932.             '∂' => '∂',
  933.             '∃' => '∃',
  934.             '∅' => '∅',
  935.             '∇' => '∇',
  936.             '∈' => '∈',
  937.             '∉' => '∉',
  938.             '∋' => '∋',
  939.             '∏' => '∏',
  940.             '∑' => '∑',
  941.             '−' => '−',
  942.             '∗' => '∗',
  943.             '√' => '√',
  944.             '∝' => '∝',
  945.             '∞' => '∞',
  946.             '∠' => '∠',
  947.             '∧' => '∧',
  948.             '∨' => '∨',
  949.             '∩' => '∩',
  950.             '∪' => '∪',
  951.             '∫' => '∫',
  952.             '∴' => '∴',
  953.             '∼' => '∼',
  954.             '≅' => '≅',
  955.             '≈' => '≈',
  956.             '≠' => '≠',
  957.             '≡' => '≡',
  958.             '≤' => '≤',
  959.             '≥' => '≥',
  960.             '⊂' => '⊂',
  961.             '⊃' => '⊃',
  962.             '⊄' => '⊄',
  963.             '⊆' => '⊆',
  964.             '⊇' => '⊇',
  965.             '⊕' => '⊕',
  966.             '⊗' => '⊗',
  967.             '⊥' => '⊥',
  968.             '⋅' => '⋅',
  969.             '⌈' => '⌈',
  970.             '⌉' => '⌉',
  971.             '⌊' => '⌊',
  972.             '⌋' => '⌋',
  973.             '⟨' => '〈',
  974.             '⟩' => '〉',
  975.             '←' => '←',
  976.             '↑' => '↑',
  977.             '→' => '→',
  978.             '↓' => '↓',
  979.             '↔' => '↔',
  980.             '◊' => '◊',
  981.             '♠' => '♠',
  982.             '♣' => '♣',
  983.             '♥' => '♥',
  984.             '♦' => '♦'
  985.     );
  986.  
  987.     foreach ($to_ncr as $entity => $ncr) {
  988.         $text = str_replace($entity, $ncr, $text);
  989.     }
  990.     return $text;
  991. }
  992.  
  993. ?>
  994.