<?php
/*
Simple:Press Forum
Filters
$LastChangedDate: 2010-03-20 14:58:12 -0700 (Sat, 20 Mar 2010) $
$Rev: 3760 $
*/

if(preg_match('#' . basename(__FILE__) . '#', $_SERVER['PHP_SELF'])) {
	echo (__('Access Denied', "sforum"));
	die();
}

# ===FILTERS - USEAGE ==============================================
#
#	sf_filter_content_save($content, $action)
#	sf_filter_content_display($content)
#	sf_filter_content_edit($content)
#		Used for main post/message content so includes html, images,
#		profanity etc.
#
#	sf_filter_text_save($content)
#	sf_filter_text_display($content)
#	sf_filter_text_edit($content)
#		Used for larger areas of text where html is allowed like
#		admin defined message areas etc.
#
#	sf_filter_title_save($content)
#	sf_filter_title_display($content)
#		Used for title text where no html allowed such as forum
#		titles, custom labels and links etc.
#
#	sf_filter_name_save($content)
#	sf_filter_name_display($content)
#		Used for user names such as guest name and display name etc.
#
#	sf_filter_email_save($email)
#	sf_filter_email_display($email)
#		Used for email addresses
#
#	sf_filter_url_save($url)
#	sf_filter_url_display($url)
#		Used for URLs
#
#	sf_filter_filename_save($filename)
#		used for all filenames - i.e., custom icons etc
#
# ==================================================================


# ===START OF SAVE FILTERS==========================================
#
# CONTENT - SAVE FILTERS UMBRELLA
#
# Used:	Forum Post (including Quick Reply)
#		Private Messages
#		Blog Linking Posts and Comments
#		?
# $action will be 'new' or 'edit'

function sf_filter_content_save($content, $action)
{
	global $sfglobals;
	$sffilters = sf_get_option('sffilters');

    # prepare edits
    if ($action == 'edit')
    {
        $content = addslashes($content);
    }

	# 1: convert code tags to our own code display tags
	$content = sf_filter_save_codetags1($content, $sfglobals['editor']['sfeditor']);

	# 2: run it through kses
	$content = sf_filter_save_kses($content);

	# 3: remove nbsp and p/br tags
	$content = sf_filter_save_linebreaks($content);

	# 4: revist code tags in case post edit save
	$content = sf_filter_save_codetags2($content, $sfglobals['editor']['sfeditor'], $action);

	# 5: remove 'pre' tags (optional)
	if ($sffilters['sffilterpre']) {
		$content = sf_filter_save_pre($content);
	}

	# 6: deal with single quotes (tinymce encodes them)
	$content = sf_filter_save_quotes($content);

	# 7: balance html tags
	$content = sf_filter_save_balancetags($content);

	# 8: add nofollow to links (optional)
	if ($sffilters['sfnofollow']) {
		$content = sf_filter_save_nofollow($content);
	}

	# 9: add target blank (optional)
	if ($sffilters['sftarget']) {
		$content = sf_filter_save_target($content);
	}

	# 10: format links (optional)
	if($sffilters['sfurlchars']) {
		$content = sf_filter_save_links($content, $sffilters['sfurlchars']);
	}

	# 11: profanity filter
	$content = sf_filter_save_profanity($content);

	# 12: escape it All
	$content = sf_filter_save_escape($content);

	# 12: apply any users custom filters
	$content = apply_filters('sf_save_post_content', $content);

	return $content;
}

# ==================================================================
#
# TEXT - SAVE FILTERS UMBRELLA
#
# Used:	Profile Description
#		Blog Linking Link Text
#		Group Message
#		Forum Message
#		Email Messages
#		Signature Text
#		Announce Tag Heading/Text
#		Sneak Peak Message
#		Admin View Message
#		Custom Editor Messages
#		Registration/Privacy Messages
#		Custom Profile Message
#		Admins Off-Line Message
#		?

function sf_filter_text_save($content)
{
	global $sfglobals;
	$sffilters = sf_get_option('sffilters');

	# Decode the entities first that were applied for display
	$content = html_entity_decode($content, ENT_COMPAT, SFCHARSET);

	# 1: run it through kses
	$content = sf_filter_save_kses($content);

	# 2: remove nbsp and p/br tags
	$content = sf_filter_save_linebreaks($content);

	# 3: deal with single quotes (tinymce encodes them)
	$content = sf_filter_save_quotes($content);

	# 4: balance html tags
	$content = sf_filter_save_balancetags($content);

	# 5: add nofollow to links (optional)
	if ($sffilters['sfnofollow']) {
		$content = sf_filter_save_nofollow($content);
	}

	# 6: add target blank (optional)
	if ($sffilters['sftarget']) {
		$content = sf_filter_save_target($content);
	}

	# 7: format links (optional)
	if($sffilters['sfurlchars']) {
		$content = sf_filter_save_links($content, $sffilters['sfurlchars']);
	}

	# 8: escape it All
	$content = sf_filter_save_escape($content);

	return $content;
}

# ==================================================================
#
# TITLE - SAVE FILTERS UMBRELLA
#
# Used:	Group Title/Description
#		Forum Title/Description
#		Topic Title
#		Message Title
#		Blog Linking Titles
#		Email Subject
#		Custom Meta Description/Keywords
#		Topic Status Name/List
#		Custom Icon Title
#		UserGroup Name/Description
#		Permission Name/Description
#		Profile Form Labels
#		?

function sf_filter_title_save($content)
{
	# 1: remove all html
	$content = sf_filter_save_nohtml($content);

	# 2: encode brackets
	$content = sf_filter_save_brackets($content);

	# 3: profanity filter
	$content = sf_filter_save_profanity($content);

	# 10: escape it All
	$content = sf_filter_save_escape($content);

	# 4: apply any users custom filters
	$content = apply_filters('sf_save_title_content', $content);

	return $content;
}

# ==================================================================
#
# USER NAMES - SAVE FILTERS UMBRELLA
#
# Used:	Display Name
#		Guest Name
#		?

function sf_filter_name_save($content)
{
	# 1: Remove any html
	$content = sf_filter_save_nohtml($content);

	# 2: Encode
	$content = sf_filter_save_encode($content);

	# 3: escape it
	$content = sf_filter_save_escape($content);

	return $content;
}

# ==================================================================
#
# EMAIL ADDRESS - SAVE FILTERS UMBRELLA
#
# Used:	Guest posts
#		User profile
#		?

function sf_filter_email_save($email)
{
	# 1: Remove any html
	$email = sf_filter_save_nohtml($email);

	# 2: Validate and Sanitise Email
	$email = sf_filter_save_cleanemail($email);

	# 3: escape it
	$email = sf_filter_save_escape($email);

	return $email;
}

# ==================================================================
#
# URL - SAVE FILTERS UMBRELLA
#
# Used: All URLs
#		?

function sf_filter_url_save($url)
{
	# 1: clean up url for database
	$url = sf_filter_save_cleanurl($url);

	return $url;
}

# ==================================================================
#
# FILENAME - SAVE FILTERS UMBRELLA
#
# Used:	Avatar Upload
#		Avatar Pool
#		Signature Image
#		Custom Icons
#		Smileys
#		Editor Stylesheets
#		Registration/Privacy Documents
#		?

function sf_filter_filename_save($filename)
{
	# 1: clean up filename
	$filename = sf_filter_save_filename($filename);

	return $filename;
}


# ===START OF SAVE FILTERS==========================================

# ------------------------------------------------------------------
# sf_filter_save_codetags1()
#
# Try and change code tags to our code divs
#	$content:		Unfiltered post content
# ------------------------------------------------------------------
function sf_filter_save_codetags1($content, $editor)
{
	global $sfglobals;

	switch($editor)
	{
		case RICHTEXT:
			# TinyMCE
			include_once (SF_PLUGIN_DIR.'/forum/parsers/sf-rtetohtml.php');
			$content = sf_RTE2Html(" ".$content);
			break;

		case BBCODE:
			# Send everything through bbCode below as some users use it in all editors
			break;

		default:
			# HTML and Plain Textaera
			include_once (SF_PLUGIN_DIR.'/forum/parsers/sf-rawtohtml.php');
			$content = sf_Raw2Html(" ".$content);
			break;
	}

	# Now perform the bbCode which will preserve above changes
	include_once (SF_PLUGIN_DIR.'/forum/parsers/sf-bbtohtml.php');
	$content = sf_BBCode2Html(" ".stripslashes($content), false);

	# Shouldn't need any of these but there just in case...
	$content = str_replace('<code>', '<div class="sfcode">', $content);
	$content = str_replace('</code>', '</div>', $content);

	$content = str_replace('&lt;code&gt;', '<div class="sfcode">', $content);
	$content = str_replace('&lt;/code&gt;', '</div>', $content);

	return $content;
}

# ------------------------------------------------------------------
# sf_filter_save_codetags2()
#
# May be post edit save - so remove br's
#	$content:		Unfiltered post content
#	$editor:		Which editor
#	$action:		'new' or 'edit'
# ------------------------------------------------------------------
function sf_filter_save_codetags2($content, $editor, $action)
{
	# ONLY used for a TintMCE RichText Save 'Edit'

	if($editor == RICHTEXT && $action == 'edit') {
		# recheck extra line breaks and p tags - might have come from an edit
		$content = preg_replace_callback('/\<div class=\"sfcode\"\>(.*?)\<\/div\>/ms', "sf_codetag_callback", stripslashes($content));
	}

	return $content;
}

function sf_codetag_callback($s)
{
	$content = str_replace("<br />", "", $s[1]);
	$content = str_replace("\n", "", $content);
	$content = '<div class="sfcode">'.$content.'</div>';

	return $content;
}

# ------------------------------------------------------------------
# sf_filter_save_kses()
#
# Run it through kses - needs to be unescaped first
#	$content:		Unfiltered post content
# ------------------------------------------------------------------
function sf_filter_save_kses($content)
{
	global $allowedforumtags, $allowedforumprotocols;

	if(!isset($allowedforumtags))
	{
		sf_kses_array();
	}

	$content = wp_kses(stripslashes($content), $allowedforumtags, $allowedforumprotocols);

	return $content;
}

# ------------------------------------------------------------------
# sf_filter_save_linebreaks()
#
# Swap tinymce constructs with br's
#	$content:		Unfiltered post content
# ------------------------------------------------------------------
function sf_filter_save_linebreaks($content)
{
	# trim unwanted empty space
	$content = trim($content);

	# change br's to linebreaks
	$content = str_replace("<br />", "\n", $content);

	# change tiny blank line to a newline
	$content = str_replace("<p>&nbsp;</p>", "\n\n", $content);

	# same for blank line with p tags
	$content = str_replace("<p></p>", "\n\n", $content);
	$content = str_replace("<p> </p>", "\n\n", $content);

	$content = str_replace("<p>", "", $content);
	$content = str_replace("</p>", "\n", $content);

	return $content;
}

# ------------------------------------------------------------------
# sf_filter_save_pre()
#
# Remove html 'pre' and '/pre' tags
#	$content:		Unfiltered post content
# ------------------------------------------------------------------
function sf_filter_save_pre($content)
{
	# remove pre tags
	$content = str_replace("<pre>", "", $content);
	$content = str_replace("</pre>", "", $content);

	$content = str_replace('&lt;pre&gt;', '', $content);
	$content = str_replace('&lt;/pre&gt;', '', $content);

	return $content;
}

# ------------------------------------------------------------------
# sf_filter_save_quotes()
#
# Turn encoded single quote back
#	$content:		Unfiltered post content
# ------------------------------------------------------------------
function sf_filter_save_quotes($content)
{
	$content = str_replace("&#39;", "'", $content);

	return $content;
}

# ------------------------------------------------------------------
# sf_filter_save_balancetags()
#
# Tried to balance html tags
#	$content:		Unfiltered post content
# ------------------------------------------------------------------
function sf_filter_save_balancetags($content)
{
	$content = balanceTags($content, true);

	return $content;
}

# ------------------------------------------------------------------
# sf_filter_save_nofollow()
#
# Adds nofollow to links at save post time
#	$content:		Unfiltered post content
# ------------------------------------------------------------------

function sf_filter_save_nofollow($content)
{
	$content = preg_replace_callback('|<a (.+?)>|i', 'sf_nofollow_callback', $content);
	return $content;
}

function sf_nofollow_callback($matches)
{
	$text = $matches[1];
	$text = str_replace(array(' rel="nofollow"', " rel='nofollow'", 'rel="nofollow"', "rel='nofollow'"), '', $text);
	return '<a '.$text.' rel="nofollow">';
}

# ------------------------------------------------------------------
# sf_filter_save_target()
#
# Forces target _blank to links at save post time
#	$content:		Unfiltered post content
# ------------------------------------------------------------------
function sf_filter_save_target($content)
{
	$content = preg_replace_callback('|<a (.+?)>|i', 'sf_target_callback', $content);
	return $content;
}

function sf_target_callback($matches)
{
	$text = $matches[1];
	if(strpos($text, 'javascript:void(0)')) return "<a ".$text.">";
	$text = str_replace(array(' target="_blank"', " target='_blank'", 'target="_blank"', "target='_blank'"), '', $text);
	return '<a '.$text.' target="_blank">';
}

# ------------------------------------------------------------------
# sf_filter_save_links()
#
# Turns urtls in posts to clickable links with shortened text
#	$content:		Unfiltered post content
# Thanks to Peter at http://www.theblog.ca/shorten-urls for this
# ------------------------------------------------------------------
function sf_filter_save_links($content, $charcount)
{
	$content = make_clickable($content);

	# pad it with a space
	$content = ' ' . $content;

	# chunk those long urls
	sf_format_links($content, $charcount);

	$content = preg_replace("#(\s)([a-z0-9\-_.]+)@([^,< \n\r]+)#i", "$1<a href=\"mailto:$2@$3\">$2@$3</a>", $content);

	# Remove our padding..
	$content = substr($content, 1);

	return($content);
}

function sf_format_links(&$content, $charcount)
{
	$links = explode('<a', $content);
	$countlinks = count($links);
	for ($i = 0; $i < $countlinks; $i++)
	{
		$link = $links[$i];
		$link = (preg_match('#(.*)(href=")#is', $link)) ? '<a' . $link : $link;
		$begin = strpos($link, '>') + 1;
		$end = strpos($link, '<', $begin);
		$length = $end - $begin;
		$urlname = substr($link, $begin, $length);

		# We chunk urls that are longer than 50 characters. Just change
		# '50' to a value that suits your taste. We are not chunking the link
		# text unless if begins with 'http://', 'ftp://', or 'www.'
		$chunked = (strlen($urlname) > $charcount && preg_match('#^(http://|ftp://|www\.)#is', $urlname)) ? substr_replace($urlname, '.....', ($charcount - 10), -10) : $urlname;
		$content = str_replace('>' . $urlname . '<', '>' . $chunked . '<', $content);
	}
}

# ------------------------------------------------------------------
# sf_filter_save_profanity()
#
# Swaps any unwanted words for alternatives in post content
#	$content:		Unfiltered post content
# ------------------------------------------------------------------
function sf_filter_save_profanity($content)
{
	$badwords = explode("\n", stripslashes(sf_get_option('sfbadwords')));
	$replacementwords = explode("\n", stripslashes(sf_get_option('sfreplacementwords')));

	# need to add in delimiter for preg replace
	foreach ($badwords as $index => $badword)
	{
        if (!empty($badword))
        {
            $badwords[$index] = '/\b'.trim($badword).'\b/i';
            $replacementwords[$index] = trim($replacementwords[$index]);
        } else {
            unset($badwords[$index]);
        }
	}

	# filter the bad words
	$content = preg_replace($badwords, $replacementwords, $content);

	return $content;
}

# ------------------------------------------------------------------
# sf_filter_save_nohtml()
#
# Remove unwanted html
#	$title:		Unfiltered title content
# ------------------------------------------------------------------
function sf_filter_save_nohtml($content)
{
	$content = wp_kses(stripslashes($content), array());
	return $content;
}

# ------------------------------------------------------------------
# sf_filter_save_brackets()
#
# Remove square brackets from titles
#	$content:		Unfiltered post content
# ------------------------------------------------------------------
function sf_filter_save_brackets($content)
{
	$content = str_replace('[', '&#091;', $content);
	$content = str_replace(']', '&#093;', $content);

	return $content;
}

# ------------------------------------------------------------------
# sf_filter_save_escape()
#
# escape content before saving
#	$content:		Unfiltered post content
# ------------------------------------------------------------------
function sf_filter_save_escape($content)
{
	$content = esc_sql($content);

	return $content;
}

# ------------------------------------------------------------------
# sf_filter_save_filename()
#
# Sanitises a filename and makes it safe
#	$filename:		Unfiltered file name
# ------------------------------------------------------------------
function sf_filter_save_filename($filename)
{
	$filename_raw = $filename;
	$special_chars = array("?", "[", "]", "/", "\\", "=", "<", ">", ":", ";", ",", "'", "\"", "&", "$", "#", "*", "(", ")", "|", "~", "`", "!", "{", "}", chr(0));
	$filename = str_replace($special_chars, '', $filename);
	$filename = preg_replace('/[\s-]+/', '-', $filename);
	$filename = trim($filename, '.-_');

	# Split the filename into a base and extension[s]
	$parts = explode('.', $filename);

	# Return if only one extension
	if ( count($parts) <= 2 )
		return $filename;

	# Process multiple extensions
	$filename = array_shift($parts);
	$extension = array_pop($parts);
	$mimes =  get_allowed_mime_types();

	# Loop over any intermediate extensions.  Munge them with a trailing underscore if they are a 2 - 5 character
	# long alpha string not in the extension whitelist.
	foreach ( (array) $parts as $part) {
		$filename .= '.' . $part;

		if ( preg_match("/^[a-zA-Z]{2,5}\d?$/", $part) ) {
			$allowed = false;
			foreach ( $mimes as $ext_preg => $mime_match ) {
				$ext_preg = '!(^' . $ext_preg . ')$!i';
				if ( preg_match( $ext_preg, $part ) ) {
					$allowed = true;
					break;
				}
			}
			if ( !$allowed )
				$filename .= '_';
		}
	}
	$filename = str_replace(' ', '_', $filename);
	$filename .= '.' . $extension;

	return $filename;
}

# ------------------------------------------------------------------
# sf_filter_save_encode()
#
# Encode atributes
#	$content:		usually a display name
# ------------------------------------------------------------------
function sf_filter_save_encode($content)
{
	$content = esc_attr($content);

	return $content;
}

# ------------------------------------------------------------------
# sf_filter_save_cleanemail()
#
# Sanitises am email address and makes it safe
#	$filename:		Unfiltered file name
# ------------------------------------------------------------------
function sf_filter_save_cleanemail($email)
{
	$email = sanitize_email($email);

	return $email;
}

# ------------------------------------------------------------------
# sf_filter_save_cleanurl()
#
# Sanitises an url for db  and makes it safe
#	$url:		Unfiltered url
# ------------------------------------------------------------------
function sf_filter_save_cleanurl($url)
{
	$url = esc_url_raw($url);

	return $url;
}


# ===END OF SAVE FILTERS============================================

# ===START OF EDIT FILTERS==========================================
#
# CONTENT - EDIT FILTERS UMBRELLA
#
# Used:	Forum Post
#		?

function sf_filter_content_edit($content)
{
	global $sfglobals;

	# 1: Convert smiley codes to images
	$content = sf_filter_display_smileys($content);

	# 2: Convert Chars
	$content = sf_filter_display_chars($content);

	# 3: Format the paragraphs (p and br onlt Richtext)
//	$content = sf_filter_display_paragraphs($content);
	if($sfglobals['editor']['sfeditor'] != RICHTEXT) {
		$content = sf_filter_save_linebreaks($content);
	} else {
		$content = sf_filter_display_paragraphs($content);
	}

	# 4: Parse post into appropriate editor format
	$content = sf_filter_edit_parser($content, $sfglobals['editor']['sfeditor']);

	# 5: remove escape slashes
	//$content = sf_filter_display_stripslashes($content);

	return $content;
}

# ==================================================================
#
# TEXT - EDIT FILTERS UMBRELLA
#
# Used:	Text Areas
#		?

function sf_filter_text_edit($content)
{
	global $sfglobals;

	# 1: Convert Chars
	$content = sf_filter_display_chars($content);

	# 2: Format the paragraphs (p and br)
	$content = sf_filter_display_paragraphs($content);
	$content = sf_filter_save_linebreaks($content);

	# 3: Parse post into appropriate editor format
	$content = sf_filter_edit_parser($content, PLAIN);

	# 4: remove escape slashes
	$content = sf_filter_display_stripslashes($content);

	# finally htnl encode it for edit display
	$content = htmlentities($content, ENT_COMPAT, SFCHARSET);

	return $content;
}

function sf_filter_edit_parser($content, $editor)
{

	if($editor == BBCODE) {
		# load the bbcode to html parser
		include_once (SF_PLUGIN_DIR.'/forum/parsers/sf-htmltobb.php');
		$content = sf_Html2BBCode($content);
	} elseif($editor == HTML || $editor == PLAIN) {
		# load the raw to html parser
		include_once (SF_PLUGIN_DIR.'/forum/parsers/sf-htmltoraw.php');
		$content = sf_Html2Raw($content);
	}

	return $content;
}


# ===END OF EDIT FILTERS============================================

# ===START OF DISPLAY FILTERS=======================================
#
# CONTENT - DISPLAY FILTERS UMBRELLA
#
# Used:	Forum Post
#		Private Messages
#		RSS Feeds
#		Post Report
#		Template Tag
#		?

function sf_filter_content_display($content)
{
	# 1: Backwards compatible make links clickable
	$content = sf_filter_display_links($content);

	# 2: Convert smiley codes to images
	$content = sf_filter_display_smileys($content);

	# 3: Convert Chars
	$content = sf_filter_display_chars($content);

	# 4: Format the paragraphs
	$content = sf_filter_display_paragraphs($content);

	# 5: Format the code select Divs.
	$content = sf_filter_display_codeselect($content);

	# 6: Format image tags
	$content = sf_filter_display_images($content);

	# 7: remove escape slashes
//	$content = sf_filter_display_stripslashes($content);

    # 8: strip shortcodes
    if (sf_get_option('sffiltershortcodes'))
    {
    	$content = sf_filter_display_shortcodes($content);
    }

	# 9: apply any users custom filters
	$content = apply_filters('sf_show_post_content', $content);

	return $content;
}

# ==================================================================
#
# TEXT - DISPLAY FILTERS UMBRELLA
#
# Used:	Profile Description
#		Blog Linking Link Text
#		Group Message
#		Forum Message
#		Email Messages
#		Signature Text
#		Announce Tag Heading/Text
#		Sneak Peak Message
#		Admin View Message
#		Custom Editor Messages
#		Registration/Privacy Messages
#		Custom Profile Message
#		Admins Off-Line Message
#		?

function sf_filter_text_display($content)
{
	# 1: Convert Chars
	$content = sf_filter_display_chars($content);

	# 2: Format the paragraphs
	$content = sf_filter_display_paragraphs($content);

	# 3: remove escape slashes
	$content = sf_filter_display_stripslashes($content);

	return $content;
}

# ==================================================================
#
# TITLE - DISPLAY FILTERS UMBRELLA
#
# Used:	Group Title/Description *
#		Forum Title/Description *
#		Topic Title *
#		Message Title *
#		Blog Linking Titles *
#		Email Subject *
#		Custom Meta Description/Keywords *
#		Topic Status Name/List *
#		Custom Icon Title *
#		UserGroup Name/Description *
#		Permission Name/Description *
#		Profile Form Labels *
#		?

function sf_filter_title_display($content)
{
	# 1: Convert Chars
	$content = sf_filter_display_chars($content);

	# 2: remove escape slashes
	$content = sf_filter_display_stripslashes($content);

	return $content;
}

# ==================================================================
#
# USER NAMES - DISPLAY FILTERS UMBRELLA
#
# Used:	Display Name
#		Guest Name
#		?

function sf_filter_name_display($content)
{
	# 1: Convert Chars
	$content = sf_filter_display_chars($content);

	# 2: remove escape slashes
	$content = sf_filter_display_stripslashes($content);

	return $content;
}

# ==================================================================
#
# EMAIL ADDRESS - DISPLAY FILTERS UMBRELLA
#
# Used:	Guest posts
#		User profile
#		?

function sf_filter_email_display($email)
{
	# 1: Convert Chars
	$email = sf_filter_display_chars($email);

	# 2: remove escape slashes
	$email = sf_filter_display_stripslashes($email);

	return $email;
}

# ==================================================================
#
# URL - DISPLAY FILTERS UMBRELLA
#
# Used: All URLs
#		?

function sf_filter_url_display($url)
{
	# 1: Clean url for display
	$url = sf_filter_display_cleanurl($url);

	return $url;
}

# ===START OF DISPLAY FILTERS=======================================

# ------------------------------------------------------------------
# sf_filter_display_links()
#
# Makes unanchored links clickable. This is here for backward
# compatibility with older storage of posts that incuded p tags
#
#	$content:		Unfiltered post content
# ------------------------------------------------------------------
function sf_filter_display_links($content)
{
	$content = make_clickable($content);

	return $content;
}

# ------------------------------------------------------------------
# sf_convert_custom_smileys()
#
# Swaps codes for smileys if using custom images
#	$content:		Unfiltered post content
# ------------------------------------------------------------------
function sf_filter_display_smileys($content)
{
	global $sfglobals;

	# Custom
	if($sfglobals['smileyoptions']['sfsmallow'] && $sfglobals['smileyoptions']['sfsmtype']==1)
	{
		if($sfglobals['smileys'])
		{
			foreach ($sfglobals['smileys'] as $sname => $sinfo)
			{
				$content = str_replace($sinfo[1], '<img src="'.SFSMILEYS.$sinfo[0].'" title="'.$sname.'" alt="'.$sname.'" />', $content);
			}
		}
	}

	# WP versions
	if($sfglobals['smileyoptions']['sfsmallow'] && $sfglobals['smileyoptions']['sfsmtype']==3)
	{
		$content = convert_smilies($content);
	}

	return $content;
}

# ------------------------------------------------------------------
# sf_filter_display_chars()
#
# Converts specific chars to entities
#	$content:		Unfiltered post content
# ------------------------------------------------------------------
function sf_filter_display_chars($content)
{
	$content = convert_chars($content);

	return $content;
}

# ------------------------------------------------------------------
# sf_filter_display_paragraphs()
#
# Breaks up into paragraphs
#	$content:		Unfiltered post content
# ------------------------------------------------------------------
function sf_filter_display_paragraphs($content)
{
	$content = wpautop($content);
	$content = shortcode_unautop($content);

	return $content;
}

# ------------------------------------------------------------------
# sf_filter_display_codeselect()
#
# Adds the 'Select Code' button to code blocks
# ------------------------------------------------------------------
function sf_filter_display_codeselect($content)
{
	# add the 'select code' button
	$pos = strpos($content, '<div class="sfcode">');
	if($pos === false) return $content;

	while($pos !== false)
	{
		$id = rand(100, 10000);
		$selector = '#sfcode'.$id;
		$replace = '<p><input type="button" class="sfcodeselect" name="sfselectit'.$id.'" value="'.__("Select Code", "sforum").'" onclick="sfjSelectCode(\'sfcode'.$id.'\');" /><div class="sfcode" id="sfcode'.$id.'"></p>';
		$content = substr_replace ($content, $replace, $pos, 20);
		$pos = $pos + 140;
		$pos = strpos($content, '<div class="sfcode">', $pos);
	}
	return $content;
}

# ------------------------------------------------------------------
# sf_filter_display_images() and support functions
#
# Change large images to small thumbnails and embed
#	$content:		Unfiltered post content
# ------------------------------------------------------------------
function sf_filter_display_images($content)
{
	return sf_swap_IMGs($content);
}

function sf_swap_IMGs($content)
{
	$content = preg_replace_callback('/<img[^>]*>/', 'sf_check_width' , $content);
	return $content;
}

function sf_check_width($match)
{
	global $SFPATHS;

	$sfimage = array();
	$sfimage = sf_get_option('sfimage');

	$thumb = $sfimage['thumbsize'];
	if((empty($thumb)) || ($thumb < 100)) $thumb=100;

	preg_match('/title="(.*?)"/', $match[0], $title);
	preg_match('/alt="(.*?)"/', $match[0], $alt);
	preg_match('/width="(.*?)"/', $match[0], $width);
	preg_match('/src="(.*?)"/', $match[0], $src);
	preg_match('/style="(.*?)"/', $match[0], $style);

	if((strpos($src[1], 'plugins/emotions')) || (strpos($src[1], 'images/smilies')) || (strpos($src[1], $SFPATHS['smileys'])))
	{
		return $match[0];
	}

	if(empty($style[1]))
	{
		if($sfimage['style'] == 'left' || $sfimage['style']=='right')
		{
			$style[1] = 'float: '.$sfimage['style'];
		} else {
			$style[1] = 'vertical-align: '.$sfimage['style'];
		}
	}

	$iclass='';
	$mclass="sfmouseother";

	switch($style[1])
	{
		case 'float: left':
			$iclass="sfimageleft";
			$mclass="sfmouseleft";
			break;
		case 'float: right':
			$iclass="sfimageright";
			$mclass="sfmouseright";
			break;
		case 'vertical-align: baseline':
			$iclass="sfimagebaseline";
			break;
		case 'vertical-align: top':
			$iclass="sfimagetop";
			break;
		case 'vertical-align: middle':
			$iclass="sfimagemiddle";
			break;
		case 'vertical-align: bottom':
			$iclass="sfimagebottom";
			break;
		case 'vertical-align: text-top':
			$iclass="sfimagetexttop";
			break;
		case 'vertical-align: text-bottom':
			$iclass="sfimagetextbottom";
			break;
	}

	# figure out whether its relative path (same server) or a url
    $parsed = parse_url($src[1]);
    if (array_key_exists('scheme', $parsed))
    {
    	$srcfile = $src[1];  # url, so leave it alone
    } else {
  		$srcfile = $_SERVER['DOCUMENT_ROOT'].$src[1];  # relative path, so add DOCUMENT_ROOT to path
  	}

	if(empty($width[1]))
	{
		global $gis_error;
		set_error_handler('sf_gis_error');

		$size = getimagesize($srcfile);
		restore_error_handler();
		if($gis_error == '')
		{
			if ($size[0])
			{
				$width[1] = $size[0];
			} else {
				return '['.__('Image Removed by User', 'sforum').']';
			}
		}
	}

	$thissrc = 'src="'.$src[1].'" ';
	$thistitle = 'title="'.$ittle[1].'" ';
	$thisalt = 'alt="'.$alt[1].'" ';
	if((int)$width[1] > (int)$thumb)
	{
		$thiswidth = 'width="'.$thumb.'" ';
		$anchor=true;
	} else {
		$thiswidth = 'width="'.$width[1].'" ';
		$mclass='';
		$anchor=false;
	}

	if(!empty($iclass))
	{
		$thisformat = 'class="'.$iclass.'" ';
	} else {
		$thisformat = 'style="'.$style[1].'" ';
	}

	if($anchor)
	{
		# Use highslide popup
		if($sfimage['enlarge'] == true)
		{
			$out = '<a onclick="return hs.expand(this)" class="highslide" href="'.$src[1].'" '.$thistitle.'>';
		} else {
			$out = '<a href="'.$src[1].'" '.$thistitle.'>';
		}
	}

	$out.= '<img '.$thissrc.$thiswidth.$thisformat.$thistitle.$thisalt.'/>';

	if($mclass)
	{
		$out.= '<img src="'.SFRESOURCES.'mouse.png" class="'.$iclass.' '.$mclass.'" alt="" />';
	}

	if($anchor)
	{
		$out.= '</a>';
	}

	return $out;
}

# ------------------------------------------------------------------
# sf_filter_display_stripslashes()
#
# Remov escaped slashes
#	$content:		Unfiltered post content
# ------------------------------------------------------------------
function sf_filter_display_stripslashes($content)
{
	$content = stripslashes($content);

	return $content;
}

# ------------------------------------------------------------------
# sf_filter_display_cleanurl()
#
# Cleans up url for display
#	$url:		Unfiltered url
# ------------------------------------------------------------------
function sf_filter_display_cleanurl($url)
{
	$url = esc_url($url);

	return $url;
}

# ------------------------------------------------------------------
# sf_filter_display_shortcodes()
#
# Removes non allowed shortcodes
# ------------------------------------------------------------------
function sf_filter_display_shortcodes($content)
{
	global $shortcode_tags;

	# Backup current registered shortcodes
	$orig_shortcode_tags = $shortcode_tags;

	$allowed_shortcodes = explode("\n", stripslashes(sf_get_option('sfshortcodes')));
    if ($allowed_shortcodes)
    {
        foreach ($allowed_shortcodes as $tag)
        {
            If (array_key_exists($tag, $orig_shortcode_tags)) unset($shortcode_tags[$tag]);
        }
    }

    # be sure to allow our spoilers
    unset($shortcode_tags['spoiler']);

    # strip all but allowed shortcodes
    $content = strip_shortcodes($content);

	# Restore registered shortcodes
	$shortcode_tags = $orig_shortcode_tags;

	return $content;
}


# ==================================================================
#
# CONTENT - PAGE LEVEL DISPLAY FILTERS
#
# The following filters and shortcodes are run at 'page' level after
# the forum page has been generated.

# ------------------------------------------------------------------
# sf_filter_display_spoiler()
#
# Converts the spoiler shortcode to the drop down spoiler div
# ------------------------------------------------------------------
function sf_filter_display_spoiler($atts, $content)
{
	global $spoilerID, $sfvars;

	# if edit mode return raw spoiler shortcode
	if($sfvars['action'] == 'editpost')
	{
		$content = '[spoiler]'.$content.'[/spoiler]';
		return $content;
	}

	if(!isset($spoilerID))
	{
		$spoilerID=1;
	} else {
		$spoilerID++;
	}

	$out = '';
	$out.= '<div class="sfspoiler">';

	$out.= '<div class="sfreveal">';
	$out.= '<a href="javascript:void(0);" onclick="sfjtoggleLayer(\'sfspoilercontent'.$spoilerID.'\');">'.__("Reveal Spoiler", "sforum").'</a>';
	$out.= '</div>';
	$out.= '<div class="sfspoilercontent" id="sfspoilercontent'.$spoilerID.'">';
	$out.= '<p>'.$content.'</p>';
	$out.= '</div></div>';

	return $out;
}

# ------------------------------------------------------------------
# sf_wptexturize()
#
# take control of wptexturize to stop it doing really nasty things
# to quotes.
#	$content:		Unfiltered post content
# ------------------------------------------------------------------
function sf_wptexturize($content)
{
	static $static_setup = false, $default_no_texturize_tags, $default_no_texturize_shortcodes, $static_characters, $static_replacements;
	$output = '';
	$curl = '';
	$textarr = preg_split('/(<.*>|\[.*\])/Us', $content, -1, PREG_SPLIT_DELIM_CAPTURE);
	$stop = count($textarr);

	# No need to setup these variables more than once
	if (!$static_setup)
	{
		$default_no_texturize_tags = array('pre', 'code', 'kbd', 'style', 'script', 'tt');
		$default_no_texturize_shortcodes = array('code');

		$static_characters = array('---', ' -- ', '--', ' - ', 'xn&#8211;', '...', ' (tm)');
		$static_replacements = array('&#8212;', ' &#8212; ', '&#8211;', ' &#8211; ', 'xn--', '&#8230;', ' &#8482;');

		$static_setup = true;
	}

	# Transform into regexp sub-expression used in _wptexturize_pushpop_element
	# Must do this everytime in case plugins use these filters in a context sensitive manner
	$no_texturize_tags = '(' . implode('|', apply_filters('no_texturize_tags', $default_no_texturize_tags) ) . ')';
	$no_texturize_shortcodes = '(' . implode('|', apply_filters('no_texturize_shortcodes', $default_no_texturize_shortcodes) ) . ')';

	$no_texturize_tags_stack = array();
	$no_texturize_shortcodes_stack = array();

	for ( $i = 0; $i < $stop; $i++ )
	{
		$curl = $textarr[$i];

		if ( !empty($curl) && '<' != $curl{0} && '[' != $curl{0} && empty($no_texturize_shortcodes_stack) && empty($no_texturize_tags_stack))
		{
			# This is not a tag, nor is the texturization disabled static strings
			$curl = str_replace($static_characters, $static_replacements, $curl);
			# regular expressions
		} elseif (!empty($curl)) {
			# Only call _wptexturize_pushpop_element if first char is correct tag opening
			if ('<' == $curl{0})
				_wptexturize_pushpop_element($curl, $no_texturize_tags_stack, $no_texturize_tags, '<', '>');
			elseif ('[' == $curl{0})
				_wptexturize_pushpop_element($curl, $no_texturize_shortcodes_stack, $no_texturize_shortcodes, '[', ']');
		}

		$curl = preg_replace('/&([^#])(?![a-zA-Z1-4]{1,8};)/', '&#038;$1', $curl);
		$output .= $curl;
	}
	return $output;
}

?>