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  ?>