* Jaime GÓMEZ OBREGÓN (jaime@iteisa.com) * * Parts Copyright (c) Bruno Torres and * The phpBB Group * * Licensed under The GPL License * Redistributions of files must retain the above copyright notice. * * @filesource * @copyright Copyright (c) 2006, ITEISA, Bruno Torres and The phpBB Group. * @link http://www.iteisa.com/phpbb2bbpress/ * @license http://www.gnu.org/copyleft/gpl.html */ /* * DISCLAIMER * ========== * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * * This software has been tested only on my own configuration and needs. * YOUR MILEAGE MAY VARY. Feel free to report any bugs or enhacements to * * ALWAYS BACKUP ALL OF THE RELATED DATABASES BEFORE USE * USE AT YOUR OWN RISK * * FEATURES * ======== * This is an enhaced version of Bruno Torres' converter. I added some features and bugfixes * to improve the conversion. Now it converts bbCode (yes, all that :wink: :roll: :-? :evil: * mad thing) to plain text equivalents and to the XHTML when allowed by bbPress (currently * a em strong code ul ol li and blockquote). Also preserves new line codes. * * Finally, it also takes care and imports topics marked as CLOSED, STICKY and ANNOUNCEMENT * as such. * * USAGE * ===== * Change this source to match your database user, password and names. Then run the script * and import the generated SQL file on a FRESH NEW bbPress installation by means of your * favourite interface for your machine's MySQL server (phpMyAdmin, command line, etc). * * TODO * ==== * * - Make
  • elements inside lists XHTML compliant (bbCode doesn't provide a
  • closing tag). * - All users are imported with Member role. This is not usually very important, but should be fixed. * - Maybe create a bbPress plugin ?. * */ /* * CONFIGURATION SECTION */ define('DB_PHPBB_HOSTNAME', 'localhost'); define('DB_PHPBB_USERNAME', 'root'); define('DB_PHPBB_PASSWORD', ''); define('DB_PHPBB_DATABASE', 'Test_phpbb'); define('DB_PHPBB_TABLEPREFIX', 'phpbb_'); define('DB_BBPRESS_HOSTNAME', 'localhost'); define('DB_BBPRESS_USERNAME', 'root'); define('DB_BBPRESS_PASSWORD', ''); define('DB_BBPRESS_DATABASE', 'Test_bbpress'); define('DB_BBPRESS_TABLEPREFIX', 'bb_'); define('I18N_QUOTE', 'Cita'); // Prefix to quotations. define('I18N_WROTE', 'Escribió'); // Prefix to attributed quotations, like this: "John Doe wrote". define('I18N_CODE', 'Código'); // Prefix to code blocks. define('EXPORT_TO_FILE', true); // Should the converted DB be exported to a file ? define('FILENAME', '/temp.sql'); // Which one ? (Ensure this path is writeable by the server) define('AUTO_IMPORT_EXPORTED_DATA', false); // Should the script automagically import the converted DB ? $smilies = array( ':lol:' => 'X-D', ':shock:' => '8-O', ':oops:' => ':-//', ':cry:' => ':\'(', ':wink:' => ';-)', ':roll:' => '', ':twisted:' => '}:-)', ':evil:' => '}:-@', ':arrow:' => '->', ':mrgreen:' => ':-D', ':green:' => ':-D', ':smile:' => ':-)', ':mad:' => ':-x', ':neutral:' => ':-|', ':razz:' => ':-P', ':cool:' => '8-)', ':sad:' => ':-(', ':eek:' => ':-O', ':idea:' => '', ':|' => ':-|', ':!:' => '(!)', ':!!!:' => '(!)', ':?:' => ':-?', ':???:' => ':-?', ); // I set these as the minimum set which is both XHTML 1.1 compliant and bbPress supported. // I don't want the imported texts to be have any visual richness than can't be obtained from bbPress default post function. $templates = '
  • {USERNAME} {L_WROTE}:

    {DESCRIPTION} '; /* * END OF CONFIGURATION SECTION - STOP EDITING BEYOND THIS LINE */ set_time_limit(0); $bbcode_tpl = null; $phpbb_tables['forums'] = DB_PHPBB_TABLEPREFIX . 'forums'; $phpbb_tables['users'] = DB_PHPBB_TABLEPREFIX . 'users'; $phpbb_tables['topics'] = DB_PHPBB_TABLEPREFIX . 'topics'; $phpbb_tables['posts'] = DB_PHPBB_TABLEPREFIX . 'posts'; $phpbb_tables['posts_text'] = DB_PHPBB_TABLEPREFIX . 'posts_text'; $bbpress_tables['forums'] = DB_BBPRESS_TABLEPREFIX . 'forums'; $bbpress_tables['users'] = DB_BBPRESS_TABLEPREFIX . 'users'; $bbpress_tables['usermeta'] = DB_BBPRESS_TABLEPREFIX . 'usermeta'; $bbpress_tables['topics'] = DB_BBPRESS_TABLEPREFIX . 'topics'; $bbpress_tables['posts'] = DB_BBPRESS_TABLEPREFIX . 'posts'; ?> phpBB to bbPress database converter

    phpBB to bbPress database converter

    This script can convert a PhpBB 2.0.X (www.phpbb.com) forum database to bbPress "Bix" 0.73 (www.bbpress.org) format.

    Developed by Jaime GÓMEZ OBREGÓN from ITEISA, based on the previous work of Bruno Torres and The phpBB Group.

    The latest version of this file can be found on http://www.iteisa.com/phpbb2bbpress/.

    Starting conversion

      Unable to connect to the phpBB database

      ".mysql_error()."
      "); echo "
    1. Connected to the phpBB database host

    2. "; flush(); @mysql_select_db(DB_PHPBB_DATABASE) or die("
    3. Unable to select the phpBB database

      ".mysql_error()."
    4. "); echo "
    5. Selected the phpBB database

    6. "; flush(); $export_sql = "SELECT forum_id, forum_name, forum_desc, forum_topics, forum_posts FROM " . $phpbb_tables['forums']; $export_result = mysql_query($export_sql) or die("
    7. Unable to retrieve the data from the phpBB forums table

      $export_sql

      ".mysql_error()."
    8. "); mysql_query($export_sql); $import_sql = "#Exporting Forums data: \n"; while($export_row = mysql_fetch_object($export_result)){ $import_sql .= "INSERT INTO " . $bbpress_tables['forums'] . " (forum_id, forum_name, forum_desc, forum_order, topics, posts) VALUES (" . $export_row->forum_id . ", '" . addslashes($export_row->forum_name) . "', '" . addslashes($export_row->forum_desc) . "', " . $export_row->forum_order . ", " . $export_row->forum_topics . ", " . $export_row->forum_posts . ");\n"; } echo "
    9. Exporting forums...

    10. "; flush(); //Now, to the users $export_sql = "SELECT user_id, username, user_password, user_email, user_website, user_regdate FROM " . $phpbb_tables['users']; $export_result = mysql_query($export_sql) or die("
    11. Unable to retrieve the data from the phpBB users table

      $export_sql

      ".mysql_error()."
    12. "); $import_sql .= "#Exporting Users data: \n"; while($export_row = mysql_fetch_object($export_result)) { $user_id = $export_row->user_id; //User ID = -1 seem to cause such a confusion. So we'll change it to a very big number if ($user_id == -1) $user_id = 999999998; $regdate = date("Y-m-d H:i:s", $export_row->user_regdate); $import_sql .= "INSERT INTO " . $bbpress_tables['users'] . " (ID, user_login, user_pass, user_nicename, user_email, user_url, user_registered, user_status, display_name) VALUES (" . $user_id . ", '" . addslashes($export_row->username) . "', '" . $export_row->user_password . "', '', '" . $export_row->user_email . "', '" . $export_row->user_website . "', '$regdate', 0, '" . addslashes($export_row->username) . "');\n"; } echo "
    13. Exporting users...

    14. "; flush(); //Users meta data //Obs: All users imported will be flagged as "members" //You can change this later from bbPress Admin Panel //using your already registered admin user $export_sql = "SELECT user_id, user_from, user_occ, user_interests FROM " . $phpbb_tables['users']; $export_result = mysql_query($export_sql) or die("
    15. Unable to retrieve the data from the phpBB users table

      $export_sql

      ".mysql_error()."
    16. "); $import_sql .= "#Exporting Users meta data: \n"; while($export_row = mysql_fetch_object($export_result)){ $user_id = $export_row->user_id; //User ID = -1 seem to cause such a confusion. So we'll change it to a very big number if ($user_id == -1) $user_id = 999999998; //capabilities $import_sql .= "INSERT INTO " . $bbpress_tables['usermeta'] . "(user_id, meta_key, meta_value) VALUES (" . $user_id . ", 'bb_capabilities', 'a:1:{s:6:\"member\";b:1;}');\n"; //From $import_sql .= "INSERT INTO " . $bbpress_tables['usermeta'] . "(user_id, meta_key, meta_value) VALUES (" . $user_id . ", 'from', '" . addslashes($export_row->user_from) . "');\n"; //Occupation $import_sql .= "INSERT INTO " . $bbpress_tables['usermeta'] . "(user_id, meta_key, meta_value) VALUES (" . $user_id . ", 'occ', '" . addslashes($export_row->user_occ) . "');\n"; //Interests $import_sql .= "INSERT INTO " . $bbpress_tables['usermeta'] . "(user_id, meta_key, meta_value) VALUES (" . $user_id . ", 'interest', '" . addslashes($export_row->user_interests) . "');\n"; } echo "
    17. Exporting user metadata...

    18. "; flush(); //Importing topics $export_sql = "SELECT * FROM " . $phpbb_tables['topics']; $export_result = mysql_query($export_sql) or die("
    19. Unable to retrieve the data from the phpBB topics table

      $export_sql

      ".mysql_error()."
    20. "); $import_sql .= "#Exporting Topics: \n"; while($export_row = mysql_fetch_object($export_result)){ $topic_poster_name = phpbb_username($export_row->topic_poster); $topic_last_poster = phpbb_post_user($export_row->topic_last_post_id); $topic_last_poster_name = phpbb_username($topic_last_poster); $topic_start_time = date("Y-m-d H:i:s", phpbb_post_time($export_row->topic_first_post_id)); $topic_time = date("Y-m-d H:i:s", $export_row->topic_time); $topic_sticky = 0; $topic_open = 0; if ($export_row->topic_status == 1) { if ($export_row->topic_type == 1) { $topic_open = 1; $topic_sticky = 1; } else { $topic_open = 0; $topic_sticky = 0; } } else { if ($export_row->topic_type == 2) { $topic_open = 1; $topic_sticky = 1; } else { $topic_open = 1; $topic_sticky = 0; } } $import_sql .= "INSERT INTO " . $bbpress_tables['topics'] . " (topic_id, topic_title, topic_poster, topic_poster_name, topic_last_poster, topic_last_poster_name, topic_start_time, topic_time, forum_id, topic_status, topic_resolved, topic_open, topic_last_post_id, topic_sticky, topic_posts, tag_count) VALUES ( " . $export_row->topic_id . ", '" . addslashes($export_row->topic_title) . "', " . $export_row->topic_poster . ", '" . addslashes($topic_poster_name) . "', " . addslashes($topic_last_poster) . ", '" . addslashes($topic_last_poster_name) . "', '" . $topic_start_time . "', '" . $topic_time . "', " . $export_row->forum_id . ", 0, 'no', ".($topic_open).", " . $export_row->topic_last_post_id . ", ".$topic_sticky.", " . ($export_row->topic_replies + 1) . ", 0);\n"; } echo "
    21. Exporting topics...

    22. "; flush(); //Importing posts $export_sql = "SELECT " . $phpbb_tables['posts'] . ".post_id AS post_id, " . $phpbb_tables['posts'] . ".forum_id AS forum_id, " . $phpbb_tables['posts'] . ".topic_id AS topic_id, " . $phpbb_tables['posts'] . ".poster_id AS poster_id, " . $phpbb_tables['posts'] . ".post_time AS post_time, " . $phpbb_tables['posts'] . ".poster_ip AS poster_ip, " . $phpbb_tables['posts'] . ".bbcode_uid AS bbcode_uid, " . $phpbb_tables['posts'] . ".post_text AS post_text FROM " . $phpbb_tables['posts']; $export_result = mysql_query($export_sql) or die("
    23. Unable to retrieve the data from the phpBB posts and posts_text tables

      $export_sql

      ".mysql_error()."
    24. "); $import_sql .= "#Exporting Posts: \n"; while($export_row = mysql_fetch_object($export_result)) { $post_time = date("Y-m-d H:i:s", $export_row->post_time); $import_sql .= "INSERT INTO " . $bbpress_tables['posts'] . " (post_id, forum_id, topic_id, poster_id, post_text, post_time, poster_ip, post_status, post_position) VALUES ( " . $export_row->post_id . ", " . $export_row->forum_id . ", " . $export_row->topic_id . ", " . $export_row->poster_id . ", '" . addslashes(bbencode_second_pass(smilies_pass(nl2br($export_row->post_text)), $export_row->bbcode_uid)) . "', '" . $post_time . "', '" . $export_row->poster_ip . "', 0, 1 );\n"; } echo "
    25. Exporting posts...

    26. "; $sql_file = $_SERVER['DOCUMENT_ROOT'].FILENAME; // DISCLAIMER: This is a joke echo "
    27. Sending all your database e-mails to all major world-wide spam sending mafias...

    28. "; if (EXPORT_TO_FILE) { if (file_put_contents($sql_file, utf8_encode($import_sql))) { echo "
    29. Writing the exported database to the file: $sql_file

    30. "; flush(); } else { echo "
    31. Unable to write to file: $sql_file. Please, check writing permissions

    32. "; flush(); } } if (AUTO_IMPORT_EXPORTED_DATA) { @mysql_connect(DB_BBPRESS_HOSTNAME, DB_BBPRESS_USERNAME, DB_BBPRESS_PASSWORD) or die("
    33. Unable to connect to the bbPress database

      ".mysql_error()."
    34. "); @mysql_select_db(DB_BBPRESS_DATABASE) or die("
    35. Unable to select the bbPress database

      ".mysql_error()."
    36. "); //Let's clean up the trash. //Your admin user will be given the biggest possible ID (I tried the biggest BIGINT but it didn't work inside bbPress) //If you have more than 999999999 users on your forum, you may have problems... ;-) @mysql_query ("UPDATE " . $bbpress_tables['users'] . " SET ID=999999999 WHERE ID=1"); @mysql_query ("UPDATE " . $bbpress_tables['usermeta'] . " SET user_id=999999999 WHERE user_id=1"); @mysql_query("TRUNCATE TABLE " . $bbpress_tables['forums']); @mysql_query("TRUNCATE TABLE " . $bbpress_tables['topics']); @mysql_query("TRUNCATE TABLE " . $bbpress_tables['posts']); //Now we'll break our SQL in an array of single INSERT instructions and will //apply them one by one. $import_sql = utf8_encode($import_sql); $import_sql_array = explode(";\n", $import_sql); echo "
    37. Importing the generated database...

      "; flush(); $ok = 0; $error = 0; foreach ($import_sql_array as $s) { if (!@mysql_query($s)){ echo "
    38. Warning, there was an error with the following query

      $s

      ".mysql_error()."
    39. "; flush(); $error++; } else { $ok++; } } // echo "Import has finished.
      \nStatistics:
      \n$ok successful, $error errors"; // flush(); } ?>
    (.*?)#', "\n" . '$bbcode_tpls[\'\\1\'] = \'\\2\';', $tpl); $bbcode_tpls = array(); eval($tpl); $bbcode_tpl = $bbcode_tpls; $bbcode_tpl['olist_open'] = str_replace('{LIST_TYPE}', '\\1', $bbcode_tpl['olist_open']); $bbcode_tpl['color_open'] = str_replace('{COLOR}', '\\1', $bbcode_tpl['color_open']); $bbcode_tpl['size_open'] = str_replace('{SIZE}', '\\1', $bbcode_tpl['size_open']); $bbcode_tpl['quote_open'] = str_replace('{L_QUOTE}', utf8_decode(I18N_QUOTE), $bbcode_tpl['quote_open']); $bbcode_tpl['quote_username_open'] = str_replace('{L_QUOTE}', utf8_decode(I18N_QUOTE), $bbcode_tpl['quote_username_open']); $bbcode_tpl['quote_username_open'] = str_replace('{L_WROTE}', utf8_decode(I18N_WROTE), $bbcode_tpl['quote_username_open']); $bbcode_tpl['quote_username_open'] = str_replace('{USERNAME}', '\\1', $bbcode_tpl['quote_username_open']); $bbcode_tpl['code_open'] = str_replace('{L_CODE}', utf8_decode(I18N_CODE), $bbcode_tpl['code_open']); $bbcode_tpl['img'] = str_replace('{URL}', '\\1', $bbcode_tpl['img']); // URLs are done in several different ways. $bbcode_tpl['url1'] = str_replace('{URL}', '\\1', $bbcode_tpl['url']); $bbcode_tpl['url1'] = str_replace('{DESCRIPTION}', '\\1', $bbcode_tpl['url1']); $bbcode_tpl['url2'] = str_replace('{URL}', 'http://\\1', $bbcode_tpl['url']); $bbcode_tpl['url2'] = str_replace('{DESCRIPTION}', '\\1', $bbcode_tpl['url2']); $bbcode_tpl['url3'] = str_replace('{URL}', '\\1', $bbcode_tpl['url']); $bbcode_tpl['url3'] = str_replace('{DESCRIPTION}', '\\2', $bbcode_tpl['url3']); $bbcode_tpl['url4'] = str_replace('{URL}', 'http://\\1', $bbcode_tpl['url']); $bbcode_tpl['url4'] = str_replace('{DESCRIPTION}', '\\3', $bbcode_tpl['url4']); $bbcode_tpl['email'] = str_replace('{EMAIL}', '\\1', $bbcode_tpl['email']); define('BBCODE_TPL_READY', true); } // [CODE] and [/CODE] for posting code (HTML, PHP, C etc etc) in your posts. $text = bbencode_second_pass_code($text, $uid, $bbcode_tpl); // [QUOTE] and [/QUOTE] for posting replies with quote, or just for quoting stuff. $text = str_replace("[quote:$uid]", $bbcode_tpl['quote_open'], $text); $text = str_replace("[/quote:$uid]", $bbcode_tpl['quote_close'], $text); // New one liner to deal with opening quotes with usernames... // replaces the two line version that I had here before.. $text = preg_replace("/\[quote:$uid=\"(.*?)\"\]/si", $bbcode_tpl['quote_username_open'], $text); // [list] and [list=x] for (un)ordered lists. // unordered lists $text = str_replace("[list:$uid]", $bbcode_tpl['ulist_open'], $text); // li tags $text = str_replace("[*:$uid]", $bbcode_tpl['listitem'], $text); // ending tags $text = str_replace("[/list:u:$uid]", $bbcode_tpl['ulist_close'], $text); $text = str_replace("[/list:o:$uid]", $bbcode_tpl['olist_close'], $text); // Ordered lists $text = preg_replace("/\[list=([a1]):$uid\]/si", $bbcode_tpl['olist_open'], $text); // colours $text = preg_replace("/\[color=(\#[0-9A-F]{6}|[a-z]+):$uid\]/si", $bbcode_tpl['color_open'], $text); $text = str_replace("[/color:$uid]", $bbcode_tpl['color_close'], $text); // size $text = preg_replace("/\[size=([1-2]?[0-9]):$uid\]/si", $bbcode_tpl['size_open'], $text); $text = str_replace("[/size:$uid]", $bbcode_tpl['size_close'], $text); // [b] and [/b] for bolding text. $text = str_replace("[b:$uid]", $bbcode_tpl['b_open'], $text); $text = str_replace("[/b:$uid]", $bbcode_tpl['b_close'], $text); // [u] and [/u] for underlining text. $text = str_replace("[u:$uid]", $bbcode_tpl['u_open'], $text); $text = str_replace("[/u:$uid]", $bbcode_tpl['u_close'], $text); // [i] and [/i] for italicizing text. $text = str_replace("[i:$uid]", $bbcode_tpl['i_open'], $text); $text = str_replace("[/i:$uid]", $bbcode_tpl['i_close'], $text); // Patterns and replacements for URL and email tags.. $patterns = array(); $replacements = array(); // [img]image_url_here[/img] code.. // This one gets first-passed.. $patterns[] = "#\[img:$uid\]([^?].*?)\[/img:$uid\]#i"; $replacements[] = $bbcode_tpl['img']; // matches a [url]xxxx://www.phpbb.com[/url] code.. $patterns[] = "#\[url\]([\w]+?://[\w\#$%&~/.\-;:=,?@\[\]+]*?)\[/url\]#is"; $replacements[] = $bbcode_tpl['url1']; // [url]www.phpbb.com[/url] code.. (no xxxx:// prefix). $patterns[] = "#\[url\]((www|ftp)\.[\w\#$%&~/.\-;:=,?@\[\]+]*?)\[/url\]#is"; $replacements[] = $bbcode_tpl['url2']; // [url=xxxx://www.phpbb.com]phpBB[/url] code.. $patterns[] = "#\[url=([\w]+?://[\w\#$%&~/.\-;:=,?@\[\]+]*?)\]([^?\n\r\t].*?)\[/url\]#is"; $replacements[] = $bbcode_tpl['url3']; // [url=www.phpbb.com]phpBB[/url] code.. (no xxxx:// prefix). $patterns[] = "#\[url=((www|ftp)\.[\w\#$%&~/.\-;:=,?@\[\]+]*?)\]([^?\n\r\t].*?)\[/url\]#is"; $replacements[] = $bbcode_tpl['url4']; // [email]user@domain.tld[/email] code.. $patterns[] = "#\[email\]([a-z0-9&\-_.]+?@[\w\-]+\.([\w\-\.]+\.)?[\w]+)\[/email\]#si"; $replacements[] = $bbcode_tpl['email']; $text = preg_replace($patterns, $replacements, $text); // Remove our padding from the string.. $text = substr($text, 1); return $text; } function bbencode_first_pass($text, $uid) { // pad it with a space so we can distinguish between FALSE and matching the 1st char (index 0). // This is important; bbencode_quote(), bbencode_list(), and bbencode_code() all depend on it. $text = " " . $text; // [CODE] and [/CODE] for posting code (HTML, PHP, C etc etc) in your posts. $text = bbencode_first_pass_pda($text, $uid, '[code]', '[/code]', '', true, ''); // [QUOTE] and [/QUOTE] for posting replies with quote, or just for quoting stuff. $text = bbencode_first_pass_pda($text, $uid, '[quote]', '[/quote]', '', false, ''); $text = bbencode_first_pass_pda($text, $uid, '/\[quote=(\\\".*?\\\")\]/is', '[/quote]', '', false, '', "[quote:$uid=\\1]"); // [list] and [list=x] for (un)ordered lists. $open_tag = array(); $open_tag[0] = "[list]"; // unordered.. $text = bbencode_first_pass_pda($text, $uid, $open_tag, "[/list]", "[/list:u]", false, 'replace_listitems'); $open_tag[0] = "[list=1]"; $open_tag[1] = "[list=a]"; // ordered. $text = bbencode_first_pass_pda($text, $uid, $open_tag, "[/list]", "[/list:o]", false, 'replace_listitems'); // [color] and [/color] for setting text color $text = preg_replace("#\[color=(\#[0-9A-F]{6}|[a-z\-]+)\](.*?)\[/color\]#si", "[color=\\1:$uid]\\2[/color:$uid]", $text); // [size] and [/size] for setting text size $text = preg_replace("#\[size=([1-2]?[0-9])\](.*?)\[/size\]#si", "[size=\\1:$uid]\\2[/size:$uid]", $text); // [b] and [/b] for bolding text. $text = preg_replace("#\[b\](.*?)\[/b\]#si", "[b:$uid]\\1[/b:$uid]", $text); // [u] and [/u] for underlining text. $text = preg_replace("#\[u\](.*?)\[/u\]#si", "[u:$uid]\\1[/u:$uid]", $text); // [i] and [/i] for italicizing text. $text = preg_replace("#\[i\](.*?)\[/i\]#si", "[i:$uid]\\1[/i:$uid]", $text); // [img]image_url_here[/img] code.. $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); // Remove our padding from the string. return substr($text, 1);; } /** * $text - The text to operate on. * $uid - The UID to add to matching tags. * $open_tag - The opening tag to match. Can be an array of opening tags. * $close_tag - The closing tag to match. * $close_tag_new - The closing tag to replace with. * $mark_lowest_level - boolean - should we specially mark the tags that occur * at the lowest level of nesting? (useful for [code], because * we need to match these tags first and transform HTML tags * in their contents.. * $func - This variable should contain a string that is the name of a function. * That function will be called when a match is found, and passed 2 * parameters: ($text, $uid). The function should return a string. * This is used when some transformation needs to be applied to the * text INSIDE a pair of matching tags. If this variable is FALSE or the * empty string, it will not be executed. * If open_tag is an array, then the pda will try to match pairs consisting of * any element of open_tag followed by close_tag. This allows us to match things * like [list=A]...[/list] and [list=1]...[/list] in one pass of the PDA. * * NOTES: - this function assumes the first character of $text is a space. * - every opening tag and closing tag must be of the [...] format. */ function bbencode_first_pass_pda($text, $uid, $open_tag, $close_tag, $close_tag_new, $mark_lowest_level, $func, $open_regexp_replace = false) { $open_tag_count = 0; if (!$close_tag_new || ($close_tag_new == '')) $close_tag_new = $close_tag; $close_tag_length = strlen($close_tag); $close_tag_new_length = strlen($close_tag_new); $uid_length = strlen($uid); $use_function_pointer = ($func && ($func != '')); $stack = array(); if (is_array($open_tag)) { if (0 == count($open_tag)) { // No opening tags to match, so return. return $text; } $open_tag_count = count($open_tag); } else { // only one opening tag. make it into a 1-element array. $open_tag_temp = $open_tag; $open_tag = array(); $open_tag[0] = $open_tag_temp; $open_tag_count = 1; } $open_is_regexp = false; if ($open_regexp_replace) { $open_is_regexp = true; if (!is_array($open_regexp_replace)) { $open_regexp_temp = $open_regexp_replace; $open_regexp_replace = array(); $open_regexp_replace[0] = $open_regexp_temp; } } if ($mark_lowest_level && $open_is_regexp) { die('Unsupported operation for bbcode_first_pass_pda().'); } // Start at the 2nd char of the string, looking for opening tags. $curr_pos = 1; while ($curr_pos && ($curr_pos < strlen($text))) { $curr_pos = strpos($text, "[", $curr_pos); // If not found, $curr_pos will be 0, and the loop will end. if ($curr_pos) { // We found a [. It starts at $curr_pos. // check if it's a starting or ending tag. $found_start = false; $which_start_tag = ""; $start_tag_index = -1; for ($i = 0; $i < $open_tag_count; $i++) { // Grab everything until the first "]"... $possible_start = substr($text, $curr_pos, strpos($text, ']', $curr_pos + 1) - $curr_pos + 1); // We're going to try and catch usernames with "[' characters. if( preg_match('#\[quote=\\\"#si', $possible_start, $match) && !preg_match('#\[quote=\\\"(.*?)\\\"\]#si', $possible_start) ) { // OK we are in a quote tag that probably contains a ] bracket. // Grab a bit more of the string to hopefully get all of it.. if ($close_pos = strpos($text, '"]', $curr_pos + 9)) { if (strpos(substr($text, $curr_pos + 9, $close_pos - ($curr_pos + 9)), '[quote') === false) { $possible_start = substr($text, $curr_pos, $close_pos - $curr_pos + 2); } } } // Now compare, either using regexp or not. if ($open_is_regexp) { $match_result = array(); if (preg_match($open_tag[$i], $possible_start, $match_result)) { $found_start = true; $which_start_tag = $match_result[0]; $start_tag_index = $i; break; } } else { // straightforward string comparison. if (0 == strcasecmp($open_tag[$i], $possible_start)) { $found_start = true; $which_start_tag = $open_tag[$i]; $start_tag_index = $i; break; } } } if ($found_start) { // We have an opening tag. // 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. $match = array("pos" => $curr_pos, "tag" => $which_start_tag, "index" => $start_tag_index); array_push($stack, $match); // Rather than just increment $curr_pos // Set it to the ending of the tag we just found // Keeps error in nested tag from breaking out // of table structure.. $curr_pos += strlen($possible_start); } else { // check for a closing tag.. $possible_end = substr($text, $curr_pos, $close_tag_length); if (0 == strcasecmp($close_tag, $possible_end)) { // We have an ending tag. // Check if we've already found a matching starting tag. if (sizeof($stack) > 0) { // There exists a starting tag. $curr_nesting_depth = sizeof($stack); // We need to do 2 replacements now. $match = array_pop($stack); $start_index = $match['pos']; $start_tag = $match['tag']; $start_length = strlen($start_tag); $start_tag_index = $match['index']; if ($open_is_regexp) { $start_tag = preg_replace($open_tag[$start_tag_index], $open_regexp_replace[$start_tag_index], $start_tag); } // everything before the opening tag. $before_start_tag = substr($text, 0, $start_index); // everything after the opening tag, but before the closing tag. $between_tags = substr($text, $start_index + $start_length, $curr_pos - $start_index - $start_length); // Run the given function on the text between the tags.. if ($use_function_pointer) { $between_tags = $func($between_tags, $uid); } // everything after the closing tag. $after_end_tag = substr($text, $curr_pos + $close_tag_length); // Mark the lowest nesting level if needed. if ($mark_lowest_level && ($curr_nesting_depth == 1)) { if ($open_tag[0] == '[code]') { $code_entities_match = array('#<#', '#>#', '#"#', '#:#', '#\[#', '#\]#', '#\(#', '#\)#', '#\{#', '#\}#'); $code_entities_replace = array('<', '>', '"', ':', '[', ']', '(', ')', '{', '}'); $between_tags = preg_replace($code_entities_match, $code_entities_replace, $between_tags); } $text = $before_start_tag . substr($start_tag, 0, $start_length - 1) . ":$curr_nesting_depth:$uid]"; $text .= $between_tags . substr($close_tag_new, 0, $close_tag_new_length - 1) . ":$curr_nesting_depth:$uid]"; } else { if ($open_tag[0] == '[code]') { $text = $before_start_tag . '[code]'; $text .= $between_tags . '[/code]'; } else { if ($open_is_regexp) { $text = $before_start_tag . $start_tag; } else { $text = $before_start_tag . substr($start_tag, 0, $start_length - 1) . ":$uid]"; } $text .= $between_tags . substr($close_tag_new, 0, $close_tag_new_length - 1) . ":$uid]"; } } $text .= $after_end_tag; // Now.. we've screwed up the indices by changing the length of the string. // So, if there's anything in the stack, we want to resume searching just after it. // otherwise, we go back to the start. if (sizeof($stack) > 0) { $match = array_pop($stack); $curr_pos = $match['pos']; } else { $curr_pos = 1; } } else { // No matching start tag found. Increment pos, keep going. ++$curr_pos; } } else { // No starting tag or ending tag.. Increment pos, keep looping., ++$curr_pos; } } } } // while return $text; } /** * Does second-pass bbencoding of the [code] tags. This includes * running htmlspecialchars() over the text contained between * any pair of [code] tags that are at the first level of * nesting. Tags at the first level of nesting are indicated * by this format: [code:1:$uid] ... [/code:1:$uid] * Other tags are in this format: [code:$uid] ... [/code:$uid] */ function bbencode_second_pass_code($text, $uid, $bbcode_tpl) { $code_start_html = $bbcode_tpl['code_open']; $code_end_html = $bbcode_tpl['code_close']; // First, do all the 1st-level matches. These need an htmlspecialchars() run, // so they have to be handled differently. $match_count = preg_match_all("#\[code:1:$uid\](.*?)\[/code:1:$uid\]#si", $text, $matches); for ($i = 0; $i < $match_count; $i++) { $before_replace = $matches[1][$i]; $after_replace = $matches[1][$i]; // Replace 2 spaces with "  " so non-tabbed code indents without making huge long lines. $after_replace = str_replace(" ", "  ", $after_replace); // now Replace 2 spaces with "  " to catch odd #s of spaces. $after_replace = str_replace(" ", "  ", $after_replace); // Replace tabs with "   " so tabbed code indents sorta right without making huge long lines. $after_replace = str_replace("\t", "   ", $after_replace); // now Replace space occurring at the beginning of a line $after_replace = preg_replace("/^ {1}/m", ' ', $after_replace); $str_to_match = "[code:1:$uid]" . $before_replace . "[/code:1:$uid]"; $replacement = $code_start_html.$after_replace.$code_end_html; $text = str_replace($str_to_match, $replacement, $text); } // Now, do all the non-first-level matches. These are simple. $text = str_replace("[code:$uid]", $code_start_html, $text); $text = str_replace("[/code:$uid]", $code_end_html, $text); return $text; } /** * This is used to change a [*] tag into a [*:$uid] tag as part * of the first-pass bbencoding of [list] tags. It fits the * standard required in order to be passed as a variable * function into bbencode_first_pass_pda(). */ function replace_listitems($text, $uid) { return str_replace("[*]", "[*:$uid]", $text); } function smilies_pass($message) { global $smilies; $orig = $repl = array(); foreach ($smilies as $smily => $translation) { $orig[] = "/(?<=.\W|\W.|^\W)" . str_replace('/', '\\'.'/', preg_quote($smily))."(?=.\W|\W.|\W$)/"; $repl[] = $translation; } if (count($orig)) $message = substr(preg_replace($orig, $repl, ' ' . $message . ' '), 1, -1); return $message; } function phpbb_username($id) { global $phpbb_tables; $sql = "SELECT username FROM " . $phpbb_tables['users'] . " WHERE user_id=$id"; $result = mysql_query($sql); if ($row = mysql_fetch_object($result)){ return $row->username; } else { return false; } } function phpbb_post_user($post_id) { global $phpbb_tables; $sql = "SELECT poster_id FROM " . $phpbb_tables['posts'] . " WHERE post_id=$post_id"; $result = mysql_query($sql); if ($row = mysql_fetch_object($result)){ return $row->poster_id; } else { return false; } } function phpbb_post_time($post_id) { global $phpbb_tables; $sql = "SELECT post_time FROM " . $phpbb_tables['posts'] . " WHERE post_id=$post_id"; $result = mysql_query($sql); if ($row = mysql_fetch_object($result)){ return $row->post_time; } else { return false; } } ?>