[ Index ]

PHP Cross Reference of phpBB 3.0 Beta 3

title

Body

[close]

/includes/ -> message_parser.php (source)

   1  <?php
   2  /** 
   3  *
   4  * @package phpBB3
   5  * @version $Id: message_parser.php,v 1.157 2006/11/12 14:29:31 naderman Exp $
   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  if (!class_exists('bbcode'))
  20  {
  21      include($phpbb_root_path . 'includes/bbcode.' . $phpEx);
  22  }
  23  
  24  /**
  25  * BBCODE FIRSTPASS
  26  * BBCODE first pass class (functions for parsing messages for db storage)
  27  * @package phpBB3
  28  */
  29  class bbcode_firstpass extends bbcode
  30  {
  31      var $message = '';
  32      var $warn_msg = array();
  33      var $parsed_items = array();
  34  
  35      /**
  36      * Parse BBCode
  37      */
  38  	function parse_bbcode()
  39      {
  40          if (!$this->bbcodes)
  41          {
  42              $this->bbcode_init();
  43          }
  44  
  45          global $user;
  46  
  47          $this->bbcode_bitfield = '';
  48          $bitfield = new bitfield();
  49  
  50          foreach ($this->bbcodes as $bbcode_name => $bbcode_data)
  51          {
  52              if (isset($bbcode_data['disabled']) && $bbcode_data['disabled'])
  53              {
  54                  foreach ($bbcode_data['regexp'] as $regexp => $replacement)
  55                  {
  56                      if (preg_match($regexp, $this->message))
  57                      {
  58                          $this->warn_msg[] = $user->lang['UNAUTHORISED_BBCODE'] . '[' . $bbcode_name . ']';
  59                          continue;
  60                      }
  61                  }
  62              }
  63              else
  64              {
  65                  foreach ($bbcode_data['regexp'] as $regexp => $replacement)
  66                  {
  67                      // The pattern gets compiled and cached by the PCRE extension,
  68                      // it should not demand recompilation
  69                      if (preg_match($regexp, $this->message))
  70                      {
  71                          $this->message = preg_replace($regexp, $replacement, $this->message);
  72                          $bitfield->set($bbcode_data['bbcode_id']);
  73                      }
  74                  }
  75              }
  76          }
  77  
  78          $this->bbcode_bitfield = $bitfield->get_base64();
  79      }
  80  
  81      /**
  82      * Prepare some bbcodes for better parsing
  83      */
  84  	function prepare_bbcodes()
  85      {
  86          // Add newline at the end and in front of each quote block to prevent parsing errors (urls, smilies, etc.)
  87          if (strpos($this->message, '[quote') !== false)
  88          {
  89              $in = str_replace("\r\n", "\n", $this->message);
  90  
  91              $this->message = preg_replace(array('#\[quote(=&quot;.*?&quot;)?\]([^\n])#is', '#([^\n])\[\/quote\]#is'), array("[quote\\1]\n\\2", "\\1\n[/quote]"), $this->message);
  92              $this->message = preg_replace(array('#\[quote(=&quot;.*?&quot;)?\]([^\n])#is', '#([^\n])\[\/quote\]#is'), array("[quote\\1]\n\\2", "\\1\n[/quote]"), $this->message);
  93          }
  94  
  95          // Add other checks which needs to be placed before actually parsing anything (be it bbcodes, smilies, urls...)
  96      }
  97  
  98      /**
  99      * Init bbcode data for later parsing
 100      */
 101  	function bbcode_init()
 102      {
 103          static $rowset;
 104  
 105          // This array holds all bbcode data. BBCodes will be processed in this
 106          // order, so it is important to keep [code] in first position and
 107          // [quote] in second position.
 108          $this->bbcodes = array(
 109              'code'            => array('bbcode_id' => 8,    'regexp' => array('#\[code(?:=([a-z]+))?\](.+\[/code\])#ise' => "\$this->bbcode_code('\$1', '\$2')")),
 110              'quote'            => array('bbcode_id' => 0,    'regexp' => array('#\[quote(?:=&quot;(.*?)&quot;)?\](.+)\[/quote\]#ise' => "\$this->bbcode_quote('\$0')")),
 111              'attachment'    => array('bbcode_id' => 12,    'regexp' => array('#\[attachment=([0-9]+)\](.*?)\[/attachment\]#ise' => "\$this->bbcode_attachment('\$1', '\$2')")),
 112              'b'                => array('bbcode_id' => 1,    'regexp' => array('#\[b\](.*?)\[/b\]#ise' => "\$this->bbcode_strong('\$1')")),
 113              'i'                => array('bbcode_id' => 2,    'regexp' => array('#\[i\](.*?)\[/i\]#ise' => "\$this->bbcode_italic('\$1')")),
 114              'url'            => array('bbcode_id' => 3,    'regexp' => array('#\[url(=(.*))?\](.*)\[/url\]#iUe' => "\$this->validate_url('\$2', '\$3')")),
 115              'img'            => array('bbcode_id' => 4,    'regexp' => array('#\[img\](https?://)([a-z0-9\-\.,\?!%\*_:;~\\&$@/=\+]+)\[/img\]#ie' => "\$this->bbcode_img('\$1\$2')")),
 116              'size'            => array('bbcode_id' => 5,    'regexp' => array('#\[size=([\-\+]?[1-2]?[0-9])\](.*?)\[/size\]#ise' => "\$this->bbcode_size('\$1', '\$2')")),
 117              'color'            => array('bbcode_id' => 6,    'regexp' => array('!\[color=(#[0-9A-Fa-f]{6}|[a-z\-]+)\](.*?)\[/color\]!ise' => "\$this->bbcode_color('\$1', '\$2')")),
 118              'u'                => array('bbcode_id' => 7,    'regexp' => array('#\[u\](.*?)\[/u\]#ise' => "\$this->bbcode_underline('\$1')")),
 119              'list'            => array('bbcode_id' => 9,    'regexp' => array('#\[list(=[a-z|0-9|(?:disc|circle|square))]+)?\].*\[/list\]#ise' => "\$this->bbcode_parse_list('\$0')")),
 120              'email'            => array('bbcode_id' => 10,    'regexp' => array('#\[email=?(.*?)?\](.*?)\[/email\]#ise' => "\$this->validate_email('\$1', '\$2')")),
 121              'flash'            => array('bbcode_id' => 11,    'regexp' => array('#\[flash=([0-9]+),([0-9]+)\](.*?)\[/flash\]#ie' => "\$this->bbcode_flash('\$1', '\$2', '\$3')"))
 122          );
 123  
 124          // Zero the parsed items array
 125          $this->parsed_items = array();
 126  
 127          foreach ($this->bbcodes as $tag => $bbcode_data)
 128          {
 129              $this->parsed_items[$tag] = 0;
 130          }
 131  
 132          if (!is_array($rowset))
 133          {
 134              global $db;
 135              $rowset = array();
 136  
 137              $sql = 'SELECT *
 138                  FROM ' . BBCODES_TABLE;
 139              $result = $db->sql_query($sql);
 140  
 141              while ($row = $db->sql_fetchrow($result))
 142              {
 143                  $rowset[] = $row;
 144              }
 145              $db->sql_freeresult($result);
 146          }
 147  
 148          foreach ($rowset as $row)
 149          {
 150              $this->bbcodes[$row['bbcode_tag']] = array(
 151                  'bbcode_id'    => (int) $row['bbcode_id'],
 152                  'regexp'    => array($row['first_pass_match'] => str_replace('$uid', $this->bbcode_uid, $row['first_pass_replace']))
 153              );
 154          }
 155      }
 156  
 157      /**
 158      * Making some pre-checks for bbcodes as well as increasing the number of parsed items
 159      */
 160  	function check_bbcode($bbcode, &$in)
 161      {
 162          // when using the /e modifier, preg_replace slashes double-quotes but does not
 163          // seem to slash anything else
 164          $in = str_replace("\r\n", "\n", str_replace('\"', '"', $in));
 165  
 166          // Trimming here to make sure no empty bbcodes are parsed accidently
 167          if (trim($in) == '')
 168          {
 169              return false;
 170          }
 171  
 172          $this->parsed_items[$bbcode]++;
 173  
 174          return true;
 175      }
 176  
 177      /**
 178      * Transform some characters in valid bbcodes
 179      */
 180  	function bbcode_specialchars($text)
 181      {
 182          $str_from = array('<', '>', '[', ']', '.', ':');
 183          $str_to = array('&lt;', '&gt;', '&#91;', '&#93;', '&#46;', '&#58;');
 184  
 185          return str_replace($str_from, $str_to, $text);
 186      }
 187  
 188      /**
 189      * Parse size tag
 190      */
 191  	function bbcode_size($stx, $in)
 192      {
 193          global $user, $config;
 194  
 195          if (!$this->check_bbcode('size', $in))
 196          {
 197              return '';
 198          }
 199  
 200          if ($config['max_' . $this->mode . '_font_size'] && $config['max_' . $this->mode . '_font_size'] < $stx)
 201          {
 202              $this->warn_msg[] = sprintf($user->lang['MAX_FONT_SIZE_EXCEEDED'], $config['max_' . $this->mode . '_font_size']);
 203          }
 204  
 205          return '[size=' . $stx . ':' . $this->bbcode_uid . ']' . $in . '[/size:' . $this->bbcode_uid . ']';
 206      }
 207  
 208      /**
 209      * Parse color tag
 210      */
 211  	function bbcode_color($stx, $in)
 212      {
 213          if (!$this->check_bbcode('color', $in))
 214          {
 215              return '';
 216          }
 217  
 218          return '[color=' . $stx . ':' . $this->bbcode_uid . ']' . $in . '[/color:' . $this->bbcode_uid . ']';
 219      }
 220  
 221      /**
 222      * Parse u tag
 223      */
 224  	function bbcode_underline($in)
 225      {
 226          if (!$this->check_bbcode('u', $in))
 227          {
 228              return '';
 229          }
 230  
 231          return '[u:' . $this->bbcode_uid . ']' . $in . '[/u:' . $this->bbcode_uid . ']';
 232      }
 233  
 234      /**
 235      * Parse b tag
 236      */
 237  	function bbcode_strong($in)
 238      {
 239          if (!$this->check_bbcode('b', $in))
 240          {
 241              return '';
 242          }
 243  
 244          return '[b:' . $this->bbcode_uid . ']' . $in . '[/b:' . $this->bbcode_uid . ']';
 245      }
 246  
 247      /**
 248      * Parse i tag
 249      */
 250  	function bbcode_italic($in)
 251      {
 252          if (!$this->check_bbcode('i', $in))
 253          {
 254              return '';
 255          }
 256  
 257          return '[i:' . $this->bbcode_uid . ']' . $in . '[/i:' . $this->bbcode_uid . ']';
 258      }
 259  
 260      /**
 261      * Parse img tag
 262      */
 263  	function bbcode_img($in)
 264      {
 265          global $user, $config, $phpEx;
 266  
 267          if (!$this->check_bbcode('img', $in))
 268          {
 269              return '';
 270          }
 271  
 272          $in = trim($in);
 273  
 274          if ($config['max_' . $this->mode . '_img_height'] || $config['max_' . $this->mode . '_img_width'])
 275          {
 276              $stats = @getimagesize($in);
 277  
 278              if ($stats === false)
 279              {
 280                  $this->warn_msg[] = $user->lang['UNABLE_GET_IMAGE_SIZE'];
 281              }
 282              else
 283              {
 284                  if ($config['max_' . $this->mode . '_img_height'] && $config['max_' . $this->mode . '_img_height'] < $stats[1])
 285                  {
 286                      $this->warn_msg[] = sprintf($user->lang['MAX_IMG_HEIGHT_EXCEEDED'], $config['max_' . $this->mode . '_img_height']);
 287                  }
 288  
 289                  if ($config['max_' . $this->mode . '_img_width'] && $config['max_' . $this->mode . '_img_width'] < $stats[0])
 290                  {
 291                      $this->warn_msg[] = sprintf($user->lang['MAX_IMG_WIDTH_EXCEEDED'], $config['max_' . $this->mode . '_img_width']);
 292                  }
 293              }
 294          }
 295  
 296          if ($this->path_in_domain($in))
 297          {
 298              return '[img]' . $in . '[/img]';
 299          }
 300  
 301          return '[img:' . $this->bbcode_uid . ']' . $this->bbcode_specialchars($in) . '[/img:' . $this->bbcode_uid . ']';
 302      }
 303  
 304      /**
 305      * Parse flash tag
 306      */
 307  	function bbcode_flash($width, $height, $in)
 308      {
 309          global $user, $config, $phpEx;
 310  
 311          if (!$this->check_bbcode('flash', $in))
 312          {
 313              return '';
 314          }
 315  
 316          $in = trim($in);
 317  
 318          // Apply the same size checks on flash files as on images
 319          if ($config['max_' . $this->mode . '_img_height'] || $config['max_' . $this->mode . '_img_width'])
 320          {
 321              if ($config['max_' . $this->mode . '_img_height'] && $config['max_' . $this->mode . '_img_height'] < $height)
 322              {
 323                  $this->warn_msg[] = sprintf($user->lang['MAX_FLASH_HEIGHT_EXCEEDED'], $config['max_' . $this->mode . '_img_height']);
 324              }
 325  
 326              if ($config['max_' . $this->mode . '_img_width'] && $config['max_' . $this->mode . '_img_width'] < $width)
 327              {
 328                  $this->warn_msg[] = sprintf($user->lang['MAX_FLASH_WIDTH_EXCEEDED'], $config['max_' . $this->mode . '_img_width']);
 329              }
 330          }
 331  
 332          if ($this->path_in_domain($in))
 333          {
 334              return '[flash=' . $width . ',' . $height . ']' . $in . '[/flash]';
 335          }
 336  
 337          return '[flash=' . $width . ',' . $height . ':' . $this->bbcode_uid . ']' . $this->bbcode_specialchars($in) . '[/flash:' . $this->bbcode_uid . ']';
 338      }
 339  
 340      /**
 341      * Parse inline attachments [ia]
 342      */
 343  	function bbcode_attachment($stx, $in)
 344      {
 345          if (!$this->check_bbcode('attachment', $in))
 346          {
 347              return '';
 348          }
 349  
 350          return '[attachment=' . $stx . ':' . $this->bbcode_uid . ']<!-- ia' . $stx . ' -->' . trim($in) . '<!-- ia' . $stx . ' -->[/attachment:' . $this->bbcode_uid . ']';
 351      }
 352  
 353      /**
 354      * Parse code tag
 355      * Expects the argument to start right after the opening [code] tag and to end with [/code]
 356      */
 357  	function bbcode_code($stx, $in)
 358      {
 359          if (!$this->check_bbcode('code', $in))
 360          {
 361              return '';
 362          }
 363  
 364          // We remove the hardcoded elements from the code block here because it is not used in code blocks
 365          // Having it here saves us one preg_replace per message containing [code] blocks
 366          // Additionally, magic url parsing should go after parsing bbcodes, but for safety those are stripped out too...
 367          $htm_match = get_preg_expression('bbcode_htm');
 368  //        $htm_match[3] = '/&#([0-9]+);/';
 369          unset($htm_match[3], $htm_match[4]);
 370  
 371          $htm_replace = array('\1', '\2', '\1'); //, '&amp;#\1;');
 372  
 373          $out = '';
 374  
 375          do
 376          {
 377              $pos = stripos($in, '[/code]') + 7;
 378              $code = substr($in, 0, $pos);
 379              $in = substr($in, $pos);
 380              
 381              // $code contains everything that was between code tags (including the ending tag) but we're trying to grab as much extra text as possible, as long as it does not contain open [code] tags
 382              while ($in)
 383              {
 384                  $pos = stripos($in, '[/code]') + 7;
 385                  $buffer = substr($in, 0, $pos);
 386  
 387                  if (preg_match('#\[code(?:=([a-z]+))?\]#i', $buffer))
 388                  {
 389                      break;
 390                  }
 391                  else
 392                  {
 393                      $in = substr($in, $pos);
 394                      $code .= $buffer;
 395                  }
 396              }
 397  
 398              $code = substr($code, 0, -7);
 399  //            $code = preg_replace('#^[\r\n]*(.*?)[\n\r\s\t]*$#s', '$1', $code);
 400              $code = preg_replace($htm_match, $htm_replace, $code);
 401  
 402              switch (strtolower($stx))
 403              {
 404                  case 'php':
 405  
 406                      $remove_tags = false;
 407                      $code = str_replace(array('&lt;', '&gt;'), array('<', '>'), $code);
 408  
 409                      if (!preg_match('/\<\?.*?\?\>/is', $code))
 410                      {
 411                          $remove_tags = true;
 412                          $code = "<?php $code ?>";
 413                      }
 414  
 415                      $conf = array('highlight.bg', 'highlight.comment', 'highlight.default', 'highlight.html', 'highlight.keyword', 'highlight.string');
 416                      foreach ($conf as $ini_var)
 417                      {
 418                          ini_set($ini_var, str_replace('highlight.', 'syntax', $ini_var));
 419                      }
 420  
 421                      // Because highlight_string is specialcharing the text (but we already did this before), we have to reverse this in order to get correct results
 422                      $code = htmlspecialchars_decode($code);
 423                      $code = highlight_string($code, true);
 424  
 425                      $str_from = array('<span style="color: ', '<font color="syntax', '</font>', '<code>', '</code>','[', ']', '.', ':');
 426                      $str_to = array('<span class="', '<span class="syntax', '</span>', '', '', '&#91;', '&#93;', '&#46;', '&#58;');
 427  
 428                      if ($remove_tags)
 429                      {
 430                          $str_from[] = '<span class="syntaxdefault">&lt;?php </span>';
 431                          $str_to[] = '';
 432                          $str_from[] = '<span class="syntaxdefault">&lt;?php&nbsp;';
 433                          $str_to[] = '<span class="syntaxdefault">';
 434                      }
 435  
 436                      $code = str_replace($str_from, $str_to, $code);
 437                      $code = preg_replace('#^(<span class="[a-z_]+">)\n?(.*?)\n?(</span>)$#is', '$1$2$3', $code);
 438  
 439                      if ($remove_tags)
 440                      {
 441                          $code = preg_replace('#(<span class="[a-z]+">)?\?&gt;</span>#', '', $code);
 442                      }
 443  
 444                      $code = preg_replace('#^<span class="[a-z]+"><span class="([a-z]+)">(.*)</span></span>#s', '<span class="$1">$2</span>', $code);
 445                      $code = preg_replace('#(?:[\n\r\s\t]|&nbsp;)*</span>$#', '</span>', $code);
 446  
 447                      // remove newline at the end
 448                      if (!empty($code) && $code{strlen($code)-1} == "\n")
 449                      {
 450                          $code = substr($code, 0, -1);
 451                      }
 452  
 453                      $out .= "[code=$stx:" . $this->bbcode_uid . ']' . $code . '[/code:' . $this->bbcode_uid . ']';
 454                  break;
 455  
 456                  default:
 457                      $out .= '[code:' . $this->bbcode_uid . ']' . $this->bbcode_specialchars($code) . '[/code:' . $this->bbcode_uid . ']';
 458                  break;
 459              }
 460  
 461              if (preg_match('#(.*?)\[code(?:=([a-z]+))?\](.+)#is', $in, $m))
 462              {
 463                  $out .= $m[1];
 464                  $stx = $m[2];
 465                  $in = $m[3];
 466              }
 467          }
 468          while ($in);
 469  
 470          return $out;
 471      }
 472  
 473      /**
 474      * Parse list bbcode
 475      * Expects the argument to start with a tag
 476      */
 477  	function bbcode_parse_list($in)
 478      {
 479          if (!$this->check_bbcode('list', $in))
 480          {
 481              return '';
 482          }
 483  
 484          $out = '[';
 485  
 486          // Grab item_start with no item_end
 487          $in = preg_replace('#\[\*\](.*?)(\[\/list\]|\[list(=?(?:[0-9]|[a-z]|))\]|\[\*\])#is', '[*:' . $this->bbcode_uid . ']\1[/*:m:' . $this->bbcode_uid . ']\2', $in);
 488  
 489          // Grab them again as backreference
 490          $in = preg_replace('#\[\*\](.*?)(\[\/list\]|\[list(=?(?:[0-9]|[a-z]|))\]|\[\*\])(^\[\/*\])#is', '[*:' . $this->bbcode_uid . ']\1[/*:m:' . $this->bbcode_uid . ']\2', $in);
 491  
 492          // Grab end tag following start tag
 493          $in = preg_replace('#\[\/\*:m:' . $this->bbcode_uid . '\](\n|)\[\*\]#is', '[/*:m:' . $this->bbcode_uid . '][*:' . $this->bbcode_uid . ']', $in);
 494  
 495          // Replace end tag
 496          $in = preg_replace('#\[\/\*\]#i', '[/*:' . $this->bbcode_uid . ']', $in);
 497  
 498          // $tok holds characters to stop at. Since the string starts with a '[' we'll get everything up to the first ']' which should be the opening [list] tag
 499          $tok = ']';
 500          $out = '[';
 501  
 502          // First character is [
 503          $in = substr($in, 1);
 504          $list_end_tags = array();
 505  
 506          do
 507          {
 508              $pos = strlen($in);
 509  
 510              for ($i = 0, $tok_len = strlen($tok); $i < $tok_len; ++$i)
 511              {
 512                  $tmp_pos = strpos($in, $tok{$i});
 513  
 514                  if ($tmp_pos !== false && $tmp_pos < $pos)
 515                  {
 516                      $pos = $tmp_pos;
 517                  }
 518              }
 519  
 520              $buffer = substr($in, 0, $pos);
 521              $tok = $in{$pos};
 522  
 523              $in = substr($in, $pos + 1);
 524  
 525              if ($tok == ']')
 526              {
 527                  // if $tok is ']' the buffer holds a tag
 528                  if (strtolower($buffer) == '/list' && sizeof($list_end_tags))
 529                  {
 530                      $out .= array_pop($list_end_tags) . ']';
 531                      $tok = '[';
 532                  }
 533                  else if (preg_match('#list(=?(?:[0-9]|[a-z]|))#i', $buffer, $m))
 534                  {
 535                      // sub-list, add a closing tag
 536                      if (!$m[1] || preg_match('/^(disc|square|circle)$/i', $m[1]))
 537                      {
 538                          array_push($list_end_tags, '/list:u:' . $this->bbcode_uid);
 539                      }
 540                      else
 541                      {
 542                          array_push($list_end_tags, '/list:o:' . $this->bbcode_uid);
 543                      }
 544  
 545                      if (strtolower(substr($buffer, 0, 4)) == 'list')
 546                      {
 547                          $buffer = 'list' . substr($buffer, 4, $pos);
 548                      }
 549  
 550                      $out .= $buffer . ':' . $this->bbcode_uid . ']';
 551                      $tok = '[';
 552                  }
 553                  else
 554                  {
 555                      $out .= $buffer . $tok;
 556                      $tok = '[]';
 557                  }
 558              }
 559              else
 560              {
 561                  // Not within a tag, just add buffer to the return string
 562                  $out .= $buffer . $tok;
 563                  $tok = ($tok == '[') ? ']' : '[]';
 564              }
 565          }
 566          while ($in);
 567  
 568          if (sizeof($list_end_tags))
 569          {
 570              $out .= '[' . implode('][', $list_end_tags) . ']';
 571          }
 572  
 573          return $out;
 574      }
 575  
 576      /**
 577      * Parse quote bbcode
 578      * Expects the argument to start with a tag
 579      */
 580  	function bbcode_quote($in)
 581      {
 582          global $config, $user;
 583  
 584          $in = str_replace("\r\n", "\n", str_replace('\"', '"', trim($in)));
 585  
 586          if (!$in)
 587          {
 588              return '';
 589          }
 590  
 591          $tok = ']';
 592          $out = '[';
 593  
 594          $in = substr($in, 1);
 595          $close_tags = $error_ary = array();
 596          $buffer = '';
 597  
 598          do
 599          {
 600              $pos = strlen($in);
 601              for ($i = 0, $tok_len = strlen($tok); $i < $tok_len; ++$i)
 602              {
 603                  $tmp_pos = strpos($in, $tok{$i});
 604                  if ($tmp_pos !== false && $tmp_pos < $pos)
 605                  {
 606                      $pos = $tmp_pos;
 607                  }
 608              }
 609  
 610              $buffer .= substr($in, 0, $pos);
 611              $tok = $in{$pos};
 612              $in = substr($in, $pos + 1);
 613  
 614              if ($tok == ']')
 615              {
 616                  if ($buffer == '/quote' && sizeof($close_tags))
 617                  {
 618                      // we have found a closing tag
 619                      // Add space at the end of the closing tag to allow following urls/smilies to be parsed correctly
 620                      $out .= array_pop($close_tags) . '] ';
 621                      $tok = '[';
 622                      $buffer = '';
 623                  }
 624                  else if (preg_match('#^quote(?:=&quot;(.*?)&quot;)?$#is', $buffer, $m))
 625                  {
 626                      $this->parsed_items['quote']++;
 627  
 628                      // the buffer holds a valid opening tag
 629                      if ($config['max_quote_depth'] && sizeof($close_tags) >= $config['max_quote_depth'])
 630                      {
 631                          // there are too many nested quotes
 632                          $error_ary['quote_depth'] = sprintf($user->lang['QUOTE_DEPTH_EXCEEDED'], $config['max_quote_depth']);
 633  
 634                          $out .= $buffer . $tok;
 635                          $tok = '[]';
 636                          $buffer = '';
 637  
 638                          continue;
 639                      }
 640  
 641                      array_push($close_tags, '/quote:' . $this->bbcode_uid);
 642  
 643                      if (isset($m[1]) && $m[1])
 644                      {
 645                          $username = preg_replace('#\[(?!b|i|u|color|url|email|/b|/i|/u|/color|/url|/email)#iU', '&#91;$1', $m[1]);
 646                          $end_tags = array();
 647                          $error = false;
 648  
 649                          preg_match_all('#\[((?:/)?(?:[a-z]+))#i', $username, $tags);
 650                          foreach ($tags[1] as $tag)
 651                          {
 652                              if ($tag[0] != '/')
 653                              {
 654                                  $end_tags[] = '/' . $tag;
 655                              }
 656                              else
 657                              {
 658                                  $end_tag = array_pop($end_tags);
 659                                  if ($end_tag != $tag)
 660                                  {
 661                                      $error = true;
 662                                  }
 663                                  else
 664                                  {
 665                                      $error = false;
 666                                  }
 667                              }
 668                          }
 669  
 670                          if ($error)
 671                          {
 672                              $username = str_replace('[', '&#91;', str_replace(']', '&#93;', $m[1]));
 673                          }
 674  
 675                          $out .= 'quote=&quot;' . $username . '&quot;:' . $this->bbcode_uid . ']';
 676                      }
 677                      else
 678                      {
 679                          $out .= 'quote:' . $this->bbcode_uid . ']';
 680                      }
 681  
 682                      $tok = '[';
 683                      $buffer = '';
 684                  }
 685                  else if (preg_match('#^quote=&quot;(.*?)#is', $buffer, $m))
 686                  {
 687                      // the buffer holds an invalid opening tag
 688                      $buffer .= ']';
 689                  }
 690                  else
 691                  {
 692                      $out .= $buffer . $tok;
 693                      $tok = '[]';
 694                      $buffer = '';
 695                  }
 696              }
 697              else
 698              {
 699                  $out .= $buffer . $tok;
 700                  // $tok = ($tok == '[') ? ']' : '[]';
 701                  $tok = '[]';
 702                  $buffer = '';
 703              }
 704          }
 705          while ($in);
 706  
 707          if (sizeof($close_tags))
 708          {
 709              $out .= '[' . implode('][', $close_tags) . ']';
 710          }
 711  
 712          foreach ($error_ary as $error_msg)
 713          {
 714              $this->warn_msg[] = $error_msg;
 715          }
 716  
 717          return $out;
 718      }
 719  
 720      /**
 721      * Validate email
 722      */
 723  	function validate_email($var1, $var2)
 724      {
 725          $var1 = str_replace("\r\n", "\n", str_replace('\"', '"', trim($var1)));
 726          $var2 = str_replace("\r\n", "\n", str_replace('\"', '"', trim($var2)));
 727  
 728          $txt = $var2;
 729          $email = ($var1) ? $var1 : $var2;
 730  
 731          $validated = true;
 732  
 733          if (!preg_match('/^' . get_preg_expression('email') . '$/i', $email))
 734          {
 735              $validated = false;
 736          }
 737  
 738          if (!$validated)
 739          {
 740              return '[email' . (($var1) ? "=$var1" : '') . ']' . $var2 . '[/email]';
 741          }
 742  
 743          $this->parsed_items['email']++;
 744  
 745          if ($var1)
 746          {
 747              $retval = '[email=' . $this->bbcode_specialchars($email) . ':' . $this->bbcode_uid . ']' . $txt . '[/email:' . $this->bbcode_uid . ']';
 748          }
 749          else
 750          {
 751              $retval = '[email:' . $this->bbcode_uid . ']' . $this->bbcode_specialchars($email) . '[/email:' . $this->bbcode_uid . ']';
 752          }
 753  
 754          return $retval;
 755      }
 756  
 757      /**
 758      * Validate url
 759      */
 760  	function validate_url($var1, $var2)
 761      {
 762          global $config;
 763  
 764          $var1 = str_replace("\r\n", "\n", str_replace('\"', '"', trim($var1)));
 765          $var2 = str_replace("\r\n", "\n", str_replace('\"', '"', trim($var2)));
 766  
 767          $url = ($var1) ? $var1 : $var2;
 768          $valid = false;
 769  
 770          if (!$url || ($var1 && !$var2))
 771          {
 772              return '';
 773          }
 774  
 775          // Checking urls
 776          if (preg_match('#' . preg_quote(generate_board_url(), '#') . '/([^ \t\n\r<"\']+)#i', $url) ||
 777              preg_match('#([\w]+?://.*?[^ \t\n\r<"\']*)#i', $url) ||
 778              preg_match('#(www\.[\w\-]+\.[\w\-.\~]+(?:/[^ \t\n\r<"\']*)?)#i', $url))
 779          {
 780              $valid = true;
 781          }
 782  
 783          if ($valid)
 784          {
 785              $this->parsed_items['url']++;
 786  
 787              if (!preg_match('#^[\w]+?://.*?#i', $url))
 788              {
 789                  $url = 'http://' . $url;
 790              }
 791  
 792              // We take our test url and stick on the first bit of text we get to check if we are really at the domain. If so, lets go!
 793              if (strpos($url, generate_board_url()) !== false && strpos($url, 'sid=') !== false)
 794              {
 795                  $url = preg_replace('/(&amp;|\?)sid=[0-9a-f]{32}/', '\1', $url);
 796              }
 797  
 798              return ($var1) ? '[url=' . $this->bbcode_specialchars($url) . ':' . $this->bbcode_uid . ']' . $var2 . '[/url:' . $this->bbcode_uid . ']' : '[url:' . $this->bbcode_uid . ']' . $this->bbcode_specialchars($url) . '[/url:' . $this->bbcode_uid . ']'; 
 799          }
 800  
 801          return '[url' . (($var1) ? '=' . $var1 : '') . ']' . $var2 . '[/url]';
 802      }
 803  
 804      /**
 805      * Check if url is pointing to this domain/script_path/php-file
 806      *
 807      * @param string $url the url to check
 808      * @return true if the url is pointing to this domain/script_path/php-file, false if not
 809      *
 810      * @access private
 811      */
 812  	function path_in_domain($url)
 813      {
 814          global $config, $phpEx, $user;
 815  
 816          $check_path = ($user->page['root_script_path'] != '/') ? substr($user->page['root_script_path'], 0, -1) : '/';
 817  
 818          // Is the user trying to link to a php file in this domain and script path?
 819          if (strpos($url, ".{$phpEx}") !== false && strpos($url, $check_path) !== false)
 820          {
 821              $server_name = (!empty($_SERVER['SERVER_NAME'])) ? $_SERVER['SERVER_NAME'] : getenv('SERVER_NAME');
 822  
 823              // Forcing server vars is the only way to specify/override the protocol
 824              if ($config['force_server_vars'] || !$server_name)
 825              {
 826                  $server_name = $config['server_name'];
 827              }
 828  
 829              // Check again in correct order...
 830              $pos_ext = strpos($url, ".{$phpEx}");
 831              $pos_path = strpos($url, $check_path);
 832              $pos_domain = strpos($url, $server_name);
 833  
 834              if ($pos_domain !== false && $pos_path >= $pos_domain && $pos_ext >= $pos_path)
 835              {
 836                  return true;
 837              }
 838          }
 839  
 840          return false;
 841      }
 842  }
 843  
 844  /**
 845  * Main message parser for posting, pm, etc. takes raw message
 846  * and parses it for attachments, bbcode and smilies
 847  * @package phpBB3
 848  */
 849  class parse_message extends bbcode_firstpass
 850  {
 851      var $attachment_data = array();
 852      var $filename_data = array();
 853  
 854      // Helps ironing out user error
 855      var $message_status = '';
 856  
 857      var $allow_img_bbcode = true;
 858      var $allow_flash_bbcode = true;
 859      var $allow_quote_bbcode = true;
 860      var $allow_url_bbcode = true;
 861  
 862      var $mode;
 863  
 864      /**
 865      * Init - give message here or manually
 866      */
 867  	function parse_message($message = '')
 868      {
 869          // Init BBCode UID
 870          $this->bbcode_uid = substr(md5(time()), 0, BBCODE_UID_LEN);
 871  
 872          if ($message)
 873          {
 874              $this->message = $message;
 875          }
 876      }
 877  
 878      /**
 879      * Parse Message
 880      */
 881  	function parse($allow_bbcode, $allow_magic_url, $allow_smilies, $allow_img_bbcode = true, $allow_flash_bbcode = true, $allow_quote_bbcode = true, $allow_url_bbcode = true, $update_this_message = true, $mode = 'post')
 882      {
 883          global $config, $db, $user;
 884  
 885          $mode = ($mode != 'post') ? 'sig' : 'post';
 886  
 887          $this->mode = $mode;
 888  
 889          $this->allow_img_bbcode = $allow_img_bbcode;
 890          $this->allow_flash_bbcode = $allow_flash_bbcode;
 891          $this->allow_quote_bbcode = $allow_quote_bbcode;
 892          $this->allow_url_bbcode = $allow_url_bbcode;
 893  
 894          // If false, then $this->message won't be altered, the text will be returned instead.
 895          if (!$update_this_message)
 896          {
 897              $tmp_message = $this->message;
 898              $return_message = &$this->message;
 899          }
 900  
 901          if ($this->message_status == 'display')
 902          {
 903              $this->decode_message();
 904          }
 905  
 906          // Do some general 'cleanup' first before processing message,
 907          // e.g. remove excessive newlines(?), smilies(?)
 908          // Transform \r\n and \r into \n
 909          $match = array('#\r\n?#', "#([\n][\s]+){3,}#", '#(script|about|applet|activex|chrome):#i');
 910          $replace = array("\n", "\n\n", "\\1&#058;");
 911          $this->message = preg_replace($match, $replace, trim($this->message));
 912  
 913          // Message length check. -1 disables this check completely.
 914          if ($config['max_' . $mode . '_chars'] != -1)
 915          {
 916              $msg_len = ($mode == 'post') ? utf8_strlen($this->message) : utf8_strlen(preg_replace('#\[\/?[a-z\*\+\-]+(=[\S]+)?\]#is', ' ', $this->message));
 917      
 918              if ((!$msg_len && $mode !== 'sig') || $config['max_' . $mode . '_chars'] && $msg_len > $config['max_' . $mode . '_chars'])
 919              {
 920                  $this->warn_msg[] = (!$msg_len) ? $user->lang['TOO_FEW_CHARS'] : $user->lang['TOO_MANY_CHARS'];
 921                  return $this->warn_msg;
 922              }
 923          }
 924  
 925          // Prepare BBcode (just prepares some tags for better parsing)
 926          if ($allow_bbcode && strpos($this->message, '[') !== false)
 927          {
 928              $this->bbcode_init();
 929              $disallow = array('img', 'flash', 'quote', 'url');
 930              foreach ($disallow as $bool)
 931              {
 932                  if (!${'allow_' . $bool . '_bbcode'})
 933                  {
 934                      $this->bbcodes[$bool]['disabled'] = true;
 935                  }
 936              }
 937  
 938              $this->prepare_bbcodes();
 939          }
 940  
 941          // Parse smilies
 942          if ($allow_smilies)
 943          {
 944              $this->smilies($config['max_' . $mode . '_smilies']);
 945          }
 946  
 947          $num_urls = 0;
 948  
 949          // Parse BBCode
 950          if ($allow_bbcode && strpos($this->message, '[') !== false)
 951          {
 952              $this->parse_bbcode();
 953              $num_urls += $this->parsed_items['url'];
 954          }
 955  
 956          // Parse URL's
 957          if ($allow_magic_url)
 958          {
 959              $this->magic_url(generate_board_url());
 960      
 961              if ($config['max_' . $mode . '_urls'])
 962              {
 963                  $num_urls += preg_match_all('#\<!-- (l|m|w|e) --\>.*?\<!-- \1 --\>#', $this->message, $matches);
 964              }
 965          }
 966  
 967          // Check number of links
 968          if ($config['max_' . $mode . '_urls'] && $num_urls > $config['max_' . $mode . '_urls'])
 969          {
 970              $this->warn_msg[] = sprintf($user->lang['TOO_MANY_URLS'], $config['max_' . $mode . '_urls']);
 971              return $this->warn_msg;
 972          }
 973  
 974          if (!$update_this_message)
 975          {
 976              unset($this->message);
 977              $this->message = $tmp_message;
 978              return $return_message;
 979          }
 980  
 981          $this->message_status = 'parsed';
 982          return false;
 983      }
 984  
 985      /**
 986      * Formatting text for display
 987      */
 988  	function format_display($allow_bbcode, $allow_magic_url, $allow_smilies, $update_this_message = true)
 989      {
 990          // If false, then the parsed message get returned but internal message not processed.
 991          if (!$update_this_message)
 992          {
 993              $tmp_message = $this->message;
 994              $return_message = &$this->message;
 995          }
 996  
 997          if ($this->message_status == 'plain')
 998          {
 999              // Force updating message - of course.
1000              $this->parse($allow_bbcode, $allow_magic_url, $allow_smilies, $this->allow_img_bbcode, $this->allow_flash_bbcode, $this->allow_quote_bbcode, $this->allow_url_bbcode, true);
1001          }
1002  
1003          // Parse BBcode
1004          if ($allow_bbcode)
1005          {
1006              $this->bbcode_cache_init();
1007  
1008              // We are giving those parameters to be able to use the bbcode class on its own
1009              $this->bbcode_second_pass($this->message, $this->bbcode_uid);
1010          }
1011  
1012          $this->message = smiley_text($this->message, !$allow_smilies);
1013  
1014          // Replace naughty words such as farty pants
1015          $this->message = str_replace("\n", '<br />', censor_text($this->message));
1016  
1017          if (!$update_this_message)
1018          {
1019              unset($this->message);
1020              $this->message = $tmp_message;
1021              return $return_message;
1022          }
1023  
1024          $this->message_status = 'display';
1025          return false;
1026      }
1027  
1028      /**
1029      * Decode message to be placed back into form box
1030      */
1031  	function decode_message($custom_bbcode_uid = '', $update_this_message = true)
1032      {
1033          // If false, then the parsed message get returned but internal message not processed.
1034          if (!$update_this_message)
1035          {
1036              $tmp_message = $this->message;
1037              $return_message = &$this->message;
1038          }
1039  
1040          ($custom_bbcode_uid) ? decode_message($this->message, $custom_bbcode_uid) : decode_message($this->message, $this->bbcode_uid);
1041  
1042          if (!$update_this_message)
1043          {
1044              unset($this->message);
1045              $this->message = $tmp_message;
1046              return $return_message;
1047          }
1048  
1049          $this->message_status = 'plain';
1050          return false;
1051      }
1052  
1053      /**
1054      * Replace magic urls of form http://xxx.xxx., www.xxx. and xxx@xxx.xxx.
1055      * Cuts down displayed size of link if over 50 chars, turns absolute links
1056      * into relative versions when the server/script path matches the link
1057      */
1058  	function magic_url($server_url)
1059      {
1060          // We use the global make_clickable function
1061          $this->message = make_clickable($this->message, $server_url);
1062      }
1063  
1064      /**
1065      * Parse Smilies
1066      */
1067  	function smilies($max_smilies = 0)
1068      {
1069          global $db, $user, $phpbb_root_path;
1070          static $match;
1071          static $replace;
1072  
1073          // See if the static arrays have already been filled on an earlier invocation
1074          if (!is_array($match))
1075          {
1076              $match = $replace = array();
1077  
1078              // NOTE: obtain_* function? chaching the table contents?
1079      
1080              // For now setting the ttl to 10 minutes
1081              switch ($db->sql_layer)
1082              {
1083                  case 'mssql':
1084                  case 'mssql_odbc':
1085                      $sql = 'SELECT * 
1086                          FROM ' . SMILIES_TABLE . '
1087                          ORDER BY LEN(code) DESC';
1088                  break;
1089      
1090                  case 'firebird':
1091                      $sql = 'SELECT * 
1092                          FROM ' . SMILIES_TABLE . '
1093                          ORDER BY CHAR_LENGTH(code) DESC';
1094                  break;
1095  
1096                  // LENGTH supported by MySQL, IBM DB2, Oracle and Access for sure...
1097                  default:
1098                      $sql = 'SELECT * 
1099                          FROM ' . SMILIES_TABLE . '
1100                          ORDER BY LENGTH(code) DESC';
1101                  break;
1102              }
1103              $result = $db->sql_query($sql, 600);
1104  
1105              while ($row = $db->sql_fetchrow($result))
1106              {
1107                  // (assertion)
1108                  $match[] = '#(?<=^|[\n ]|\.)' . preg_quote($row['code'], '#') . '#';
1109                  $replace[] = '<!-- s' . $row['code'] . ' --><img src="{SMILIES_PATH}/' . $row['smiley_url'] . '" alt="' . $row['emotion'] . '" title="' . $row['emotion'] . '" /><!-- s' . $row['code'] . ' -->';
1110              }
1111              $db->sql_freeresult($result);
1112          }
1113  
1114          if (sizeof($match))
1115          {
1116              if ($max_smilies)
1117              {
1118                  $num_matches = preg_match_all('#' . str_replace('#', '', implode('|', $match)) . '#', $this->message, $matches);
1119                  unset($matches);
1120  
1121                  if ($num_matches !== false && $num_matches > $max_smilies)
1122                  {
1123                      $this->warn_msg[] = sprintf($user->lang['TOO_MANY_SMILIES'], $max_smilies);
1124                      return;
1125                  }
1126              }
1127              $this->message = trim(preg_replace($match, $replace, $this->message));
1128          }
1129      }
1130  
1131      /**
1132      * Parse Attachments
1133      */
1134  	function parse_attachments($form_name, $mode, $forum_id, $submit, $preview, $refresh, $is_message = false)
1135      {
1136          global $config, $auth, $user, $phpbb_root_path, $phpEx, $db;
1137  
1138          $error = array();
1139  
1140          $num_attachments = sizeof($this->attachment_data);
1141          $this->filename_data['filecomment'] = request_var('filecomment', '', true);
1142          utf8_normalize_nfc(&$this->filename_data['filecomment']);
1143          $upload_file = (isset($_FILES[$form_name]) && $_FILES[$form_name]['name'] != 'none' && trim($_FILES[$form_name]['name'])) ? true : false;
1144  
1145          $add_file        = (isset($_POST['add_file'])) ? true : false;
1146          $delete_file    = (isset($_POST['delete_file'])) ? true : false;
1147          $edit_comment    = (isset($_POST['edit_comment'])) ? true : false;
1148  
1149          $cfg = array();
1150          $cfg['max_attachments'] = ($is_message) ? $config['max_attachments_pm'] : $config['max_attachments'];
1151          $forum_id = ($is_message) ? 0 : $forum_id;
1152  
1153          if ($submit && in_array($mode, array('post', 'reply', 'quote', 'edit')) && $upload_file)
1154          {
1155              if ($num_attachments < $cfg['max_attachments'] || $auth->acl_get('a_') || $auth->acl_get('m_', $forum_id))
1156              {
1157                  $filedata = upload_attachment($form_name, $forum_id, false, '', $is_message);
1158                  $error = $filedata['error'];
1159  
1160                  if ($filedata['post_attach'] && !sizeof($error))
1161                  {
1162                      $sql_ary = array(
1163                          'physical_filename'    => $filedata['physical_filename'],
1164                          'attach_comment'    => $this->filename_data['filecomment'],
1165                          'real_filename'        => $filedata['real_filename'],
1166                          'extension'            => $filedata['extension'],
1167                          'mimetype'            => $filedata['mimetype'],
1168                          'filesize'            => $filedata['filesize'],
1169                          'filetime'            => $filedata['filetime'],
1170                          'thumbnail'            => $filedata['thumbnail'],
1171                          'is_orphan'            => 1,
1172                          'in_message'        => ($is_message) ? 1 : 0,
1173                          'poster_id'            => $user->data['user_id'],
1174                      );
1175  
1176                      $db->sql_query('INSERT INTO ' . ATTACHMENTS_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary));
1177  
1178                      $new_entry = array(
1179                          'attach_id'        => $db->sql_nextid(),
1180                          'is_orphan'        => 1,
1181                          'real_filename'    => $filedata['real_filename'],
1182                          'attach_comment'=> $this->filename_data['filecomment'],
1183                      );
1184  
1185                      $this->attachment_data = array_merge(array(0 => $new_entry), $this->attachment_data);
1186                      $this->message = preg_replace('#\[attachment=([0-9]+)\](.*?)\[\/attachment\]#e', "'[attachment='.(\\1 + 1).']\\2[/attachment]'", $this->message);
1187  
1188                      $this->filename_data['filecomment'] = '';
1189  
1190                      // This Variable is set to false here, because Attachments are entered into the
1191                      // Database in two modes, one if the id_list is 0 and the second one if post_attach is true
1192                      // Since post_attach is automatically switched to true if an Attachment got added to the filesystem,
1193                      // but we are assigning an id of 0 here, we have to reset the post_attach variable to false.
1194                      //
1195                      // This is very relevant, because it could happen that the post got not submitted, but we do not
1196                      // know this circumstance here. We could be at the posting page or we could be redirected to the entered
1197                      // post. :)
1198                      $filedata['post_attach'] = false;
1199                  }
1200              }
1201              else
1202              {
1203                  $error[] = sprintf($user->lang['TOO_MANY_ATTACHMENTS'], $cfg['max_attachments']);
1204              }
1205          }
1206  
1207          if ($preview || $refresh || sizeof($error))
1208          {
1209              // Perform actions on temporary attachments
1210              if ($delete_file)
1211              {
1212                  include_once($phpbb_root_path . 'includes/functions_admin.' . $phpEx);
1213  
1214                  $index = (int) key($_POST['delete_file']);
1215  
1216                  if (!empty($this->attachment_data[$index]))
1217                  {
1218  
1219                      // delete selected attachment
1220                      if ($this->attachment_data[$index]['is_orphan'])
1221                      {
1222                          $sql = 'SELECT attach_id, physical_filename, thumbnail
1223                              FROM ' . ATTACHMENTS_TABLE . '
1224                              WHERE attach_id = ' . (int) $this->attachment_data[$index]['attach_id'] . '
1225                                  AND is_orphan = 1
1226                                  AND poster_id = ' . $user->data['user_id'];
1227                          $result = $db->sql_query($sql);
1228                          $row = $db->sql_fetchrow($result);
1229                          $db->sql_freeresult($result);
1230  
1231                          if ($row)
1232                          {
1233                              phpbb_unlink($row['physical_filename'], 'file');
1234  
1235                              if ($row['thumbnail'])
1236                              {
1237                                  phpbb_unlink($row['physical_filename'], 'thumbnail');
1238                              }
1239  
1240                              $db->sql_query('DELETE FROM ' . ATTACHMENTS_TABLE . ' WHERE attach_id = ' . (int) $this->attachment_data[$index]['attach_id']);
1241                          }
1242                      }
1243                      else
1244                      {
1245                          delete_attachments('attach', array(intval($this->attachment_data[$index]['attach_id'])));
1246                      }
1247  
1248                      unset($this->attachment_data[$index]);
1249                      $this->message = preg_replace('#\[attachment=([0-9]+)\](.*?)\[\/attachment\]#e', "(\\1 == \$index) ? '' : ((\\1 > \$index) ? '[attachment=' . (\\1 - 1) . ']\\2[/attachment]' : '\\0')", $this->message);
1250  
1251                      // Reindex Array
1252                      $this->attachment_data = array_values($this->attachment_data);
1253                  }
1254              }
1255              else if ($edit_comment || $add_file || $preview)
1256              {
1257                  if ($edit_comment)
1258                  {
1259                      $actual_comment_list = request_var('comment_list', array(''), true);
1260                      utf8_normalize_nfc(&$actual_comment_list);
1261  
1262                      $edit_comment = request_var('edit_comment', array(0 => ''));
1263                      $edit_comment = key($edit_comment);
1264                      $this->attachment_data[$edit_comment]['attach_comment'] = $actual_comment_list[$edit_comment];
1265                  }
1266  
1267                  if (($add_file || $preview) && $upload_file)
1268                  {
1269                      if ($num_attachments < $cfg['max_attachments'] || $auth->acl_gets('m_', 'a_', $forum_id))
1270                      {
1271                          $filedata = upload_attachment($form_name, $forum_id, false, '', $is_message);
1272                          $error = array_merge($error, $filedata['error']);
1273  
1274                          if (!sizeof($error))
1275                          {
1276                              $sql_ary = array(
1277                                  'physical_filename'    => $filedata['physical_filename'],
1278                                  'attach_comment'    => $this->filename_data['filecomment'],
1279                                  'real_filename'        => $filedata['real_filename'],
1280                                  'extension'            => $filedata['extension'],
1281                                  'mimetype'            => $filedata['mimetype'],
1282                                  'filesize'            => $filedata['filesize'],
1283                                  'filetime'            => $filedata['filetime'],
1284                                  'thumbnail'            => $filedata['thumbnail'],
1285                                  'is_orphan'            => 1,
1286                                  'in_message'        => ($is_message) ? 1 : 0,
1287                                  'poster_id'            => $user->data['user_id'],
1288                              );
1289  
1290                              $db->sql_query('INSERT INTO ' . ATTACHMENTS_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary));
1291  
1292                              $new_entry = array(
1293                                  'attach_id'        => $db->sql_nextid(),
1294                                  'is_orphan'        => 1,
1295                                  'real_filename'    => $filedata['real_filename'],
1296                                  'attach_comment'=> $this->filename_data['filecomment'],
1297                              );
1298  
1299                              $this->attachment_data = array_merge(array(0 => $new_entry), $this->attachment_data);
1300                              $this->message = preg_replace('#\[attachment=([0-9]+)\](.*?)\[\/attachment\]#e', "'[attachment='.(\\1 + 1).']\\2[/attachment]'", $this->message);
1301                              $this->filename_data['filecomment'] = '';
1302                          }
1303                      }
1304                      else
1305                      {
1306                          $error[] = sprintf($user->lang['TOO_MANY_ATTACHMENTS'], $cfg['max_attachments']);
1307                      }
1308                  }
1309              }
1310          }
1311  
1312          foreach ($error as $error_msg)
1313          {
1314              $this->warn_msg[] = $error_msg;
1315          }
1316      }
1317  
1318      /**
1319      * Get Attachment Data
1320      */
1321  	function get_submitted_attachment_data($check_user_id = false)
1322      {
1323          global $user, $db, $phpbb_root_path, $phpEx, $config;
1324  
1325          $this->filename_data['filecomment'] = request_var('filecomment', '', true);
1326          utf8_normalize_nfc(&$this->filename_data['filecomment']);
1327          $attachment_data = (isset($_POST['attachment_data'])) ? $_POST['attachment_data'] : array();
1328          $this->attachment_data = array();
1329  
1330          $check_user_id = ($check_user_id === false) ? $user->data['user_id'] : $check_user_id;
1331  
1332          if (!sizeof($attachment_data))
1333          {
1334              return;
1335          }
1336  
1337          $not_orphan = $orphan = array();
1338  
1339          foreach ($attachment_data as $pos => $var_ary)
1340          {
1341              if ($var_ary['is_orphan'])
1342              {
1343                  $orphan[(int) $var_ary['attach_id']] = $pos;
1344              }
1345              else
1346              {
1347                  $not_orphan[(int) $var_ary['attach_id']] = $pos;
1348              }
1349          }
1350  
1351          // Regenerate already posted attachments
1352          if (sizeof($not_orphan))
1353          {
1354              // Get the attachment data, based on the poster id...
1355              $sql = 'SELECT attach_id, is_orphan, real_filename, attach_comment
1356                  FROM ' . ATTACHMENTS_TABLE . '
1357                  WHERE ' . $db->sql_in_set('attach_id', array_keys($not_orphan)) . '
1358                      AND poster_id = ' . $check_user_id;
1359              $result = $db->sql_query($sql);
1360  
1361              while ($row = $db->sql_fetchrow($result))
1362              {
1363                  $pos = $not_orphan[$row['attach_id']];
1364                  $this->attachment_data[$pos] = $row;
1365                  set_var($this->attachment_data[$pos]['attach_comment'], $_POST['attachment_data'][$pos]['attach_comment'], 'string', true);
1366  
1367                  unset($not_orphan[$row['attach_id']]);
1368              }
1369              $db->sql_freeresult($result);
1370          }
1371  
1372          if (sizeof($not_orphan))
1373          {
1374              trigger_error($user->lang['NO_ACCESS_ATTACHMENT'], E_USER_ERROR);
1375          }
1376  
1377          // Regenerate newly uploaded attachments
1378          if (sizeof($orphan))
1379          {
1380              $sql = 'SELECT attach_id, is_orphan, real_filename, attach_comment
1381                  FROM ' . ATTACHMENTS_TABLE . '
1382                  WHERE ' . $db->sql_in_set('attach_id', array_keys($orphan)) . '
1383                      AND poster_id = ' . $user->data['user_id'] . '
1384                      AND is_orphan = 1';
1385              $result = $db->sql_query($sql);
1386  
1387              while ($row = $db->sql_fetchrow($result))
1388              {
1389                  $pos = $orphan[$row['attach_id']];
1390                  $this->attachment_data[$pos] = $row;
1391                  set_var($this->attachment_data[$pos]['attach_comment'], $_POST['attachment_data'][$pos]['attach_comment'], 'string', true);
1392  
1393                  unset($orphan[$row['attach_id']]);
1394              }
1395              $db->sql_freeresult($result);
1396          }
1397  
1398          if (sizeof($orphan))
1399          {
1400              trigger_error($user->lang['NO_ACCESS_ATTACHMENT'], E_USER_ERROR);
1401          }
1402  
1403          ksort($this->attachment_data);
1404      }
1405  
1406      /**
1407      * Parse Poll
1408      */
1409  	function parse_poll(&$poll)
1410      {
1411          global $auth, $user, $config;
1412  
1413          $poll_max_options = $poll['poll_max_options'];
1414  
1415          // Parse Poll Option text ;)
1416          $tmp_message = $this->message;
1417          $this->message = $poll['poll_option_text'];
1418  
1419  
1420          $poll['poll_option_text'] = $this->parse($poll['enable_bbcode'], ($config['allow_post_links']) ? $poll['enable_urls'] : false, $poll['enable_smilies'], $poll['img_status'], false, false, $config['allow_post_links'], false);
1421  
1422          $this->message = $tmp_message;
1423  
1424          // Parse Poll Title
1425          $tmp_message = $this->message;
1426          $this->message = $poll['poll_title'];
1427  
1428  
1429          $poll['poll_title'] = $this->parse($poll['enable_bbcode'], ($config['allow_post_links']) ? $poll['enable_urls'] : false, $poll['enable_smilies'], $poll['img_status'], false, false, $config['allow_post_links'], false);
1430  
1431          $this->message = $tmp_message;
1432  
1433          unset($tmp_message);
1434  
1435          $poll['poll_options'] = explode("\n", trim($poll['poll_option_text']));
1436          $poll['poll_options_size'] = sizeof($poll['poll_options']);
1437  
1438          if (sizeof($poll['poll_options']) == 1)
1439          {
1440              $this->warn_msg[] = $user->lang['TOO_FEW_POLL_OPTIONS'];
1441          }
1442          else if ($poll['poll_options_size'] > (int) $config['max_poll_options'])
1443          {
1444              $this->warn_msg[] = $user->lang['TOO_MANY_POLL_OPTIONS'];
1445          }
1446          else if ($poll_max_options > $poll['poll_options_size'])
1447          {
1448              $this->warn_msg[] = $user->lang['TOO_MANY_USER_OPTIONS'];
1449          }
1450  
1451          if (!$poll['poll_title'] && $poll['poll_options_size'])
1452          {
1453              $this->warn_msg[] = $user->lang['NO_POLL_TITLE'];
1454          }
1455  
1456          $poll['poll_max_options'] = ($poll['poll_max_options'] < 1) ? 1 : (($poll['poll_max_options'] > $config['max_poll_options']) ? $config['max_poll_options'] : $poll['poll_max_options']);
1457      }
1458  }
1459  
1460  ?>


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