[ Index ]

PHP Cross Reference of phpBB 3.0 Beta 3

title

Body

[close]

/includes/ -> bbcode.php (source)

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


Generated: Wed Nov 22 00:35:05 2006 Cross-referenced by PHPXref 0.6