".$st[2]."";
}
function bb_cleanclass($st) {
  return "".$st[2]."";
}
function cleancss($input) {
	$cleaned = "";
	$input = strtolower($input);
	for ($i = 0; $i < strlen($input); $i++) {
		$char = substr($input, $i, 1);
		if (($char >= "a") and ($char <= "z"))
			$cleaned .= $char;
		if (!(strpos(" #;:0123456789", $char) === false))
			$cleaned .= $char;
	}
	return($cleaned);
}
function stripcode_br_cb($s) {
	return '[code]' . str_replace('
', '', $s[1]) . '[/code]';
}
function tryoembed($match){
	$url = ((count($match)==2)?$match[1]:$match[2]);
//	logger("tryoembed: $url");
	$o = oembed_fetch_url($url);
	//echo "
"; var_dump($match, $url, $o); killme();
	if ($o->type=="error") return $match[0];
	$html = oembed_format_object($o);
	return $html; //oembed_iframe($html,$o->width,$o->height);
}
// [noparse][i]italic[/i][/noparse] turns into
// [noparse][ i ]italic[ /i ][/noparse],
// to hide them from parser.
function bb_spacefy($st) {
  $whole_match = $st[0];
  $captured = $st[1];
  $spacefied = preg_replace("/\[(.*?)\]/", "[ $1 ]", $captured);
  $new_str = str_replace($captured, $spacefied, $whole_match);
  return $new_str;
}
// The previously spacefied [noparse][ i ]italic[ /i ][/noparse],
// now turns back and the [noparse] tags are trimed
// returning [i]italic[/i]
function bb_unspacefy_and_trim($st) {
  $whole_match = $st[0];
  $captured = $st[1];
  $unspacefied = preg_replace("/\[ (.*?)\ ]/", "[$1]", $captured);
  return $unspacefied;
}
function bb_find_open_close($s, $open, $close, $occurance = 1) {
	if($occurance < 1)
		$occurance = 1;
	$start_pos = -1;
	for($i = 1; $i <= $occurance; $i++) {
		if( $start_pos !== false)
			$start_pos = strpos($s, $open, $start_pos + 1);
	}
	if( $start_pos === false)
		return false;
	$end_pos = strpos($s, $close, $start_pos);
	if( $end_pos === false)
		return false;
	$res = array( 'start' => $start_pos, 'end' => $end_pos );
	return $res;
}
function get_bb_tag_pos($s, $name, $occurance = 1) {
	if($occurance < 1)
		$occurance = 1;
	$start_open = -1;
	for($i = 1; $i <= $occurance; $i++) {
		if( $start_open !== false)
			$start_open = strpos($s, '[' . $name, $start_open + 1); // allow [name= type tags
	}
	if( $start_open === false)
		return false;
	$start_equal = strpos($s, '=', $start_open);
	$start_close = strpos($s, ']', $start_open);
	if( $start_close === false)
		return false;
	$start_close++;
	$end_open = strpos($s, '[/' . $name . ']', $start_close);
	if( $end_open === false)
		return false;
	$res = array( 'start' => array('open' => $start_open, 'close' => $start_close),
	              'end' => array('open' => $end_open, 'close' => $end_open + strlen('[/' . $name . ']')) );
	if( $start_equal !== false)
		$res['start']['equal'] = $start_equal + 1;
	return $res;
}
function bb_tag_preg_replace($pattern, $replace, $name, $s) {
	$string = $s;
	$occurance = 1;
	$pos = get_bb_tag_pos($string, $name, $occurance);
	while($pos !== false && $occurance < 1000) {
		$start = substr($string, 0, $pos['start']['open']);
		$subject = substr($string, $pos['start']['open'], $pos['end']['close'] - $pos['start']['open']);
		$end = substr($string, $pos['end']['close']);
		if($end === false)
			$end = '';
		$subject = preg_replace($pattern, $replace, $subject);
		$string = $start . $subject . $end;
		$occurance++;
		$pos = get_bb_tag_pos($string, $name, $occurance);
	}
	return $string;
}
if(! function_exists('bb_extract_images')) {
function bb_extract_images($body) {
	$saved_image = array();
	$orig_body = $body;
	$new_body = '';
	$cnt = 0;
	$img_start = strpos($orig_body, '[img');
	$img_st_close = ($img_start !== false ? strpos(substr($orig_body, $img_start), ']') : false);
	$img_end = ($img_start !== false ? strpos(substr($orig_body, $img_start), '[/img]') : false);
	while(($img_st_close !== false) && ($img_end !== false)) {
		$img_st_close++; // make it point to AFTER the closing bracket
		$img_end += $img_start;
		if(! strcmp(substr($orig_body, $img_start + $img_st_close, 5), 'data:')) {
			// This is an embedded image
			$saved_image[$cnt] = substr($orig_body, $img_start + $img_st_close, $img_end - ($img_start + $img_st_close));
			$new_body = $new_body . substr($orig_body, 0, $img_start) . '[$#saved_image' . $cnt . '#$]';
			$cnt++;
		}
		else
			$new_body = $new_body . substr($orig_body, 0, $img_end + strlen('[/img]'));
		$orig_body = substr($orig_body, $img_end + strlen('[/img]'));
		if($orig_body === false) // in case the body ends on a closing image tag
			$orig_body = '';
		$img_start = strpos($orig_body, '[img');
		$img_st_close = ($img_start !== false ? strpos(substr($orig_body, $img_start), ']') : false);
		$img_end = ($img_start !== false ? strpos(substr($orig_body, $img_start), '[/img]') : false);
	}
	$new_body = $new_body . $orig_body;
	return array('body' => $new_body, 'images' => $saved_image);
}}
if(! function_exists('bb_replace_images')) {
function bb_replace_images($body, $images) {
	$newbody = $body;
	$cnt = 0;
	foreach($images as $image) {
		// We're depending on the property of 'foreach' (specified on the PHP website) that
		// it loops over the array starting from the first element and going sequentially
		// to the last element
		$newbody = str_replace('[$#saved_image' . $cnt . '#$]', '
', $newbody);
		$cnt++;
	}
	return $newbody;
}}
function bb_ShareAttributes($match) {
        $attributes = $match[1];
        $author = "";
        preg_match("/author='(.*?)'/ism", $attributes, $matches);
        if ($matches[1] != "")
                $author = html_entity_decode($matches[1],ENT_QUOTES,'UTF-8');
        preg_match('/author="(.*?)"/ism', $attributes, $matches);
        if ($matches[1] != "")
                $author = $matches[1];
        $link = "";
        preg_match("/link='(.*?)'/ism", $attributes, $matches);
        if ($matches[1] != "")
                $link = $matches[1];
        preg_match('/link="(.*?)"/ism', $attributes, $matches);
        if ($matches[1] != "")
                $link = $matches[1];
        $avatar = "";
        preg_match("/avatar='(.*?)'/ism", $attributes, $matches);
        if ($matches[1] != "")
                $avatar = $matches[1];
        preg_match('/avatar="(.*?)"/ism', $attributes, $matches);
        if ($matches[1] != "")
                $avatar = $matches[1];
        $profile = "";
        preg_match("/profile='(.*?)'/ism", $attributes, $matches);
        if ($matches[1] != "")
                $profile = $matches[1];
        preg_match('/profile="(.*?)"/ism', $attributes, $matches);
        if ($matches[1] != "")
                $profile = $matches[1];
        $posted = "";
        preg_match("/posted='(.*?)'/ism", $attributes, $matches);
        if ($matches[1] != "")
                $posted = $matches[1];
        preg_match('/posted="(.*?)"/ism', $attributes, $matches);
        if ($matches[1] != "")
                $posted = $matches[1];
		$reldate = (($posted) ? " " . relative_date($posted) : ''); 
        $headline = '";
        $text = $headline.''.trim($match[2])."
";
        return($text);
}
function bb_ShareAttributesSimple($match) {
        $attributes = $match[1];
        $author = "";
        preg_match("/author='(.*?)'/ism", $attributes, $matches);
        if ($matches[1] != "")
                $author = html_entity_decode($matches[1],ENT_QUOTES,'UTF-8');
        preg_match('/author="(.*?)"/ism', $attributes, $matches);
        if ($matches[1] != "")
                $author = $matches[1];
        $profile = "";
        preg_match("/profile='(.*?)'/ism", $attributes, $matches);
        if ($matches[1] != "")
                $profile = $matches[1];
        preg_match('/profile="(.*?)"/ism', $attributes, $matches);
        if ($matches[1] != "")
                $profile = $matches[1];
        $text = "
".html_entity_decode("♲ ", ENT_QUOTES, 'UTF-8').' '.$author.": 
»".$match[2]."«";
        return($text);
}
	// BBcode 2 HTML was written by WAY2WEB.net
	// extended to work with Mistpark/Friendica - Mike Macgirvin
function bbcode($Text,$preserve_nl = false, $tryoembed = true, $simplehtml = false) {
	$stamp1 = microtime(true);
	$a = get_app();
	// Hide all [noparse] contained bbtags by spacefying them
	// POSSIBLE BUG --> Will the 'preg' functions crash if there's an embedded image?
	$Text = preg_replace_callback("/\[noparse\](.*?)\[\/noparse\]/ism", 'bb_spacefy',$Text);
	$Text = preg_replace_callback("/\[nobb\](.*?)\[\/nobb\]/ism", 'bb_spacefy',$Text);
	$Text = preg_replace_callback("/\[pre\](.*?)\[\/pre\]/ism", 'bb_spacefy',$Text);
	// Move all spaces out of the tags
	$Text = preg_replace("/\[(\w*)\](\s*)/ism", '$2[$1]', $Text);
	$Text = preg_replace("/(\s*)\[\/(\w*)\]/ism", '[/$2]$1', $Text);
	// Extract the private images which use data url's since preg has issues with
	// large data sizes. Stash them away while we do bbcode conversion, and then put them back
	// in after we've done all the regex matching. We cannot use any preg functions to do this.
	$extracted = bb_extract_images($Text);
	$Text = $extracted['body'];
	$saved_image = $extracted['images'];
	// If we find any event code, turn it into an event.
	// After we're finished processing the bbcode we'll
	// replace all of the event code with a reformatted version.
	$ev = bbtoevent($Text);
	// Replace any html brackets with HTML Entities to prevent executing HTML or script
	// Don't use strip_tags here because it breaks [url] search by replacing & with amp
	$Text = str_replace("<", "<", $Text);
	$Text = str_replace(">", ">", $Text);
	// remove some newlines before the general conversion
	$Text = preg_replace("/\s?\[share(.*?)\]\s?(.*?)\s?\[\/share\]\s?/ism","[share$1]$2[/share]",$Text);
	$Text = preg_replace("/\s?\[quote(.*?)\]\s?(.*?)\s?\[\/quote\]\s?/ism","[quote$1]$2[/quote]",$Text);
	$Text = preg_replace("/\n\[code\]/ism", "[code]", $Text);
	$Text = preg_replace("/\[\/code\]\n/ism", "[/code]", $Text);
	// when the content is meant exporting to other systems then remove the avatar picture since this doesn't really look good on these systems
	if (!$tryoembed)
		$Text = preg_replace("/\[share(.*?)avatar\s?=\s?'.*?'\s?(.*?)\]\s?(.*?)\s?\[\/share\]\s?/ism","\n[share$1$2]$3[/share]",$Text);
	// Convert new line chars to html 
 tags
	// nlbr seems to be hopelessly messed up
	//	$Text = nl2br($Text);
	// We'll emulate it.
	$Text = trim($Text);
	$Text = str_replace("\r\n","\n", $Text);
	// removing multiplicated newlines
	if (get_config("system", "remove_multiplicated_lines")) {
		$search = array("\n\n\n", "\n ", " \n", "[/quote]\n\n", "\n[/quote]");
		$replace = array("\n\n", "\n", "\n", "[/quote]\n", "[/quote]");
		do {
			$oldtext = $Text;
			$Text = str_replace($search, $replace, $Text);
		} while ($oldtext != $Text);
	}
	$Text = str_replace(array("\r","\n"), array('
','
'), $Text);
	if($preserve_nl)
		$Text = str_replace(array("\n","\r"), array('',''),$Text);
	// Set up the parameters for a URL search string
	$URLSearchString = "^\[\]";
	// Set up the parameters for a MAIL search string
	$MAILSearchString = $URLSearchString;
	// Perform URL Search
	$Text = preg_replace("/([^\]\='".'"'."]|^)(https?\:\/\/[a-zA-Z0-9\:\/\-\?\&\;\.\=\_\~\#\%\$\!\+\,]+)/ism", '$1$2', $Text);
	if ($tryoembed)
		$Text = preg_replace_callback("/\[bookmark\=([^\]]*)\].*?\[\/bookmark\]/ism",'tryoembed',$Text);
	$Text = preg_replace("/\[bookmark\=([^\]]*)\](.*?)\[\/bookmark\]/ism",'[url=$1]$2[/url]',$Text);
	if ($tryoembed)
		$Text = preg_replace_callback("/\[url\]([$URLSearchString]*)\[\/url\]/ism",'tryoembed',$Text);
	$Text = preg_replace("/\[url\]([$URLSearchString]*)\[\/url\]/ism", '$1', $Text);
	$Text = preg_replace("/\[url\=([$URLSearchString]*)\](.*?)\[\/url\]/ism", '$2', $Text);
	//$Text = preg_replace("/\[url\=([$URLSearchString]*)\]([$URLSearchString]*)\[\/url\]/ism", '$2', $Text);
	// Red compatibility, though the link can't be authenticated on Friendica
	$Text = preg_replace("/\[zrl\=([$URLSearchString]*)\](.*?)\[\/zrl\]/ism", '$2', $Text);
	// we may need to restrict this further if it picks up too many strays
	// link acct:user@host to a webfinger profile redirector
	$Text = preg_replace('/acct:(.*?)@(.*?)([ ,])/', 'acct:' . "$1@$2$3" . '',$Text);
	// Perform MAIL Search
	$Text = preg_replace("/\[mail\]([$MAILSearchString]*)\[\/mail\]/", '$1', $Text);
	$Text = preg_replace("/\[mail\=([$MAILSearchString]*)\](.*?)\[\/mail\]/", '$2', $Text);
	// Check for bold text
	$Text = preg_replace("(\[b\](.*?)\[\/b\])ism",'$1',$Text);
	// Check for Italics text
	$Text = preg_replace("(\[i\](.*?)\[\/i\])ism",'$1',$Text);
	// Check for Underline text
	$Text = preg_replace("(\[u\](.*?)\[\/u\])ism",'$1',$Text);
	// Check for strike-through text
	$Text = preg_replace("(\[s\](.*?)\[\/s\])ism",'$1',$Text);
	// Check for over-line text
	$Text = preg_replace("(\[o\](.*?)\[\/o\])ism",'$1',$Text);
	// Check for colored text
	$Text = preg_replace("(\[color=(.*?)\](.*?)\[\/color\])ism","$2",$Text);
	// Check for sized text
        // [size=50] --> font-size: 50px (with the unit).
	$Text = preg_replace("(\[size=(\d*?)\](.*?)\[\/size\])ism","$2",$Text);
	$Text = preg_replace("(\[size=(.*?)\](.*?)\[\/size\])ism","$2",$Text);
	// Check for centered text
	$Text = preg_replace("(\[center\](.*?)\[\/center\])ism","$1",$Text);
	// Check for list text
	$Text = str_replace("[*]", "$1';
	// Check for [code] text
	$Text = preg_replace("/\[code\](.*?)\[\/code\]/ism","$CodeLayout", $Text);
	// Declare the format for [spoiler] layout
	$SpoilerLayout = '$1'; // Check for [spoiler] text // handle nested quotes $endlessloop = 0; while ((strpos($Text, "[/spoiler]") !== false) and (strpos($Text, "[spoiler]") !== false) and (++$endlessloop < 20)) $Text = preg_replace("/\[spoiler\](.*?)\[\/spoiler\]/ism","$SpoilerLayout", $Text); // Check for [spoiler=Author] text $t_wrote = t('$1 wrote:'); // handle nested quotes $endlessloop = 0; while ((strpos($Text, "[/spoiler]")!== false) and (strpos($Text, "[spoiler=") !== false) and (++$endlessloop < 20)) $Text = preg_replace("/\[spoiler=[\"\']*(.*?)[\"\']*\](.*?)\[\/spoiler\]/ism", "
$2", $Text); // Declare the format for [quote] layout $QuoteLayout = '
$1'; // Check for [quote] text // handle nested quotes $endlessloop = 0; while ((strpos($Text, "[/quote]") !== false) and (strpos($Text, "[quote]") !== false) and (++$endlessloop < 20)) $Text = preg_replace("/\[quote\](.*?)\[\/quote\]/ism","$QuoteLayout", $Text); // Check for [quote=Author] text $t_wrote = t('$1 wrote:'); // handle nested quotes $endlessloop = 0; while ((strpos($Text, "[/quote]")!== false) and (strpos($Text, "[quote=") !== false) and (++$endlessloop < 20)) $Text = preg_replace("/\[quote=[\"\']*(.*?)[\"\']*\](.*?)\[\/quote\]/ism", "
$2", $Text); // [img=widthxheight]image source[/img] //$Text = preg_replace("/\[img\=([0-9]*)x([0-9]*)\](.*?)\[\/img\]/ism", '