strpos($_SERVER['HTTP_USER_AGENT'], 'Opera') !== false,
	'is_opera6' => strpos($_SERVER['HTTP_USER_AGENT'], 'Opera 6') !== false,
	'is_opera7' => strpos($_SERVER['HTTP_USER_AGENT'], 'Opera 7') !== false || strpos($_SERVER['HTTP_USER_AGENT'], 'Opera/7') !== false,
	'is_opera8' => strpos($_SERVER['HTTP_USER_AGENT'], 'Opera 8') !== false || strpos($_SERVER['HTTP_USER_AGENT'], 'Opera/8') !== false,
	'is_ie4' => strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE 4') !== false && strpos($_SERVER['HTTP_USER_AGENT'], 'WebTV') === false,
	'is_safari' => strpos($_SERVER['HTTP_USER_AGENT'], 'Safari') !== false,
	'is_mac_ie' => strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE 5.') !== false && strpos($_SERVER['HTTP_USER_AGENT'], 'Mac') !== false,
	'is_web_tv' => strpos($_SERVER['HTTP_USER_AGENT'], 'WebTV') !== false,
	'is_konqueror' => strpos($_SERVER['HTTP_USER_AGENT'], 'Konqueror') !== false,
	'is_firefox' => strpos($_SERVER['HTTP_USER_AGENT'], 'Firefox') !== false,
	'is_firefox1' => strpos($_SERVER['HTTP_USER_AGENT'], 'Firefox/1.') !== false,
	'is_firefox2' => strpos($_SERVER['HTTP_USER_AGENT'], 'Firefox/2.') !== false,
);
	$context['browser']['is_gecko'] = strpos($_SERVER['HTTP_USER_AGENT'], 'Gecko') !== false && !$context['browser']['is_safari'] && !$context['browser']['is_konqueror'];
// Internet Explorer 5 and 6 are often "emulated".
$context['browser']['is_ie7'] = strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE 7') !== false && !$context['browser']['is_opera'] && !$context['browser']['is_gecko'] && !$context['browser']['is_web_tv'];
$context['browser']['is_ie6'] = strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE 6') !== false && !$context['browser']['is_opera'] && !$context['browser']['is_gecko'] && !$context['browser']['is_web_tv'];
$context['browser']['is_ie5.5'] = strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE 5.5') !== false && !$context['browser']['is_opera'] && !$context['browser']['is_gecko'] && !$context['browser']['is_web_tv'];
$context['browser']['is_ie5'] = strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE 5.0') !== false && !$context['browser']['is_opera'] && !$context['browser']['is_gecko'] && !$context['browser']['is_web_tv'];
$context['browser']['is_ie'] = $context['browser']['is_ie4'] || $context['browser']['is_ie5'] || $context['browser']['is_ie5.5'] || $context['browser']['is_ie6'] || $context['browser']['is_ie7'];
$context['browser']['needs_size_fix'] = ($context['browser']['is_ie5'] || $context['browser']['is_ie5.5'] || $context['browser']['is_ie4'] || $context['browser']['is_opera6']) && strpos($_SERVER['HTTP_USER_AGENT'], 'Mac') === false;
// This isn't meant to be reliable, it's just meant to catch most bots to prevent PHPSESSID from showing up.
$ci_user_agent = strtolower($_SERVER['HTTP_USER_AGENT']);
$context['browser']['possibly_robot'] = (strpos($_SERVER['HTTP_USER_AGENT'], 'Mozilla') === false && strpos($_SERVER['HTTP_USER_AGENT'], 'Opera') === false) || strpos($ci_user_agent, 'googlebot') !== false || strpos($ci_user_agent, 'slurp') !== false || strpos($ci_user_agent, 'crawl') !== false;
$modSettings['max_image_width'] = 400;
$modSettings['max_image_height'] = 400;
$modSettings['autoLinkUrls'] = true;
$context['utf8'] = false;	
// Parse bulletin board code in a string, as well as smileys optionally.
function parse_bbc($message)
{
	global $txt, $scripturl, $context, $modSettings, $user_info;
	static $bbc_codes = array(), $itemcodes = array(), $no_autolink_tags = array();
	static $disabled;
	// Sift out the bbc for a performance improvement.
	if (empty($bbc_codes) || $message === false)
	{
		$disabled['flash'] = true;
		/* The following bbc are formatted as an array, with keys as follows:
			tag: the tag's name - should be lowercase!
			type: one of...
				- (missing): [tag]parsed content[/tag]
				- unparsed_equals: [tag=xyz]parsed content[/tag]
				- parsed_equals: [tag=parsed data]parsed content[/tag]
				- unparsed_content: [tag]unparsed content[/tag]
				- closed: [tag], [tag/], [tag /]
				- unparsed_commas: [tag=1,2,3]parsed content[/tag]
				- unparsed_commas_content: [tag=1,2,3]unparsed content[/tag]
				- unparsed_equals_content: [tag=...]unparsed content[/tag]
			parameters: an optional array of parameters, for the form
			  [tag abc=123]content[/tag].  The array is an associative array
			  where the keys are the parameter names, and the values are an
			  array which may contain the following:
				- match: a regular expression to validate and match the value.
				- quoted: true if the value should be quoted.
				- validate: callback to evaluate on the data, which is $data.
				- value: a string in which to replace $1 with the data.
				  either it or validate may be used, not both.
				- optional: true if the parameter is optional.
			test: a regular expression to test immediately after the tag's
			  '=', ' ' or ']'.  Typically, should have a \] at the end.
			  Optional.
			content: only available for unparsed_content, closed,
			  unparsed_commas_content, and unparsed_equals_content.
			  $1 is replaced with the content of  the tag.  Parameters
			  are repalced in the form {param}.  For unparsed_commas_content,
			  $2, $3, ..., $n are replaced.
			before: only when content is not used, to go before any
			  content.  For unparsed_equals, $1 is replaced with the value.
			  For unparsed_commas, $1, $2, ..., $n are replaced.
			after: similar to before in every way, except that it is used
			  when the tag is closed.
			disabled_content: used in place of content when the tag is
			  disabled.  For closed, default is '', otherwise it is '$1' if
			  block_level is false, '
$1
' elsewise.
			disabled_before: used in place of before when disabled.  Defaults
			  to '' if block_level, '' if not.
			disabled_after: used in place of after when disabled.  Defaults
			  to '
' if block_level, '' if not.
			block_level: set to true the tag is a "block level" tag, similar
			  to HTML.  Block level tags cannot be nested inside tags that are
			  not block level, and will not be implicitly closed as easily.
			  One break following a block level tag may also be removed.
			trim: if set, and 'inside' whitespace after the begin tag will be
			  removed.  If set to 'outside', whitespace after the end tag will
			  meet the same fate.
			validate: except when type is missing or 'closed', a callback to
			  validate the data as $data.  Depending on the tag's type, $data
			  may be a string or an array of strings (corresponding to the
			  replacement.)
			quoted: when type is 'unparsed_equals' or 'parsed_equals' only,
			  may be not set, 'optional', or 'required' corresponding to if
			  the content may be quoted.  This allows the parser to read
			  [tag="abc]def[esdf]"] properly.
			require_parents: an array of tag names, or not set.  If set, the
			  enclosing tag *must* be one of the listed tags, or parsing won't
			  occur.
			require_children: similar to require_parents, if set children
			  won't be parsed if they are not in the list.
			disallow_children: similar to, but very different from,
			  require_children, if it is set the listed tags will not be
			  parsed inside the tag.
		*/
		$codes = array(
			array(
				'tag' => 'abbr',
				'type' => 'unparsed_equals',
				'before' => '',
				'after' => ' ',
				'quoted' => 'optional',
				'disabled_after' => ' ($1)',
			),
			array(
				'tag' => 'acronym',
				'type' => 'unparsed_equals',
				'before' => '',
				'after' => ' ',
				'quoted' => 'optional',
				'disabled_after' => ' ($1)',
			),
			array(
				'tag' => 'anchor',
				'type' => 'unparsed_equals',
				'test' => '[#]?([A-Za-z][A-Za-z0-9_\-]*)\]',
				'before' => '',
				'after' => ' ',
			),
			array(
				'tag' => 'black',
				'before' => '',
				'after' => ' ',
			),
			array(
				'tag' => 'blue',
				'before' => '',
				'after' => ' ',
			),
			array(
				'tag' => 'br',
				'type' => 'closed',
				'content' => '' . ($context['browser']['is_gecko'] ? '
$1 ' : '$1') . '
\t ", "\t", implode(\'\', $php_parts));
						// Older browsers are annoying, aren\'t they?
						if ($context[\'browser\'][\'is_ie4\'] || $context[\'browser\'][\'is_ie5\'] || $context[\'browser\'][\'is_ie5.5\'])
							$data = str_replace("\t", "\t ", $data);
						elseif (!$context[\'browser\'][\'is_gecko\'])
							$data = str_replace("\t", "\t ", $data);
					}'),
				'block_level' => true,
			),
			array(
				'tag' => 'code',
				'type' => 'unparsed_equals_content',
				'content' => '' . ($context['browser']['is_gecko'] ? '
$1 ' : '$1') . '
\t ", "\t", implode(\'\', $php_parts));
						// Older browsers are annoying, aren\'t they?
						if ($context[\'browser\'][\'is_ie4\'] || $context[\'browser\'][\'is_ie5\'] || $context[\'browser\'][\'is_ie5.5\'])
							$data = str_replace("\t", "\t ", $data);
						elseif (!$context[\'browser\'][\'is_gecko\'])
							$data = str_replace("\t", "\t ", $data);
					}'),
				'block_level' => true,
			),
			array(
				'tag' => 'center',
				'before' => '',
				'after' => '
',
				'block_level' => true,
			),
			array(
				'tag' => 'color',
				'type' => 'unparsed_equals',
				'test' => '(#[\da-fA-F]{3}|#[\da-fA-F]{6}|[A-Za-z]{1,12})\]',
				'before' => '',
				'after' => ' ',
			),
			array(
				'tag' => 'email',
				'type' => 'unparsed_content',
				'content' => '$1 ',
				// !!! Should this respect guest_hideContacts?
				'validate' => create_function('&$tag, &$data, $disabled', '$data = strtr($data, array(\'',
				'after' => ' ',
				// !!! Should this respect guest_hideContacts?
				'disallow_children' => array('email', 'ftp', 'url', 'iurl'),
				'disabled_after' => ' ($1)',
			),
			array(
				'tag' => 'ftp',
				'type' => 'unparsed_content',
				'content' => '$1 ',
				'validate' => create_function('&$tag, &$data, $disabled', '$data = strtr($data, array(\'',
				'after' => ' ',
				'disallow_children' => array('email', 'ftp', 'url', 'iurl'),
				'disabled_after' => ' ($1)',
			),
			array(
				'tag' => 'font',
				'type' => 'unparsed_equals',
				'test' => '[A-Za-z0-9_,\-\s]+?\]',
				'before' => '',
				'after' => ' ',
			),
			array(
				'tag' => 'flash',
				'type' => 'unparsed_commas_content',
				'test' => '\d+,\d+\]',
				'content' => ($context['browser']['is_ie'] && !$context['browser']['is_mac_ie'] ? '$1 $1 $1 ',
			),
			array(
				'tag' => 'green',
				'before' => '',
				'after' => ' ',
			),
			array(
				'tag' => 'glow',
				'type' => 'unparsed_commas',
				'test' => '[#0-9a-zA-Z\-]{3,12},([012]\d{1,2}|\d{1,2})(,[^]]+)?\]',
				'before' => $context['browser']['is_ie'] ? '' : '',
				'after' => $context['browser']['is_ie'] ? '  
 ' : '',
			),
			array(
				'tag' => 'hr',
				'type' => 'closed',
				'content' => '$1 ',
				'validate' => create_function('&$tag, &$data, $disabled', '$data = strtr($data, array(\'',
				'after' => ' ',
			),
			array(
				'tag' => 'iurl',
				'type' => 'unparsed_content',
				'content' => '$1 ',
				'validate' => create_function('&$tag, &$data, $disabled', '$data = strtr($data, array(\'',
				'after' => ' ',
				'validate' => create_function('&$tag, &$data, $disabled', '
					if (substr($data, 0, 1) == \'#\')
						$data = \'#post_\' . substr($data, 1);'),
				'disallow_children' => array('email', 'ftp', 'url', 'iurl'),
				'disabled_after' => ' ($1)',
			),
			array(
				'tag' => 'li',
				'before' => '',
				'after' => ' ',
				'trim' => 'outside',
				'require_parents' => array('list'),
				'block_level' => true,
				'disabled_before' => '',
				'disabled_after' => '',
				'after' => '
',
				'block_level' => true,
			),
			array(
				'tag' => 'ltr',
				'before' => '',
				'after' => '
',
				'block_level' => true,
			),
			array(
				'tag' => 'me',
				'type' => 'unparsed_equals',
				'before' => '* $1 ',
				'after' => '
',
				'quoted' => 'optional',
				'block_level' => true,
				'disabled_before' => '/me ',
				'disabled_after' => '',
				'after' => ' ',
				'block_level' => true,
			),
			array(
				'tag' => 'nobbc',
				'type' => 'unparsed_content',
				'content' => '$1',
			),
			array(
				'tag' => 'pre',
				'before' => '',
				'after' => ' ',
			),
			array(
				'tag' => 'php',
				'type' => 'unparsed_content',
				'content' => '',
				'validate' => create_function('&$tag, &$data, $disabled', '
					if (!isset($disabled[\'php\']))
					{
						$add_begin = substr(trim($data), 0, 5) != \'<?\';
						$data = highlight_php_code($add_begin ? \'<?php \' . $data . \'?>\' : $data);
						if ($add_begin)
							$data = preg_replace(array(\'~^(.+?)<\?.{0,40}?php( |\s)~\', \'~\?>((?:(font|span)>)*)$~\'), \'$1\', $data, 2);
					}'),
				'block_level' => true,
				'disabled_content' => '$1',
			),
			array(
				'tag' => 'sm',
				'type' => 'unparsed_content',
				'content' => '$1
',
				'validate' => create_function('&$tag, &$data, $disabled', '
						$add_begin = substr(trim($data), 0, 5) != \'<?\';
						$data = highlight_sm_code($add_begin ? \'<?php \' . $data . \'?>\' : $data);
						if ($add_begin)
							$data = preg_replace(array(\'~^(.+?)<\?.{0,40}?php( |\s)~\', \'~\?>((?:(font|span)>)*)$~\'), \'$1\', $data, 2);
					'),
				'block_level' => true,
				'disabled_content' => '$1',
			),
			array(
				'tag' => 'quote',
				'before' => '',
				'after' => '
',
				'block_level' => true,
			),
			array(
				'tag' => 'quote',
				'parameters' => array(
					'author' => array('match' => '(.{1,192}?)', 'quoted' => true, 'validate' => 'parse_bbc'),
				),
				'before' => '',
				'after' => '
',
				'block_level' => true,
			),
			array(
				'tag' => 'quote',
				'type' => 'parsed_equals',
				'before' => '',
				'after' => '
',
				'quoted' => 'optional',
				'block_level' => true,
			),
			array(
				'tag' => 'quote',
				'parameters' => array(
					'author' => array('match' => '(.{1,192}?)', 'validate' => 'parse_bbc'),
				),
				'before' => '',
				'after' => '
',
				'block_level' => true,
			),
			array(
				'tag' => 'right',
				'before' => '',
				'after' => '
',
				'block_level' => true,
			),
			array(
				'tag' => 'red',
				'before' => '',
				'after' => ' ',
			),
			array(
				'tag' => 'rtl',
				'before' => '',
				'after' => '
',
				'block_level' => true,
			),
			array(
				'tag' => 's',
				'before' => '',
				'after' => '',
			),
			array(
				'tag' => 'size',
				'type' => 'unparsed_equals',
				'test' => '([1-9][\d]?p[xt]|(?:x-)?small(?:er)?|(?:x-)?large[r]?)\]',
				// !!! line-height
				'before' => '',
				'after' => ' ',
			),
			array(
				'tag' => 'size',
				'type' => 'unparsed_equals',
				'test' => '[1-9]\]',
				// !!! line-height
				'before' => '',
				'after' => ' ',
			),
			array(
				'tag' => 'sub',
				'before' => '',
				'after' => ' ',
			),
			array(
				'tag' => 'sup',
				'before' => '',
				'after' => ' ',
			),
			array(
				'tag' => 'shadow',
				'type' => 'unparsed_commas',
				'test' => '[#0-9a-zA-Z\-]{3,12},(left|right|top|bottom|[0123]\d{0,2})\]',
				'before' => $context['browser']['is_ie'] ? '' : '',
				'after' => ' ',
				'validate' => $context['browser']['is_ie'] ? create_function('&$tag, &$data, $disabled', '
					if ($data[1] == \'left\')
						$data[1] = 270;
					elseif ($data[1] == \'right\')
						$data[1] = 90;
					elseif ($data[1] == \'top\')
						$data[1] = 0;
					elseif ($data[1] == \'bottom\')
						$data[1] = 180;
					else
						$data[1] = (int) $data[1];') : create_function('&$tag, &$data, $disabled', '
					if ($data[1] == \'top\' || (is_numeric($data[1]) && $data[1] < 50))
						return \'0 -2px\';
					elseif ($data[1] == \'right\' || (is_numeric($data[1]) && $data[1] < 100))
						return \'2px 0\';
					elseif ($data[1] == \'bottom\' || (is_numeric($data[1]) && $data[1] < 190))
						return \'0 2px\';
					elseif ($data[1] == \'left\' || (is_numeric($data[1]) && $data[1] < 280))
						return \'-2px 0\';
					else
						return \'0 0\';'),
			),
			array(
				'tag' => 'time',
				'type' => 'unparsed_content',
				'content' => '$1',
				'validate' => create_function('&$tag, &$data, $disabled', '
					if (is_numeric($data))
						$data = timeformat($data);
					else
						$tag[\'content\'] = \'[time]$1[/time]\';'),
			),
			array(
				'tag' => 'tt',
				'before' => '',
				'after' => ' ',
			),
			array(
				'tag' => 'table',
				'before' => '',
				'trim' => 'inside',
				'require_children' => array('tr'),
				'block_level' => true,
			),
			array(
				'tag' => 'tr',
				'before' => '',
				'after' => ' ',
				'require_parents' => array('table'),
				'require_children' => array('td'),
				'trim' => 'both',
				'block_level' => true,
				'disabled_before' => '',
				'disabled_after' => '',
			),
			array(
				'tag' => 'td',
				'before' => ' ',
				'after' => ' ',
				'require_parents' => array('tr'),
				'trim' => 'outside',
				'block_level' => true,
				'disabled_before' => '',
				'disabled_after' => '',
			),
			array(
				'tag' => 'url',
				'type' => 'unparsed_content',
				'content' => '$1 ',
				'validate' => create_function('&$tag, &$data, $disabled', '$data = strtr($data, array(\'',
				'after' => ' ',
				'disallow_children' => array('email', 'ftp', 'url', 'iurl'),
				'disabled_after' => ' ($1)',
			),
			array(
				'tag' => 'u',
				'before' => '',
				'after' => ' ',
			),
			array(
				'tag' => 'white',
				'before' => '',
				'after' => ' ',
			),
		);
		// This is mainly for the bbc manager, so it's easy to add tags above.  Custom BBC should be added above this line.
		if ($message === false)
			return $codes;
		// So the parser won't skip them.
		$itemcodes = array(
			'*' => '',
			'@' => 'disc',
			'+' => 'square',
			'x' => 'square',
			'#' => 'square',
			'o' => 'circle',
			'O' => 'circle',
			'0' => 'circle',
		);
		// Inside these tags autolink is not recommendable.
		$no_autolink_tags = array(
			'url', 
			'iurl', 
			'ftp', 
			'email',
		);
		
		foreach ($codes as $c)
			$bbc_codes[substr($c['tag'], 0, 1)][] = $c;
		$codes = null;
	}
	$open_tags = array();
	$message = strtr($message, array("\n" => '\.(;\'"]|^)((?:http|https|ftp|ftps)://[\w\-_%@:|]+(?:\.[\w\-_%]+)*(?::\d+)?(?:/[\w\-_\~%\.@,\?&;=#+:\'\\\\]*|[\(\{][\w\-_\~%\.@,\?&;=#(){}+:\'\\\\]*)*[/\w\-_\~%@\?;=#}\\\\])~i', '~(?<=[\s>(\'<]|^)(www(?:\.[\w\-_]+)+(?::\d+)?(?:/[\w\-_\~%\.@,\?&;=#+:\'\\\\]*|[\(\{][\w\-_\~%\.@,\?&;=#(){}+:\'\\\\]*)*[/\w\-_\~%@\?;=#}\\\\])~i'), array('[url]$1[/url]', '[url=http://$1]$1[/url]'), $data);
						$data = strtr($data, array('\'' => ''', $context['utf8'] ? "\xC2\xA0" : "\xA0" => ' ', '>">' => '"', '<"<' => '"', ' '<'));
					}
					// Next, emails...
					if (!isset($disabled['email']) && strpos($data, '@') !== false)
					{
						$data = preg_replace('~(?<=[\?\s' . $non_breaking_space . '\[\]()*\\\;>]|^)([\w\-\.]{1,80}@[\w\-]+\.[\w\-\.]+[\w\-])(?=[?,\s' . $non_breaking_space . '\[\]()*\\\]|$|  ';
				// Opera...
				elseif ($context['browser']['is_opera'])
					$breaker = '  ';
				// Internet Explorer...
				else
					$breaker = '  ';
				// PCRE will not be happy if we don't give it a short.
				$modSettings['fixLongWords'] = (int) min(65535, $modSettings['fixLongWords']);
				// The idea is, find words xx long, and then replace them with xx + space + more.
				if (strlen($data) > $modSettings['fixLongWords'])
				{
					// This is done in a roundabout way because $breaker has "long words" :P.
					$data = strtr($data, array($breaker => '< >', ' ' => $context['utf8'] ? "\xC2\xA0" : "\xA0"));
					$data = preg_replace(
						'~(?<=[>;:!? ' . $non_breaking_space . '\]()]|^)([\w\.]{' . $modSettings['fixLongWords'] . ',})~e' . ($context['utf8'] ? 'u' : ''),
						"preg_replace('/(.{" . ($modSettings['fixLongWords'] - 1) . '})/' . ($context['utf8'] ? 'u' : '') . "', '\\\$1< >', '\$1')",
						$data);
					$data = strtr($data, array('< >' => $breaker, $context['utf8'] ? "\xC2\xA0" : "\xA0" => ' '));
				}
			}*/
			// Do any smileys!
			/*if ($smileys === true)
				parsesmileys($data);
			*/
			// If it wasn't changed, no copying or other boring stuff has to happen!
			if ($data != substr($message, $last_pos, $pos - $last_pos + 1))
			{
				$message = substr($message, 0, $last_pos) . $data . substr($message, $pos + 1);
				// Since we changed it, look again incase we added or removed a tag.  But we don't want to skip any.
				$old_pos = strlen($data) + $last_pos - 1;
				$pos = strpos($message, '[', $last_pos);
				$pos = $pos === false ? $old_pos : min($pos, $old_pos);
			} 
		}
		// Are we there yet?  Are we there yet?
		if ($pos >= strlen($message) - 1)
			break;
		$tags = strtolower(substr($message, $pos + 1, 1));
		if ($tags == '/' && !empty($open_tags))
		{
			$pos2 = strpos($message, ']', $pos + 1);
			if ($pos2 == $pos + 2)
				continue;
			$look_for = strtolower(substr($message, $pos + 2, $pos2 - $pos - 2));
			$to_close = array();
			$block_level = null;
			do
			{
				$tag = array_pop($open_tags);
				if (!$tag)
					break;
				if (!empty($tag['block_level']))
				{
					// Only find out if we need to.
					if ($block_level === false)
					{
						array_push($open_tags, $tag);
						break;
					}
					// The idea is, if we are LOOKING for a block level tag, we can close them on the way.
					if (strlen($look_for) > 0 && isset($bbc_codes[$look_for{0}]))
					{
						foreach ($bbc_codes[$look_for{0}] as $temp)
							if ($temp['tag'] == $look_for)
							{
								$block_level = !empty($temp['block_level']);
								break;
							}
					}
					if ($block_level !== true)
					{
						$block_level = false;
						array_push($open_tags, $tag);
						break;
					}
				}
				$to_close[] = $tag;
			}
			while ($tag['tag'] != $look_for);
			// Did we just eat through everything and not find it?
			if ((empty($open_tags) && (empty($tag) || $tag['tag'] != $look_for)))
			{
				$open_tags = $to_close;
				continue;
			}
			elseif (!empty($to_close) && $tag['tag'] != $look_for)
			{
				if ($block_level === null && isset($look_for{0}, $bbc_codes[$look_for{0}]))
				{
					foreach ($bbc_codes[$look_for{0}] as $temp)
						if ($temp['tag'] == $look_for)
						{
							$block_level = !empty($temp['block_level']);
							break;
						}
				}
				// We're not looking for a block level tag (or maybe even a tag that exists...)
				if (!$block_level)
				{
					foreach ($to_close as $tag)
						array_push($open_tags, $tag);
					continue;
				}
			}
			foreach ($to_close as $tag)
			{
				$message = substr($message, 0, $pos) . $tag['after'] . substr($message, $pos2 + 1);
				$pos += strlen($tag['after']);
				$pos2 = $pos - 1;
				// See the comment at the end of the big loop - just eating whitespace ;).
				if (!empty($tag['block_level']) && substr($message, $pos, 6) == '';
			}
			// We're in a list item already: another itemcode?  Close it first.
			elseif ($inside['tag'] == 'li')
			{
				array_pop($open_tags);
				$code = '';
			}
			else
				$code = '';
			// Now we open a new tag.
			$open_tags[] = array(
				'tag' => 'li',
				'after' => '',
				'trim' => 'outside',
				'block_level' => true,
				'disallow_children' => isset($inside['disallow_children']) ? $inside['disallow_children'] : null,
			);
			// First, open the tag...
			$code .= '';
			$message = substr($message, 0, $pos) . $code . substr($message, $pos + 3);
			$pos += strlen($code) - 1;
			// Next, find the next break (if any.)  If there's more itemcode after it, keep it going - otherwise close!
			$pos2 = strpos($message, '  ';
			}
			// Tell the [list] that it needs to close specially.
			else
			{
				// Move the li over, because we're not sure what we'll hit.
				$open_tags[count($open_tags) - 1]['after'] = '';
				$open_tags[count($open_tags) - 2]['after'] = '';
			}
			continue;
		}
		// Implicitly close lists and tables if something other than what's required is in them.  This is needed for itemcode.
		if ($tag === null && $inside !== null && !empty($inside['require_children']))
		{
			array_pop($open_tags);
			$message = substr($message, 0, $pos) . $inside['after'] . substr($message, $pos);
			$pos += strlen($inside['after']) - 1;
		}
		// No tag?  Keep looking, then.  Silly people using brackets without actual tags.
		if ($tag === null)
			continue;
		// Propagate the list to the child (so wrapping the disallowed tag won't work either.)
		if (isset($inside['disallow_children']))
			$tag['disallow_children'] = isset($tag['disallow_children']) ? array_unique(array_merge($tag['disallow_children'], $inside['disallow_children'])) : $inside['disallow_children'];
		// Is this tag disabled?
		if (isset($disabled[$tag['tag']]))
		{
			if (!isset($tag['disabled_before']) && !isset($tag['disabled_after']) && !isset($tag['disabled_content']))
			{
				$tag['before'] = !empty($tag['block_level']) ? '' : '';
				$tag['after'] = !empty($tag['block_level']) ? '
' : '';
				$tag['content'] = isset($tag['type']) && $tag['type'] == 'closed' ? '' : (!empty($tag['block_level']) ? '$1
' : '$1');
			}
			elseif (isset($tag['disabled_before']) || isset($tag['disabled_after']))
			{
				$tag['before'] = isset($tag['disabled_before']) ? $tag['disabled_before'] : (!empty($tag['block_level']) ? '' : '');
				$tag['after'] = isset($tag['disabled_after']) ? $tag['disabled_after'] : (!empty($tag['block_level']) ? '
' : '');
			}
			else
				$tag['content'] = $tag['disabled_content'];
		}
		// The only special case is 'html', which doesn't need to close things.
		if (!empty($tag['block_level']) && $tag['tag'] != 'html' && empty($inside['block_level']))
		{
			$n = count($open_tags) - 1;
			while (empty($open_tags[$n]['block_level']) && $n >= 0)
				$n--;
			// Close all the non block level tags so this tag isn't surrounded by them.
			for ($i = count($open_tags) - 1; $i > $n; $i--)
			{
				$message = substr($message, 0, $pos) . $open_tags[$i]['after'] . substr($message, $pos);
				$pos += strlen($open_tags[$i]['after']);
				$pos1 += strlen($open_tags[$i]['after']);
				// Trim or eat trailing stuff... see comment at the end of the big loop.
				if (!empty($open_tags[$i]['block_level']) && substr($message, $pos, 6) == 'Link to page ';
				$data = '  ';	
			
			} elseif($extrainfo['host'] == "www.youtube.com" || $extrainfo['host'] =="youtube.com"){
			 	$thehead = 'YouTube - Link to page ';
			 	$newextra = substr($extrainfo['query'],2);
				$data = ''.$thehead.'
' . $data . '
\t ", $buffer);
	return strtr($buffer, array('\'' => ''', '' => '', '' => ''));
}
function CompareSTRLEN( $a , $b){
	if ($a['strlen'] == $b['strlen']) {
        return 0;
    }
    return ($a['strlen'] > $b['strlen']) ? -1 : 1;
}
function PrepareSMList(){
	global $context;
	
	if(isset($context['sm']['search']))
		return;
		
	$context['sm']['haslibary'] = isset($context['sm']['haslibary']) ? $context['sm']['haslibary'] : false;
		
	$theresults = Array();
	
	$resultquery =  $context['sm']['haslibary'] ? '' : ',description';		
	$result = db_query('SELECT id,func'. $resultquery.' FROM sm_smfunctions',__FILE__,__LINE__);
	
	while ($line = mysql_fetch_array($result, MYSQL_ASSOC)) {
	 	$theresults[] = Array (
		 	'id' => $line['id'],
			'func' => $line['func'],
			'strlen' => strlen($line['func']),
			'descriptions' => $context['sm']['haslibary'] ? '' : $line['description']
		);
	}
	
	//I need to sort it and do that stupid thing of $thereplaceid so that one function becomes two, like SetClientListeningFlags and SetClientListening		
	usort($theresults, "CompareSTRLEN");
	
	foreach($theresults as $go){
	 	$thereplaceid = "!>";
		$context['sm']['search'][0][0][] = $go['func'];
		$context['sm']['search'][0][1][] = $thereplaceid;
		
		$context['sm']['search'][1][0][] = $thereplaceid;
		if($context['sm']['haslibary'])
			$context['sm']['search'][1][1][] = '' . $go['func'] . ' ';
		else
			$context['sm']['search'][1][1][] = '' . $go['func'] . ' ';
	}
	
	
	$resultquery =  $context['sm']['haslibary'] ? '' : ',value,comment';		
	$result = mysql_query('SELECT id,variable'. $resultquery.' FROM sm_smdefine') or die('Query failed: ' . mysql_error());
	while ($line = mysql_fetch_array($result, MYSQL_ASSOC)) {
	 	$context['sm']['search'][2][0][] = $line['variable'];
	 	if($context['sm']['haslibary'])
	 		$context['sm']['search'][2][1][] = '' . $line['variable'] . ' ';
		else{
			$context['sm']['search'][2][1][] = '' . $line['variable'] . ' ';
		}
	}	
}
// Highlight any code...
function highlight_sm_code($code)
{
	global $context;
	// Remove special characters.
	$code = un_htmlspecialchars(strtr($code, array('';
		$c = $i + 1;
		for($a = $numcount - strlen($c); $a > 0 ; $a-- )
			$buffer .= "0";
		$buffer .= $c . ':  ' . $line . "\n";
	}
	// Yes, I know this is kludging it, but this is the best way to preserve tabs from PHP :P.
	$buffer = preg_replace('~SMF_TAB((font|span)><(font color|span style)="[^"]*?">)?\(\);~', "\t ", $buffer);
	if(!isset($context['sm']['search']))
		PrepareSMList();
	
	$buffer = strtr($buffer, array('\'' => ''', '' => '', '' => ''));
	
	foreach($context['sm']['search'] as $replace){
		$buffer = str_replace($replace[0], $replace[1], $buffer);
	} 
	return $buffer;
}
// Removes special entities from strings.  Compatibility...
function un_htmlspecialchars($string)
{
	return strtr($string, array_flip(get_html_translation_table(HTML_SPECIALCHARS, ENT_QUOTES)) + array(''' => '\'', ' ' => ' '));
}
?>