[ Index ]

PHP Cross Reference of Unnamed Project

title

Body

[close]

/includes/ -> bbcode.php (source)

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


Generated: Wed Oct 2 15:03:47 2013 Cross-referenced by PHPXref 0.7.1