Advertisement
Guest User

Untitled

a guest
Nov 27th, 2013
138
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PHP 34.20 KB | None | 0 0
  1. <?php
  2.  
  3. /**
  4.  * Copyright (C) 2008-2012 FluxBB
  5.  * based on code by Rickard Andersson copyright (C) 2002-2008 PunBB
  6.  * License: http://www.gnu.org/licenses/gpl.html GPL version 2 or higher
  7.  */
  8.  
  9. // Make sure no one attempts to run this script "directly"
  10. if (!defined('PUN'))
  11.     exit;
  12.  
  13. // Global variables
  14. /* regular expression to match nested BBCode LIST tags
  15. '%
  16. \[list                # match opening bracket and tag name of outermost LIST tag
  17. (?:=([1a*]))?+        # optional attribute capture in group 1
  18. \]                    # closing bracket of outermost opening LIST tag
  19. (                     # capture contents of LIST tag in group 2
  20.   (?:                 # non capture group for either contents or whole nested LIST
  21.     [^\[]*+           # unroll the loop! consume everything up to next [ (normal *)
  22.     (?:               # (See "Mastering Regular Expressions" chapter 6 for details)
  23.       (?!             # negative lookahead ensures we are NOT on [LIST*] or [/LIST]
  24.         \[list        # opening LIST tag
  25.         (?:=[1a*])?+  # with optional attribute
  26.         \]            # closing bracket of opening LIST tag
  27.         |             # or...
  28.         \[/list\]     # a closing LIST tag
  29.       )               # end negative lookahead assertion (we are not on a LIST tag)
  30.       \[              # match the [ which is NOT the start of LIST tag (special)
  31.       [^\[]*+         # consume everything up to next [ (normal *)
  32.     )*+               # finish up "unrolling the loop" technique (special (normal*))*
  33.   |                   # or...
  34.     (?R)              # recursively match a whole nested LIST element
  35.   )*                  # as many times as necessary until deepest nested LIST tag grabbed
  36. )                     # end capturing contents of LIST tag into group 2
  37. \[/list\]             # match outermost closing LIST tag
  38. %iex' */
  39. $re_list = '%\[list(?:=([1a*]))?+\]((?:[^\[]*+(?:(?!\[list(?:=[1a*])?+\]|\[/list\])\[[^\[]*+)*+|(?R))*)\[/list\]%i';
  40.  
  41. /// Load smilies cache MODIFIER (VOIR README.TXT SMILIES MANAGER V1.4.1)
  42. if (file_exists(FORUM_CACHE_DIR.'cache_smilies.php'))
  43.  
  44.     include FORUM_CACHE_DIR.'cache_smilies.php';
  45. else
  46. {
  47.  
  48.     require_once PUN_ROOT.'include/cache_smilies.php';
  49.  
  50.     generate_smiley_cache();
  51.  
  52.     require FORUM_CACHE_DIR.'cache_smilies.php';
  53. }
  54.  
  55. //
  56. // Make sure all BBCodes are lower case and do a little cleanup
  57. //
  58. function preparse_bbcode($text, &$errors, $is_signature = false)
  59. {
  60.     global $pun_config, $lang_common, $lang_post, $re_list;
  61.  
  62.     // Remove empty tags
  63.     while (($new_text = strip_empty_bbcode($text)) !== false)
  64.     {
  65.         if ($new_text != $text)
  66.         {
  67.             $text = $new_text;
  68.             if ($new_text == '')
  69.             {
  70.                 $errors[] = $lang_post['Empty after strip'];
  71.                 return '';
  72.             }
  73.         }
  74.         else
  75.             break;
  76.     }
  77.  
  78.     if ($is_signature)
  79.     {
  80.         global $lang_profile;
  81.  
  82.         if (preg_match('%\[/?(?:quote|code|list|h)\b[^\]]*\]%i', $text))
  83.             $errors[] = $lang_profile['Signature quote/code/list/h'];
  84.     }
  85.    
  86.     //AJOUTER (VOIR TUTO README.TXT FLUXTOOLBAR V2.1.1)
  87.             global $pun_user;
  88.         if (preg_match('%\[/?(?:video|left|right|center|justify)\b[^\]]*\]%i', $text))
  89.         {
  90.             if (file_exists(PUN_ROOT.'lang/'.$pun_user['language'].'/fluxtoolbar.php'))
  91.                 require PUN_ROOT.'lang/'.$pun_user['language'].'/fluxtoolbar.php';
  92.             else
  93.                 require PUN_ROOT.'lang/English/fluxtoolbar.php';
  94.             $errors[] = $lang_ftb['Signature balises'];
  95.         }
  96.  
  97.     // If the message contains a code tag we have to split it up (text within [code][/code] shouldn't be touched)
  98.     if (strpos($text, '[code]') !== false && strpos($text, '[/code]') !== false)
  99.         list($inside, $text) = extract_blocks($text, '[code]', '[/code]');
  100.  
  101.     // Tidy up lists
  102.     $temp = preg_replace_callback($re_list, create_function('$matches', 'return preparse_list_tag($matches[2], $matches[1]);'), $text);
  103.  
  104.     // If the regex failed
  105.     if (is_null($temp))
  106.         $errors[] = $lang_common['BBCode list size error'];
  107.     else
  108.         $text = str_replace('*'."\0".']', '*]', $temp);
  109.  
  110.     if ($pun_config['o_make_links'] == '1')
  111.         $text = do_clickable($text);
  112.  
  113.     $temp_text = false;
  114.     if (empty($errors))
  115.         $temp_text = preparse_tags($text, $errors, $is_signature);
  116.  
  117.     if ($temp_text !== false)
  118.         $text = $temp_text;
  119.  
  120.     // If we split up the message before we have to concatenate it together again (code tags)
  121.     if (isset($inside))
  122.     {
  123.         $outside = explode("\1", $text);
  124.         $text = '';
  125.  
  126.         $num_tokens = count($outside);
  127.         for ($i = 0; $i < $num_tokens; ++$i)
  128.         {
  129.             $text .= $outside[$i];
  130.             if (isset($inside[$i]))
  131.                 $text .= '[code]'.$inside[$i].'[/code]';
  132.         }
  133.  
  134.         unset($inside);
  135.     }
  136.  
  137.     // Remove empty tags
  138.     while (($new_text = strip_empty_bbcode($text)) !== false)
  139.     {
  140.         if ($new_text != $text)
  141.         {
  142.             $text = $new_text;
  143.             if ($new_text == '')
  144.             {
  145.                 $errors[] = $lang_post['Empty after strip'];
  146.                 break;
  147.             }
  148.         }
  149.         else
  150.             break;
  151.     }
  152.  
  153.     return pun_trim($text);
  154. }
  155.  
  156.  
  157. //
  158. // Strip empty bbcode tags from some text
  159. //
  160. function strip_empty_bbcode($text)
  161. {
  162.     // If the message contains a code tag we have to split it up (empty tags within [code][/code] are fine)
  163.     if (strpos($text, '[code]') !== false && strpos($text, '[/code]') !== false)
  164.         list($inside, $text) = extract_blocks($text, '[code]', '[/code]');
  165.    
  166.     // Remove empty tags (MODIFIER (VOIR README.TXT FLUXTOOLBAR 2.1.1) >> while (!is_null($new_text = preg_replace('%\[(b|u|s|ins|del|em|i|h|colou?r|quote|img|url|email|list|topic|post|forum|user)(?:\=[^\]]*)?\]\s*\[/\1\]%', '', $text)))
  167.     while (!is_null($new_text = preg_replace('%\[(b|u|s|ins|del|em|i|h|colou?r|quote|img|url|email|list|topic|post|forum|user|acronym|q|sup|sub|left|right|center|justify|video)(?:\=[^\]]*)?\]\s*\[/\1\]%', '', $text)))
  168.     {
  169.         if ($new_text != $text)
  170.             $text = $new_text;
  171.         else
  172.             break;
  173.     }
  174.  
  175.     return $text;
  176. }
  177.  
  178.     // If we split up the message before we have to concatenate it together again (code tags)
  179.     if (isset($inside))
  180.     {
  181.         $parts = explode("\1", $text);
  182.         $text = '';
  183.         foreach ($parts as $i => $part)
  184.         {
  185.             $text .= $part;
  186.             if (isset($inside[$i]))
  187.                 $text .= '[code]'.$inside[$i].'[/code]';
  188.         }
  189.     }
  190.  
  191.  
  192. //
  193. // Check the structure of bbcode tags and fix simple mistakes where possible
  194. //
  195. function preparse_tags($text, &$errors, $is_signature = false)
  196. {
  197.     global $lang_common, $pun_config, $pun_user;
  198.  
  199.     // Start off by making some arrays of bbcode tags and what we need to do with each one
  200.  
  201.     // List of all the tags MODIFIER (VOIR README.TXT FLUXTOOLBAR 2.1.1)
  202.     $tags = array('quote', 'code', 'b', 'i', 'u', 's', 'ins', 'del', 'em', 'color', 'colour', 'url', 'email', 'img', 'list', '*', 'h', 'topic', 'post', 'forum', 'user', 'acronym', 'q', 'sup', 'sub', 'left', 'right', 'center', 'justify', 'video');
  203.     // List of tags that we need to check are open (You could not put b,i,u in here then illegal nesting like [b][i][/b][/i] would be allowed)
  204.     $tags_opened = $tags;
  205.     // and tags we need to check are closed (the same as above, added it just in case)
  206.     $tags_closed = $tags;
  207.     // Tags we can nest and the depth they can be nested to
  208.     $tags_nested = array('quote' => $pun_config['o_quote_depth'], 'list' => 5, '*' => 5);
  209.     // Tags to ignore the contents of completely (just code)
  210.     $tags_ignore = array('code');
  211.     // Tags not allowed
  212.     $tags_forbidden = array();
  213.     // Block tags, block tags can only go within another block tag, they cannot be in a normal tag
  214.     $tags_block = array('quote', 'code', 'list', 'h', '*', 'left', 'right', 'center', 'justify');
  215.     // Inline tags, we do not allow new lines in these
  216.     $tags_inline = array('b', 'i', 'u', 's', 'ins', 'del', 'em', 'color', 'colour', 'h', 'topic', 'post', 'forum', 'user', 'acronym', 'q', 'sup', 'sub', 'video');
  217.     // Tags we trim interior space
  218.     $tags_trim = array('img', 'video');
  219.     // Tags we remove quotes from the argument
  220.     $tags_quotes = array('url', 'email', 'img', 'topic', 'post', 'forum', 'user', 'video');
  221.     // Tags we limit bbcode in
  222.     $tags_limit_bbcode = array(
  223.         '*'     => array('b', 'i', 'u', 's', 'ins', 'del', 'em', 'color', 'colour', 'url', 'email', 'list', 'img', 'code', 'topic', 'post', 'forum', 'user', 'acronym', 'q', 'sup', 'sub', 'video'),
  224.         'list'  => array('*'),
  225.         'url'   => array('img', 'acronym', 'q', 'sup', 'sub'),
  226.         'email' => array('img', 'acronym', 'q', 'sup', 'sub'),
  227.         'topic' => array('img'),
  228.         'post'  => array('img'),
  229.         'forum' => array('img'),
  230.         'user'  => array('img'),
  231.         'img'   => array(),
  232.         'h' => array('b', 'i', 'u', 's', 'ins', 'del', 'em', 'color', 'colour', 'url', 'email', 'topic', 'post', 'forum', 'user'),
  233.         'video'  => array()
  234.     );
  235.     // Tags we can automatically fix bad nesting
  236.     $tags_fix = array('quote', 'b', 'i', 'u', 's', 'ins', 'del', 'em', 'color', 'colour', 'url', 'email', 'h', 'topic', 'post', 'forum', 'user');
  237.  
  238.     // Disallow URL tags
  239.     if ($pun_user['g_post_links'] != '1')
  240.         $tags_forbidden[] = 'url';
  241.  
  242.     $split_text = preg_split('%(\[[\*a-zA-Z0-9-/]*?(?:=.*?)?\])%', $text, -1, PREG_SPLIT_DELIM_CAPTURE|PREG_SPLIT_NO_EMPTY);
  243.  
  244.     $open_tags = array('fluxbb-bbcode');
  245.     $open_args = array('');
  246.     $opened_tag = 0;
  247.     $new_text = '';
  248.     $current_ignore = '';
  249.     $current_nest = '';
  250.     $current_depth = array();
  251.     $limit_bbcode = $tags;
  252.     $count_ignored = array();
  253.  
  254.     foreach ($split_text as $current)
  255.     {
  256.         if ($current == '')
  257.             continue;
  258.  
  259.         // Are we dealing with a tag?
  260.         if (substr($current, 0, 1) != '[' || substr($current, -1, 1) != ']')
  261.         {
  262.             // It's not a bbcode tag so we put it on the end and continue
  263.             // If we are nested too deeply don't add to the end
  264.             if ($current_nest)
  265.                 continue;
  266.  
  267.             $current = str_replace("\r\n", "\n", $current);
  268.             $current = str_replace("\r", "\n", $current);
  269.             if (in_array($open_tags[$opened_tag], $tags_inline) && strpos($current, "\n") !== false)
  270.             {
  271.                 // Deal with new lines
  272.                 $split_current = preg_split('%(\n\n+)%', $current, -1, PREG_SPLIT_DELIM_CAPTURE|PREG_SPLIT_NO_EMPTY);
  273.                 $current = '';
  274.  
  275.                 if (!pun_trim($split_current[0], "\n")) // The first part is a linebreak so we need to handle any open tags first
  276.                     array_unshift($split_current, '');
  277.  
  278.                 for ($i = 1; $i < count($split_current); $i += 2)
  279.                 {
  280.                     $temp_opened = array();
  281.                     $temp_opened_arg = array();
  282.                     $temp = $split_current[$i - 1];
  283.                     while (!empty($open_tags))
  284.                     {
  285.                         $temp_tag = array_pop($open_tags);
  286.                         $temp_arg = array_pop($open_args);
  287.  
  288.                         if (in_array($temp_tag , $tags_inline))
  289.                         {
  290.                             array_push($temp_opened, $temp_tag);
  291.                             array_push($temp_opened_arg, $temp_arg);
  292.                             $temp .= '[/'.$temp_tag.']';
  293.                         }
  294.                         else
  295.                         {
  296.                             array_push($open_tags, $temp_tag);
  297.                             array_push($open_args, $temp_arg);
  298.                             break;
  299.                         }
  300.                     }
  301.                     $current .= $temp.$split_current[$i];
  302.                     $temp = '';
  303.                     while (!empty($temp_opened))
  304.                     {
  305.                         $temp_tag = array_pop($temp_opened);
  306.                         $temp_arg = array_pop($temp_opened_arg);
  307.                         if (empty($temp_arg))
  308.                             $temp .= '['.$temp_tag.']';
  309.                         else
  310.                             $temp .= '['.$temp_tag.'='.$temp_arg.']';
  311.                         array_push($open_tags, $temp_tag);
  312.                         array_push($open_args, $temp_arg);
  313.                     }
  314.                     $current .= $temp;
  315.                 }
  316.  
  317.                 if (array_key_exists($i - 1, $split_current))
  318.                     $current .= $split_current[$i - 1];
  319.             }
  320.  
  321.             if (in_array($open_tags[$opened_tag], $tags_trim))
  322.                 $new_text .= pun_trim($current);
  323.             else
  324.                 $new_text .= $current;
  325.  
  326.             continue;
  327.         }
  328.  
  329.         // Get the name of the tag
  330.         $current_arg = '';
  331.         if (strpos($current, '/') === 1)
  332.         {
  333.             $current_tag = substr($current, 2, -1);
  334.         }
  335.         else if (strpos($current, '=') === false)
  336.         {
  337.             $current_tag = substr($current, 1, -1);
  338.         }
  339.         else
  340.         {
  341.             $current_tag = substr($current, 1, strpos($current, '=')-1);
  342.             $current_arg = substr($current, strpos($current, '=')+1, -1);
  343.         }
  344.         $current_tag = strtolower($current_tag);
  345.  
  346.         // Is the tag defined?
  347.         if (!in_array($current_tag, $tags))
  348.         {
  349.             // It's not a bbcode tag so we put it on the end and continue
  350.             if (!$current_nest)
  351.                 $new_text .= $current;
  352.  
  353.             continue;
  354.         }
  355.  
  356.         // We definitely have a bbcode tag
  357.  
  358.         // Make the tag string lower case
  359.         if ($equalpos = strpos($current,'='))
  360.         {
  361.             // We have an argument for the tag which we don't want to make lowercase
  362.             if (strlen(substr($current, $equalpos)) == 2)
  363.             {
  364.                 // Empty tag argument
  365.                 $errors[] = sprintf($lang_common['BBCode error empty attribute'], $current_tag);
  366.                 return false;
  367.             }
  368.             $current = strtolower(substr($current, 0, $equalpos)).substr($current, $equalpos);
  369.         }
  370.         else
  371.             $current = strtolower($current);
  372.  
  373.         // This is if we are currently in a tag which escapes other bbcode such as code
  374.         // We keep a count of ignored bbcodes (code tags) so we can nest them, but
  375.         // only balanced sets of tags can be nested
  376.         if ($current_ignore)
  377.         {
  378.             // Increase the current ignored tags counter
  379.             if ('['.$current_ignore.']' == $current)
  380.                 $count_ignored[$current_tag]++;
  381.  
  382.             // Decrease the current ignored tags counter
  383.             if ('[/'.$current_ignore.']' == $current)
  384.                 $count_ignored[$current_tag]--;
  385.  
  386.             if ('[/'.$current_ignore.']' == $current && $count_ignored[$current_tag] == 0)
  387.             {
  388.                 // We've finished the ignored section
  389.                 $current = '[/'.$current_tag.']';
  390.                 $current_ignore = '';
  391.                 $count_ignored = array();
  392.             }
  393.  
  394.             $new_text .= $current;
  395.  
  396.             continue;
  397.         }
  398.  
  399.         // Is the tag forbidden?
  400.         if (in_array($current_tag, $tags_forbidden))
  401.         {
  402.             if (isset($lang_common['BBCode error tag '.$current_tag.' not allowed']))
  403.                 $errors[] = sprintf($lang_common['BBCode error tag '.$current_tag.' not allowed']);
  404.             else
  405.                 $errors[] = sprintf($lang_common['BBCode error tag not allowed'], $current_tag);
  406.  
  407.             return false;
  408.         }
  409.  
  410.         if ($current_nest)
  411.         {
  412.             // We are currently too deeply nested so lets see if we are closing the tag or not
  413.             if ($current_tag != $current_nest)
  414.                 continue;
  415.  
  416.             if (substr($current, 1, 1) == '/')
  417.                 $current_depth[$current_nest]--;
  418.             else
  419.                 $current_depth[$current_nest]++;
  420.  
  421.             if ($current_depth[$current_nest] <= $tags_nested[$current_nest])
  422.                 $current_nest = '';
  423.  
  424.             continue;
  425.         }
  426.  
  427.         // Check the current tag is allowed here
  428.         if (!in_array($current_tag, $limit_bbcode) && $current_tag != $open_tags[$opened_tag])
  429.         {
  430.             $errors[] = sprintf($lang_common['BBCode error invalid nesting'], $current_tag, $open_tags[$opened_tag]);
  431.             return false;
  432.         }
  433.  
  434.         if (substr($current, 1, 1) == '/')
  435.         {
  436.             // This is if we are closing a tag
  437.             if ($opened_tag == 0 || !in_array($current_tag, $open_tags))
  438.             {
  439.                 // We tried to close a tag which is not open
  440.                 if (in_array($current_tag, $tags_opened))
  441.                 {
  442.                     $errors[] = sprintf($lang_common['BBCode error no opening tag'], $current_tag);
  443.                     return false;
  444.                 }
  445.             }
  446.             else
  447.             {
  448.                 // Check nesting
  449.                 while (true)
  450.                 {
  451.                     // Nesting is ok
  452.                     if ($open_tags[$opened_tag] == $current_tag)
  453.                     {
  454.                         array_pop($open_tags);
  455.                         array_pop($open_args);
  456.                         $opened_tag--;
  457.                         break;
  458.                     }
  459.  
  460.                     // Nesting isn't ok, try to fix it
  461.                     if (in_array($open_tags[$opened_tag], $tags_closed) && in_array($current_tag, $tags_closed))
  462.                     {
  463.                         if (in_array($current_tag, $open_tags))
  464.                         {
  465.                             $temp_opened = array();
  466.                             $temp_opened_arg = array();
  467.                             $temp = '';
  468.                             while (!empty($open_tags))
  469.                             {
  470.                                 $temp_tag = array_pop($open_tags);
  471.                                 $temp_arg = array_pop($open_args);
  472.  
  473.                                 if (!in_array($temp_tag, $tags_fix))
  474.                                 {
  475.                                     // We couldn't fix nesting
  476.                                     $errors[] = sprintf($lang_common['BBCode error no closing tag'], array_pop($temp_opened));
  477.                                     return false;
  478.                                 }
  479.                                 array_push($temp_opened, $temp_tag);
  480.                                 array_push($temp_opened_arg, $temp_arg);
  481.  
  482.                                 if ($temp_tag == $current_tag)
  483.                                     break;
  484.                                 else
  485.                                     $temp .= '[/'.$temp_tag.']';
  486.                             }
  487.                             $current = $temp.$current;
  488.                             $temp = '';
  489.                             array_pop($temp_opened);
  490.                             array_pop($temp_opened_arg);
  491.  
  492.                             while (!empty($temp_opened))
  493.                             {
  494.                                 $temp_tag = array_pop($temp_opened);
  495.                                 $temp_arg = array_pop($temp_opened_arg);
  496.                                 if (empty($temp_arg))
  497.                                     $temp .= '['.$temp_tag.']';
  498.                                 else
  499.                                     $temp .= '['.$temp_tag.'='.$temp_arg.']';
  500.                                 array_push($open_tags, $temp_tag);
  501.                                 array_push($open_args, $temp_arg);
  502.                             }
  503.                             $current .= $temp;
  504.                             $opened_tag--;
  505.                             break;
  506.                         }
  507.                         else
  508.                         {
  509.                             // We couldn't fix nesting
  510.                             $errors[] = sprintf($lang_common['BBCode error no opening tag'], $current_tag);
  511.                             return false;
  512.                         }
  513.                     }
  514.                     else if (in_array($open_tags[$opened_tag], $tags_closed))
  515.                         break;
  516.                     else
  517.                     {
  518.                         array_pop($open_tags);
  519.                         array_pop($open_args);
  520.                         $opened_tag--;
  521.                     }
  522.                 }
  523.             }
  524.  
  525.             if (in_array($current_tag, array_keys($tags_nested)))
  526.             {
  527.                 if (isset($current_depth[$current_tag]))
  528.                     $current_depth[$current_tag]--;
  529.             }
  530.  
  531.             if (in_array($open_tags[$opened_tag], array_keys($tags_limit_bbcode)))
  532.                 $limit_bbcode = $tags_limit_bbcode[$open_tags[$opened_tag]];
  533.             else
  534.                 $limit_bbcode = $tags;
  535.  
  536.             $new_text .= $current;
  537.  
  538.             continue;
  539.         }
  540.         else
  541.         {
  542.             // We are opening a tag
  543.             if (in_array($current_tag, array_keys($tags_limit_bbcode)))
  544.                 $limit_bbcode = $tags_limit_bbcode[$current_tag];
  545.             else
  546.                 $limit_bbcode = $tags;
  547.  
  548.             if (in_array($current_tag, $tags_block) && !in_array($open_tags[$opened_tag], $tags_block) && $opened_tag != 0)
  549.             {
  550.                 // We tried to open a block tag within a non-block tag
  551.                 $errors[] = sprintf($lang_common['BBCode error invalid nesting'], $current_tag, $open_tags[$opened_tag]);
  552.                 return false;
  553.             }
  554.  
  555.             if (in_array($current_tag, $tags_ignore))
  556.             {
  557.                 // It's an ignore tag so we don't need to worry about what's inside it
  558.                 $current_ignore = $current_tag;
  559.                 $count_ignored[$current_tag] = 1;
  560.                 $new_text .= $current;
  561.                 continue;
  562.             }
  563.  
  564.             // Deal with nested tags
  565.             if (in_array($current_tag, $open_tags) && !in_array($current_tag, array_keys($tags_nested)))
  566.             {
  567.                 // We nested a tag we shouldn't
  568.                 $errors[] = sprintf($lang_common['BBCode error invalid self-nesting'], $current_tag);
  569.                 return false;
  570.             }
  571.             else if (in_array($current_tag, array_keys($tags_nested)))
  572.             {
  573.                 // We are allowed to nest this tag
  574.  
  575.                 if (isset($current_depth[$current_tag]))
  576.                     $current_depth[$current_tag]++;
  577.                 else
  578.                     $current_depth[$current_tag] = 1;
  579.  
  580.                 // See if we are nested too deep
  581.                 if ($current_depth[$current_tag] > $tags_nested[$current_tag])
  582.                 {
  583.                     $current_nest = $current_tag;
  584.                     continue;
  585.                 }
  586.             }
  587.  
  588.             // Remove quotes from arguments for certain tags
  589.             if (strpos($current, '=') !== false && in_array($current_tag, $tags_quotes))
  590.             {
  591.                 $current = preg_replace('%\['.$current_tag.'=("|\'|)(.*?)\\1\]\s*%i', '['.$current_tag.'=$2]', $current);
  592.             }
  593.  
  594.             if (in_array($current_tag, array_keys($tags_limit_bbcode)))
  595.                 $limit_bbcode = $tags_limit_bbcode[$current_tag];
  596.  
  597.             $open_tags[] = $current_tag;
  598.             $open_args[] = $current_arg;
  599.             $opened_tag++;
  600.             $new_text .= $current;
  601.             continue;
  602.         }
  603.     }
  604.  
  605.     // Check we closed all the tags we needed to
  606.     foreach ($tags_closed as $check)
  607.     {
  608.         if (in_array($check, $open_tags))
  609.         {
  610.             // We left an important tag open
  611.             $errors[] = sprintf($lang_common['BBCode error no closing tag'], $check);
  612.             return false;
  613.         }
  614.     }
  615.  
  616.     if ($current_ignore)
  617.     {
  618.         // We left an ignore tag open
  619.         $errors[] = sprintf($lang_common['BBCode error no closing tag'], $current_ignore);
  620.         return false;
  621.     }
  622.  
  623.     return $new_text;
  624. }
  625.  
  626.  
  627. //
  628. // Preparse the contents of [list] bbcode
  629. //
  630. function preparse_list_tag($content, $type = '*')
  631. {
  632.     global $lang_common, $re_list;
  633.  
  634.     if (strlen($type) != 1)
  635.         $type = '*';
  636.  
  637.     if (strpos($content,'[list') !== false)
  638.     {
  639.         $content = preg_replace_callback($re_list, create_function('$matches', 'return preparse_list_tag($matches[2], $matches[1]);'), $content);
  640.     }
  641.  
  642.     $items = explode('[*]', str_replace('\"', '"', $content));
  643.  
  644.     $content = '';
  645.     foreach ($items as $item)
  646.     {
  647.         if (pun_trim($item) != '')
  648.             $content .= '[*'."\0".']'.str_replace('[/*]', '', pun_trim($item)).'[/*'."\0".']'."\n";
  649.     }
  650.  
  651.     return '[list='.$type.']'."\n".$content.'[/list]';
  652. }
  653.  
  654.  
  655. //
  656. // Truncate URL if longer than 55 characters (add http:// or ftp:// if missing)
  657. //
  658. function handle_url_tag($url, $link = '', $bbcode = false)
  659. {
  660.     $url = pun_trim($url);
  661.  
  662.     // Deal with [url][img]http://example.com/test.png[/img][/url]
  663.     if (preg_match('%<img src=\\\\"(.*?)\\\\"%', $url, $matches))
  664.         return handle_url_tag($matches[1], $url, $bbcode);
  665.  
  666.     $full_url = str_replace(array(' ', '\'', '`', '"'), array('%20', '', '', ''), $url);
  667.     if (strpos($url, 'www.') === 0) // If it starts with www, we add http://
  668.         $full_url = 'http://'.$full_url;
  669.     else if (strpos($url, 'ftp.') === 0) // Else if it starts with ftp, we add ftp://
  670.         $full_url = 'ftp://'.$full_url;
  671.     else if (strpos($url, '/') === 0) // Allow for relative URLs that start with a slash
  672.         $full_url = get_base_url(true).$full_url;
  673.     else if (!preg_match('#^([a-z0-9]{3,6})://#', $url)) // Else if it doesn't start with abcdef://, we add http://
  674.         $full_url = 'http://'.$full_url;
  675.  
  676.     // Ok, not very pretty :-)
  677.     if ($bbcode)
  678.     {
  679.         if ($full_url == $link)
  680.             return '[url]'.$link.'[/url]';
  681.         else
  682.             return '[url='.$full_url.']'.$link.'[/url]';
  683.     }
  684.     else
  685.     {
  686.         if ($link == '' || $link == $url)
  687.         {
  688.             $url = pun_htmlspecialchars_decode($url);
  689.             $link = utf8_strlen($url) > 55 ? utf8_substr($url, 0 , 39).' … '.utf8_substr($url, -10) : $url;
  690.             $link = pun_htmlspecialchars($link);
  691.         }
  692.         else
  693.             $link = stripslashes($link);
  694.  
  695.         return '<a href="'.$full_url.'" rel="nofollow">'.$link.'</a>';
  696.     }
  697. }
  698.  
  699.  
  700. //
  701. // Turns an URL from the [img] tag into an <img> tag or a <a href...> tag
  702. //
  703. function handle_img_tag($url, $is_signature = false, $alt = null)
  704. {
  705.     global $lang_common, $pun_user;
  706.  
  707.     if (is_null($alt))
  708.         $alt = basename($url);
  709.  
  710.     $img_tag = '<a href="'.$url.'" rel="nofollow">&lt;'.$lang_common['Image link'].' - '.$alt.'&gt;</a>';
  711.  
  712.     if ($is_signature && $pun_user['show_img_sig'] != '0')
  713.         $img_tag = '<img class="sigimage" src="'.$url.'" alt="'.$alt.'" />';
  714.     else if (!$is_signature && $pun_user['show_img'] != '0')
  715.         $img_tag = '<span class="postimg"><img src="'.$url.'" alt="'.$alt.'" /></span>';
  716.  
  717.     return $img_tag;
  718. }
  719.  
  720.  
  721. //
  722. // Parse the contents of [list] bbcode
  723. //
  724. function handle_list_tag($content, $type = '*')
  725. {
  726.     global $re_list;
  727.  
  728.     if (strlen($type) != 1)
  729.         $type = '*';
  730.  
  731.     if (strpos($content,'[list') !== false)
  732.     {
  733.         $content = preg_replace_callback($re_list, create_function('$matches', 'return handle_list_tag($matches[2], $matches[1]);'), $content);
  734.     }
  735.  
  736.     $content = preg_replace('#\s*\[\*\](.*?)\[/\*\]\s*#s', '<li><p>$1</p></li>', pun_trim($content));
  737.  
  738.     if ($type == '*')
  739.         $content = '<ul>'.$content.'</ul>';
  740.     else
  741.         if ($type == 'a')
  742.             $content = '<ol class="alpha">'.$content.'</ol>';
  743.         else
  744.             $content = '<ol class="decimal">'.$content.'</ol>';
  745.  
  746.     return '</p>'.$content.'<p>';
  747. }
  748.  
  749.  
  750. //
  751. // Convert BBCodes to their HTML equivalent
  752. //
  753. function do_bbcode($text, $is_signature = false)
  754. {
  755.     global $lang_common, $pun_user, $pun_config, $re_list;
  756.  
  757.     if (strpos($text, '[quote') !== false)
  758.     {
  759.         $text = preg_replace('%\[quote\]\s*%', '</p><div class="quotebox"><blockquote><div><p>', $text);
  760.         $text = preg_replace_callback('%\[quote=(&quot;|&\#039;|"|\'|)(.*?)\\1\]%s', create_function('$matches', 'global $lang_common; return "</p><div class=\"quotebox\"><cite>".str_replace(array(\'[\', \'\\"\'), array(\'&#91;\', \'"\'), $matches[2])." ".$lang_common[\'wrote\']."</cite><blockquote><div><p>";'), $text);
  761.         $text = preg_replace('%\s*\[\/quote\]%S', '</p></div></blockquote></div><p>', $text);
  762.     }
  763.     if (!$is_signature)
  764.     {
  765.         $pattern_callback[] = $re_list;
  766.         $replace_callback[] = 'handle_list_tag($matches[2], $matches[1])';
  767.     }
  768.  
  769.     // MODIFIER (VOIR README.TXT FLUXTOOLBAR 2.1.1)
  770.     $pattern[] = '%\[b\](.*?)\[/b\]%ms';
  771.     $pattern[] = '%\[i\](.*?)\[/i\]%ms';
  772.     $pattern[] = '%\[u\](.*?)\[/u\]%ms';
  773.     $pattern[] = '%\[s\](.*?)\[/s\]%ms';
  774.     $pattern[] = '%\[del\](.*?)\[/del\]%ms';
  775.     $pattern[] = '%\[ins\](.*?)\[/ins\]%ms';
  776.     $pattern[] = '%\[em\](.*?)\[/em\]%ms';
  777.     $pattern[] = '%\[colou?r=([a-zA-Z]{3,20}|\#[0-9a-fA-F]{6}|\#[0-9a-fA-F]{3})](.*?)\[/colou?r\]%ms';
  778.     $pattern[] = '%\[h\](.*?)\[/h\]%ms';
  779.     $pattern[] = '%\[acronym\](.*?)\[/acronym\]%ms';
  780.     $pattern[] = '%\[acronym=(.*?)\](.*?)\[/acronym\]%ms';
  781.     $pattern[] = '%\[q\](.*?)\[/q\]%ms';
  782.     $pattern[] = '%\[sup\](.*?)\[/sup\]%ms';
  783.     $pattern[] = '%\[sub\](.*?)\[/sub\]%ms';
  784.     $pattern[] = '%\[left\](.*?)\[/left\]%ms';
  785.     $pattern[] = '%\[right\](.*?)\[/right\]%ms';
  786.     $pattern[] = '%\[center\](.*?)\[/center\]%ms';
  787.     $pattern[] = '%\[justify\](.*?)\[/justify\]%ms';
  788.     $pattern[] = '%\[video\]([^\[<]*?)/video/([^_\[<]*?)_([^\[<]*?)\[/video\]%ms';
  789.     $pattern[] = '%\[video=([0-9]+),([0-9]+)\]([^\[<]*?)/video/([^_\[<]*?)_([^\[<]*?)\[/video\]%ms';
  790.     $pattern[] = '%\[video\]([^\[<]*?)/(v/|watch\?v=)([^\[<]*?)\[/video\]%ms';
  791.     $pattern[] = '%\[video=([0-9]+),([0-9]+)\]([^\[<]*?)/(v/|watch\?v=)([^\[<]*?)\[/video\]%ms';
  792.  
  793.     $replace[] = '<strong>$1</strong>';
  794.     $replace[] = '<em>$1</em>';
  795.     $replace[] = '<span class="bbu">$1</span>';
  796.     $replace[] = '<span class="bbs">$1</span>';
  797.     $replace[] = '<del>$1</del>';
  798.     $replace[] = '<ins>$1</ins>';
  799.     $replace[] = '<em>$1</em>';
  800.     $replace[] = '<span style="color: $1">$2</span>';
  801.     $replace[] = '</p><h5>$1</h5><p>';
  802.     $replace[] = '<acronym>$1</acronym>';
  803.     $replace[] = '<acronym title="$1">$2</acronym>';
  804.     $replace[] = '<q>$1</q>';
  805.     $replace[] = '<sup>$1</sup>';
  806.     $replace[] = '<sub>$1</sub>';
  807.     $replace[] = '</p><p style="text-align: left">$1</p><p>';
  808.     $replace[] = '</p><p style="text-align: right">$1</p><p>';
  809.     $replace[] = '</p><p style="text-align: center">$1</p><p>';
  810.     $replace[] = '</p><p style="text-align: justify">$1</p><p>';
  811.     $replace[] = '<object type="application/x-shockwave-flash" data="http://www.dailymotion.com/swf/video/$2" width="480" height="384"><param name="movie" value="http://www.dailymotion.com/swf/video/$2" /><param name="allowFullScreen" value="true" /><param name="allowScriptAccess" value="always" /><p>Flash required</p></object>';
  812.     $replace[] = '<object type="application/x-shockwave-flash" data="http://www.dailymotion.com/swf/video/$4" width="$1" height="$2"><param name="movie" value="http://www.dailymotion.com/swf/video/$4" /><param name="allowFullScreen" value="true" /><param name="allowScriptAccess" value="always" /><p>Flash required</p></object>';
  813.     $replace[] = '<object type="application/x-shockwave-flash" data="http://www.youtube.com/v/$3" width="425" height="344"><param name="movie" value="http://www.youtube.com/v/$3" /><param name="allowFullScreen" value="true" /><param name="allowScriptAccess" value="always" /><p>Flash required</p></object>';
  814.     $replace[] = '<object type="application/x-shockwave-flash" data="http://www.youtube.com/v/$5" width="$1" height="$2"><param name="movie" value="http://www.youtube.com/v/$5" /><param name="allowFullScreen" value="true" /><param name="allowScriptAccess" value="always" /><p>Flash required</p></object>';
  815.  
  816.     if (($is_signature && $pun_config['p_sig_img_tag'] == '1') || (!$is_signature && $pun_config['p_message_img_tag'] == '1'))
  817.     {
  818.         $pattern_callback[] = '%\[img\]((ht|f)tps?://)([^\s<"]*?)\[/img\]%';
  819.         $pattern_callback[] = '%\[img=([^\[]*?)\]((ht|f)tps?://)([^\s<"]*?)\[/img\]%';
  820.         if ($is_signature)
  821.         {
  822.             $replace_callback[] = 'handle_img_tag($matches[1].$matches[3], true)';
  823.             $replace_callback[] = 'handle_img_tag($matches[2].$matches[4], true, $matches[1])';
  824.         }
  825.         else
  826.         {
  827.             $replace_callback[] = 'handle_img_tag($matches[1].$matches[3], false)';
  828.             $replace_callback[] = 'handle_img_tag($matches[2].$matches[4], false, $matches[1])';
  829.         }
  830.     }
  831.  
  832.     $pattern_callback[] = '%\[url\]([^\[]*?)\[/url\]%';
  833.     $pattern_callback[] = '%\[url=([^\[]+?)\](.*?)\[/url\]%';
  834.     $pattern[] = '%\[email\]([^\[]*?)\[/email\]%';
  835.     $pattern[] = '%\[email=([^\[]+?)\](.*?)\[/email\]%';
  836.     $pattern_callback[] = '%\[topic\]([1-9]\d*)\[/topic\]%';
  837.     $pattern_callback[] = '%\[topic=([1-9]\d*)\](.*?)\[/topic\]%';
  838.     $pattern_callback[] = '%\[post\]([1-9]\d*)\[/post\]%';
  839.     $pattern_callback[] = '%\[post=([1-9]\d*)\](.*?)\[/post\]%';
  840.     $pattern_callback[] = '%\[forum\]([1-9]\d*)\[/forum\]%';
  841.     $pattern_callback[] = '%\[forum=([1-9]\d*)\](.*?)\[/forum\]%';
  842.     $pattern_callback[] = '%\[user\]([1-9]\d*)\[/user\]%';
  843.     $pattern_callback[] = '%\[user=([1-9]\d*)\](.*?)\[/user\]%';
  844.  
  845.     $replace_callback[] = 'handle_url_tag($matches[1])';
  846.     $replace_callback[] = 'handle_url_tag($matches[1], $matches[2])';
  847.     $replace[] = '<a href="mailto:$1">$1</a>';
  848.     $replace[] = '<a href="mailto:$1">$2</a>';
  849.     $replace_callback[] = 'handle_url_tag(\''.get_base_url(true).'/viewtopic.php?id=.$matches[1]\')';
  850.     $replace_callback[] = 'handle_url_tag(\''.get_base_url(true).'/viewtopic.php?id=.$matches[1],$matches[2]\')';
  851.     $replace_callback[] = 'handle_url_tag(\''.get_base_url(true).'/viewtopic.php?pid=.$matches[1].#p.$matches[1]\')';
  852.     $replace_callback[] = 'handle_url_tag(\''.get_base_url(true).'/viewtopic.php?pid=.$matches[1].#p.$matches[1],$matches[2]\')';
  853.     $replace_callback[] = 'handle_url_tag(\''.get_base_url(true).'/viewforum.php?id=.$matches[1]\')';
  854.     $replace_callback[] = 'handle_url_tag(\''.get_base_url(true).'/viewforum.php?id=.$matches[1],$matches[2]\')';
  855.     $replace_callback[] = 'handle_url_tag(\''.get_base_url(true).'/profile.php?id=.$matches[1]\')';
  856.     $replace_callback[] = 'handle_url_tag(\''.get_base_url(true).'/profile.php?id=.$matches[1],$matches[2]\')';
  857.  
  858.     // This thing takes a while! :)
  859.     $text = preg_replace($pattern, $replace, $text);
  860.     $count = count($pattern_callback);
  861.     for($i = 0 ; $i < $count ; $i++)
  862.     {
  863.         $text = preg_replace_callback($pattern_callback[$i], create_function('$matches', 'return '.$replace_callback[$i].';'), $text);
  864.     }
  865.     return $text;
  866. }
  867.  
  868.  
  869. //
  870. // Make hyperlinks clickable
  871. //
  872. function do_clickable($text)
  873. {
  874.     $text = ' '.$text;
  875.     $text = ucp_preg_replace_callback('%(?<=[\s\]\)])(<)?(\[)?(\()?([\'"]?)(https?|ftp|news){1}://([\p{L}\p{N}\-]+\.([\p{L}\p{N}\-]+\.)*[\p{L}\p{N}]+(:[0-9]+)?(/(?:[^\s\[]*[^\s.,?!\[;:-])?)?)\4(?(3)(\)))(?(2)(\]))(?(1)(>))(?![^\s]*\[/(?:url|img)\])%ui', 'stripslashes($matches[1].$matches[2].$matches[3].$matches[4]).handle_url_tag($matches[5]."://".$matches[6], $matches[5]."://".$matches[6], true).stripslashes($matches[4].$matches[10].$matches[11].$matches[12])', $text);
  876.     $text = ucp_preg_replace_callback('%(?<=[\s\]\)])(<)?(\[)?(\()?([\'"]?)(www|ftp)\.(([\p{L}\p{N}\-]+\.)+[\p{L}\p{N}]+(:[0-9]+)?(/(?:[^\s\[]*[^\s.,?!\[;:-])?)?)\4(?(3)(\)))(?(2)(\]))(?(1)(>))(?![^\s]*\[/(?:url|img)\])%ui','stripslashes($matches[1].$matches[2].$matches[3].$matches[4]).handle_url_tag($matches[5].".".$matches[6], $matches[5].".".$matches[6], true).stripslashes($matches[4].$matches[10].$matches[11].$matches[12])', $text);
  877.  
  878.     return substr($text, 1);
  879. }
  880.  
  881.  
  882. //
  883. // Convert a series of smilies to images
  884. //
  885. function do_smilies($text)
  886. {
  887.     global $pun_config, $smilies;
  888.  
  889.     $text = ' '.$text.' ';
  890.  
  891.     foreach ($smilies as $smiley_text => $smiley_img)
  892.     {
  893.         if (strpos($text, $smiley_text) !== false)
  894.             $text = ucp_preg_replace('%(?<=[>\s])'.preg_quote($smiley_text, '%').'(?=[^\p{L}\p{N}])%um', '<img src="'.pun_htmlspecialchars(get_base_url(true).'/img/smilies/'.$smiley_img).'" alt="'.substr($smiley_img, 0, strrpos($smiley_img, '.')).'" />', $text); // SUPPRIMER(width="15" height="15")
  895.     }
  896.  
  897.     return substr($text, 1, -1);
  898. }
  899.  
  900.  
  901. //
  902. // Parse message text
  903. //
  904. function parse_message($text, $hide_smilies)
  905. {
  906.     global $pun_config, $lang_common, $pun_user;
  907.  
  908.     if ($pun_config['o_censoring'] == '1')
  909.         $text = censor_words($text);
  910.  
  911.     // Convert applicable characters to HTML entities
  912.     $text = pun_htmlspecialchars($text);
  913.  
  914.     // If the message contains a code tag we have to split it up (text within [code][/code] shouldn't be touched)
  915.     if (strpos($text, '[code]') !== false && strpos($text, '[/code]') !== false)
  916.         list($inside, $text) = extract_blocks($text, '[code]', '[/code]');
  917.  
  918.     if ($pun_config['p_message_bbcode'] == '1' && strpos($text, '[') !== false && strpos($text, ']') !== false)
  919.         $text = do_bbcode($text);
  920.  
  921.     if ($pun_config['o_smilies'] == '1' && $pun_user['show_smilies'] == '1' && $hide_smilies == '0')
  922.         $text = do_smilies($text);
  923.  
  924.     // Deal with newlines, tabs and multiple spaces
  925.     $pattern = array("\n", "\t", '  ', '  ');
  926.     $replace = array('<br />', '&#160; &#160; ', '&#160; ', ' &#160;');
  927.     $text = str_replace($pattern, $replace, $text);
  928.  
  929.     // If we split up the message before we have to concatenate it together again (code tags)
  930.     if (isset($inside))
  931.     {
  932.         $parts = explode("\1", $text);
  933.         $text = '';
  934.         foreach ($parts as $i => $part)
  935.         {
  936.             $text .= $part;
  937.             if (isset($inside[$i]))
  938.             {
  939.                 $num_lines = (substr_count($inside[$i], "\n"));
  940.                 $text .= '</p><div class="codebox"><pre'.(($num_lines > 28) ? ' class="vscroll"' : '').'><code>'.pun_trim($inside[$i], "\n\r").'</code></pre></div><p>';
  941.             }
  942.         }
  943.     }
  944.  
  945.     return clean_paragraphs($text);
  946. }
  947.  
  948.  
  949. //
  950. // Clean up paragraphs and line breaks
  951. //
  952. function clean_paragraphs($text)
  953. {
  954.     // Add paragraph tag around post, but make sure there are no empty paragraphs
  955.  
  956.     $text = '<p>'.$text.'</p>';
  957.  
  958.     // Replace any breaks next to paragraphs so our replace below catches them
  959.     $text = preg_replace('%(</?p>)(?:\s*?<br />){1,2}%i', '$1', $text);
  960.     $text = preg_replace('%(?:<br />\s*?){1,2}(</?p>)%i', '$1', $text);
  961.  
  962.     // Remove any empty paragraph tags (inserted via quotes/lists/code/etc) which should be stripped
  963.     $text = str_replace('<p></p>', '', $text);
  964.  
  965.     $text = preg_replace('%<br />\s*?<br />%i', '</p><p>', $text);
  966.  
  967.     $text = str_replace('<p><br />', '<br /><p>', $text);
  968.     $text = str_replace('<br /></p>', '</p><br />', $text);
  969.     $text = str_replace('<p></p>', '<br /><br />', $text);
  970.  
  971.     return $text;
  972. }
  973.  
  974.  
  975. //
  976. // Parse signature text
  977. //
  978. function parse_signature($text)
  979. {
  980.     global $pun_config, $lang_common, $pun_user;
  981.  
  982.     if ($pun_config['o_censoring'] == '1')
  983.         $text = censor_words($text);
  984.  
  985.     // Convert applicable characters to HTML entities
  986.     $text = pun_htmlspecialchars($text);
  987.  
  988.     if ($pun_config['p_sig_bbcode'] == '1' && strpos($text, '[') !== false && strpos($text, ']') !== false)
  989.         $text = do_bbcode($text, true);
  990.  
  991.     if ($pun_config['o_smilies_sig'] == '1' && $pun_user['show_smilies'] == '1')
  992.         $text = do_smilies($text);
  993.  
  994.  
  995.     // Deal with newlines, tabs and multiple spaces
  996.     $pattern = array("\n", "\t", '  ', '  ');
  997.     $replace = array('<br />', '&#160; &#160; ', '&#160; ', ' &#160;');
  998.     $text = str_replace($pattern, $replace, $text);
  999.  
  1000.     return clean_paragraphs($text);
  1001. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement