Verzeichnisstruktur phpBB-2.0.0


Veröffentlicht
03.04.2002

So funktioniert es


Auf das letzte Element klicken. Dies geht jeweils ein Schritt zurück

Auf das Icon klicken, dies öffnet das Verzeichnis. Nochmal klicken schließt das Verzeichnis.
Auf den Verzeichnisnamen klicken, dies zeigt nur das Verzeichnis mit Inhalt an

      (Beispiel Datei-Icons)

Auf das Icon klicken um den Quellcode anzuzeigen

bbcode.php

Zuletzt modifiziert: 09.10.2024, 12:51 - Dateigröße: 26.52 KiB


 001  <?php
 002  /***************************************************************************
 003   *                              bbcode.php
 004   *                            -------------------
 005   *   begin                : Saturday, Feb 13, 2001
 006   *   copyright            : (C) 2001 The phpBB Group
 007   *   email                : support@phpbb.com
 008   *
 009   *   $Id$
 010   *
 011   ***************************************************************************/
 012   
 013  /***************************************************************************
 014   *
 015   *   This program is free software; you can redistribute it and/or modify
 016   *   it under the terms of the GNU General Public License as published by
 017   *   the Free Software Foundation; either version 2 of the License, or
 018   *   (at your option) any later version.
 019   *
 020   ***************************************************************************/
 021   
 022  if ( !defined('IN_PHPBB') )
 023  {
 024      die("Hacking attempt");
 025  }
 026   
 027  define("BBCODE_UID_LEN", 10);
 028   
 029  // global that holds loaded-and-prepared bbcode templates, so we only have to do
 030  // that stuff once.
 031   
 032  $bbcode_tpl = null;
 033   
 034  /**
 035   * Loads bbcode templates from the bbcode.tpl file of the current template set.
 036   * Creates an array, keys are bbcode names like "b_open" or "url", values
 037   * are the associated template.
 038   * Probably pukes all over the place if there's something really screwed
 039   * with the bbcode.tpl file.
 040   *
 041   * Nathan Codding, Sept 26 2001.
 042   */
 043  function load_bbcode_template()
 044  {
 045      global $template;
 046      $tpl_filename = $template->make_filename('bbcode.tpl');
 047      $tpl = fread(fopen($tpl_filename, 'r'), filesize($tpl_filename));
 048   
 049      // replace \ with \\ and then ' with \'.
 050      $tpl = str_replace('\\', '\\\\', $tpl);
 051      $tpl  = str_replace('\'', '\\\'', $tpl);
 052   
 053      // strip newlines.
 054      $tpl  = str_replace("\n", '', $tpl);
 055   
 056      // Turn template blocks into PHP assignment statements for the values of $bbcode_tpls..
 057      $tpl = preg_replace('#<!-- BEGIN (.*?) -->(.*?)<!-- END (.*?) -->#', "\n" . '$bbcode_tpls[\'\\1\'] = \'\\2\';', $tpl);
 058   
 059      $bbcode_tpls = array();
 060   
 061      eval($tpl);
 062   
 063      return $bbcode_tpls;
 064  }
 065   
 066   
 067  /**
 068   * Prepares the loaded bbcode templates for insertion into preg_replace()
 069   * or str_replace() calls in the bbencode_second_pass functions. This
 070   * means replacing template placeholders with the appropriate preg backrefs
 071   * or with language vars. NOTE: If you change how the regexps work in
 072   * bbencode_second_pass(), you MUST change this function.
 073   *
 074   * Nathan Codding, Sept 26 2001
 075   *
 076   */
 077  function prepare_bbcode_template($bbcode_tpl)
 078  {
 079      global $lang;
 080   
 081      $bbcode_tpl['olist_open'] = str_replace('{LIST_TYPE}', '\\1', $bbcode_tpl['olist_open']);
 082   
 083      $bbcode_tpl['color_open'] = str_replace('{COLOR}', '\\1', $bbcode_tpl['color_open']);
 084   
 085      $bbcode_tpl['size_open'] = str_replace('{SIZE}', '\\1', $bbcode_tpl['size_open']);
 086   
 087      $bbcode_tpl['quote_open'] = str_replace('{L_QUOTE}', $lang['Quote'], $bbcode_tpl['quote_open']);
 088   
 089      $bbcode_tpl['quote_username_open'] = str_replace('{L_QUOTE}', $lang['Quote'], $bbcode_tpl['quote_username_open']);
 090      $bbcode_tpl['quote_username_open'] = str_replace('{L_WROTE}', $lang['wrote'], $bbcode_tpl['quote_username_open']);
 091      $bbcode_tpl['quote_username_open'] = str_replace('{USERNAME}', '\\1', $bbcode_tpl['quote_username_open']);
 092   
 093      $bbcode_tpl['code_open'] = str_replace('{L_CODE}', $lang['Code'], $bbcode_tpl['code_open']);
 094   
 095      $bbcode_tpl['img'] = str_replace('{URL}', '\\1', get_image_tag_replacement($bbcode_tpl));
 096   
 097      // We do URLs in several different ways..
 098      $bbcode_tpl['url1'] = str_replace('{URL}', '\\1', $bbcode_tpl['url']);
 099      $bbcode_tpl['url1'] = str_replace('{DESCRIPTION}', '\\1', $bbcode_tpl['url1']);
 100   
 101      $bbcode_tpl['url2'] = str_replace('{URL}', 'http://\\1', $bbcode_tpl['url']);
 102      $bbcode_tpl['url2'] = str_replace('{DESCRIPTION}', '\\1', $bbcode_tpl['url2']);
 103   
 104      $bbcode_tpl['url3'] = str_replace('{URL}', '\\1', $bbcode_tpl['url']);
 105      $bbcode_tpl['url3'] = str_replace('{DESCRIPTION}', '\\2', $bbcode_tpl['url3']);
 106   
 107      $bbcode_tpl['url4'] = str_replace('{URL}', 'http://\\1', $bbcode_tpl['url']);
 108      $bbcode_tpl['url4'] = str_replace('{DESCRIPTION}', '\\3', $bbcode_tpl['url4']);
 109   
 110      $bbcode_tpl['email'] = str_replace('{EMAIL}', '\\1', $bbcode_tpl['email']);
 111   
 112      define("BBCODE_TPL_READY", true);
 113   
 114      return $bbcode_tpl;
 115  }
 116   
 117   
 118  /**
 119  * Disables the img tag for privileged pages. It also implements a compability hack for old templates.
 120  */
 121  function get_image_tag_replacement($bbcode_tpl)
 122  {
 123      global $lang, $HTTP_POST_VARS, $HTTP_GET_VARS;
 124      $bb_tmpl = '';
 125      if (isset($HTTP_POST_VARS['p_sid']))
 126      {
 127          if (isset($bbcode_tpl['p_img']))
 128          {
 129              $bb_tmpl = str_replace('{L_PRIV_IMG}', $lang['Priv_Img'], $bbcode_tpl['p_img']);
 130          }
 131          else
 132          {
 133              $bb_tmpl = $lang['Priv_Img'] . ': {URL}';
 134          }
 135      }
 136      else
 137      {
 138          $bb_tmpl = $bbcode_tpl['img'];
 139      }
 140      return $bb_tmpl;
 141  }
 142   
 143  /**
 144   * Does second-pass bbencoding. This should be used before displaying the message in
 145   * a thread. Assumes the message is already first-pass encoded, and we are given the
 146   * correct UID as used in first-pass encoding.
 147   */
 148  function bbencode_second_pass($text, $uid)
 149  {
 150      global $lang, $bbcode_tpl;
 151   
 152      $text = preg_replace('#(script|about|applet|activex|chrome):#is', "\\1&#058;", $text);
 153   
 154      // pad it with a space so we can distinguish between FALSE and matching the 1st char (index 0).
 155      // This is important; bbencode_quote(), bbencode_list(), and bbencode_code() all depend on it.
 156      $text = " " . $text;
 157   
 158      // First: If there isn't a "[" and a "]" in the message, don't bother.
 159      if (! (strpos($text, "[") && strpos($text, "]")) )
 160      {
 161          // Remove padding, return.
 162          $text = substr($text, 1);
 163          return $text;
 164      }
 165   
 166      // Only load the templates ONCE..
 167      if (!defined("BBCODE_TPL_READY"))
 168      {
 169          // load templates from file into array.
 170          $bbcode_tpl = load_bbcode_template();
 171   
 172          // prepare array for use in regexps.
 173          $bbcode_tpl = prepare_bbcode_template($bbcode_tpl);
 174      }
 175   
 176      // [CODE] and [/CODE] for posting code (HTML, PHP, C etc etc) in your posts.
 177      $text = bbencode_second_pass_code($text, $uid, $bbcode_tpl);
 178   
 179      // [QUOTE] and [/QUOTE] for posting replies with quote, or just for quoting stuff.
 180      $text = str_replace("[quote:$uid]", $bbcode_tpl['quote_open'], $text);
 181      $text = str_replace("[/quote:$uid]", $bbcode_tpl['quote_close'], $text);
 182   
 183      // New one liner to deal with opening quotes with usernames...
 184      // replaces the two line version that I had here before..
 185      $text = preg_replace("/\[quote:$uid=\"(.*?)\"\]/si", $bbcode_tpl['quote_username_open'], $text);
 186   
 187      // [list] and [list=x] for (un)ordered lists.
 188      // unordered lists
 189      $text = str_replace("[list:$uid]", $bbcode_tpl['ulist_open'], $text);
 190      // li tags
 191      $text = str_replace("[*:$uid]", $bbcode_tpl['listitem'], $text);
 192      // ending tags
 193      $text = str_replace("[/list:u:$uid]", $bbcode_tpl['ulist_close'], $text);
 194      $text = str_replace("[/list:o:$uid]", $bbcode_tpl['olist_close'], $text);
 195      // Ordered lists
 196      $text = preg_replace("/\[list=([a1]):$uid\]/si", $bbcode_tpl['olist_open'], $text);
 197   
 198      // colours
 199      $text = preg_replace("/\[color=(\#[0-9A-F]{6}|[a-z]+):$uid\]/si", $bbcode_tpl['color_open'], $text);
 200      $text = str_replace("[/color:$uid]", $bbcode_tpl['color_close'], $text);
 201   
 202      // size
 203      $text = preg_replace("/\[size=([1-2]?[0-9]):$uid\]/si", $bbcode_tpl['size_open'], $text);
 204      $text = str_replace("[/size:$uid]", $bbcode_tpl['size_close'], $text);
 205   
 206      // [b] and [/b] for bolding text.
 207      $text = str_replace("[b:$uid]", $bbcode_tpl['b_open'], $text);
 208      $text = str_replace("[/b:$uid]", $bbcode_tpl['b_close'], $text);
 209   
 210      // [u] and [/u] for underlining text.
 211      $text = str_replace("[u:$uid]", $bbcode_tpl['u_open'], $text);
 212      $text = str_replace("[/u:$uid]", $bbcode_tpl['u_close'], $text);
 213   
 214      // [i] and [/i] for italicizing text.
 215      $text = str_replace("[i:$uid]", $bbcode_tpl['i_open'], $text);
 216      $text = str_replace("[/i:$uid]", $bbcode_tpl['i_close'], $text);
 217   
 218      // Patterns and replacements for URL and email tags..
 219      $patterns = array();
 220      $replacements = array();
 221   
 222      // [img]image_url_here[/img] code..
 223      // This one gets first-passed..
 224      $patterns[] = "#\[img:$uid\]([^?](?:[^\[]+|\[(?!url))*?)\[/img:$uid\]#i";
 225      $replacements[] = $bbcode_tpl['img'];
 226   
 227      // matches a [url]xxxx://www.phpbb.com[/url] code..
 228      $patterns[] = "#\[url\]([\w]+?://([\w\#$%&~/.\-;:=,?@\]+]+|\[(?!url=))*?)\[/url\]#is";
 229      $replacements[] = $bbcode_tpl['url1'];
 230   
 231      // [url]www.phpbb.com[/url] code.. (no xxxx:// prefix).
 232      $patterns[] = "#\[url\]((www|ftp)\.([\w\#$%&~/.\-;:=,?@\]+]+|\[(?!url=))*?)\[/url\]#is";
 233      $replacements[] = $bbcode_tpl['url2'];
 234   
 235      // [url=xxxx://www.phpbb.com]phpBB[/url] code..
 236      $patterns[] = "#\[url=([\w]+?://[\w\#$%&~/.\-;:=,?@\[\]+]*?)\]([^?\n\r\t].*?)\[/url\]#is";
 237      $replacements[] = $bbcode_tpl['url3'];
 238   
 239      // [url=www.phpbb.com]phpBB[/url] code.. (no xxxx:// prefix).
 240      $patterns[] = "#\[url=((www|ftp)\.[\w\#$%&~/.\-;:=,?@\[\]+]*?)\]([^?\n\r\t].*?)\[/url\]#is";
 241      $replacements[] = $bbcode_tpl['url4'];
 242   
 243      // [email]user@domain.tld[/email] code..
 244      $patterns[] = "#\[email\]([a-z0-9&\-_.]+?@[\w\-]+\.([\w\-\.]+\.)?[\w]+)\[/email\]#si";
 245      $replacements[] = $bbcode_tpl['email'];
 246   
 247      $text = preg_replace($patterns, $replacements, $text);
 248   
 249      // Remove our padding from the string..
 250      $text = substr($text, 1);
 251   
 252      return $text;
 253   
 254  } // bbencode_second_pass()
 255   
 256  function make_bbcode_uid()
 257  {
 258      // Unique ID for this message..
 259   
 260      $uid = dss_rand();
 261      $uid = substr($uid, 0, BBCODE_UID_LEN);
 262   
 263      return $uid;
 264  }
 265   
 266  function bbencode_first_pass($text, $uid)
 267  {
 268      // pad it with a space so we can distinguish between FALSE and matching the 1st char (index 0).
 269      // This is important; bbencode_quote(), bbencode_list(), and bbencode_code() all depend on it.
 270      $text = " " . $text;
 271   
 272      // [CODE] and [/CODE] for posting code (HTML, PHP, C etc etc) in your posts.
 273      $text = bbencode_first_pass_pda($text, $uid, '[code]', '[/code]', '', true, '');
 274   
 275      // [QUOTE] and [/QUOTE] for posting replies with quote, or just for quoting stuff.
 276      $text = bbencode_first_pass_pda($text, $uid, '[quote]', '[/quote]', '', false, '');
 277      $text = bbencode_first_pass_pda($text, $uid, '/\[quote=\\\\&quot;(.*?)\\\\&quot;\]/is', '[/quote]', '', false, '', "[quote:$uid=\\\"\\1\\\"]");
 278   
 279      // [list] and [list=x] for (un)ordered lists.
 280      $open_tag = array();
 281      $open_tag[0] = "[list]";
 282   
 283      // unordered..
 284      $text = bbencode_first_pass_pda($text, $uid, $open_tag, "[/list]", "[/list:u]", false, 'replace_listitems');
 285   
 286      $open_tag[0] = "[list=1]";
 287      $open_tag[1] = "[list=a]";
 288   
 289      // ordered.
 290      $text = bbencode_first_pass_pda($text, $uid, $open_tag, "[/list]", "[/list:o]",  false, 'replace_listitems');
 291   
 292      // [color] and [/color] for setting text color
 293      $text = preg_replace("#\[color=(\#[0-9A-F]{6}|[a-z\-]+)\](.*?)\[/color\]#si", "[color=\\1:$uid]\\2[/color:$uid]", $text);
 294   
 295      // [size] and [/size] for setting text size
 296      $text = preg_replace("#\[size=([1-2]?[0-9])\](.*?)\[/size\]#si", "[size=\\1:$uid]\\2[/size:$uid]", $text);
 297   
 298      // [b] and [/b] for bolding text.
 299      $text = preg_replace("#\[b\](.*?)\[/b\]#si", "[b:$uid]\\1[/b:$uid]", $text);
 300   
 301      // [u] and [/u] for underlining text.
 302      $text = preg_replace("#\[u\](.*?)\[/u\]#si", "[u:$uid]\\1[/u:$uid]", $text);
 303   
 304      // [i] and [/i] for italicizing text.
 305      $text = preg_replace("#\[i\](.*?)\[/i\]#si", "[i:$uid]\\1[/i:$uid]", $text);
 306   
 307      // [img]image_url_here[/img] code..
 308      $text = preg_replace("#\[img\]((http|ftp|https|ftps)://)([^ \?&=\#\"\n\r\t<]*?(\.(jpg|jpeg|gif|png)))\[/img\]#sie", "'[img:$uid]\\1' . str_replace(' ', '%20', '\\3') . '[/img:$uid]'", $text);
 309   
 310      // Remove our padding from the string..
 311      return substr($text, 1);;
 312   
 313  } // bbencode_first_pass()
 314   
 315  /**
 316   * $text - The text to operate on.
 317   * $uid - The UID to add to matching tags.
 318   * $open_tag - The opening tag to match. Can be an array of opening tags.
 319   * $close_tag - The closing tag to match.
 320   * $close_tag_new - The closing tag to replace with.
 321   * $mark_lowest_level - boolean - should we specially mark the tags that occur
 322   *                     at the lowest level of nesting? (useful for [code], because
 323   *                        we need to match these tags first and transform HTML tags
 324   *                        in their contents..
 325   * $func - This variable should contain a string that is the name of a function.
 326   *                That function will be called when a match is found, and passed 2
 327   *                parameters: ($text, $uid). The function should return a string.
 328   *                This is used when some transformation needs to be applied to the
 329   *                text INSIDE a pair of matching tags. If this variable is FALSE or the
 330   *                empty string, it will not be executed.
 331   * If open_tag is an array, then the pda will try to match pairs consisting of
 332   * any element of open_tag followed by close_tag. This allows us to match things
 333   * like [list=A]...[/list] and [list=1]...[/list] in one pass of the PDA.
 334   *
 335   * NOTES:    - this function assumes the first character of $text is a space.
 336   *                - every opening tag and closing tag must be of the [...] format.
 337   */
 338  function bbencode_first_pass_pda($text, $uid, $open_tag, $close_tag, $close_tag_new, $mark_lowest_level, $func, $open_regexp_replace = false)
 339  {
 340      $open_tag_count = 0;
 341   
 342      if (!$close_tag_new || ($close_tag_new == ''))
 343      {
 344          $close_tag_new = $close_tag;
 345      }
 346   
 347      $close_tag_length = strlen($close_tag);
 348      $close_tag_new_length = strlen($close_tag_new);
 349      $uid_length = strlen($uid);
 350   
 351      $use_function_pointer = ($func && ($func != ''));
 352   
 353      $stack = array();
 354   
 355      if (is_array($open_tag))
 356      {
 357          if (0 == count($open_tag))
 358          {
 359              // No opening tags to match, so return.
 360              return $text;
 361          }
 362          $open_tag_count = count($open_tag);
 363      }
 364      else
 365      {
 366          // only one opening tag. make it into a 1-element array.
 367          $open_tag_temp = $open_tag;
 368          $open_tag = array();
 369          $open_tag[0] = $open_tag_temp;
 370          $open_tag_count = 1;
 371      }
 372   
 373      $open_is_regexp = false;
 374   
 375      if ($open_regexp_replace)
 376      {
 377          $open_is_regexp = true;
 378          if (!is_array($open_regexp_replace))
 379          {
 380              $open_regexp_temp = $open_regexp_replace;
 381              $open_regexp_replace = array();
 382              $open_regexp_replace[0] = $open_regexp_temp;
 383          }
 384      }
 385   
 386      if ($mark_lowest_level && $open_is_regexp)
 387      {
 388          message_die(GENERAL_ERROR, "Unsupported operation for bbcode_first_pass_pda().");
 389      }
 390   
 391      // Start at the 2nd char of the string, looking for opening tags.
 392      $curr_pos = 1;
 393      while ($curr_pos && ($curr_pos < strlen($text)))
 394      {
 395          $curr_pos = strpos($text, "[", $curr_pos);
 396   
 397          // If not found, $curr_pos will be 0, and the loop will end.
 398          if ($curr_pos)
 399          {
 400              // We found a [. It starts at $curr_pos.
 401              // check if it's a starting or ending tag.
 402              $found_start = false;
 403              $which_start_tag = "";
 404              $start_tag_index = -1;
 405   
 406              for ($i = 0; $i < $open_tag_count; $i++)
 407              {
 408                  // Grab everything until the first "]"...
 409                  $possible_start = substr($text, $curr_pos, strpos($text, ']', $curr_pos + 1) - $curr_pos + 1);
 410   
 411                  //
 412                  // We're going to try and catch usernames with "[' characters.
 413                  //
 414                  if( preg_match('#\[quote=\\\&quot;#si', $possible_start, $match) && !preg_match('#\[quote=\\\&quot;(.*?)\\\&quot;\]#si', $possible_start) )
 415                  {
 416                      // OK we are in a quote tag that probably contains a ] bracket.
 417                      // Grab a bit more of the string to hopefully get all of it..
 418                      if ($close_pos = strpos($text, '&quot;]', $curr_pos + 14))
 419                      {
 420                          if (strpos(substr($text, $curr_pos + 14, $close_pos - ($curr_pos + 14)), '[quote') === false)
 421                          {
 422                              $possible_start = substr($text, $curr_pos, $close_pos - $curr_pos + 7);
 423                          }
 424                      }
 425                  }
 426   
 427                  // Now compare, either using regexp or not.
 428                  if ($open_is_regexp)
 429                  {
 430                      $match_result = array();
 431                      if (preg_match($open_tag[$i], $possible_start, $match_result))
 432                      {
 433                          $found_start = true;
 434                          $which_start_tag = $match_result[0];
 435                          $start_tag_index = $i;
 436                          break;
 437                      }
 438                  }
 439                  else
 440                  {
 441                      // straightforward string comparison.
 442                      if (0 == strcasecmp($open_tag[$i], $possible_start))
 443                      {
 444                          $found_start = true;
 445                          $which_start_tag = $open_tag[$i];
 446                          $start_tag_index = $i;
 447                          break;
 448                      }
 449                  }
 450              }
 451   
 452              if ($found_start)
 453              {
 454                  // We have an opening tag.
 455                  // Push its position, the text we matched, and its index in the open_tag array on to the stack, and then keep going to the right.
 456                  $match = array("pos" => $curr_pos, "tag" => $which_start_tag, "index" => $start_tag_index);
 457                  array_push($stack, $match);
 458                  //
 459                  // Rather than just increment $curr_pos
 460                  // Set it to the ending of the tag we just found
 461                  // Keeps error in nested tag from breaking out
 462                  // of table structure..
 463                  //
 464                  $curr_pos += strlen($possible_start);
 465              }
 466              else
 467              {
 468                  // check for a closing tag..
 469                  $possible_end = substr($text, $curr_pos, $close_tag_length);
 470                  if (0 == strcasecmp($close_tag, $possible_end))
 471                  {
 472                      // We have an ending tag.
 473                      // Check if we've already found a matching starting tag.
 474                      if (sizeof($stack) > 0)
 475                      {
 476                          // There exists a starting tag.
 477                          $curr_nesting_depth = sizeof($stack);
 478                          // We need to do 2 replacements now.
 479                          $match = array_pop($stack);
 480                          $start_index = $match['pos'];
 481                          $start_tag = $match['tag'];
 482                          $start_length = strlen($start_tag);
 483                          $start_tag_index = $match['index'];
 484   
 485                          if ($open_is_regexp)
 486                          {
 487                              $start_tag = preg_replace($open_tag[$start_tag_index], $open_regexp_replace[$start_tag_index], $start_tag);
 488                          }
 489   
 490                          // everything before the opening tag.
 491                          $before_start_tag = substr($text, 0, $start_index);
 492   
 493                          // everything after the opening tag, but before the closing tag.
 494                          $between_tags = substr($text, $start_index + $start_length, $curr_pos - $start_index - $start_length);
 495   
 496                          // Run the given function on the text between the tags..
 497                          if ($use_function_pointer)
 498                          {
 499                              $between_tags = $func($between_tags, $uid);
 500                          }
 501   
 502                          // everything after the closing tag.
 503                          $after_end_tag = substr($text, $curr_pos + $close_tag_length);
 504   
 505                          // Mark the lowest nesting level if needed.
 506                          if ($mark_lowest_level && ($curr_nesting_depth == 1))
 507                          {
 508                              if ($open_tag[0] == '[code]')
 509                              {
 510                                  $code_entities_match = array('#<#', '#>#', '#"#', '#:#', '#\[#', '#\]#', '#\(#', '#\)#', '#\{#', '#\}#');
 511                                  $code_entities_replace = array('&lt;', '&gt;', '&quot;', '&#58;', '&#91;', '&#93;', '&#40;', '&#41;', '&#123;', '&#125;');
 512                                  $between_tags = preg_replace($code_entities_match, $code_entities_replace, $between_tags);
 513                              }
 514                              $text = $before_start_tag . substr($start_tag, 0, $start_length - 1) . ":$curr_nesting_depth:$uid]";
 515                              $text .= $between_tags . substr($close_tag_new, 0, $close_tag_new_length - 1) . ":$curr_nesting_depth:$uid]";
 516                          }
 517                          else
 518                          {
 519                              if ($open_tag[0] == '[code]')
 520                              {
 521                                  $text = $before_start_tag . '&#91;code&#93;';
 522                                  $text .= $between_tags . '&#91;/code&#93;';
 523                              }
 524                              else
 525                              {
 526                                  if ($open_is_regexp)
 527                                  {
 528                                      $text = $before_start_tag . $start_tag;
 529                                  }
 530                                  else
 531                                  {
 532                                      $text = $before_start_tag . substr($start_tag, 0, $start_length - 1) . ":$uid]";
 533                                  }
 534                                  $text .= $between_tags . substr($close_tag_new, 0, $close_tag_new_length - 1) . ":$uid]";
 535                              }
 536                          }
 537   
 538                          $text .= $after_end_tag;
 539   
 540                          // Now.. we've screwed up the indices by changing the length of the string.
 541                          // So, if there's anything in the stack, we want to resume searching just after it.
 542                          // otherwise, we go back to the start.
 543                          if (sizeof($stack) > 0)
 544                          {
 545                              $match = array_pop($stack);
 546                              $curr_pos = $match['pos'];
 547  //                            bbcode_array_push($stack, $match);
 548  //                            ++$curr_pos;
 549                          }
 550                          else
 551                          {
 552                              $curr_pos = 1;
 553                          }
 554                      }
 555                      else
 556                      {
 557                          // No matching start tag found. Increment pos, keep going.
 558                          ++$curr_pos;
 559                      }
 560                  }
 561                  else
 562                  {
 563                      // No starting tag or ending tag.. Increment pos, keep looping.,
 564                      ++$curr_pos;
 565                  }
 566              }
 567          }
 568      } // while
 569   
 570      return $text;
 571   
 572  } // bbencode_first_pass_pda()
 573   
 574  /**
 575   * Does second-pass bbencoding of the [code] tags. This includes
 576   * running htmlspecialchars() over the text contained between
 577   * any pair of [code] tags that are at the first level of
 578   * nesting. Tags at the first level of nesting are indicated
 579   * by this format: [code:1:$uid] ... [/code:1:$uid]
 580   * Other tags are in this format: [code:$uid] ... [/code:$uid]
 581   */
 582  function bbencode_second_pass_code($text, $uid, $bbcode_tpl)
 583  {
 584      global $lang;
 585   
 586      $code_start_html = $bbcode_tpl['code_open'];
 587      $code_end_html =  $bbcode_tpl['code_close'];
 588   
 589      // First, do all the 1st-level matches. These need an htmlspecialchars() run,
 590      // so they have to be handled differently.
 591      $match_count = preg_match_all("#\[code:1:$uid\](.*?)\[/code:1:$uid\]#si", $text, $matches);
 592   
 593      for ($i = 0; $i < $match_count; $i++)
 594      {
 595          $before_replace = $matches[1][$i];
 596          $after_replace = $matches[1][$i];
 597   
 598          // Replace 2 spaces with "&nbsp; " so non-tabbed code indents without making huge long lines.
 599          $after_replace = str_replace("  ", "&nbsp; ", $after_replace);
 600          // now Replace 2 spaces with " &nbsp;" to catch odd #s of spaces.
 601          $after_replace = str_replace("  ", " &nbsp;", $after_replace);
 602   
 603          // Replace tabs with "&nbsp; &nbsp;" so tabbed code indents sorta right without making huge long lines.
 604          $after_replace = str_replace("\t", "&nbsp; &nbsp;", $after_replace);
 605   
 606          // now Replace space occurring at the beginning of a line
 607          $after_replace = preg_replace("/^ {1}/m", '&nbsp;', $after_replace);
 608   
 609          $str_to_match = "[code:1:$uid]" . $before_replace . "[/code:1:$uid]";
 610   
 611          $replacement = $code_start_html;
 612          $replacement .= $after_replace;
 613          $replacement .= $code_end_html;
 614   
 615          $text = str_replace($str_to_match, $replacement, $text);
 616      }
 617   
 618      // Now, do all the non-first-level matches. These are simple.
 619      $text = str_replace("[code:$uid]", $code_start_html, $text);
 620      $text = str_replace("[/code:$uid]", $code_end_html, $text);
 621   
 622      return $text;
 623   
 624  } // bbencode_second_pass_code()
 625   
 626  /**
 627   * Rewritten by Nathan Codding - Feb 6, 2001.
 628   * - Goes through the given string, and replaces xxxx://yyyy with an HTML <a> tag linking
 629   *     to that URL
 630   * - Goes through the given string, and replaces www.xxxx.yyyy[zzzz] with an HTML <a> tag linking
 631   *     to http://www.xxxx.yyyy[/zzzz]
 632   * - Goes through the given string, and replaces xxxx@yyyy with an HTML mailto: tag linking
 633   *        to that email address
 634   * - Only matches these 2 patterns either after a space, or at the beginning of a line
 635   *
 636   * Notes: the email one might get annoying - it's easy to make it more restrictive, though.. maybe
 637   * have it require something like xxxx@yyyy.zzzz or such. We'll see.
 638   */
 639  function make_clickable($text)
 640  {
 641      $text = preg_replace('#(script|about|applet|activex|chrome):#is', "\\1&#058;", $text);
 642   
 643      // pad it with a space so we can match things at the start of the 1st line.
 644      $ret = ' ' . $text;
 645   
 646      // matches an "xxxx://yyyy" URL at the start of a line, or after a space.
 647      // xxxx can only be alpha characters.
 648      // yyyy is anything up to the first space, newline, comma, double quote or <
 649      $ret = preg_replace("#(^|[\n ])([\w]+?://[\w\#$%&~/.\-;:=,?@\[\]+]*)#is", "\\1<a href=\"\\2\" target=\"_blank\">\\2</a>", $ret);
 650   
 651      // matches a "www|ftp.xxxx.yyyy[/zzzz]" kinda lazy URL thing
 652      // Must contain at least 2 dots. xxxx contains either alphanum, or "-"
 653      // zzzz is optional.. will contain everything up to the first space, newline, 
 654      // comma, double quote or <.
 655      $ret = preg_replace("#(^|[\n ])((www|ftp)\.[\w\#$%&~/.\-;:=,?@\[\]+]*)#is", "\\1<a href=\"http://\\2\" target=\"_blank\">\\2</a>", $ret);
 656   
 657      // matches an email@domain type address at the start of a line, or after a space.
 658      // Note: Only the followed chars are valid; alphanums, "-", "_" and or ".".
 659      $ret = preg_replace("#(^|[\n ])([a-z0-9&\-_.]+?)@([\w\-]+\.([\w\-\.]+\.)*[\w]+)#i", "\\1<a href=\"mailto:\\2@\\3\">\\2@\\3</a>", $ret);
 660   
 661      // Remove our padding..
 662      $ret = substr($ret, 1);
 663   
 664      return($ret);
 665  }
 666   
 667  /**
 668   * Nathan Codding - Feb 6, 2001
 669   * Reverses the effects of make_clickable(), for use in editpost.
 670   * - Does not distinguish between "www.xxxx.yyyy" and "http://aaaa.bbbb" type URLs.
 671   *
 672   */
 673  function undo_make_clickable($text)
 674  {
 675      $text = preg_replace("#<!-- BBCode auto-link start --><a href=\"(.*?)\" target=\"_blank\">.*?</a><!-- BBCode auto-link end -->#i", "\\1", $text);
 676      $text = preg_replace("#<!-- BBcode auto-mailto start --><a href=\"mailto:(.*?)\">.*?</a><!-- BBCode auto-mailto end -->#i", "\\1", $text);
 677   
 678      return $text;
 679   
 680  }
 681   
 682  /**
 683   * Nathan Codding - August 24, 2000.
 684   * Takes a string, and does the reverse of the PHP standard function
 685   * htmlspecialchars().
 686   */
 687  function undo_htmlspecialchars($input)
 688  {
 689      $input = preg_replace("/&gt;/i", ">", $input);
 690      $input = preg_replace("/&lt;/i", "<", $input);
 691      $input = preg_replace("/&quot;/i", "\"", $input);
 692      $input = preg_replace("/&amp;/i", "&", $input);
 693   
 694      return $input;
 695  }
 696   
 697  /**
 698   * This is used to change a [*] tag into a [*:$uid] tag as part
 699   * of the first-pass bbencoding of [list] tags. It fits the
 700   * standard required in order to be passed as a variable
 701   * function into bbencode_first_pass_pda().
 702   */
 703  function replace_listitems($text, $uid)
 704  {
 705      $text = str_replace("[*]", "[*:$uid]", $text);
 706   
 707      return $text;
 708  }
 709   
 710  /**
 711   * Escapes the "/" character with "\/". This is useful when you need
 712   * to stick a runtime string into a PREG regexp that is being delimited
 713   * with slashes.
 714   */
 715  function escape_slashes($input)
 716  {
 717      $output = str_replace('/', '\/', $input);
 718      return $output;
 719  }
 720   
 721  /**
 722   * This function does exactly what the PHP4 function array_push() does
 723   * however, to keep phpBB compatable with PHP 3 we had to come up with our own
 724   * method of doing it.
 725   * This function was deprecated in phpBB 2.0.18
 726   */
 727  function bbcode_array_push(&$stack, $value)
 728  {
 729     $stack[] = $value;
 730     return(sizeof($stack));
 731  }
 732   
 733  /**
 734   * This function does exactly what the PHP4 function array_pop() does
 735   * however, to keep phpBB compatable with PHP 3 we had to come up with our own
 736   * method of doing it.
 737   * This function was deprecated in phpBB 2.0.18
 738   */
 739  function bbcode_array_pop(&$stack)
 740  {
 741     $arrSize = count($stack);
 742     $x = 1;
 743   
 744     while(list($key, $val) = each($stack))
 745     {
 746        if($x < count($stack))
 747        {
 748               $tmpArr[] = $val;
 749        }
 750        else
 751        {
 752               $return_val = $val;
 753        }
 754        $x++;
 755     }
 756     $stack = $tmpArr;
 757   
 758     return($return_val);
 759  }
 760   
 761  //
 762  // Smilies code ... would this be better tagged on to the end of bbcode.php?
 763  // Probably so and I'll move it before B2
 764  //
 765  function smilies_pass($message)
 766  {
 767      static $orig, $repl;
 768   
 769      if (!isset($orig))
 770      {
 771          global $db, $board_config;
 772          $orig = $repl = array();
 773   
 774          $sql = 'SELECT * FROM ' . SMILIES_TABLE;
 775          if( !$result = $db->sql_query($sql) )
 776          {
 777              message_die(GENERAL_ERROR, "Couldn't obtain smilies data", "", __LINE__, __FILE__, $sql);
 778          }
 779          $smilies = $db->sql_fetchrowset($result);
 780   
 781          if (count($smilies))
 782          {
 783              usort($smilies, 'smiley_sort');
 784          }
 785   
 786          for ($i = 0; $i < count($smilies); $i++)
 787          {
 788              $orig[] = "/(?<=.\W|\W.|^\W)" . preg_quote($smilies[$i]['code'], "/") . "(?=.\W|\W.|\W$)/";
 789              $repl[] = '<img src="'. $board_config['smilies_path'] . '/' . $smilies[$i]['smile_url'] . '" alt="' . $smilies[$i]['emoticon'] . '" border="0" />';
 790          }
 791      }
 792   
 793      if (count($orig))
 794      {
 795          $message = preg_replace($orig, $repl, ' ' . $message . ' ');
 796          $message = substr($message, 1, -1);
 797      }
 798      
 799      return $message;
 800  }
 801   
 802  function smiley_sort($a, $b)
 803  {
 804      if ( strlen($a['code']) == strlen($b['code']) )
 805      {
 806          return 0;
 807      }
 808   
 809      return ( strlen($a['code']) > strlen($b['code']) ) ? -1 : 1;
 810  }
 811   
 812  ?>