Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.65% covered (danger)
0.65%
2 / 308
11.11% covered (danger)
11.11%
1 / 9
CRAP
0.00% covered (danger)
0.00%
0 / 1
bbcode
0.65% covered (danger)
0.65%
2 / 308
11.11% covered (danger)
11.11%
1 / 9
7003.44
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 bbcode_set_bitfield
33.33% covered (danger)
33.33%
1 / 3
0.00% covered (danger)
0.00%
0 / 1
3.19
 bbcode_second_pass
0.00% covered (danger)
0.00%
0 / 33
0.00% covered (danger)
0.00%
0 / 1
210
 bbcode_cache_init
0.00% covered (danger)
0.00%
0 / 180
0.00% covered (danger)
0.00%
0 / 1
1056
 bbcode_tpl
0.00% covered (danger)
0.00%
0 / 31
0.00% covered (danger)
0.00%
0 / 1
182
 bbcode_tpl_replace
0.00% covered (danger)
0.00%
0 / 15
0.00% covered (danger)
0.00%
0 / 1
12
 bbcode_list
0.00% covered (danger)
0.00%
0 / 24
0.00% covered (danger)
0.00%
0 / 1
72
 bbcode_second_pass_quote
0.00% covered (danger)
0.00%
0 / 6
0.00% covered (danger)
0.00%
0 / 1
12
 bbcode_second_pass_code
0.00% covered (danger)
0.00%
0 / 15
0.00% covered (danger)
0.00%
0 / 1
72
1<?php
2/**
3*
4* This file is part of the phpBB Forum Software package.
5*
6* @copyright (c) phpBB Limited <https://www.phpbb.com>
7* @license GNU General Public License, version 2 (GPL-2.0)
8*
9* For full copyright and license information, please see
10* the docs/CREDITS.txt file.
11*
12*/
13
14/**
15* @ignore
16*/
17if (!defined('IN_PHPBB'))
18{
19    exit;
20}
21
22/**
23* BBCode class
24*/
25class bbcode
26{
27    var $bbcode_uid = '';
28    var $bbcode_bitfield = '';
29    var $bbcode_cache = array();
30    var $bbcode_template = array();
31
32    var $bbcodes = array();
33
34    var $template_bitfield;
35
36    protected $template_filename;
37
38    /**
39    * Constructor
40    */
41    function __construct($bitfield = '')
42    {
43        $this->bbcode_set_bitfield($bitfield);
44    }
45
46    /**
47    * Init bbcode cache entries if bitfield is specified
48    *
49    * @param    string    $bitfield    The bbcode bitfield
50    */
51    function bbcode_set_bitfield($bitfield = '')
52    {
53        if ($bitfield)
54        {
55            $this->bbcode_bitfield = $bitfield;
56            $this->bbcode_cache_init();
57        }
58    }
59
60    /**
61    * Second pass bbcodes
62    */
63    function bbcode_second_pass(&$message, $bbcode_uid = '', $bbcode_bitfield = false)
64    {
65        if ($bbcode_uid)
66        {
67            $this->bbcode_uid = $bbcode_uid;
68        }
69
70        if ($bbcode_bitfield !== false)
71        {
72            $this->bbcode_bitfield = $bbcode_bitfield;
73
74            // Init those added with a new bbcode_bitfield (already stored codes will not get parsed again)
75            $this->bbcode_cache_init();
76        }
77
78        if (!$this->bbcode_bitfield)
79        {
80            // Remove the uid from tags that have not been transformed into HTML
81            if ($this->bbcode_uid)
82            {
83                $message = str_replace(':' . $this->bbcode_uid, '', $message);
84            }
85
86            return;
87        }
88
89        $str = array('search' => array(), 'replace' => array());
90        $preg = array('search' => array(), 'replace' => array());
91
92        $bitfield = new bitfield($this->bbcode_bitfield);
93        $bbcodes_set = $bitfield->get_all_set();
94
95        $undid_bbcode_specialchars = false;
96        foreach ($bbcodes_set as $bbcode_id)
97        {
98            if (!empty($this->bbcode_cache[$bbcode_id]))
99            {
100                foreach ($this->bbcode_cache[$bbcode_id] as $type => $array)
101                {
102                    foreach ($array as $search => $replace)
103                    {
104                        ${$type}['search'][] = str_replace('$uid', $this->bbcode_uid, $search);
105                        ${$type}['replace'][] = $replace;
106                    }
107
108                    if (count($str['search']))
109                    {
110                        $message = str_replace($str['search'], $str['replace'], $message);
111                        $str = array('search' => array(), 'replace' => array());
112                    }
113
114                    if (count($preg['search']))
115                    {
116                        // we need to turn the entities back into their original form to allow the
117                        // search patterns to work properly
118                        if (!$undid_bbcode_specialchars)
119                        {
120                            $message = str_replace(array('&#58;', '&#46;'), array(':', '.'), $message);
121                            $undid_bbcode_specialchars = true;
122                        }
123
124                        foreach ($preg['search'] as $key => $search)
125                        {
126                            if (is_callable($preg['replace'][$key]))
127                            {
128                                $message = preg_replace_callback($search, $preg['replace'][$key], $message);
129                            }
130                            else
131                            {
132                                $message = preg_replace($search, $preg['replace'][$key], $message);
133                            }
134                        }
135
136                        $preg = array('search' => array(), 'replace' => array());
137                    }
138                }
139            }
140        }
141
142        // Remove the uid from tags that have not been transformed into HTML
143        $message = str_replace(':' . $this->bbcode_uid, '', $message);
144    }
145
146    /**
147    * Init bbcode cache
148    *
149    * requires: $this->bbcode_bitfield
150    * sets: $this->bbcode_cache with bbcode templates needed for bbcode_bitfield
151    */
152    function bbcode_cache_init()
153    {
154        global $user, $phpbb_dispatcher, $phpbb_extension_manager, $phpbb_container;
155
156        if (empty($this->template_filename))
157        {
158            $this->template_bitfield = new bitfield($user->style['bbcode_bitfield']);
159
160            $template = new \phpbb\template\twig\twig(
161                $phpbb_container->get('path_helper'),
162                $phpbb_container->get('config'),
163                new \phpbb\template\context(),
164                new \phpbb\template\twig\environment(
165                    $phpbb_container->get('assets.bag'),
166                    $phpbb_container->get('config'),
167                    $phpbb_container->get('filesystem'),
168                    $phpbb_container->get('path_helper'),
169                    $phpbb_container->getParameter('core.cache_dir'),
170                    $phpbb_container->get('ext.manager'),
171                    new \phpbb\template\twig\loader()
172                ),
173                $phpbb_container->getParameter('core.cache_dir'),
174                $phpbb_container->get('user'),
175                $phpbb_container->get('template.twig.extensions.collection'),
176                $phpbb_extension_manager
177            );
178
179            $template->set_style();
180            $template->set_filenames(array('bbcode.html' => 'bbcode.html'));
181            $this->template_filename = $template->get_source_file_for_handle('bbcode.html');
182        }
183
184        $bbcode_ids = $rowset = $sql = array();
185
186        $bitfield = new bitfield($this->bbcode_bitfield);
187        $bbcodes_set = $bitfield->get_all_set();
188
189        foreach ($bbcodes_set as $bbcode_id)
190        {
191            if (isset($this->bbcode_cache[$bbcode_id]))
192            {
193                // do not try to re-cache it if it's already in
194                continue;
195            }
196            $bbcode_ids[] = $bbcode_id;
197
198            if ($bbcode_id > NUM_CORE_BBCODES)
199            {
200                $sql[] = $bbcode_id;
201            }
202        }
203
204        if (count($sql))
205        {
206            global $db;
207
208            $sql = 'SELECT *
209                FROM ' . BBCODES_TABLE . '
210                WHERE ' . $db->sql_in_set('bbcode_id', $sql);
211            $result = $db->sql_query($sql, 3600);
212
213            while ($row = $db->sql_fetchrow($result))
214            {
215                // To circumvent replacing newlines with <br /> for the generated html,
216                // we use carriage returns here. They are later changed back to newlines
217                $row['bbcode_tpl'] = str_replace("\n", "\r", $row['bbcode_tpl']);
218                $row['second_pass_replace'] = str_replace("\n", "\r", $row['second_pass_replace']);
219
220                $rowset[$row['bbcode_id']] = $row;
221            }
222            $db->sql_freeresult($result);
223        }
224
225        foreach ($bbcode_ids as $bbcode_id)
226        {
227            switch ($bbcode_id)
228            {
229                case BBCODE_ID_QUOTE:
230                    $this->bbcode_cache[$bbcode_id] = array(
231                        'str' => array(
232                            '[/quote:$uid]'    => $this->bbcode_tpl('quote_close', $bbcode_id)
233                        ),
234                        'preg' => array(
235                            '#\[quote(?:=&quot;(.*?)&quot;)?:$uid\]((?!\[quote(?:=&quot;.*?&quot;)?:$uid\]).)?#is'    => function ($match) {
236                                if (!isset($match[2]))
237                                {
238                                    $match[2] = '';
239                                }
240
241                                return $this->bbcode_second_pass_quote($match[1], $match[2]);
242                            },
243                        )
244                    );
245                break;
246
247                case BBCODE_ID_B:
248                    $this->bbcode_cache[$bbcode_id] = array(
249                        'str' => array(
250                            '[b:$uid]'    => $this->bbcode_tpl('b_open', $bbcode_id),
251                            '[/b:$uid]'    => $this->bbcode_tpl('b_close', $bbcode_id),
252                        )
253                    );
254                break;
255
256                case BBCODE_ID_I:
257                    $this->bbcode_cache[$bbcode_id] = array(
258                        'str' => array(
259                            '[i:$uid]'    => $this->bbcode_tpl('i_open', $bbcode_id),
260                            '[/i:$uid]'    => $this->bbcode_tpl('i_close', $bbcode_id),
261                        )
262                    );
263                break;
264
265                case BBCODE_ID_URL:
266                    $this->bbcode_cache[$bbcode_id] = array(
267                        'preg' => array(
268                            '#\[url:$uid\]((.*?))\[/url:$uid\]#s'            => $this->bbcode_tpl('url', $bbcode_id),
269                            '#\[url=([^\[]+?):$uid\](.*?)\[/url:$uid\]#s'    => $this->bbcode_tpl('url', $bbcode_id),
270                        )
271                    );
272                break;
273
274                case BBCODE_ID_IMG:
275                    if ($user->optionget('viewimg'))
276                    {
277                        $this->bbcode_cache[$bbcode_id] = array(
278                            'preg' => array(
279                                '#\[img:$uid\](.*?)\[/img:$uid\]#s'        => $this->bbcode_tpl('img', $bbcode_id),
280                            )
281                        );
282                    }
283                    else
284                    {
285                        $this->bbcode_cache[$bbcode_id] = array(
286                            'preg' => array(
287                                '#\[img:$uid\](.*?)\[/img:$uid\]#s'        => str_replace('$2', '[ img ]', $this->bbcode_tpl('url', $bbcode_id, true)),
288                            )
289                        );
290                    }
291                break;
292
293                case BBCODE_ID_SIZE:
294                    $this->bbcode_cache[$bbcode_id] = array(
295                        'preg' => array(
296                            '#\[size=([\-\+]?\d+):$uid\](.*?)\[/size:$uid\]#s'    => $this->bbcode_tpl('size', $bbcode_id),
297                        )
298                    );
299                break;
300
301                case BBCODE_ID_COLOR:
302                    $this->bbcode_cache[$bbcode_id] = array(
303                        'preg' => array(
304                            '!\[color=(#[0-9a-f]{3}|#[0-9a-f]{6}|[a-z\-]+):$uid\](.*?)\[/color:$uid\]!is'    => $this->bbcode_tpl('color', $bbcode_id),
305                        )
306                    );
307                break;
308
309                case BBCODE_ID_U:
310                    $this->bbcode_cache[$bbcode_id] = array(
311                        'str' => array(
312                            '[u:$uid]'    => $this->bbcode_tpl('u_open', $bbcode_id),
313                            '[/u:$uid]'    => $this->bbcode_tpl('u_close', $bbcode_id),
314                        )
315                    );
316                break;
317
318                case BBCODE_ID_CODE:
319                    $this->bbcode_cache[$bbcode_id] = array(
320                        'preg' => array(
321                            '#\[code(?:=([a-z]+))?:$uid\](.*?)\[/code:$uid\]#is'    => function ($match) {
322                                return $this->bbcode_second_pass_code($match[1], $match[2]);
323                            },
324                        )
325                    );
326                break;
327
328                case BBCODE_ID_LIST:
329                    $this->bbcode_cache[$bbcode_id] = array(
330                        'preg' => array(
331                            '#(\[\/?(list|\*):[mou]?:?$uid\])[\n]{1}#'    => "\$1",
332                            '#(\[list=([^\[]+):$uid\])[\n]{1}#'            => "\$1",
333                            '#\[list=([^\[]+):$uid\]#'                    => function ($match) {
334                                return $this->bbcode_list($match[1]);
335                            },
336                        ),
337                        'str' => array(
338                            '[list:$uid]'        => $this->bbcode_tpl('ulist_open_default', $bbcode_id),
339                            '[/list:u:$uid]'    => $this->bbcode_tpl('ulist_close', $bbcode_id),
340                            '[/list:o:$uid]'    => $this->bbcode_tpl('olist_close', $bbcode_id),
341                            '[*:$uid]'            => $this->bbcode_tpl('listitem', $bbcode_id),
342                            '[/*:$uid]'            => $this->bbcode_tpl('listitem_close', $bbcode_id),
343                            '[/*:m:$uid]'        => $this->bbcode_tpl('listitem_close', $bbcode_id)
344                        ),
345                    );
346                break;
347
348                case BBCODE_ID_EMAIL:
349                    $this->bbcode_cache[$bbcode_id] = array(
350                        'preg' => array(
351                            '#\[email:$uid\]((.*?))\[/email:$uid\]#is'            => $this->bbcode_tpl('email', $bbcode_id),
352                            '#\[email=([^\[]+):$uid\](.*?)\[/email:$uid\]#is'    => $this->bbcode_tpl('email', $bbcode_id)
353                        )
354                    );
355                break;
356
357                case BBCODE_ID_ATTACH:
358                    $this->bbcode_cache[$bbcode_id] = array(
359                        'str'    => array(
360                            '[/attachment:$uid]'    => $this->bbcode_tpl('inline_attachment_close', $bbcode_id)
361                        ),
362                        'preg'    => array(
363                            '#\[attachment=([0-9]+):$uid\]#'    => $this->bbcode_tpl('inline_attachment_open', $bbcode_id)
364                        )
365                    );
366                break;
367
368                default:
369                    if (isset($rowset[$bbcode_id]))
370                    {
371                        if ($this->template_bitfield->get($bbcode_id))
372                        {
373                            // The bbcode requires a custom template to be loaded
374                            if (!$bbcode_tpl = $this->bbcode_tpl($rowset[$bbcode_id]['bbcode_tag'], $bbcode_id))
375                            {
376                                // For some reason, the required template seems not to be available, use the default template
377                                $bbcode_tpl = (!empty($rowset[$bbcode_id]['second_pass_replace'])) ? $rowset[$bbcode_id]['second_pass_replace'] : $rowset[$bbcode_id]['bbcode_tpl'];
378                            }
379                            else
380                            {
381                                // In order to use templates with custom bbcodes we need
382                                // to replace all {VARS} to corresponding backreferences
383                                // Note that backreferences are numbered from bbcode_match
384                                if (preg_match_all('/\{(URL|LOCAL_URL|EMAIL|TEXT|SIMPLETEXT|INTTEXT|IDENTIFIER|COLOR|NUMBER)[0-9]*\}/', $rowset[$bbcode_id]['bbcode_match'], $m))
385                                {
386                                    foreach ($m[0] as $i => $tok)
387                                    {
388                                        $bbcode_tpl = str_replace($tok, '$' . ($i + 1), $bbcode_tpl);
389                                    }
390                                }
391                            }
392                        }
393                        else
394                        {
395                            // Default template
396                            $bbcode_tpl = (!empty($rowset[$bbcode_id]['second_pass_replace'])) ? $rowset[$bbcode_id]['second_pass_replace'] : $rowset[$bbcode_id]['bbcode_tpl'];
397                        }
398
399                        // Replace {L_*} lang strings
400                        $bbcode_tpl = preg_replace_callback('/{L_([A-Z0-9_]+)}/', function ($match) use ($user) {
401                            return (!empty($user->lang[$match[1]])) ? $user->lang($match[1]) : ucwords(strtolower(str_replace('_', ' ', $match[1])));
402                        }, $bbcode_tpl);
403
404                        if (!empty($rowset[$bbcode_id]['second_pass_replace']))
405                        {
406                            // The custom BBCode requires second-pass pattern replacements
407                            $this->bbcode_cache[$bbcode_id] = array(
408                                'preg' => array($rowset[$bbcode_id]['second_pass_match'] => $bbcode_tpl)
409                            );
410                        }
411                        else
412                        {
413                            $this->bbcode_cache[$bbcode_id] = array(
414                                'str' => array($rowset[$bbcode_id]['second_pass_match'] => $bbcode_tpl)
415                            );
416                        }
417                    }
418                    else
419                    {
420                        $this->bbcode_cache[$bbcode_id] = false;
421                    }
422                break;
423            }
424        }
425
426        $bbcode_cache = $this->bbcode_cache;
427        $bbcode_bitfield = $this->bbcode_bitfield;
428        $bbcode_uid = $this->bbcode_uid;
429
430        /**
431        * Use this event to modify the bbcode_cache
432        *
433        * @event core.bbcode_cache_init_end
434        * @var    array    bbcode_cache        The array of cached search and replace patterns of bbcodes
435        * @var    string    bbcode_bitfield        The bbcode bitfield
436        * @var    string    bbcode_uid            The bbcode uid
437        * @since 3.1.3-RC1
438        */
439        $vars = array('bbcode_cache', 'bbcode_bitfield', 'bbcode_uid');
440        extract($phpbb_dispatcher->trigger_event('core.bbcode_cache_init_end', compact($vars)));
441
442        $this->bbcode_cache = $bbcode_cache;
443        $this->bbcode_bitfield = $bbcode_bitfield;
444        $this->bbcode_uid = $bbcode_uid;
445    }
446
447    /**
448    * Return bbcode template
449    */
450    function bbcode_tpl($tpl_name, $bbcode_id = -1, $skip_bitfield_check = false)
451    {
452        static $bbcode_hardtpl = array();
453        if (empty($bbcode_hardtpl))
454        {
455            global $user;
456
457            $bbcode_hardtpl = array(
458                'b_open'    => '<span style="font-weight: bold">',
459                'b_close'    => '</span>',
460                'i_open'    => '<span style="font-style: italic">',
461                'i_close'    => '</span>',
462                'u_open'    => '<span style="text-decoration: underline">',
463                'u_close'    => '</span>',
464                'img'        => '<img src="$1" class="postimage" alt="' . $user->lang['IMAGE'] . '" />',
465                'size'        => '<span style="font-size: $1%; line-height: normal">$2</span>',
466                'color'        => '<span style="color: $1">$2</span>',
467                'email'        => '<a href="mailto:$1">$2</a>'
468            );
469        }
470
471        if ($bbcode_id != -1 && !$skip_bitfield_check && !$this->template_bitfield->get($bbcode_id))
472        {
473            return (isset($bbcode_hardtpl[$tpl_name])) ? $bbcode_hardtpl[$tpl_name] : false;
474        }
475
476        if (empty($this->bbcode_template))
477        {
478            if (($tpl = file_get_contents($this->template_filename)) === false)
479            {
480                trigger_error('Could not load bbcode template', E_USER_ERROR);
481            }
482
483            // replace \ with \\ and then ' with \'.
484            $tpl = str_replace('\\', '\\\\', $tpl);
485            $tpl = str_replace("'", "\'", $tpl);
486
487            // strip newlines and indent
488            $tpl = preg_replace("/\n[\n\r\s\t]*/", '', $tpl);
489
490            // Turn template blocks into PHP assignment statements for the values of $bbcode_tpl..
491            $this->bbcode_template = array();
492
493            // Capture the BBCode template matches
494            // Allow phpBB template or the Twig syntax
495            $matches = (preg_match_all('#<!-- BEGIN (.*?) -->(.*?)<!-- END (?:.*?) -->#', $tpl, $match)) ?:
496                            preg_match_all('#{% for (.*?) in .*? %}(.*?){% endfor %}#s', $tpl, $match);
497
498            for ($i = 0; $i < $matches; $i++)
499            {
500                if (empty($match[1][$i]))
501                {
502                    continue;
503                }
504
505                $this->bbcode_template[$match[1][$i]] = $this->bbcode_tpl_replace($match[1][$i], $match[2][$i]);
506            }
507        }
508
509        return (isset($this->bbcode_template[$tpl_name])) ? $this->bbcode_template[$tpl_name] : ((isset($bbcode_hardtpl[$tpl_name])) ? $bbcode_hardtpl[$tpl_name] : false);
510    }
511
512    /**
513    * Return bbcode template replacement
514    */
515    function bbcode_tpl_replace($tpl_name, $tpl)
516    {
517        global $user;
518
519        static $replacements = array(
520            'quote_username_open'    => array('{USERNAME}'    => '$1'),
521            'color'                    => array('{COLOR}'        => '$1', '{TEXT}'            => '$2'),
522            'size'                    => array('{SIZE}'        => '$1', '{TEXT}'            => '$2'),
523            'img'                    => array('{URL}'        => '$1'),
524            'url'                    => array('{URL}'        => '$1', '{DESCRIPTION}'    => '$2'),
525            'email'                    => array('{EMAIL}'        => '$1', '{DESCRIPTION}'    => '$2')
526        );
527
528        $tpl = preg_replace_callback('/{L_([A-Z0-9_]+)}/', function ($match) use ($user) {
529            return (!empty($user->lang[$match[1]])) ? $user->lang($match[1]) : ucwords(strtolower(str_replace('_', ' ', $match[1])));
530        }, $tpl);
531
532        if (!empty($replacements[$tpl_name]))
533        {
534            $tpl = strtr($tpl, $replacements[$tpl_name]);
535        }
536
537        return trim($tpl);
538    }
539
540    /**
541    * Second parse list bbcode
542    */
543    function bbcode_list($type)
544    {
545        if ($type == '')
546        {
547            $tpl = 'ulist_open_default';
548            $type = 'default';
549        }
550        else if ($type == 'i')
551        {
552            $tpl = 'olist_open';
553            $type = 'lower-roman';
554        }
555        else if ($type == 'I')
556        {
557            $tpl = 'olist_open';
558            $type = 'upper-roman';
559        }
560        else if (preg_match('#^(disc|circle|square)$#i', $type))
561        {
562            $tpl = 'ulist_open';
563            $type = strtolower($type);
564        }
565        else if (preg_match('#^[a-z]$#', $type))
566        {
567            $tpl = 'olist_open';
568            $type = 'lower-alpha';
569        }
570        else if (preg_match('#[A-Z]#', $type))
571        {
572            $tpl = 'olist_open';
573            $type = 'upper-alpha';
574        }
575        else if (is_numeric($type))
576        {
577            $tpl = 'olist_open';
578            $type = 'decimal';
579        }
580        else
581        {
582            $tpl = 'olist_open';
583            $type = 'decimal';
584        }
585
586        return str_replace('{LIST_TYPE}', $type, $this->bbcode_tpl($tpl));
587    }
588
589    /**
590    * Second parse quote tag
591    */
592    function bbcode_second_pass_quote($username, $quote)
593    {
594        // when using the /e modifier, preg_replace slashes double-quotes but does not
595        // seem to slash anything else
596        $quote = str_replace('\"', '"', $quote);
597        $username = str_replace('\"', '"', $username);
598
599        // remove newline at the beginning
600        if ($quote == "\n")
601        {
602            $quote = '';
603        }
604
605        $quote = (($username) ? str_replace('$1', $username, $this->bbcode_tpl('quote_username_open')) : $this->bbcode_tpl('quote_open')) . $quote;
606
607        return $quote;
608    }
609
610    /**
611    * Second parse code tag
612    */
613    function bbcode_second_pass_code($type, $code)
614    {
615        // when using the /e modifier, preg_replace slashes double-quotes but does not
616        // seem to slash anything else
617        $code = str_replace('\"', '"', $code);
618
619        switch ($type)
620        {
621            case 'php':
622                // Not the english way, but valid because of hardcoded syntax highlighting
623                if (strpos($code, '<span class="syntaxdefault"><br /></span>') === 0)
624                {
625                    $code = substr($code, 41);
626                }
627
628            // no break;
629
630            default:
631                $code = str_replace("\t", '&nbsp; &nbsp;', $code);
632                $code = str_replace('  ', '&nbsp; ', $code);
633                $code = str_replace('  ', ' &nbsp;', $code);
634                $code = str_replace("\n ", "\n&nbsp;", $code);
635
636                // keep space at the beginning
637                if (!empty($code) && $code[0] == ' ')
638                {
639                    $code = '&nbsp;' . substr($code, 1);
640                }
641
642                // remove newline at the beginning
643                if (!empty($code) && $code[0] == "\n")
644                {
645                    $code = substr($code, 1);
646                }
647            break;
648        }
649
650        $code = $this->bbcode_tpl('code_open') . $code . $this->bbcode_tpl('code_close');
651
652        return $code;
653    }
654}