<?php

if (!defined('BB_ROOT')) die(basename(__FILE__));

$datastore->enqueue(array(
	'smile_replacements',
));

$page_cfg['include_bbcode_js'] = true;

//
// BBCode templates
//
function get_bbcode_tpl ()
{
$bbcode_tpl = array();

// Quote
$bbcode_tpl['quote_open'] = <<<HTML
	<div class="q-wrap">
		<div class="q">
HTML;

$bbcode_tpl['quote_username_open'] = <<<HTML
	<div class="q-wrap">
		<div class="q" head="\\1">
HTML;

$bbcode_tpl['quote_close'] = <<<HTML
		</div>
	</div>
HTML;

// Code
$bbcode_tpl['code_open'] = <<<HTML
	<div class="c-wrap">
		<div class="c-body">
HTML;

$bbcode_tpl['code_close'] = <<<HTML
		</div>
	</div>
HTML;

// Spoiler
$bbcode_tpl['spoiler_open'] = <<<HTML
	<div class="sp-wrap">
		<div class="sp-body">
HTML;

$bbcode_tpl['spoiler_title_open'] = <<<HTML
	<div class="sp-wrap">
		<div class="sp-body" title="\\1">
		<h3 class="sp-title">\\1</h3>
HTML;

$bbcode_tpl['spoiler_close'] = <<<HTML
		</div>
	</div>
HTML;

// Image
$bbcode_tpl['img'] = <<<HTML
	<var class="postImg" title="$1">&#10;</var>
HTML;

$bbcode_tpl['img_aligned'] = <<<HTML
	<var class="postImg postImgAligned img-\\1" title="\\2">&#10;</var>
HTML;

// HR
$bbcode_tpl['hr'] = <<<HTML
	<span class="post-hr">-</span>
HTML;

array_deep($bbcode_tpl, 'bbcode_tpl_compact');
return $bbcode_tpl;
}

function bbcode_tpl_compact ($text)
{
	$text = str_compact($text);
	$text = str_replace('> <', '><', $text);
	return $text;
}

// prepare a posted message for entry into the database
function prepare_message ($message)
{
	$message = bbcode::clean_up($message);
	$message = htmlCHR($message, false, ENT_NOQUOTES);
	return $message;
}

// Fill smiley templates (or just the variables) with smileys
// Either in a window or inline
function generate_smilies($mode)
{
	global $bb_cfg, $template, $lang, $user, $datastore;

	$inline_columns = 4;
	$inline_rows = 7;
	$window_columns = 8;

	if ($mode == 'window')
	{
		$user->session_start();
	}

	$data = $datastore->get('smile_replacements');

	if ($sql = $data['smile'])
	{
		$num_smilies = 0;
		$rowset = array();
		foreach ($sql as $row)
		{
			if (empty($rowset[$row['smile_url']]))
			{
				$rowset[$row['smile_url']]['code'] = addslashes($row['code']);
				$rowset[$row['smile_url']]['emoticon'] = $row['emoticon'];
				$num_smilies++;
			}
		}

		if ($num_smilies)
		{
			$smilies_count = ($mode == 'inline') ? min(19, $num_smilies) : $num_smilies;
			$smilies_split_row = ($mode == 'inline') ? $inline_columns - 1 : $window_columns - 1;

			$s_colspan = 0;
			$row = 0;
			$col = 0;

			while (list($smile_url, $data) = @each($rowset))
			{
				if (!$col)
				{
					$template->assign_block_vars('smilies_row', array());
				}

				$template->assign_block_vars('smilies_row.smilies_col', array(
					'SMILEY_CODE' => $data['code'],
					'SMILEY_IMG' => $bb_cfg['smilies_path'] . '/' . $smile_url,
					'SMILEY_DESC' => $data['emoticon'],
				));

				$s_colspan = max($s_colspan, $col + 1);

				if ($col == $smilies_split_row)
				{
					if ($mode == 'inline' && $row == $inline_rows - 1)
					{
						break;
					}
					$col = 0;
					$row++;
				}
				else
				{
					$col++;
				}
			}

			if ($mode == 'inline' && $num_smilies > $inline_rows * $inline_columns)
			{
				$template->assign_block_vars('switch_smilies_extra', array());

				$template->assign_vars(array(
					'U_MORE_SMILIES' => POSTING_URL ."?mode=smilies",
				));
			}

			$template->assign_vars(array(
				'PAGE_TITLE' => $lang['EMOTICONS'],
				'S_SMILIES_COLSPAN' => $s_colspan,
			));
		}
	}

	if ($mode == 'window')
	{
		print_page('posting_smilies.tpl', 'simple');
	}
}

// some functions from vB
// #############################################################################
/**
* Strips away [quote] tags and their contents from the specified string
*
* @param	string	Text to be stripped of quote tags
*
* @return	string
*/
function strip_quotes ($text)
{
	$lowertext = strtolower($text);

	// find all [quote tags
	$start_pos = array();
	$curpos = 0;
	do
	{
		$pos = strpos($lowertext, '[quote', $curpos);
		if ($pos !== false)
		{
			$start_pos["$pos"] = 'start';
			$curpos = $pos + 6;
		}
	}
	while ($pos !== false);

	if (sizeof($start_pos) == 0)
	{
		return $text;
	}

	// find all [/quote] tags
	$end_pos = array();
	$curpos = 0;
	do
	{
		$pos = strpos($lowertext, '[/quote', $curpos);
		if ($pos !== false)
		{
			$end_pos["$pos"] = 'end';
			$curpos = $pos + 8;
		}
	}
	while ($pos !== false);

	if (sizeof($end_pos) == 0)
	{
		return $text;
	}

	// merge them together and sort based on position in string
	$pos_list = $start_pos + $end_pos;
	ksort($pos_list);

	do
	{
		// build a stack that represents when a quote tag is opened
		// and add non-quote text to the new string
		$stack = array();
		$newtext = '[...] ';
		$substr_pos = 0;
		foreach ($pos_list AS $pos => $type)
		{
			$stacksize = sizeof($stack);
			if ($type == 'start')
			{
				// empty stack, so add from the last close tag or the beginning of the string
				if ($stacksize == 0)
				{
					$newtext .= substr($text, $substr_pos, $pos - $substr_pos);
				}
				array_push($stack, $pos);
			}
			else
			{
				// pop off the latest opened tag
				if ($stacksize)
				{
					array_pop($stack);
					$substr_pos = $pos + 8;
				}
			}
		}

		// add any trailing text
		$newtext .= substr($text, $substr_pos);

		// check to see if there's a stack remaining, remove those points
		// as key points, and repeat. Allows emulation of a non-greedy-type
		// recursion.
		if ($stack)
		{
			foreach ($stack AS $pos)
			{
				unset($pos_list["$pos"]);
			}
		}
	}
	while ($stack);

	return $newtext;
}

// #############################################################################
/**
 * Strips away bbcode from a given string, leaving plain text
 *
 * @param	string	Text to be stripped of bbcode tags
 * @param	boolean	If true, strip away quote tags AND their contents
 * @param	boolean	If true, use the fast-and-dirty method rather than the shiny and nice method
 *
 * @return	string
 */
function strip_bbcode ($message, $stripquotes = true, $fast_and_dirty = false, $showlinks = true)
{
	$find = array();
	$replace = array();

	if ($stripquotes)
	{
		// [quote=username] and [quote]
		$message = strip_quotes($message);
	}

	// a really quick and rather nasty way of removing bbcode
	if ($fast_and_dirty)
	{
		// any old thing in square brackets
		$find[] = '#\[.*/?\]#siU';
		$replace = '';

		$message = preg_replace($find, $replace, $message);
	}
	// the preferable way to remove bbcode
	else
	{
		// simple links
		$find[] = '#\[(email|url)=("??)(.+)\\2\]\\3\[/\\1\]#siU';
		$replace[] = '\3';

		// named links
		$find[] = '#\[(email|url)=("??)(.+)\\2\](.+)\[/\\1\]#siU';
		$replace[] = ($showlinks ? '\4 (\3)' : '\4');

		// smilies
		$find[] = '#(?<=^|\W)(:\w+?:)(?=$|\W)#';
		$replace[] = '';

		// replace
		$message = preg_replace($find, $replace, $message);

		// strip out all other instances of [x]...[/x]
		while (preg_match('#\[([a-z]+)\s*?(?:[^\]]*?)\](.*?)(\[/\1\])#is', $message, $m))
		{
			$message = str_replace($m[0], $m[2], $message);
		}

		$replace = array('[*]', '[hr]', '[br]', '[align=center]', '[align=left]', '[align=right]');
		$message = str_replace($replace, ' ', $message);
	}

	return $message;
}

function extract_search_words ($text)
{
	global $bb_cfg;

	$max_words_count = $bb_cfg['max_search_words_per_post'];
	$min_word_len    = max(2, $bb_cfg['search_min_word_len'] - 1);
	$max_word_len    = $bb_cfg['search_max_word_len'];

	$text = ' ' . str_compact(strip_tags(mb_strtolower($text))) . ' ';
	$text = str_replace(array('&#91;', '&#93;'), array('[', ']'), $text);

	// HTML entities like &nbsp;
	$text = preg_replace('/(\w*?)&#?[0-9a-z]+;(\w*?)/iu', '', $text);
	// Remove URL's       ((www|ftp)\.[\w\#!$%&~/.\-;:=,?@а-яА-Я\[\]+]*?)
	$text = preg_replace('#\b[a-z0-9]+://[\w\#!$%&~/.\-;:=,?@а-яА-Я\[\]+]+(/[0-9a-z\?\.%_\-\+=&/]+)?#u', ' ', $text);
	$text = str_replace('[url=', ' ', $text);
	$text = str_replace('?', ' ', $text);
	$text = str_replace('!', ' ', $text);

	$text = strip_bbcode($text);

	// Filter out characters like ^, $, &, change "it's" to "its"
	$text = preg_replace('#[.,:;]#u', ' ', $text);

	// short & long words
	// $text = preg_replace('#(?<=^|\s)(\S{1,'.$min_word_len.'}|\S{'.$max_word_len.',}|\W*)(?=$|\s)#u', ' ', $text);

	$text = remove_stopwords($text);
#	$text = replace_synonyms($text);

	// Trim 1+ spaces to one space and split this string into unique words
	$text = array_unique(explode(' ', str_compact($text)));

	// short & long words 2
	$text_out = array();
	foreach ($text as $word)
	{
		if (mb_strlen($word) > $min_word_len && mb_strlen($word) <= $max_word_len) $text_out[] = $word;
	}
	$text = $text_out;

	if (sizeof($text) > $max_words_count)
	{
#		shuffle($text);
		$text = array_splice($text, 0, $max_words_count);
	}

	return $text;
}

function replace_synonyms ($text)
{
	static $syn_match = null, $syn_replace = null;

	if (is_null($syn_match))
	{
		preg_match_all("#(\w+) (\w+)(\r?\n|$)#", @file_get_contents(LANG_DIR .'search_synonyms.txt'), $m);

		$syn_match   = $m[2];
		$syn_replace = $m[1];

		array_deep($syn_match,   'pad_with_space');
		array_deep($syn_replace, 'pad_with_space');
	}

	return ($syn_match && $syn_replace) ? str_replace($syn_match, $syn_replace, $text) : $text;
}

function add_search_words ($post_id, $post_message, $topic_title = '', $only_return_words = false)
{
	global $bb_cfg;

	$text  = $topic_title .' '. $post_message;
	$words = ($text) ? extract_search_words($text) : array();

	if ($only_return_words || $bb_cfg['search_engine_type'] == 'sphinx')
	{
		return join("\n", $words);
	}
	else
	{
		DB()->query("DELETE FROM ". BB_POSTS_SEARCH ." WHERE post_id = $post_id");

		if ($words_sql = DB()->escape(join("\n", $words)))
		{
			DB()->query("REPLACE INTO ". BB_POSTS_SEARCH ." (post_id, search_words) VALUES ($post_id, '$words_sql')");
		}
	}
}

class bbcode
{
	var $tpl        = array(); // шаблоны для замены тегов
	var $smilies    = null;    // смайлы
	var $found_spam = null;    // найденные спам "слова"
	var $del_words  = array(); // см. get_words_rate()
	var $tidy_cfg   = array(
				'drop-empty-paras'  => false,
				'fix-uri'           => false,
				'force-output'      => true,
				'hide-comments'     => true,
				'join-classes'      => false,
				'join-styles'       => false,
				'merge-divs'        => false,
				'newline'           => 'LF',
				'output-xhtml'      => true,
				'preserve-entities' => true,
				'quiet'             => true,
				'quote-ampersand'   => false,
				'show-body-only'    => true,
				'show-errors'       => false,
				'show-warnings'     => false,
				'wrap'              => 0,
	);
	var $block_tags = array(
				'align',
				'br',
				'clear',
				'hr',
				'list',
				'pre',
				'quote',
				'spoiler',
	);
	var $preg        = array();
	var $str         = array();
	var $preg_search = array();
	var $preg_repl   = array();
	var $str_search  = array();
	var $str_repl    = array();

	/**
	* Constructor
	*/
	function bbcode ()
	{
		$this->tpl = get_bbcode_tpl();

		$this->init_replacements();
	}

	/**
	* init_replacements
	*/
	function init_replacements ()
	{
		$tpl       = $this->tpl;
		$img_exp   = '(https?:)?//[^\s\?&;=\#\"<>]+?\.(jpg|jpeg|gif|png|webp|bmp)([a-z0-9/?&%;][^\[\]]*)?';
		$email_exp = '[a-z0-9&\-_.]+?@[\w\-]+\.([\w\-\.]+\.)?[\w]+';

		$this->preg = array(
			'#\[quote="(.+?)"\]#isu'                                 => $tpl['quote_username_open'],
			'#\[spoiler="(.+?)"\]#isu'                               => $tpl['spoiler_title_open'],
			'#\[list=(a|A|i|I|1)\]#isu'                              => '<ul type="$1">',
			'#\[\*=(\d+)\]#isu'                                      => '<li value="$1">',
			'#\[pre\](.*?)\[/pre\]#isu'                              => '<pre class="post-pre">$1</pre>',
			'#\[name=([a-zA-Z0-9_]+?)\]#isu'                         => '<a name="$1"></a>',
			'#\[url=\#([a-zA-Z0-9_]+?)\](.*?)\[/url\]#isu'           => '<a class="postLink-name" href="#$1">$2</a>',
			'#\[color=([\#0-9a-zA-Z]+)\]#isu'                        => '<span style="color: $1;">',
			'#\[size=([1-2]?[0-9])\]#isu'                            => '<span style="font-size: $1px; line-height: normal;">',
			'#\[align=(left|right|center|justify)\]#isu'             => '<span class="post-align" style="text-align: $1;">',
			'#\[font="([\w\- \']+)"\]#isu'                           => '<span style="font-family: $1;">',
			"#\[img\]($img_exp)\[/img\]#isu"                         => $tpl['img'],
			"#\[img=(left|right|center)\]($img_exp)\[/img\]\s*#isu"  => $tpl['img_aligned'],
			"#\[email\]($email_exp)\[/email\]#isu"                   => '<a href="mailto:$1">$1</a>',
			"#\[qpost=([0-9]*)\]#isu"                                => '<u class="q-post">$1</u>',
		);

		$this->str = array(
			'[quote]'    => $tpl['quote_open'],
			'[/quote]'   => $tpl['quote_close'],
			'[spoiler]'  => $tpl['spoiler_open'],
			'[/spoiler]' => $tpl['spoiler_close'],
			'[list]'     => '<ul>',
			'[*]'        => '<li>',
			'[/list]'    => '</ul>',
			'[/color]'   => '</span>',
			'[/size]'    => '</span>',
			'[/align]'   => '</span>',
			'[/font]'    => '</span>',
			'[tab]'      => '&nbsp;&nbsp;&nbsp;&nbsp;',
			'[br]'       => "\n\n",
			'[hr]'       => $tpl['hr'],
			'[b]'        => '<span class="post-b">',
			'[/b]'       => '</span>',
			'[u]'        => '<span class="post-u">',
			'[/u]'       => '</span>',
			'[i]'        => '<span class="post-i">',
			'[/i]'       => '</span>',
			'[s]'        => '<span class="post-s">',
			'[/s]'       => '</span>',
			'[del]'      => '<span class="post-s">',
			'[/del]'     => '</span>',
			'[clear]'    => '<div class="clear">&nbsp;</div>',
		);

		$this->preg_search = array_keys($this->preg);
		$this->preg_repl   = array_values($this->preg);
		$this->str_search  = array_keys($this->str);
		$this->str_repl    = array_values($this->str);
	}

	/**
	* bbcode2html
	* $text должен быть уже обработан htmlCHR($text, false, ENT_NOQUOTES);
	*/
	function bbcode2html ($text)
	{
		global $bb_cfg;

		$text = " $text ";
		$text = static::clean_up($text);
		$text = $this->spam_filter($text);

		// Tag parse
		if (strpos($text, '[') !== false)
		{
			// [code]
			$text = preg_replace_callback('#(\s*)\[code\](.+?)\[/code\](\s*)#s', array(&$this, 'code_callback'), $text);

			// Escape tags inside tiltes in [quote="tilte"]
			$text = preg_replace_callback('#(\[(quote|spoiler)=")(.+?)("\])#', array(&$this, 'escape_tiltes_callback'), $text);

			// [url]
			$url_exp = '[\w\#!$%&~/.\-;:=,?@а-яА-Я()\[\]+]+?';
			$text = preg_replace_callback("#\[url\]((?:https?://)?$url_exp)\[/url\]#isu", array(&$this, 'url_callback'), $text);
			$text = preg_replace_callback("#\[url\](www\.$url_exp)\[/url\]#isu", array(&$this, 'url_callback'), $text);
			$text = preg_replace_callback("#\[url=((?:https?://)?$url_exp)\]([^?\n\t].*?)\[/url\]#isu", array(&$this, 'url_callback'), $text);
			$text = preg_replace_callback("#\[url=(www\.$url_exp)\]([^?\n\t].*?)\[/url\]#isu", array(&$this, 'url_callback'), $text);

			// Normalize block level tags wrapped with new lines
			$block_tags = join('|', $this->block_tags);
			$text = str_replace("\n\n[hr]\n\n", '[br][hr][br]', $text);
			$text = preg_replace("#(\s*)(\[/?($block_tags)(.*?)\])(\s*)#", '$2', $text);

			// Tag replacements
			$text = preg_replace($this->preg_search, $this->preg_repl, $text);
			$text = str_replace($this->str_search, $this->str_repl, $text);
		}

		$text = $this->make_clickable($text);
		$text = $this->smilies_pass($text);
		$text = $this->new_line2html($text);
		$text = trim($text);

		if ($bb_cfg['tidy_post'])
		{
			$text = $this->tidy($text);
		}

		return trim($text);
	}

	/**
	* Clean up
	*/
	static function clean_up ($text)
	{
		$text = trim($text);
		$text = str_replace("\r", '', $text);
		$text = preg_replace('#[ \t]+$#m', '', $text); // trailing spaces
		$text = preg_replace('#\n{3,}#', "\n\n", $text);
		return $text;
	}

	/**
	* Spam filter
	*/
	private function spam_filter ($text)
	{
		global $bb_cfg;
		static $spam_words = null;

		if (isset($this))
		{
			$found_spam =& $this->found_spam;
		}

		// set $spam_words and $spam_replace
		if (!$bb_cfg['spam_filter_file_path'])
		{
			return $text;
		}
		if (is_null($spam_words))
		{
			$spam_words = file_get_contents($bb_cfg['spam_filter_file_path']);
			$spam_words = strtolower($spam_words);
			$spam_words = explode("\n", $spam_words);
		}

		$found_spam = array();

		$tm_start = utime();

		$msg_decoded = $text;
		$msg_decoded = html_entity_decode($msg_decoded);
		$msg_decoded = urldecode($msg_decoded);
		$msg_decoded = str_replace('&', ' &', $msg_decoded);

		$msg_search = strtolower($msg_decoded);

		foreach ($spam_words as $spam_str)
		{
			if (!$spam_str = trim($spam_str))
			{
				continue;
			}
			if (strpos($msg_search, $spam_str) !== false)
			{
				$found_spam[] = $spam_str;
			}
		}
		if ($found_spam)
		{
			$spam_exp = array();
			foreach ($found_spam as $keyword)
			{
				$spam_exp[] = preg_quote($keyword, '/');
			}
			$spam_exp = join('|', $spam_exp);

			$text = preg_replace("/($spam_exp)(\S*)/i", $bb_cfg['spam_filter_replacement'], $msg_decoded);
			$text = htmlCHR($text, false, ENT_NOQUOTES);
#			bb_log(date("H:i:s") ." | ". sprintf('%.4f', (utime() - $tm_start)) ." | ". sprintf('%-6s', strlen($text)) ." | ". join(' ** ', $found_spam) ."\n", 'spam_filter');
		}

		return $text;
	}

	/**
	* [code] callback
	*/
	function code_callback ($m)
	{
		$code = trim($m[2]);
		$code = str_replace('  ', '&nbsp; ', $code);
		$code = str_replace('  ', ' &nbsp;', $code);
		$code = str_replace("\t", '&nbsp; ', $code);
		$code = str_replace(array('[', ']', ':', ')'), array('&#91;', '&#93;', '&#58;', '&#41;'), $code);
		return $this->tpl['code_open'] . $code . $this->tpl['code_close'];
	}

	/**
	* [url] callback
	*/
	function url_callback ($m)
	{
		global $bb_cfg;

		$url = trim($m[1]);
		$url_name = (isset($m[2])) ? trim($m[2]) : $url;

		if (!preg_match("#^https?://#isu", $url) && !preg_match("/^#/", $url)) $url = 'http://' . $url;

		if (in_array(parse_url($url, PHP_URL_HOST), $bb_cfg['nofollow']['allowed_url']) || $bb_cfg['nofollow']['disabled'])
		{
			$link = "<a href=\"$url\" class=\"postLink\">$url_name</a>";
		}
		else
		{
			$link = "<a href=\"$url\" class=\"postLink\" rel=\"nofollow\">$url_name</a>";
		}

		return $link;
	}

	/**
	* Escape tags inside tiltes in [quote="tilte"]
	*/
	function escape_tiltes_callback ($m)
	{
		$tilte = substr($m[3], 0, 250);
		$tilte = str_replace(array('[', ']', ':', ')', '"'), array('&#91;', '&#93;', '&#58;', '&#41;', '&#34;'), $tilte);
		// еще раз htmlspecialchars, т.к. при извлечении из title происходит обратное преобразование
		$tilte = htmlspecialchars($tilte, ENT_QUOTES);
		return $m[1] . $tilte . $m[4];
	}

	/**
	* make_clickable
	*/
	function make_clickable ($text)
	{
		$url_regexp = "#
			(?<![\"'=])
			\b
			(
				https?://[\w\#!$%&~/.\-;:=?@а-яА-Я()\[\]+]+
			)
			(?![\"']|\[/url|\[/img|</a)
			(?=[,!]?\s|[\)<!])
		#xiu";

		// pad it with a space so we can match things at the start of the 1st line.
		$ret = " $text ";

		// hide passkey
		$ret = hide_passkey($ret);

		// matches an "xxxx://yyyy" URL at the start of a line, or after a space.
		$ret = preg_replace_callback($url_regexp, array(&$this, 'make_url_clickable_callback'), $ret);

		// Remove our padding..
		$ret = substr(substr($ret, 0, -1), 1);

		return($ret);
	}

	/**
	* make_url_clickable_callback
	*/
	function make_url_clickable_callback ($m)
	{
		global $bb_cfg;

		$max_len = 70;
		$href    = $m[1];
		$name    = (mb_strlen($href, 'UTF-8') > $max_len) ? mb_substr($href, 0, $max_len - 19) .'...'. mb_substr($href, -16) : $href;

		if (in_array(parse_url($href, PHP_URL_HOST), $bb_cfg['nofollow']['allowed_url']) || $bb_cfg['nofollow']['disabled'])
		{
			$link = "<a href=\"$href\" class=\"postLink\">$name</a>";
		}
		else
		{
			$link = "<a href=\"$href\" class=\"postLink\" rel=\"nofollow\">$name</a>";
		}

		return $link;
	}

	/**
	* smilies_pass
	*/
	function smilies_pass ($text)
	{
		global $datastore;

		if (is_null($this->smilies))
		{
			$this->smilies = $datastore->get('smile_replacements');
		}
		if ($this->smilies)
		{
			$parsed_text = preg_replace($this->smilies['orig'], $this->smilies['repl'], $text);
			$text = $parsed_text;
		}

		return $text;
	}

	/**
	* new_line2html
	*/
	function new_line2html ($text)
	{
		$text = preg_replace('#\n{2,}#', '<span class="post-br"><br /></span>', $text);
		$text = str_replace("\n", '<br />', $text);
		return $text;
	}

	/**
	* tidy
	*/
	function tidy ($text)
	{
		$text = tidy_repair_string($text, $this->tidy_cfg, 'utf8');
		return $text;
	}
}

function bbcode2html ($text)
{
	global $bbcode;

	if (!isset($bbcode))
	{
		$bbcode = new bbcode();
	}
	$orig_word = array();
	$replacement_word = array();
	obtain_word_list($orig_word, $replacement_word);
	if ( count($orig_word) )
	{
		$text = preg_replace($orig_word, $replacement_word, $text);
	}
	return $bbcode->bbcode2html($text);
}

class words_rate
{
	var $dbg_mode      = false;
	var $words_rate    = 0;
	var $deleted_words = array();
	var $del_text_hl   = '';
	var $words_del_exp = '';
	var $words_cnt_exp = '#[a-zA-Zа-яА-ЯёЁ]{4,}#';

	function words_rate ()
	{
		// слова начинающиеся на..
		$del_list = file_get_contents(BB_ROOT .'/library/words_rate_del_list.txt');
		$del_list = str_compact($del_list);
		$del_list = str_replace(' ', '|', preg_quote($del_list, '/'));
		$del_exp  = '/\b('.$del_list.')[\w\-]*/i';

		$this->words_del_exp = $del_exp;
	}

	/**
	* возвращает "показатель полезности" сообщения используемый для автоудаления коротких сообщений типа "спасибо", "круто" и т.д.
	*/
	function get_words_rate ($text)
	{
		$this->words_rate    = 127;     // максимальное значение по умолчанию
		$this->deleted_words = array();
		$this->del_text_hl   = $text;

		// длинное сообщение
		if (strlen($text) > 600)
		{
			return $this->words_rate;
		}
		// вырезаем цитаты если содержит +1
		if (preg_match('#\+\d+#', $text))
		{
			$text = strip_quotes($text);
		}
		// содержит ссылку
		if (strpos($text, '://'))
		{
			return $this->words_rate;
		}
		// вопрос
		if ($questions = preg_match_all('#\w\?+#', $text, $m))
		{
			if ($questions >= 1)
			{
				return $this->words_rate;
			}
		}

		if ($this->dbg_mode)
		{
			preg_match_all($this->words_del_exp, $text, $this->deleted_words);
			$text_dbg = preg_replace($this->words_del_exp, '<span class="del-word">$0</span>', $text);
			$this->del_text_hl = '<div class="prune-post">'. $text_dbg . '</div>';
		}
		$text = preg_replace($this->words_del_exp, '', $text);

		// удаление смайлов
		$text = preg_replace('#:\w+:#', '', $text);
		// удаление bbcode тегов
		$text = preg_replace('#\[\S+\]#', '', $text);

		$words_count = preg_match_all($this->words_cnt_exp, $text, $m);

		if ($words_count !== false && $words_count < 127)
		{
			$this->words_rate = ($words_count == 0) ? 1 : $words_count;
		}

		return $this->words_rate;
	}
}

function get_words_rate ($text)
{
	static $wr = null;
	if (!isset($wr))
	{
		$wr = new words_rate();
	}
	return $wr->get_words_rate($text);
}

function hide_passkey ($str)
{
	global $bb_cfg;
	return preg_replace("#\?{$bb_cfg['passkey_key']}=[a-zA-Z0-9]{". BT_AUTH_KEY_LENGTH ."}#", "?{$bb_cfg['passkey_key']}=passkey", $str);
}

function get_parsed_post ($postrow, $mode = 'full', $return_chars = 600)
{
	global $bb_cfg;

	if ($bb_cfg['use_posts_cache'] && !empty($postrow['post_html']))
	{
		return $postrow['post_html'];
	}

	$message = bbcode2html($postrow['post_text']);

	// Posts cache
	if ($bb_cfg['use_posts_cache'])
	{
		DB()->shutdown['post_html'][] = array(
			'post_id'   => (int) $postrow['post_id'],
			'post_html' => (string) $message,
		);
	}

	return $message;
}

function update_post_html ($postrow)
{
	DB()->query("DELETE FROM ". BB_POSTS_HTML ." WHERE post_id = ". (int) $postrow['post_id'] ." LIMIT 1");
}
