Ignore:
Timestamp:
Nov 14, 2011, 11:17:15 PM (13 years ago)
Author:
dj3c1t
Message:

passage a Fluxbb 1.4.7

File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/rsr.v5.1.dev/web/punbb/include/parser.php

    r1 r3  
    11<?php
    2 /***********************************************************************
    3 
    4   Copyright (C) 2002-2005  Rickard Andersson (rickard@punbb.org)
    5 
    6   This file is part of PunBB.
    7 
    8   PunBB is free software; you can redistribute it and/or modify it
    9   under the terms of the GNU General Public License as published
    10   by the Free Software Foundation; either version 2 of the License,
    11   or (at your option) any later version.
    12 
    13   PunBB is distributed in the hope that it will be useful, but
    14   WITHOUT ANY WARRANTY; without even the implied warranty of
    15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    16   GNU General Public License for more details.
    17 
    18   You should have received a copy of the GNU General Public License
    19   along with this program; if not, write to the Free Software
    20   Foundation, Inc., 59 Temple Place, Suite 330, Boston,
    21   MA  02111-1307  USA
    22 
    23 ************************************************************************/
     2
     3/**
     4 * Copyright (C) 2008-2011 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 */
    248
    259// Make sure no one attempts to run this script "directly"
     
    2711        exit;
    2812
    29 
    30 // Load cache smiley
    31 @include_once PUN_ROOT.'cache/cache_smilies.php';
    32 if (!defined('PUN_CACHE_SMILEY'))
    33 {
    34         require_once PUN_ROOT.'include/cache_smilies.php';
    35         generate_smiley_cache();
    36         require PUN_ROOT.'cache/cache_smilies.php';
    37 }
    38 
     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\]%ie';
     40
     41// Here you can add additional smilies if you like (please note that you must escape single quote and backslash)
     42$smilies = array(
     43        ':)' => 'smile.png',
     44        '=)' => 'smile.png',
     45        ':|' => 'neutral.png',
     46        '=|' => 'neutral.png',
     47        ':(' => 'sad.png',
     48        '=(' => 'sad.png',
     49        ':D' => 'big_smile.png',
     50        '=D' => 'big_smile.png',
     51        ':o' => 'yikes.png',
     52        ':O' => 'yikes.png',
     53        ';)' => 'wink.png',
     54        ':/' => 'hmm.png',
     55        ':P' => 'tongue.png',
     56        ':p' => 'tongue.png',
     57        ':lol:' => 'lol.png',
     58        ':mad:' => 'mad.png',
     59        ':rolleyes:' => 'roll.png',
     60        ':cool:' => 'cool.png');
    3961
    4062//
     
    4365function preparse_bbcode($text, &$errors, $is_signature = false)
    4466{
    45         // Change all simple BBCodes to lower case
    46         $a = array('[B]', '[I]', '[U]', '[/B]', '[/I]', '[/U]');
    47         $b = array('[b]', '[i]', '[u]', '[/b]', '[/i]', '[/u]');
    48         $text = str_replace($a, $b, $text);
    49 
    50         // Do the more complex BBCodes (also strip excessive whitespace and useless quotes)
    51         $a = array( '#\[url=("|\'|)(.*?)\\1\]\s*#i',
    52                                 '#\[url\]\s*#i',
    53                                 '#\s*\[/url\]#i',
    54                                 '#\[email=("|\'|)(.*?)\\1\]\s*#i',
    55                                 '#\[email\]\s*#i',
    56                                 '#\s*\[/email\]#i',
    57                                 '#\[img\]\s*(.*?)\s*\[/img\]#is',
    58                                 '#\[colou?r=("|\'|)(.*?)\\1\](.*?)\[/colou?r\]#is');
    59 
    60         $b = array(     '[url=$2]',
    61                                 '[url]',
    62                                 '[/url]',
    63                                 '[email=$2]',
    64                                 '[email]',
    65                                 '[/email]',
    66                                 '[img]$1[/img]',
    67                                 '[color=$2]$3[/color]');
     67        global $pun_config, $lang_common, $lang_post, $re_list;
     68
     69        if ($is_signature)
     70        {
     71                global $lang_profile;
     72
     73                if (preg_match('%\[/?(?:quote|code|list|h)\b[^\]]*\]%i', $text))
     74                        $errors[] = $lang_profile['Signature quote/code/list/h'];
     75        }
     76
     77        // If the message contains a code tag we have to split it up (text within [code][/code] shouldn't be touched)
     78        if (strpos($text, '[code]') !== false && strpos($text, '[/code]') !== false)
     79                list($inside, $text) = extract_blocks($text, '[code]', '[/code]', $errors);
     80
     81        // Tidy up lists
     82        $temp = preg_replace($re_list, 'preparse_list_tag(\'$2\', \'$1\', $errors)', $text);
     83
     84        // If the regex failed
     85        if ($temp === null)
     86                $errors[] = $lang_common['BBCode list size error'];
     87        else
     88                $text = str_replace('*'."\0".']', '*]', $temp);
     89
     90        if ($pun_config['o_make_links'] == '1')
     91                $text = do_clickable($text);
     92
     93        // If we split up the message before we have to concatenate it together again (code tags)
     94        if (isset($inside))
     95        {
     96                $outside = explode("\1", $text);
     97                $text = '';
     98
     99                $num_tokens = count($outside);
     100                for ($i = 0; $i < $num_tokens; ++$i)
     101                {
     102                        $text .= $outside[$i];
     103                        if (isset($inside[$i]))
     104                                $text .= '[code]'.$inside[$i].'[/code]';
     105                }
     106
     107                unset($inside);
     108        }
     109
     110        $temp_text = false;
     111        if (empty($errors))
     112                $temp_text = preparse_tags($text, $errors, $is_signature);
     113
     114        if ($temp_text !== false)
     115                $text = $temp_text;
     116
     117        // Remove empty tags
     118        while (($new_text = strip_empty_bbcode($text, $errors)) !== false)
     119        {
     120                if ($new_text != $text)
     121                {
     122                        $text = $new_text;
     123                        if ($new_text == '')
     124                        {
     125                                $errors[] = $lang_post['Empty after strip'];
     126                                break;
     127                        }
     128                }
     129                else
     130                        break;
     131        }
     132
     133        return pun_trim($text);
     134}
     135
     136
     137//
     138// Strip empty bbcode tags from some text
     139//
     140function strip_empty_bbcode($text, &$errors)
     141{
     142        // If the message contains a code tag we have to split it up (empty tags within [code][/code] are fine)
     143        if (strpos($text, '[code]') !== false && strpos($text, '[/code]') !== false)
     144                list($inside, $text) = extract_blocks($text, '[code]', '[/code]', $errors);
     145
     146        // Remove empty tags
     147        while (($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)) !== NULL)
     148        {
     149                if ($new_text != $text)
     150                        $text = $new_text;
     151                else
     152                        break;
     153        }
     154
     155        // If we split up the message before we have to concatenate it together again (code tags)
     156    if (isset($inside)) {
     157        $parts = explode("\1", $text);
     158        $text = '';
     159        foreach ($parts as $i => $part)
     160        {
     161            $text .= $part;
     162            if (isset($inside[$i]))
     163                $text .= '[code]'.$inside[$i].'[/code]';
     164        }
     165    }
     166
     167        // Remove empty code tags
     168        while (($new_text = preg_replace('%\[(code)\]\s*\[/\1\]%', '', $text)) !== NULL)
     169        {
     170                if ($new_text != $text)
     171                        $text = $new_text;
     172                else
     173                        break;
     174        }
     175
     176        return $text;
     177}
     178
     179
     180//
     181// Check the structure of bbcode tags and fix simple mistakes where possible
     182//
     183function preparse_tags($text, &$errors, $is_signature = false)
     184{
     185        global $lang_common, $pun_config;
     186
     187        // Start off by making some arrays of bbcode tags and what we need to do with each one
     188
     189        // List of all the tags
     190        $tags = array('quote', 'code', 'b', 'i', 'u', 's', 'ins', 'del', 'em', 'color', 'colour', 'url', 'email', 'img', 'list', '*', 'h', 'topic', 'post', 'forum', 'user');
     191        // 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)
     192        $tags_opened = $tags;
     193        // and tags we need to check are closed (the same as above, added it just in case)
     194        $tags_closed = $tags;
     195        // Tags we can nest and the depth they can be nested to
     196        $tags_nested = array('quote' => $pun_config['o_quote_depth'], 'list' => 5, '*' => 5);
     197        // Tags to ignore the contents of completely (just code)
     198        $tags_ignore = array('code');
     199        // Block tags, block tags can only go within another block tag, they cannot be in a normal tag
     200        $tags_block = array('quote', 'code', 'list', 'h', '*');
     201        // Inline tags, we do not allow new lines in these
     202        $tags_inline = array('b', 'i', 'u', 's', 'ins', 'del', 'em', 'color', 'colour', 'h', 'topic', 'post', 'forum', 'user');
     203        // Tags we trim interior space
     204        $tags_trim = array('img');
     205        // Tags we remove quotes from the argument
     206        $tags_quotes = array('url', 'email', 'img', 'topic', 'post', 'forum', 'user');
     207        // Tags we limit bbcode in
     208        $tags_limit_bbcode = array(
     209                '*'     => array('b', 'i', 'u', 's', 'ins', 'del', 'em', 'color', 'colour', 'url', 'email', 'list', 'img', 'code', 'topic', 'post', 'forum', 'user'),
     210                'list'  => array('*'),
     211                'url'   => array('img'),
     212                'email' => array('img'),
     213                'topic' => array('img'),
     214                'post'  => array('img'),
     215                'forum' => array('img'),
     216                'user'  => array('img'),
     217                'img'   => array(),
     218                'h'             => array('b', 'i', 'u', 's', 'ins', 'del', 'em', 'color', 'colour', 'url', 'email', 'topic', 'post', 'forum', 'user'),
     219        );
     220        // Tags we can automatically fix bad nesting
     221        $tags_fix = array('quote', 'b', 'i', 'u', 's', 'ins', 'del', 'em', 'color', 'colour', 'url', 'email', 'h', 'topic', 'post', 'forum', 'user');
     222
     223        $split_text = preg_split('%(\[[\*a-zA-Z0-9-/]*?(?:=.*?)?\])%', $text, -1, PREG_SPLIT_DELIM_CAPTURE|PREG_SPLIT_NO_EMPTY);
     224
     225        $open_tags = array('fluxbb-bbcode');
     226        $open_args = array('');
     227        $opened_tag = 0;
     228        $new_text = '';
     229        $current_ignore = '';
     230        $current_nest = '';
     231        $current_depth = array();
     232        $limit_bbcode = $tags;
     233        $count_ignored = array();
     234
     235        foreach ($split_text as $current)
     236        {
     237                if ($current == '')
     238                        continue;
     239
     240                // Are we dealing with a tag?
     241                if (substr($current, 0, 1) != '[' || substr($current, -1, 1) != ']')
     242                {
     243                        // It's not a bbcode tag so we put it on the end and continue
     244                        // If we are nested too deeply don't add to the end
     245                        if ($current_nest)
     246                                continue;
     247
     248                        $current = str_replace("\r\n", "\n", $current);
     249                        $current = str_replace("\r", "\n", $current);
     250                        if (in_array($open_tags[$opened_tag], $tags_inline) && strpos($current, "\n") !== false)
     251                        {
     252                                // Deal with new lines
     253                                $split_current = preg_split('%(\n\n+)%', $current, -1, PREG_SPLIT_DELIM_CAPTURE|PREG_SPLIT_NO_EMPTY);
     254                                $current = '';
     255
     256                                if (!pun_trim($split_current[0], "\n")) // The first part is a linebreak so we need to handle any open tags first
     257                                        array_unshift($split_current, '');
     258
     259                                for ($i = 1; $i < count($split_current); $i += 2)
     260                                {
     261                                        $temp_opened = array();
     262                                        $temp_opened_arg = array();
     263                                        $temp = $split_current[$i - 1];
     264                                        while (!empty($open_tags))
     265                                        {
     266                                                $temp_tag = array_pop($open_tags);
     267                                                $temp_arg = array_pop($open_args);
     268
     269                                                if (in_array($temp_tag , $tags_inline))
     270                                                {
     271                                                        array_push($temp_opened, $temp_tag);
     272                                                        array_push($temp_opened_arg, $temp_arg);
     273                                                        $temp .= '[/'.$temp_tag.']';
     274                                                }
     275                                                else
     276                                                {
     277                                                        array_push($open_tags, $temp_tag);
     278                                                        array_push($open_args, $temp_arg);
     279                                                        break;
     280                                                }
     281                                        }
     282                                        $current .= $temp.$split_current[$i];
     283                                        $temp = '';
     284                                        while (!empty($temp_opened))
     285                                        {
     286                                                $temp_tag = array_pop($temp_opened);
     287                                                $temp_arg = array_pop($temp_opened_arg);
     288                                                if (empty($temp_arg))
     289                                                        $temp .= '['.$temp_tag.']';
     290                                                else
     291                                                        $temp .= '['.$temp_tag.'='.$temp_arg.']';
     292                                                array_push($open_tags, $temp_tag);
     293                                                array_push($open_args, $temp_arg);
     294                                        }
     295                                        $current .= $temp;
     296                                }
     297
     298                                if (array_key_exists($i - 1, $split_current))
     299                                        $current .= $split_current[$i - 1];
     300                        }
     301
     302                        if (in_array($open_tags[$opened_tag], $tags_trim))
     303                                $new_text .= pun_trim($current);
     304                        else
     305                                $new_text .= $current;
     306
     307                        continue;
     308                }
     309
     310                // Get the name of the tag
     311                $current_arg = '';
     312                if (strpos($current, '/') === 1)
     313                {
     314                        $current_tag = substr($current, 2, -1);
     315                }
     316                else if (strpos($current, '=') === false)
     317                {
     318                        $current_tag = substr($current, 1, -1);
     319                }
     320                else
     321                {
     322                        $current_tag = substr($current, 1, strpos($current, '=')-1);
     323                        $current_arg = substr($current, strpos($current, '=')+1, -1);
     324                }
     325                $current_tag = strtolower($current_tag);
     326
     327                // Is the tag defined?
     328                if (!in_array($current_tag, $tags))
     329                {
     330                        // It's not a bbcode tag so we put it on the end and continue
     331                        if (!$current_nest)
     332                                $new_text .= $current;
     333
     334                        continue;
     335                }
     336
     337                // We definitely have a bbcode tag
     338
     339                // Make the tag string lower case
     340                if ($equalpos = strpos($current,'='))
     341                {
     342                        // We have an argument for the tag which we don't want to make lowercase
     343                        if (strlen(substr($current, $equalpos)) == 2)
     344                        {
     345                                // Empty tag argument
     346                                $errors[] = sprintf($lang_common['BBCode error empty attribute'], $current_tag);
     347                                return false;
     348                        }
     349                        $current = strtolower(substr($current, 0, $equalpos)).substr($current, $equalpos);
     350                }
     351                else
     352                        $current = strtolower($current);
     353
     354                // This is if we are currently in a tag which escapes other bbcode such as code
     355                // We keep a cound of ignored bbcodes (code tags) so we can nest them, but
     356                // only balanced sets of tags can be nested
     357                if ($current_ignore)
     358                {
     359                        // Increase the current ignored tags counter
     360                        if ('['.$current_ignore.']' == $current)
     361                        {
     362                                if (!isset($count_ignored[$current_tag]))
     363                                        $count_ignored[$current_tag] = 2;
     364                                else
     365                                        $count_ignored[$current_tag]++;
     366                        }
     367
     368                        // Decrease the current ignored tags counter
     369                        if ('[/'.$current_ignore.']' == $current)
     370                                $count_ignored[$current_tag]--;
     371
     372                        if ('[/'.$current_ignore.']' == $current && $count_ignored[$current_tag] == 0)
     373                        {
     374                                // We've finished the ignored section
     375                                $current = '[/'.$current_tag.']';
     376                                $current_ignore = '';
     377                                $count_ignored = array();
     378                        }
     379
     380                        $new_text .= $current;
     381
     382                        continue;
     383                }
     384
     385                if ($current_nest)
     386                {
     387                        // We are currently too deeply nested so lets see if we are closing the tag or not
     388                        if ($current_tag != $current_nest)
     389                                continue;
     390
     391                        if (substr($current, 1, 1) == '/')
     392                                $current_depth[$current_nest]--;
     393                        else
     394                                $current_depth[$current_nest]++;
     395
     396                        if ($current_depth[$current_nest] <= $tags_nested[$current_nest])
     397                                $current_nest = '';
     398
     399                        continue;
     400                }
     401
     402                // Check the current tag is allowed here
     403                if (!in_array($current_tag, $limit_bbcode) && $current_tag != $open_tags[$opened_tag])
     404                {
     405                        $errors[] = sprintf($lang_common['BBCode error invalid nesting'], $current_tag, $open_tags[$opened_tag]);
     406                        return false;
     407                }
     408
     409                if (substr($current, 1, 1) == '/')
     410                {
     411                        // This is if we are closing a tag
     412                        if ($opened_tag == 0 || !in_array($current_tag, $open_tags))
     413                        {
     414                                // We tried to close a tag which is not open
     415                                if (in_array($current_tag, $tags_opened))
     416                                {
     417                                        $errors[] = sprintf($lang_common['BBCode error no opening tag'], $current_tag);
     418                                        return false;
     419                                }
     420                        }
     421                        else
     422                        {
     423                                // Check nesting
     424                                while (true)
     425                                {
     426                                        // Nesting is ok
     427                                        if ($open_tags[$opened_tag] == $current_tag)
     428                                        {
     429                                                array_pop($open_tags);
     430                                                array_pop($open_args);
     431                                                $opened_tag--;
     432                                                break;
     433                                        }
     434
     435                                        // Nesting isn't ok, try to fix it
     436                                        if (in_array($open_tags[$opened_tag], $tags_closed) && in_array($current_tag, $tags_closed))
     437                                        {
     438                                                if (in_array($current_tag, $open_tags))
     439                                                {
     440                                                        $temp_opened = array();
     441                                                        $temp_opened_arg = array();
     442                                                        $temp = '';
     443                                                        while (!empty($open_tags))
     444                                                        {
     445                                                                $temp_tag = array_pop($open_tags);
     446                                                                $temp_arg = array_pop($open_args);
     447
     448                                                                if (!in_array($temp_tag, $tags_fix))
     449                                                                {
     450                                                                        // We couldn't fix nesting
     451                                                                        $errors[] = sprintf($lang_common['BBCode error no closing tag'], array_pop($temp_opened));
     452                                                                        return false;
     453                                                                }
     454                                                                array_push($temp_opened, $temp_tag);
     455                                                                array_push($temp_opened_arg, $temp_arg);
     456
     457                                                                if ($temp_tag == $current_tag)
     458                                                                        break;
     459                                                                else
     460                                                                        $temp .= '[/'.$temp_tag.']';
     461                                                        }
     462                                                        $current = $temp.$current;
     463                                                        $temp = '';
     464                                                        array_pop($temp_opened);
     465                                                        array_pop($temp_opened_arg);
     466
     467                                                        while (!empty($temp_opened))
     468                                                        {
     469                                                                $temp_tag = array_pop($temp_opened);
     470                                                                $temp_arg = array_pop($temp_opened_arg);
     471                                                                if (empty($temp_arg))
     472                                                                        $temp .= '['.$temp_tag.']';
     473                                                                else
     474                                                                        $temp .= '['.$temp_tag.'='.$temp_arg.']';
     475                                                                array_push($open_tags, $temp_tag);
     476                                                                array_push($open_args, $temp_arg);
     477                                                        }
     478                                                        $current .= $temp;
     479                                                        $opened_tag--;
     480                                                        break;
     481                                                }
     482                                                else
     483                                                {
     484                                                        // We couldn't fix nesting
     485                                                        $errors[] = sprintf($lang_common['BBCode error no opening tag'], $current_tag);
     486                                                        return false;
     487                                                }
     488                                        }
     489                                        else if (in_array($open_tags[$opened_tag], $tags_closed))
     490                                                break;
     491                                        else
     492                                        {
     493                                                array_pop($open_tags);
     494                                                array_pop($open_args);
     495                                                $opened_tag--;
     496                                        }
     497                                }
     498                        }
     499
     500                        if (in_array($current_tag, array_keys($tags_nested)))
     501                        {
     502                                if (isset($current_depth[$current_tag]))
     503                                        $current_depth[$current_tag]--;
     504                        }
     505
     506                        if (in_array($open_tags[$opened_tag], array_keys($tags_limit_bbcode)))
     507                                $limit_bbcode = $tags_limit_bbcode[$open_tags[$opened_tag]];
     508                        else
     509                                $limit_bbcode = $tags;
     510
     511                        $new_text .= $current;
     512
     513                        continue;
     514                }
     515                else
     516                {
     517                        // We are opening a tag
     518                        if (in_array($current_tag, array_keys($tags_limit_bbcode)))
     519                                $limit_bbcode = $tags_limit_bbcode[$current_tag];
     520                        else
     521                                $limit_bbcode = $tags;
     522
     523                        if (in_array($current_tag, $tags_block) && !in_array($open_tags[$opened_tag], $tags_block) && $opened_tag != 0)
     524                        {
     525                                // We tried to open a block tag within a non-block tag
     526                                $errors[] = sprintf($lang_common['BBCode error invalid nesting'], $current_tag, $open_tags[$opened_tag]);
     527                                return false;
     528                        }
     529
     530                        if (in_array($current_tag, $tags_ignore))
     531                        {
     532                                // It's an ignore tag so we don't need to worry about what's inside it
     533                                $current_ignore = $current_tag;
     534                                $new_text .= $current;
     535                                continue;
     536                        }
     537
     538                        // Deal with nested tags
     539                        if (in_array($current_tag, $open_tags) && !in_array($current_tag, array_keys($tags_nested)))
     540                        {
     541                                // We nested a tag we shouldn't
     542                                $errors[] = sprintf($lang_common['BBCode error invalid self-nesting'], $current_tag);
     543                                return false;
     544                        }
     545                        else if (in_array($current_tag, array_keys($tags_nested)))
     546                        {
     547                                // We are allowed to nest this tag
     548
     549                                if (isset($current_depth[$current_tag]))
     550                                        $current_depth[$current_tag]++;
     551                                else
     552                                        $current_depth[$current_tag] = 1;
     553
     554                                // See if we are nested too deep
     555                                if ($current_depth[$current_tag] > $tags_nested[$current_tag])
     556                                {
     557                                        $current_nest = $current_tag;
     558                                        continue;
     559                                }
     560                        }
     561
     562                        // Remove quotes from arguments for certain tags
     563                        if (strpos($current, '=') !== false && in_array($current_tag, $tags_quotes))
     564                        {
     565                                $current = preg_replace('%\['.$current_tag.'=("|\'|)(.*?)\\1\]\s*%i', '['.$current_tag.'=$2]', $current);
     566                        }
     567
     568                        if (in_array($current_tag, array_keys($tags_limit_bbcode)))
     569                                $limit_bbcode = $tags_limit_bbcode[$current_tag];
     570
     571                        $open_tags[] = $current_tag;
     572                        $open_args[] = $current_arg;
     573                        $opened_tag++;
     574                        $new_text .= $current;
     575                        continue;
     576                }
     577        }
     578
     579        // Check we closed all the tags we needed to
     580        foreach ($tags_closed as $check)
     581        {
     582                if (in_array($check, $open_tags))
     583                {
     584                        // We left an important tag open
     585                        $errors[] = sprintf($lang_common['BBCode error no closing tag'], $check);
     586                        return false;
     587                }
     588        }
     589
     590        if ($current_ignore)
     591        {
     592                // We left an ignore tag open
     593                $errors[] = sprintf($lang_common['BBCode error no closing tag'], $current_ignore);
     594                return false;
     595        }
     596
     597        return $new_text;
     598}
     599
     600
     601//
     602// Preparse the contents of [list] bbcode
     603//
     604function preparse_list_tag($content, $type = '*', &$errors)
     605{
     606        global $lang_common, $re_list;
     607
     608        if (strlen($type) != 1)
     609                $type = '*';
     610
     611        if (strpos($content,'[list') !== false)
     612        {
     613                $content = preg_replace($re_list, 'preparse_list_tag(\'$2\', \'$1\', $errors)', $content);
     614        }
     615
     616        $items = explode('[*]', str_replace('\"', '"', $content));
     617
     618        $content = '';
     619        foreach ($items as $item)
     620        {
     621                if (pun_trim($item) != '')
     622                        $content .= '[*'."\0".']'.str_replace('[/*]', '', pun_trim($item)).'[/*'."\0".']'."\n";
     623        }
     624
     625        return '[list='.$type.']'."\n".$content.'[/list]';
     626}
     627
     628
     629//
     630// Truncate URL if longer than 55 characters (add http:// or ftp:// if missing)
     631//
     632function handle_url_tag($url, $link = '', $bbcode = false)
     633{
     634        $url = pun_trim($url);
     635        $full_url = str_replace(array(' ', '\'', '`', '"'), array('%20', '', '', ''), $url);
     636        if (strpos($url, 'www.') === 0) // If it starts with www, we add http://
     637                $full_url = 'http://'.$full_url;
     638        else if (strpos($url, 'ftp.') === 0) // Else if it starts with ftp, we add ftp://
     639                $full_url = 'ftp://'.$full_url;
     640        else if (strpos($url, '/') === 0) // Allow for relative URLs that start with a slash
     641                $full_url = get_base_url(true).$full_url;
     642        else if (!preg_match('#^([a-z0-9]{3,6})://#', $url)) // Else if it doesn't start with abcdef://, we add http://
     643                $full_url = 'http://'.$full_url;
     644
     645        // Ok, not very pretty :-)
     646        if ($bbcode)
     647        {
     648                if ($full_url == $link)
     649                        return '[url]'.$link.'[/url]';
     650                else
     651                        return '[url='.$full_url.']'.$link.'[/url]';
     652        }
     653        else
     654        {
     655                if ($link == '' || $link == $url)
     656                {
     657                        $url = pun_htmlspecialchars_decode($url);
     658                        $link = utf8_strlen($url) > 55 ? utf8_substr($url, 0 , 39).' 
 '.utf8_substr($url, -10) : $url;
     659                        $link = pun_htmlspecialchars($link);
     660                }
     661                else
     662                        $link = stripslashes($link);
     663
     664                return '<a href="'.$full_url.'">'.$link.'</a>';
     665        }
     666}
     667
     668
     669//
     670// Turns an URL from the [img] tag into an <img> tag or a <a href...> tag
     671//
     672function handle_img_tag($url, $is_signature = false, $alt = null)
     673{
     674        global $lang_common, $pun_user;
     675
     676        if ($alt == null)
     677                $alt = basename($url);
     678
     679        $img_tag = '<a href="'.$url.'">&lt;'.$lang_common['Image link'].' - '.$alt.'&gt;</a>';
     680
     681        if ($is_signature && $pun_user['show_img_sig'] != '0')
     682                $img_tag = '<img class="sigimage" src="'.$url.'" alt="'.$alt.'" />';
     683        else if (!$is_signature && $pun_user['show_img'] != '0')
     684                $img_tag = '<span class="postimg"><img src="'.$url.'" alt="'.$alt.'" /></span>';
     685
     686        return $img_tag;
     687}
     688
     689
     690//
     691// Parse the contents of [list] bbcode
     692//
     693function handle_list_tag($content, $type = '*')
     694{
     695        global $re_list;
     696
     697        if (strlen($type) != 1)
     698                $type = '*';
     699
     700        if (strpos($content,'[list') !== false)
     701        {
     702                $content = preg_replace($re_list, 'handle_list_tag(\'$2\', \'$1\')', $content);
     703        }
     704
     705        $content = preg_replace('#\s*\[\*\](.*?)\[/\*\]\s*#s', '<li><p>$1</p></li>', pun_trim($content));
     706
     707        if ($type == '*')
     708                $content = '<ul>'.$content.'</ul>';
     709        else
     710                if ($type == 'a')
     711                        $content = '<ol class="alpha">'.$content.'</ol>';
     712                else
     713                        $content = '<ol class="decimal">'.$content.'</ol>';
     714
     715        return '</p>'.$content.'<p>';
     716}
     717
     718
     719//
     720// Convert BBCodes to their HTML equivalent
     721//
     722function do_bbcode($text, $is_signature = false)
     723{
     724        global $lang_common, $pun_user, $pun_config, $re_list;
     725
     726        if (strpos($text, '[quote') !== false)
     727        {
     728                $text = preg_replace('%\[quote\]\s*%', '</p><div class="quotebox"><blockquote><div><p>', $text);
     729                $text = preg_replace('%\[quote=(&quot;|&\#039;|"|\'|)(.*?)\\1\]%se', '"</p><div class=\"quotebox\"><cite>".str_replace(array(\'[\', \'\\"\'), array(\'&#91;\', \'"\'), \'$2\')." ".$lang_common[\'wrote\']."</cite><blockquote><div><p>"', $text);
     730                $text = preg_replace('%\s*\[\/quote\]%S', '</p></div></blockquote></div><p>', $text);
     731        }
    68732
    69733        if (!$is_signature)
    70734        {
    71                 // For non-signatures, we have to do the quote and code tags as well
    72                 $a[] = '#\[quote=(&quot;|"|\'|)(.*?)\\1\]\s*#i';
    73                 $a[] = '#\[quote\]\s*#i';
    74                 $a[] = '#\s*\[/quote\]\s*#i';
    75                 $a[] = '#\[code\][\r\n]*(.*?)\s*\[/code\]\s*#is';
    76 
    77                 $b[] = '[quote=$1$2$1]';
    78                 $b[] = '[quote]';
    79                 $b[] = '[/quote]'."\n";
    80                 $b[] = '[code]$1[/code]'."\n";
    81         }
    82 
    83         // Run this baby!
    84         $text = preg_replace($a, $b, $text);
    85 
    86         if (!$is_signature)
    87         {
    88                 $overflow = check_tag_order($text, $error);
    89 
    90                 if ($error)
    91                         // A BBCode error was spotted in check_tag_order()
    92                         $errors[] = $error;
    93                 else if ($overflow)
    94                         // The quote depth level was too high, so we strip out the inner most quote(s)
    95                         $text = substr($text, 0, $overflow[0]).substr($text, $overflow[1], (strlen($text) - $overflow[0]));
    96         }
    97         else
    98         {
    99                 global $lang_prof_reg;
    100 
    101                 if (preg_match('#\[quote=(&quot;|"|\'|)(.*)\\1\]|\[quote\]|\[/quote\]|\[code\]|\[/code\]#i', $text))
    102                         message($lang_prof_reg['Signature quote/code']);
    103         }
    104 
    105         return trim($text);
    106 }
    107 
    108 
    109 //
    110 // Parse text and make sure that [code] and [quote] syntax is correct
    111 //
    112 function check_tag_order($text, &$error)
    113 {
    114         global $lang_common;
    115 
    116         // The maximum allowed quote depth
    117         $max_depth = 3;
    118 
    119         $cur_index = 0;
    120         $q_depth = 0;
    121 
    122         while (true)
    123         {
    124                 // Look for regular code and quote tags
    125                 $c_start = strpos($text, '[code]');
    126                 $c_end = strpos($text, '[/code]');
    127                 $q_start = strpos($text, '[quote]');
    128                 $q_end = strpos($text, '[/quote]');
    129 
    130                 // Look for [quote=username] style quote tags
    131                 if (preg_match('#\[quote=(&quot;|"|\'|)(.*)\\1\]#sU', $text, $matches))
    132                         $q2_start = strpos($text, $matches[0]);
     735                $pattern[] = $re_list;
     736                $replace[] = 'handle_list_tag(\'$2\', \'$1\')';
     737        }
     738
     739        $pattern[] = '%\[b\](.*?)\[/b\]%ms';
     740        $pattern[] = '%\[i\](.*?)\[/i\]%ms';
     741        $pattern[] = '%\[u\](.*?)\[/u\]%ms';
     742        $pattern[] = '%\[s\](.*?)\[/s\]%ms';
     743        $pattern[] = '%\[del\](.*?)\[/del\]%ms';
     744        $pattern[] = '%\[ins\](.*?)\[/ins\]%ms';
     745        $pattern[] = '%\[em\](.*?)\[/em\]%ms';
     746        $pattern[] = '%\[colou?r=([a-zA-Z]{3,20}|\#[0-9a-fA-F]{6}|\#[0-9a-fA-F]{3})](.*?)\[/colou?r\]%ms';
     747        $pattern[] = '%\[h\](.*?)\[/h\]%ms';
     748
     749        $replace[] = '<strong>$1</strong>';
     750        $replace[] = '<em>$1</em>';
     751        $replace[] = '<span class="bbu">$1</span>';
     752        $replace[] = '<span class="bbs">$1</span>';
     753        $replace[] = '<del>$1</del>';
     754        $replace[] = '<ins>$1</ins>';
     755        $replace[] = '<em>$1</em>';
     756        $replace[] = '<span style="color: $1">$2</span>';
     757        $replace[] = '</p><h5>$1</h5><p>';
     758
     759        if (($is_signature && $pun_config['p_sig_img_tag'] == '1') || (!$is_signature && $pun_config['p_message_img_tag'] == '1'))
     760        {
     761                $pattern[] = '%\[img\]((ht|f)tps?://)([^\s<"]*?)\[/img\]%e';
     762                $pattern[] = '%\[img=([^\[]*?)\]((ht|f)tps?://)([^\s<"]*?)\[/img\]%e';
     763                if ($is_signature)
     764                {
     765                        $replace[] = 'handle_img_tag(\'$1$3\', true)';
     766                        $replace[] = 'handle_img_tag(\'$2$4\', true, \'$1\')';
     767                }
    133768                else
    134                         $q2_start = 65536;
    135 
    136                 // Deal with strpos() returning false when the string is not found
    137                 // (65536 is one byte longer than the maximum post length)
    138                 if ($c_start === false) $c_start = 65536;
    139                 if ($c_end === false) $c_end = 65536;
    140                 if ($q_start === false) $q_start = 65536;
    141                 if ($q_end === false) $q_end = 65536;
    142 
    143                 // If none of the strings were found
    144                 if (min($c_start, $c_end, $q_start, $q_end, $q2_start) == 65536)
    145                         break;
    146 
    147                 // We are interested in the first quote (regardless of the type of quote)
    148                 $q3_start = ($q_start < $q2_start) ? $q_start : $q2_start;
    149 
    150                 // We found a [quote] or a [quote=username]
    151                 if ($q3_start < min($q_end, $c_start, $c_end))
    152                 {
    153                         $step = ($q_start < $q2_start) ? 7 : strlen($matches[0]);
    154 
    155                         $cur_index += $q3_start + $step;
    156 
    157                         // Did we reach $max_depth?
    158                         if ($q_depth == $max_depth)
    159                                 $overflow_begin = $cur_index - $step;
    160 
    161                         ++$q_depth;
    162                         $text = substr($text, $q3_start + $step);
    163                 }
    164 
    165                 // We found a [/quote]
    166                 else if ($q_end < min($q_start, $c_start, $c_end))
    167                 {
    168                         if ($q_depth == 0)
    169                         {
    170                                 $error = $lang_common['BBCode error'].' '.$lang_common['BBCode error 1'];
    171                                 return;
    172                         }
    173 
    174                         $q_depth--;
    175                         $cur_index += $q_end+8;
    176 
    177                         // Did we reach $max_depth?
    178                         if ($q_depth == $max_depth)
    179                                 $overflow_end = $cur_index;
    180 
    181                         $text = substr($text, $q_end+8);
    182                 }
    183 
    184                 // We found a [code]
    185                 else if ($c_start < min($c_end, $q_start, $q_end))
    186                 {
    187                         // Make sure there's a [/code] and that any new [code] doesn't occur before the end tag
    188                         $tmp = strpos($text, '[/code]');
    189                         $tmp2 = strpos(substr($text, $c_start+6), '[code]');
    190                         if ($tmp2 !== false)
    191                                 $tmp2 += $c_start+6;
    192                                
    193                         if ($tmp === false || ($tmp2 !== false && $tmp2 < $tmp))
    194                         {
    195                                 $error = $lang_common['BBCode error'].' '.$lang_common['BBCode error 2'];
    196                                 return;
    197                         }
    198                         else
    199                                 $text = substr($text, $tmp+7);
    200 
    201                         $cur_index += $tmp+7;
    202                 }
    203 
    204                 // We found a [/code] (this shouldn't happen since we handle both start and end tag in the if clause above)
    205                 else if ($c_end < min($c_start, $q_start, $q_end))
    206                 {
    207                         $error = $lang_common['BBCode error'].' '.$lang_common['BBCode error 3'];
    208                         return;
    209                 }
    210         }
    211 
    212         // If $q_depth <> 0 something is wrong with the quote syntax
    213         if ($q_depth)
    214         {
    215                 $error = $lang_common['BBCode error'].' '.$lang_common['BBCode error 4'];
    216                 return;
    217         }
    218         else if ($q_depth < 0)
    219         {
    220                 $error = $lang_common['BBCode error'].' '.$lang_common['BBCode error 5'];
    221                 return;
    222         }
    223 
    224         // If the quote depth level was higher than $max_depth we return the index for the
    225         // beginning and end of the part we should strip out
    226         if (isset($overflow_begin))
    227                 return array($overflow_begin, $overflow_end);
    228         else
    229                 return null;
    230 }
    231 
    232 
    233 //
    234 // Split text into chunks ($inside contains all text inside $start and $end, and $outside contains all text outside)
    235 //
    236 function split_text($text, $start, $end)
    237 {
    238         global $pun_config;
    239 
    240         $tokens = explode($start, $text);
    241 
    242         $outside[] = $tokens[0];
    243 
    244         $num_tokens = count($tokens);
    245         for ($i = 1; $i < $num_tokens; ++$i)
    246         {
    247                 $temp = explode($end, $tokens[$i]);
    248                 $inside[] = $temp[0];
    249                 $outside[] = $temp[1];
    250         }
    251 
    252         if ($pun_config['o_indent_num_spaces'] != 8 && $start == '[code]')
    253         {
    254                 $spaces = str_repeat(' ', $pun_config['o_indent_num_spaces']);
    255                 $inside = str_replace("\t", $spaces, $inside);
    256         }
    257 
    258         return array($inside, $outside);
    259 }
    260 
    261 
    262 //
    263 // Truncate URL if longer than 55 characters (add http:// or ftp:// if missing)
    264 //
    265 function handle_url_tag($url, $link = '')
    266 {
    267         global $pun_user;
    268 
    269         $full_url = str_replace(array(' ', '\'', '`'), array('%20', '', ''), $url);
    270         if (strpos($url, 'www.') === 0)                 // If it starts with www, we add http://
    271                 $full_url = 'http://'.$full_url;
    272         else if (strpos($url, 'ftp.') === 0)    // Else if it starts with ftp, we add ftp://
    273                 $full_url = 'ftp://'.$full_url;
    274         else if (!preg_match('#^([a-z0-9]{3,6})://#', $url, $bah))      // Else if it doesn't start with abcdef://, we add http://
    275                 $full_url = 'http://'.$full_url;
    276 
    277         // Ok, not very pretty :-)
    278         $link = ($link == '' || $link == $url) ? ((strlen($url) > 55) ? substr($url, 0 , 39).' &hellip; '.substr($url, -10) : $url) : stripslashes($link);
    279 
    280         return '<a href="'.$full_url.'" target=\"_blank\">'.$link.'</a>';
    281 }
    282 
    283 
    284 //
    285 // Turns an URL from the [img] tag into an <img> tag or a <a href...> tag
    286 //
    287 function handle_img_tag($url, $is_signature = false)
    288 {
    289         global $lang_common, $pun_config, $pun_user;
    290 
    291         $img_tag = '<a href="'.$url.'">&lt;'.$lang_common['Image link'].'&gt;</a>';
    292 
    293         if ($is_signature && $pun_user['show_img_sig'] != '0')
    294                 $img_tag = '<img class="sigimage" src="'.$url.'" alt="'.htmlspecialchars($url).'" />';
    295         else if (!$is_signature && $pun_user['show_img'] != '0')
    296                 $img_tag = '<img class="postimg" src="'.$url.'" alt="'.htmlspecialchars($url).'" />';
    297 
    298         return $img_tag;
    299 }
    300 
    301 
    302 //
    303 // Convert BBCodes to their HTML equivalent
    304 //
    305 function do_bbcode($text)
    306 {
    307         global $lang_common, $pun_user;
    308 
    309         if (strpos($text, 'quote') !== false)
    310         {
    311                 $text = str_replace('[quote]', '</p><blockquote><div class="incqbox"><p>', $text);
    312                 $text = preg_replace('#\[quote=(&quot;|"|\'|)(.*)\\1\]#seU', '"</p><blockquote><div class=\"incqbox\"><h4>".str_replace(array(\'[\', \'\\"\'), array(\'&#91;\', \'"\'), \'$2\')." ".$lang_common[\'wrote\'].":</h4><p>"', $text);
    313                 $text = preg_replace('#\[\/quote\]\s*#', '</p></div></blockquote><p>', $text);
    314         }
    315        
    316         $pattern = array('#\[b\](.*?)\[/b\]#s',
    317                                          '#\[i\](.*?)\[/i\]#s',
    318                                          '#\[u\](.*?)\[/u\]#s',
    319                                          '#\[url\]([^\[]*?)\[/url\]#e',
    320                                          '#\[url=([^\[]*?)\](.*?)\[/url\]#e',
    321                                          '#\[email\]([^\[]*?)\[/email\]#',
    322                                          '#\[email=([^\[]*?)\](.*?)\[/email\]#',
    323                                          '#\[color=([a-zA-Z]*|\#?[0-9a-fA-F]{6})](.*?)\[/color\]#s',
    324                                          '#\[font=(.*?)](.*?)\[/font\]#s',
    325                                          '#\[align=(.*?)\](.*?)\[/align\]#s',
    326                                          '#\[hr /\]#',
    327                                          '#\[hr\]#',
    328                                          '#\[s\](.*?)\[/s\]#s',
    329                                          '#\[h\](.*?)\[/h\]#s',
    330                                '#\[size=([0-9]{1,2})](.*?)\[/size\]#s');
    331 
    332         $replace = array('<strong>$1</strong>',
    333                                          '<em>$1</em>',
    334                                          '<span class="bbu">$1</span>',
    335                                          'handle_url_tag(\'$1\')',
    336                                          'handle_url_tag(\'$1\', \'$2\')',
    337                                          '<a href="mailto:$1">$1</a>',
    338                                          '<a href="mailto:$1">$2</a>',
    339                                          '<span style="color: $1">$2</span>',
    340                                          '<span style="font-family: $1">$2</span>',
    341                                          '<div align="$1">$2</div>',
    342                                          '<hr />',
    343                                          '<hr />',
    344                                          '<del>$1</del>',
    345                                          '<span style="background-color: #FFFF00; color: #000000">$1</span>',
    346                                '<span style="font-size: $1pt;">$2</span>');
     769                {
     770                        $replace[] = 'handle_img_tag(\'$1$3\', false)';
     771                        $replace[] = 'handle_img_tag(\'$2$4\', false, \'$1\')';
     772                }
     773        }
     774
     775        $pattern[] = '%\[url\]([^\[]*?)\[/url\]%e';
     776        $pattern[] = '%\[url=([^\[]+?)\](.*?)\[/url\]%e';
     777        $pattern[] = '%\[email\]([^\[]*?)\[/email\]%';
     778        $pattern[] = '%\[email=([^\[]+?)\](.*?)\[/email\]%';
     779        $pattern[] = '%\[topic\]([^\[]*?)\[/topic\]%e';
     780        $pattern[] = '%\[topic=([^\[]+?)\](.*?)\[/topic\]%e';
     781        $pattern[] = '%\[post\]([^\[]*?)\[/post\]%e';
     782        $pattern[] = '%\[post=([^\[]+?)\](.*?)\[/post\]%e';
     783        $pattern[] = '%\[forum\]([^\[]*?)\[/forum\]%e';
     784        $pattern[] = '%\[forum=([^\[]+?)\](.*?)\[/forum\]%e';
     785        $pattern[] = '%\[user\]([^\[]*?)\[/user\]%e';
     786        $pattern[] = '%\[user=([^\[]+?)\](.*?)\[/user\]%e';
     787
     788        $replace[] = 'handle_url_tag(\'$1\')';
     789        $replace[] = 'handle_url_tag(\'$1\', \'$2\')';
     790        $replace[] = '<a href="mailto:$1">$1</a>';
     791        $replace[] = '<a href="mailto:$1">$2</a>';
     792        $replace[] = 'handle_url_tag(\''.get_base_url(true).'/viewtopic.php?id=$1\')';
     793        $replace[] = 'handle_url_tag(\''.get_base_url(true).'/viewtopic.php?id=$1\', \'$2\')';
     794        $replace[] = 'handle_url_tag(\''.get_base_url(true).'/viewtopic.php?pid=$1#p$1\')';
     795        $replace[] = 'handle_url_tag(\''.get_base_url(true).'/viewtopic.php?pid=$1#p$1\', \'$2\')';
     796        $replace[] = 'handle_url_tag(\''.get_base_url(true).'/viewforum.php?id=$1\')';
     797        $replace[] = 'handle_url_tag(\''.get_base_url(true).'/viewforum.php?id=$1\', \'$2\')';
     798        $replace[] = 'handle_url_tag(\''.get_base_url(true).'/profile.php?id=$1\')';
     799        $replace[] = 'handle_url_tag(\''.get_base_url(true).'/profile.php?id=$1\', \'$2\')';
    347800
    348801        // This thing takes a while! :)
     
    358811function do_clickable($text)
    359812{
    360         global $pun_user;
    361 
    362813        $text = ' '.$text;
    363814
    364         $text = preg_replace('#([\s\(\)])(https?|ftp|news){1}://([\w\-]+\.([\w\-]+\.)*[\w]+(:[0-9]+)?(/[^"\s\(\)<\[]*)?)#ie', '\'$1\'.handle_url_tag(\'$2://$3\')', $text);
    365         $text = preg_replace('#([\s\(\)])(www|ftp)\.(([\w\-]+\.)*[\w]+(:[0-9]+)?(/[^"\s\(\)<\[]*)?)#ie', '\'$1\'.handle_url_tag(\'$2.$3\', \'$2.$3\')', $text);
     815        $text = ucp_preg_replace('%(?<=[\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)\])%uie', 'stripslashes(\'$1$2$3$4\').handle_url_tag(\'$5://$6\', \'$5://$6\', true).stripslashes(\'$4$10$11$12\')', $text);
     816        $text = ucp_preg_replace('%(?<=[\s\]\)])(<)?(\[)?(\()?([\'"]?)(www|ftp)\.(([\p{L}\p{N}\-]+\.)*[\p{L}\p{N}]+(:[0-9]+)?(/[^\s\[]*[^\s.,?!\[;:-])?)\4(?(3)(\)))(?(2)(\]))(?(1)(>))(?![^\s]*\[/(?:url|img)\])%uie', 'stripslashes(\'$1$2$3$4\').handle_url_tag(\'$5.$6\', \'$5.$6\', true).stripslashes(\'$4$10$11$12\')', $text);
    366817
    367818        return substr($text, 1);
     
    374825function do_smilies($text)
    375826{
    376         global $smiley_text, $smiley_img;
     827        global $pun_config, $smilies;
    377828
    378829        $text = ' '.$text.' ';
    379830
    380         $num_smilies = count($smiley_text);
    381         for ($i = 0; $i < $num_smilies; ++$i)
    382                 $text = preg_replace("#(?<=.\W|\W.|^\W)".preg_quote($smiley_text[$i], '#')."(?=.\W|\W.|\W$)#m", '$1<img src="'.PUN_ROOT.'img/smilies/'.$smiley_img[$i].'" alt="'.substr($smiley_img[$i], 0, strrpos($smiley_img[$i], '.')).'" />$2', $text);
     831        foreach ($smilies as $smiley_text => $smiley_img)
     832        {
     833                if (strpos($text, $smiley_text) !== false)
     834                        $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).'" width="15" height="15" alt="'.substr($smiley_img, 0, strrpos($smiley_img, '.')).'" />', $text);
     835        }
    383836
    384837        return substr($text, 1, -1);
     
    401854        // If the message contains a code tag we have to split it up (text within [code][/code] shouldn't be touched)
    402855        if (strpos($text, '[code]') !== false && strpos($text, '[/code]') !== false)
    403         {
    404                 list($inside, $outside) = split_text($text, '[code]', '[/code]');
    405                 $outside = array_map('ltrim', $outside);
    406                 $text = implode('<">', $outside);
    407         }
    408 
    409         if ($pun_config['o_make_links'] == '1')
    410                 $text = do_clickable($text);
     856                list($inside, $text) = extract_blocks($text, '[code]', '[/code]', $errors);
     857
     858        if ($pun_config['p_message_bbcode'] == '1' && strpos($text, '[') !== false && strpos($text, ']') !== false)
     859                $text = do_bbcode($text);
    411860
    412861        if ($pun_config['o_smilies'] == '1' && $pun_user['show_smilies'] == '1' && $hide_smilies == '0')
    413862                $text = do_smilies($text);
    414 
    415         if ($pun_config['p_message_bbcode'] == '1' && strpos($text, '[') !== false && strpos($text, ']') !== false)
    416         {
    417                 $text = do_bbcode($text);
    418 
    419                 if ($pun_config['p_message_img_tag'] == '1')
    420                 {
    421 //                      $text = preg_replace('#\[img\]((ht|f)tps?://)([^\s<"]*?)\.(jpg|jpeg|png|gif)\[/img\]#e', 'handle_img_tag(\'$1$3.$4\')', $text);
    422                         $text = preg_replace('#\[img\]((ht|f)tps?://)([^\s<"]*?)\[/img\]#e', 'handle_img_tag(\'$1$3\')', $text);
    423                 }
    424         }
    425863
    426864        // Deal with newlines, tabs and multiple spaces
     
    430868
    431869        // If we split up the message before we have to concatenate it together again (code tags)
    432         if (isset($inside))
    433         {
    434                 $outside = explode('<">', $text);
    435                 $text = '';
    436 
    437                 $num_tokens = count($outside);
    438 
    439                 for ($i = 0; $i < $num_tokens; ++$i)
    440                 {
    441                         $text .= $outside[$i];
    442                         if (isset($inside[$i]))
    443                         {
    444                                 $num_lines = ((substr_count($inside[$i], "\n")) + 3) * 1.5;
    445                                 $height_str = ($num_lines > 35) ? '35em' : $num_lines.'em';
    446                                 $text .= '</p><div class="codebox"><div class="incqbox"><h4>'.$lang_common['Code'].':</h4><div class="scrollbox" style="height: '.$height_str.'"><pre>'.$inside[$i].'</pre></div></div></div><p>';
    447                         }
    448                 }
    449         }
     870    if (isset($inside)) {
     871        $parts = explode("\1", $text);
     872        $text = '';
     873        foreach ($parts as $i => $part)
     874        {
     875            $text .= $part;
     876            if (isset($inside[$i]))
     877            {
     878                $num_lines = (substr_count($inside[$i], "\n"));
     879                $text .= '</p><div class="codebox"><pre'.(($num_lines > 28) ? ' class="vscroll"' : '').'><code>'.pun_trim($inside[$i], "\n\r").'</code></pre></div><p>';
     880            }
     881        }
     882    }
    450883
    451884        // Add paragraph tag around post, but make sure there are no empty paragraphs
     885        $text = preg_replace('%<br />\s*?<br />((\s*<br />)*)%i', "</p>$1<p>", $text);
     886        $text = str_replace('<p><br />', '<p>', $text);
    452887        $text = str_replace('<p></p>', '', '<p>'.$text.'</p>');
    453 
    454         // Mod: Flash MP3 Player (8 nouvelles lignes suivent)
    455         $player_url     = 'dewplayer-multi.swf';
    456         $player_bgcolor = 'ffffff';
    457         $player_width   = 240;
    458         $player_height  = 20;
    459         $player_param   = '?bgcolor='.$player_bgcolor.'&amp;mp3=$1';  // Pour plus d'options: http://www.alsacreations.fr/?dewplayer
    460         $player_alternative = '<strong>Flash non détécté</strong>';
    461         $player_code = "\n\t\t\t\t\t<object type=\"application/x-shockwave-flash\" data=\"".$player_url.$player_param."\" width=\"".$player_width."\" height=\"".$player_height."\">\n\t\t\t\t\t  <param name=\"movie\" value=\"".$player_url.$player_param."\" />\n\t\t\t\t\t  <param name=\"bgcolor\" value=\"#".$player_bgcolor."\" />\n\t\t\t\t\t  ".$player_alternative."\n\t\t\t\t\t</object>\n\t\t\t\t\t";
    462         $text = preg_replace("/\[mp3 url=([^ ]+)\]/", $player_code, $text);
    463888
    464889        return $text;
     
    476901                $text = censor_words($text);
    477902
     903        // Convert applicable characters to HTML entities
    478904        $text = pun_htmlspecialchars($text);
    479905
    480         if ($pun_config['o_make_links'] == '1')
    481                 $text = do_clickable($text);
    482 
    483         if ($pun_config['o_smilies_sig'] == '1' && $pun_user['show_smilies'] != '0')
     906        if ($pun_config['p_sig_bbcode'] == '1' && strpos($text, '[') !== false && strpos($text, ']') !== false)
     907                $text = do_bbcode($text, true);
     908
     909        if ($pun_config['o_smilies_sig'] == '1' && $pun_user['show_smilies'] == '1')
    484910                $text = do_smilies($text);
    485911
    486         if ($pun_config['p_sig_bbcode'] == '1' && strpos($text, '[') !== false && strpos($text, ']') !== false)
    487         {
    488                 $text = do_bbcode($text);
    489 
    490                 if ($pun_config['p_sig_img_tag'] == '1')
    491                 {
    492 //                      $text = preg_replace('#\[img\]((ht|f)tps?://)([^\s<"]*?)\.(jpg|jpeg|png|gif)\[/img\]#e', 'handle_img_tag(\'$1$3.$4\', true)', $text);
    493                         $text = preg_replace('#\[img\]((ht|f)tps?://)([^\s<"]*?)\[/img\]#e', 'handle_img_tag(\'$1$3\', true)', $text);
    494                 }
    495         }
    496912
    497913        // Deal with newlines, tabs and multiple spaces
     
    500916        $text = str_replace($pattern, $replace, $text);
    501917
     918        // Add paragraph tag around post, but make sure there are no empty paragraphs
     919        $text = preg_replace('%<br />\s*?<br />((\s*<br />)*)%i', "</p>$1<p>", $text);
     920        $text = str_replace('<p><br />', '<p>', $text);
     921        $text = str_replace('<p></p>', '', '<p>'.$text.'</p>');
     922
    502923        return $text;
    503924}
    504 ?>
Note: See TracChangeset for help on using the changeset viewer.