Version 3.1.4
This commit is contained in:
1 parent
1d4720f3e2
commit
ae5c01cc78
2563 files changed
+283048
-240689
No files matched your search
@@ -1,18 +1,20 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* Invision Power Services
|
||||
* IP.Board v3.0.5
|
||||
* IP.Board v3.1.4
|
||||
* BBCode parsing core - common methods
|
||||
* Last Updated: $Date: 2009-12-07 21:57:46 -0500 (Mon, 07 Dec 2009) $
|
||||
* Last Updated: $Date: 2010-10-12 18:11:21 -0400 (Tue, 12 Oct 2010) $
|
||||
* </pre>
|
||||
*
|
||||
* @author $Author: bfarber $
|
||||
* @copyright (c) 2001 - 2009 Invision Power Services, Inc.
|
||||
* @license http://www.iinvisionpower.com/community/board/license.html
|
||||
* @package Invision Power Board
|
||||
* @link http://www.iinvisionpower.com
|
||||
* @license http://www.invisionpower.com/community/board/license.html
|
||||
* @package IP.Board
|
||||
* @link http://www.invisionpower.com
|
||||
* @since 9th March 2005 11:03
|
||||
* @version $Revision: 5529 $
|
||||
* @version $Revision: 6965 $
|
||||
*
|
||||
* Basic usage examples
|
||||
* <code>
|
||||
@@ -181,6 +183,14 @@ class class_bbcode_core
|
||||
* @var integer
|
||||
*/
|
||||
protected $emoticon_count = 0;
|
||||
|
||||
/**
|
||||
* Array of emoticon alt tags
|
||||
*
|
||||
* @access protected
|
||||
* @var array
|
||||
*/
|
||||
protected $emoticon_alts = array();
|
||||
|
||||
/**
|
||||
* Registry object
|
||||
@@ -342,6 +352,12 @@ class class_bbcode_core
|
||||
|
||||
foreach( $this->cache->getCache('bbcode') as $bbcode )
|
||||
{
|
||||
/* Cheat a bit */
|
||||
if ( $bbcode['bbcode_tag'] == 'code' OR $bbcode['bbcode_tag'] == 'acronym' OR $bbcode['bbcode_tag'] == 'img' )
|
||||
{
|
||||
$bbcode['bbcode_no_auto_url_parse'] = 1;
|
||||
}
|
||||
|
||||
//-----------------------------------------
|
||||
// BBcode allowed in this section?
|
||||
//-----------------------------------------
|
||||
@@ -370,7 +386,7 @@ class class_bbcode_core
|
||||
// Store into the array
|
||||
//-----------------------------------------
|
||||
|
||||
$this->_bbcodes[ $bbcode['bbcode_parse'] == 1 ? 'db' : 'display' ][ $bbcode['bbcode_tag'] ] = $bbcode;
|
||||
$this->_bbcodes['display'][ $bbcode['bbcode_tag'] ] = $bbcode;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -425,7 +441,7 @@ class class_bbcode_core
|
||||
* @param boolean Fix script HTML tags
|
||||
* @return string "Cleaned" text
|
||||
*/
|
||||
public function checkXss( $txt='', $fixScript=false )
|
||||
public function checkXss( $txt='', $fixScript=false, $tag='' )
|
||||
{
|
||||
//-----------------------------------------
|
||||
// Opening script tags...
|
||||
@@ -434,10 +450,101 @@ class class_bbcode_core
|
||||
|
||||
if ( $fixScript )
|
||||
{
|
||||
$txt = preg_replace( "#<(\s+?)?s(\s+?)?c(\s+?)?r(\s+?)?i(\s+?)?p(\s+?)?t#is" , "<script" , $txt );
|
||||
$txt = preg_replace( "#<(\s+?)?/(\s+?)?s(\s+?)?c(\s+?)?r(\s+?)?i(\s+?)?p(\s+?)?t#is", "</script", $txt );
|
||||
$txt = preg_replace( '#<(\s+?)?s(\s+?)?c(\s+?)?r(\s+?)?i(\s+?)?p(\s+?)?t#is' , "<script" , $txt );
|
||||
$txt = preg_replace( '#<(\s+?)?/(\s+?)?s(\s+?)?c(\s+?)?r(\s+?)?i(\s+?)?p(\s+?)?t#is', "</script", $txt );
|
||||
}
|
||||
|
||||
/* got a tag? */
|
||||
if ( $tag )
|
||||
{
|
||||
$tag = strip_tags( $tag, '<br>' );
|
||||
|
||||
switch ($tag)
|
||||
{
|
||||
case 'entry':
|
||||
case 'blog':
|
||||
case 'topic':
|
||||
case 'post':
|
||||
$test = str_replace( array( '"', "'", '"', ''' ), "", $txt );
|
||||
if ( ! is_numeric( $test ) )
|
||||
{
|
||||
$txt = false;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'acronym':
|
||||
$test = str_replace( array( '"', "'", '"', ''' ), "", $txt );
|
||||
$test1 = str_replace( array( '<', ">", '[', ']' ), "", $test );//IPSText::alphanumericalClean( $test, '.+&#; ' );
|
||||
if ( $test != $test1 )
|
||||
{
|
||||
$txt = false;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'email':
|
||||
$test = str_replace( array( '"', "'", '"', ''' ), "", $txt );
|
||||
$test = ( IPSText::checkEmailAddress( $test ) ) ? $txt : FALSE;
|
||||
break;
|
||||
|
||||
case 'font':
|
||||
case 'color':
|
||||
case 'background':
|
||||
/* Make sure it's clean */
|
||||
$test = str_replace( array( '"', "'", '"', ''' ), "", $txt );
|
||||
$test1 = IPSText::alphanumericalClean( $test, '#.+, ' );
|
||||
if ( $test != $test1 )
|
||||
{
|
||||
$txt = false;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
$_regex = null;
|
||||
|
||||
foreach( $this->cache->getCache('bbcode') as $bbcode )
|
||||
{
|
||||
if( $bbcode['bbcode_tag'] == $tag )
|
||||
{
|
||||
$_regex = $bbcode['bbcode_custom_regex'];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if( $_regex )
|
||||
{
|
||||
$test = str_replace( array( '"', "'", '"', ''' ), "", $txt );
|
||||
|
||||
if( !preg_match( $_regex, $test ) )
|
||||
{
|
||||
$txt = false;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
/* If we didn't actually get any option data, then return false */
|
||||
$test = str_replace( array( '"', "'", '"', ''' ), "", $txt );
|
||||
|
||||
if ( strlen($txt) AND strlen( $test ) < 1 )
|
||||
{
|
||||
$txt = false;
|
||||
}
|
||||
|
||||
if ( $txt === false )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Still here? Safety, then */
|
||||
$txt = strip_tags( $txt, '<br>' );
|
||||
|
||||
if( strpos( $txt, '[' ) !== false OR strpos( $txt, ']' ) !== false )
|
||||
{
|
||||
$txt = str_replace( array( '[', ']' ), array( '[', ']' ), $txt );
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------
|
||||
// Here we can do some generic checking for XSS
|
||||
// This should not be considered fool proof, though can provide
|
||||
@@ -446,10 +553,10 @@ class class_bbcode_core
|
||||
|
||||
$txt = preg_replace( "/(j)avascript/i" , "\\1avascript", $txt );
|
||||
//$txt = str_ireplace( "alert" , "alert" , $txt );
|
||||
$txt = str_ireplace( "behavior" , "behavior" , $txt );
|
||||
$txt = preg_replace( "/(e)((\/\*.*?\*\/)*)x((\/\*.*?\*\/)*)p((\/\*.*?\*\/)*)r((\/\*.*?\*\/)*)e((\/\*.*?\*\/)*)s((\/\*.*?\*\/)*)s((\/\*.*?\*\/)*)i((\/\*.*?\*\/)*)o((\/\*.*?\*\/)*)n/is" , "\\1xp<b></b>ression" , $txt );
|
||||
$txt = preg_replace( "/(e)((\\\|\)*)x((\\\|\)*)p((\\\|\)*)r((\\\|\)*)e((\\\|\)*)s((\\\|\)*)s((\\\|\)*)i((\\\|\)*)o((\\\|\)*)n/is" , "\\1xp<b></b>ression" , $txt );
|
||||
$txt = preg_replace( "/m((\\\|\)*)o((\\\|\)*)z((\\\|\)*)\-((\\\|\)*)b((\\\|\)*)i((\\\|\)*)n((\\\|\)*)d((\\\|\)*)i((\\\|\)*)n((\\\|\)*)g/is" , "moz-<b></b>binding" , $txt );
|
||||
//$txt = preg_replace( "/(b)(e)(h)(a)(v)(i)(o)(r)/is" , "\\1\\2\\3<b></b>\\4\\5\\6\\7\\8" , $txt );
|
||||
$txt = preg_replace( '/(e)((\/\*.*?\*\/)*)x((\/\*.*?\*\/)*)p((\/\*.*?\*\/)*)r((\/\*.*?\*\/)*)e((\/\*.*?\*\/)*)s((\/\*.*?\*\/)*)s((\/\*.*?\*\/)*)i((\/\*.*?\*\/)*)o((\/\*.*?\*\/)*)n/is' , "\\1xp<b></b>ression" , $txt );
|
||||
$txt = preg_replace( '/(e)((\\\|\)*)x((\\\|\)*)p((\\\|\)*)r((\\\|\)*)e((\\\|\)*)s((\\\|\)*)s((\\\|\)*)i((\\\|\)*)o((\\\|\)*)n/is' , "\\1xp<b></b>ression" , $txt );
|
||||
$txt = preg_replace( '/m((\\\|\)*)o((\\\|\)*)z((\\\|\)*)\-((\\\|\)*)b((\\\|\)*)i((\\\|\)*)n((\\\|\)*)d((\\\|\)*)i((\\\|\)*)n((\\\|\)*)g/is' , "moz-<b></b>binding" , $txt );
|
||||
$txt = str_ireplace( "about:" , "about:" , $txt );
|
||||
$txt = str_ireplace( "<body" , "<body" , $txt );
|
||||
$txt = str_ireplace( "<html" , "<html" , $txt );
|
||||
@@ -524,11 +631,11 @@ class class_bbcode_core
|
||||
foreach( $this->cache->getCache('badwords') as $r )
|
||||
{
|
||||
$replace = $r['swop'] ? $r['swop'] : '######';
|
||||
$r['type'] = preg_quote( $r['type'], "/" );
|
||||
|
||||
if ( $r['m_exact'] )
|
||||
{
|
||||
$text = preg_replace( "/(^|\b|\s)" . $r['type'] . "(\b|!|\?|\.|,|$)/i", "\\1{$replace}\\2", $text );
|
||||
$r['type'] = preg_quote( $r['type'], "/" );
|
||||
$text = preg_replace( "/(^|a-zа-я0-9|\s)" . $r['type'] . "([^a-zа-я0-9]|!|\?|\.|,|$)/ui", "\\1{$replace}\\2", $text );
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -538,11 +645,11 @@ class class_bbcode_core
|
||||
|
||||
if( $r['type'] == 'ass' )
|
||||
{
|
||||
$text = preg_replace( "/(?<!cl)" . $r['type'] . "/i", $replace, $text );
|
||||
$text = preg_replace( "/(?<!cl)" . $r['type'] . "/i", $replace, $text );
|
||||
}
|
||||
else
|
||||
{
|
||||
$text = str_ireplace( $r['type'], $replace, $text );
|
||||
$text = str_ireplace( $r['type'], $replace, $text );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -551,6 +658,75 @@ class class_bbcode_core
|
||||
|
||||
return $text ? $text : $temp_text;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check against blacklisted URLs
|
||||
*
|
||||
* @access public
|
||||
* @param string Raw posted text
|
||||
* @return bool False if blacklisted url present, otherwise true
|
||||
*/
|
||||
public function checkBlacklistUrls( $t )
|
||||
{
|
||||
if( !$t )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if ( $this->settings['ipb_use_url_filter'] )
|
||||
{
|
||||
$list_type = $this->settings['ipb_url_filter_option'] == "black" ? "blacklist" : "whitelist";
|
||||
|
||||
if( $this->settings['ipb_url_' . $list_type ] )
|
||||
{
|
||||
$list_values = array();
|
||||
$list_values = explode( "\n", str_replace( "\r", "", $this->settings['ipb_url_' . $list_type ] ) );
|
||||
|
||||
if( $list_type == 'whitelist' )
|
||||
{
|
||||
$list_values[] = "http://{$_SERVER['HTTP_HOST']}/*";
|
||||
}
|
||||
|
||||
if ( count( $list_values ) )
|
||||
{
|
||||
$good_url = 0;
|
||||
|
||||
foreach( $list_values as $my_url )
|
||||
{
|
||||
if( !trim($my_url) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
$my_url = preg_quote( $my_url, '/' );
|
||||
$my_url = str_replace( '\*', "(.*?)", $my_url );
|
||||
|
||||
if ( $list_type == "blacklist" )
|
||||
{
|
||||
if( preg_match( '/' . $my_url . '/i', $t ) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( preg_match( '/' . $my_url . '/i', $t ) )
|
||||
{
|
||||
$good_url = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! $good_url AND $list_type == "whitelist" )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Custom word wrap : attempts to not break HTML tags (*ha!)
|
||||
@@ -601,7 +777,7 @@ class class_bbcode_core
|
||||
$totalLength = strlen( $txt );
|
||||
$curPos = 0;
|
||||
$charsSince = 0;
|
||||
|
||||
$iterations = 0;
|
||||
//-----------------------------------------
|
||||
// Loop over each char
|
||||
//-----------------------------------------
|
||||
@@ -609,6 +785,14 @@ class class_bbcode_core
|
||||
while( $curPos < $totalLength )
|
||||
{
|
||||
$curPos++;
|
||||
|
||||
/**
|
||||
* @link http://community.invisionpower.com/tracker/issue-23818-wordwrap-bug-with-amp%3Blt%3B/
|
||||
*/
|
||||
if( $curPos < 1 )
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
//-----------------------------------------
|
||||
// We within a tag?
|
||||
@@ -763,12 +947,12 @@ class class_bbcode_core
|
||||
|
||||
static $iteration = array();
|
||||
|
||||
if( array_key_exists( $tag, $iteration ) AND $iteration[ $tag ] > 2000 )
|
||||
if( array_key_exists( $tag, $iteration ) AND $iteration[ $tag ] > $this->settings['max_bbcodes_per_post'] )
|
||||
{
|
||||
return $txt;
|
||||
}
|
||||
|
||||
$iteration[ $tag ]++;
|
||||
$iteration[ $tag ] = isset($iteration[ $tag ]) ? $iteration[ $tag ]++ : 1;
|
||||
|
||||
// Got Quotes (tm)? or any tag really
|
||||
if( stripos( $txt, '[' . $tag ) !== false )
|
||||
@@ -861,9 +1045,9 @@ class class_bbcode_core
|
||||
else
|
||||
{
|
||||
//$txt = preg_replace( "#\[{$bbcode['bbcode_tag']}\](.+?)\[/{$bbcode['bbcode_tag']}\]#is", "\\1 ", $txt );
|
||||
$txt = preg_replace( "#\[{$bbcode['bbcode_tag']}=(.+?)\](.+?)\[/{$bbcode['bbcode_tag']}\]#is", "\\2 ", $txt );
|
||||
$txt = str_replace( "[{$bbcode['bbcode_tag']}]", '', $txt );
|
||||
$txt = str_replace( "[/{$bbcode['bbcode_tag']}]", '', $txt );
|
||||
$txt = preg_replace( "#\[{$bbcode['bbcode_tag']}=([^\]]+?)\](.+?)\[/{$bbcode['bbcode_tag']}\]#ius", "\\2 ", $txt );
|
||||
$txt = str_ireplace( "[{$bbcode['bbcode_tag']}]", '', $txt );
|
||||
$txt = str_ireplace( "[/{$bbcode['bbcode_tag']}]", '', $txt );
|
||||
}
|
||||
|
||||
//-----------------------------------------
|
||||
@@ -880,17 +1064,17 @@ class class_bbcode_core
|
||||
|
||||
if( $bbcode['bbcode_useoption'] )
|
||||
{
|
||||
$regex .= '=([^\]]+)';
|
||||
$regex .= '=([^\]]+?)';
|
||||
}
|
||||
|
||||
$txt = preg_replace( "#\[{$regex}\]#is", " ", $txt );
|
||||
}
|
||||
}
|
||||
|
||||
$txt = preg_replace( "#\[(.+?)\]#is", " ", $txt );
|
||||
$txt = preg_replace( "#\[(.+?)=(.+?)\]#is", " ", $txt );
|
||||
$txt = preg_replace( "#\[/(.+?)\]#is", " ", $txt );
|
||||
$txt = preg_replace( "#\[attachment=(.+?)\]#is", " ", $txt );
|
||||
//$txt = preg_replace( "#\[(.+?)\]#is", " ", $txt );
|
||||
$txt = preg_replace( '#\[([^\]]+?)=([^\]]+?)\]#is', " ", $txt );
|
||||
$txt = preg_replace( '#\[/([^\]]+?)\]#is', " ", $txt );
|
||||
$txt = preg_replace( '#\[attachment=(.+?)\]#is', " ", $txt );
|
||||
$txt = str_replace( '[*]', '', $txt );
|
||||
|
||||
return $txt;
|
||||
@@ -919,14 +1103,31 @@ class class_bbcode_core
|
||||
|
||||
$_codeboxes = array();
|
||||
$_increment = 0;
|
||||
$_codes = array();
|
||||
|
||||
while( preg_match( "/\[code\](.+?)\[\/code\]/is", $t, $matches ) )
|
||||
foreach( $this->_bbcodes['display'] as $code => $data )
|
||||
{
|
||||
$_codeboxes[ $_increment ] = $matches[0];
|
||||
|
||||
$t = str_replace( $matches[0], "__CODEBOX_{$_increment}__", $t );
|
||||
|
||||
$_increment++;
|
||||
if( $data['bbcode_no_parsing'] )
|
||||
{
|
||||
if( $code == 'img' )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
$_codes[] = $code;
|
||||
}
|
||||
}
|
||||
|
||||
foreach( $_codes as $_aCode )
|
||||
{
|
||||
while( preg_match( "/\[{$_aCode}\](.+?)\[\/{$_aCode}\]/is", $t, $matches ) )
|
||||
{
|
||||
$_codeboxes[ $_increment ] = $matches[0];
|
||||
|
||||
$t = str_replace( $matches[0], "__CODEBOX_{$_increment}__", $t );
|
||||
|
||||
$_increment++;
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------
|
||||
@@ -1020,7 +1221,7 @@ class class_bbcode_core
|
||||
// Remove all macros
|
||||
//-----------------------------------------
|
||||
|
||||
$t = preg_replace( "#<\{.+?\}>#", "", $t );
|
||||
$t = preg_replace( '#<\{.+?\}>#', "", $t );
|
||||
|
||||
//-----------------------------------------
|
||||
// Reset the bbcodes to be safe
|
||||
@@ -1093,7 +1294,7 @@ class class_bbcode_core
|
||||
{
|
||||
$txt = substr_replace( $txt, '', $position, strlen($_emoCode) );
|
||||
|
||||
$position += strlen($replace);
|
||||
$position += strlen($_emoCode);
|
||||
}
|
||||
|
||||
$emoPosition = $position + 1;
|
||||
@@ -1123,13 +1324,15 @@ class class_bbcode_core
|
||||
//-----------------------------------------
|
||||
|
||||
$this->_resetPointers();
|
||||
$this->cache->updateCacheWithoutSaving( '_tmp_bbcode_media', 0 );
|
||||
$this->cache->updateCacheWithoutSaving( '_tmp_bbcode_images', 0 );
|
||||
|
||||
//-----------------------------------------
|
||||
// Remove session id's from any post
|
||||
//-----------------------------------------
|
||||
|
||||
//$txt = htmlspecialchars( $txt, ENT_NOQUOTES );
|
||||
$txt = preg_replace_callback( "#(\?|&|;|&)s=([0-9a-zA-Z]){32}(&|;|&|$)?#", array( $this, '_bashSession' ), $txt );
|
||||
$txt = preg_replace_callback( '#(\?|&|;|&)s=([0-9a-zA-Z]){32}(&|;|&|$)?#', array( $this, '_bashSession' ), $txt );
|
||||
|
||||
//-----------------------------------------
|
||||
// convert <br> to \n
|
||||
@@ -1164,7 +1367,7 @@ class class_bbcode_core
|
||||
|
||||
if ( $this->parse_bbcode )
|
||||
{
|
||||
$this->parseBbcode( $txt, 'db' );
|
||||
$txt = $this->parseBbcode( $txt, 'db' );
|
||||
}
|
||||
|
||||
//-----------------------------------------
|
||||
@@ -1177,6 +1380,12 @@ class class_bbcode_core
|
||||
$txt = preg_replace("/&#([0-9]+);/s", "&#\\1;", $txt );
|
||||
}
|
||||
|
||||
/* Parse smililes before bbcode, and remove elemnts that will not be parsed on display. Bug Fix: #20964 */
|
||||
// Parsing here causes nonparsed stuff to be double stored in the storeNonParsed array. This causes problems
|
||||
// when you limit images per post.
|
||||
// @link http://community.invisionpower.com/tracker/issue-23024-images-per-post-not-working
|
||||
// $txt = $this->_storeNonParsed( $txt, 'display' );
|
||||
|
||||
//-----------------------------------------
|
||||
// Parse smilies
|
||||
//-----------------------------------------
|
||||
@@ -1184,7 +1393,7 @@ class class_bbcode_core
|
||||
if ( $this->parse_smilies )
|
||||
{
|
||||
$codes_seen = array();
|
||||
|
||||
|
||||
if ( count( $this->cache->getCache('emoticons') ) > 0 )
|
||||
{
|
||||
foreach( $this->cache->getCache('emoticons') as $row )
|
||||
@@ -1193,62 +1402,62 @@ class class_bbcode_core
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
$code = $row['typed'];
|
||||
|
||||
|
||||
if ( in_array( $code, $codes_seen ) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
$codes_seen[] = $code;
|
||||
|
||||
|
||||
//-----------------------------------------
|
||||
// Now, check for the html safe versions
|
||||
//-----------------------------------------
|
||||
|
||||
|
||||
$_emoCode = str_replace( '<', '<', str_replace( '>', '>', $code ) );
|
||||
$_emoImage = $row['image'];
|
||||
$emoPosition = 0;
|
||||
|
||||
|
||||
//-----------------------------------------
|
||||
// These are chars that can't surround the emo
|
||||
//-----------------------------------------
|
||||
|
||||
|
||||
$invalidWrappers = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'\"";
|
||||
|
||||
|
||||
//-----------------------------------------
|
||||
// Have any more chars to look at?
|
||||
//-----------------------------------------
|
||||
|
||||
|
||||
while( ( $position = stripos( $txt, $_emoCode, $emoPosition ) ) !== false )
|
||||
{
|
||||
//-----------------------------------------
|
||||
// Are we at the start of the string, or
|
||||
// is the preceeding char not an invalid wrapper?
|
||||
//-----------------------------------------
|
||||
|
||||
|
||||
if( ( $position === 0 OR stripos( $invalidWrappers, substr( $txt, $position-1, 1 ) ) === false )
|
||||
|
||||
|
||||
//-----------------------------------------
|
||||
// Are we at the end of the string or is the
|
||||
// next char not an invalid wrapper?
|
||||
//-----------------------------------------
|
||||
|
||||
AND ( strlen($txt) == ($position + strlen($_emoCode)) OR stripos( $invalidWrappers, substr( $txt, ($position + strlen($_emoCode)), 1 ) ) === false ) )
|
||||
|
||||
AND ( strlen($txt) == ($position + strlen($_emoCode)) OR stripos( $invalidWrappers, substr( $txt, ($position + strlen($_emoCode)), 1 ) ) === false ) )
|
||||
{
|
||||
//-----------------------------------------
|
||||
// Replace the emoticon and increment position counter
|
||||
//-----------------------------------------
|
||||
|
||||
|
||||
$replace = $this->_retrieveSmiley( $_emoCode, $_emoImage );
|
||||
$txt = substr_replace( $txt, $replace, $position, strlen($_emoCode) );
|
||||
|
||||
|
||||
$position += strlen($replace);
|
||||
}
|
||||
|
||||
|
||||
$emoPosition = $position + 1;
|
||||
|
||||
|
||||
if( $emoPosition > strlen($txt) )
|
||||
{
|
||||
break;
|
||||
@@ -1264,6 +1473,24 @@ class class_bbcode_core
|
||||
$this->error = 'too_many_emoticons';
|
||||
}
|
||||
}
|
||||
|
||||
/* Put alt tags in */
|
||||
if( is_array( $this->emoticon_alts ) && count( $this->emoticon_alts ) )
|
||||
{
|
||||
foreach( $this->emoticon_alts as $r )
|
||||
{
|
||||
$txt = str_replace( $r[0], $r[1], $txt );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Put back non parsed code. Bug Fix: #20964 */
|
||||
if( is_array( $this->noParseStorage ) && count( $this->noParseStorage ) )
|
||||
{
|
||||
foreach( $this->noParseStorage as $r )
|
||||
{
|
||||
$txt = str_replace( $r['find'], $r['replace'], $txt );
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------
|
||||
@@ -1284,6 +1511,9 @@ class class_bbcode_core
|
||||
*/
|
||||
public function preDisplayParse( $txt="" )
|
||||
{
|
||||
$this->cache->updateCacheWithoutSaving( '_tmp_bbcode_media', 0 );
|
||||
$this->cache->updateCacheWithoutSaving( '_tmp_bbcode_images', 0 );
|
||||
|
||||
if ( $this->parse_html )
|
||||
{
|
||||
//-----------------------------------------
|
||||
@@ -1325,12 +1555,6 @@ class class_bbcode_core
|
||||
}
|
||||
|
||||
IPSDebug::setMemoryDebugFlag( "PreDisplayParse - applied wordwrap", $_NOW );
|
||||
|
||||
//-----------------------------------------
|
||||
// Protect against XSS
|
||||
//-----------------------------------------
|
||||
|
||||
$txt = $this->checkXss($txt);
|
||||
|
||||
//-----------------------------------------
|
||||
// Fix line breaks
|
||||
@@ -1340,7 +1564,7 @@ class class_bbcode_core
|
||||
{
|
||||
$txt = str_replace( "~~~~~_____~~~~~", '<br />', $txt );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------
|
||||
// And fix old youtube embedded videos..
|
||||
//-----------------------------------------
|
||||
@@ -1427,11 +1651,13 @@ class class_bbcode_core
|
||||
|
||||
$this->emoticon_count++;
|
||||
|
||||
$this->emoticon_alts[] = array( "#EMO_ALT_{$this->emoticon_count}#", $_emoCode );
|
||||
|
||||
//-----------------------------------------
|
||||
// Return
|
||||
//-----------------------------------------
|
||||
|
||||
return "<img src='" . $this->settings['emoticons_url'] . "/{$_emoImage}' class='bbc_emoticon' alt='{$_emoCode}' />";
|
||||
return "<img src='" . $this->settings['emoticons_url'] . "/{$_emoImage}' class='bbc_emoticon' alt='#EMO_ALT_{$this->emoticon_count}#' />";
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1454,15 +1680,6 @@ class class_bbcode_core
|
||||
$txt = $this->_storeNonParsed( $txt, $cur_method );
|
||||
}
|
||||
|
||||
//-----------------------------------------
|
||||
// Auto parse URLs (only if this is full sweep)
|
||||
//-----------------------------------------
|
||||
|
||||
if( !$_code AND $cur_method == 'display' )
|
||||
{
|
||||
$txt = preg_replace_callback( "#(^|\s|>|\](?<!\[url\]))((http|https|news|ftp)://\w+[^,\s\<\[]+)#is", array( $this, '_autoParseUrls' ), $txt );
|
||||
}
|
||||
|
||||
//-----------------------------------------
|
||||
// Regular replacing
|
||||
//-----------------------------------------
|
||||
@@ -1485,7 +1702,7 @@ class class_bbcode_core
|
||||
{
|
||||
$mygroups = array_diff( array_merge( $mygroups, explode( ',', IPSText::cleanPermString( $this->parsing_mgroup_others ) ) ), array('') );
|
||||
}
|
||||
|
||||
|
||||
foreach( $groups as $g_id )
|
||||
{
|
||||
if( in_array( $g_id, $mygroups ) )
|
||||
@@ -1630,7 +1847,7 @@ class class_bbcode_core
|
||||
// New instance of class, store in plugin registry for use next time
|
||||
//-----------------------------------------
|
||||
|
||||
$plugin = new $_classname( $this->registry );
|
||||
$plugin = new $_classname( $this->registry, $this );
|
||||
$method = "pre" . ucwords($cur_method) . "Parse";
|
||||
|
||||
$this->plugins[ md5($_bbcode['bbcode_tag']) ] = $plugin;
|
||||
@@ -1674,7 +1891,7 @@ class class_bbcode_core
|
||||
//-----------------------------------------
|
||||
|
||||
foreach( $_tags as $_tag )
|
||||
{
|
||||
{
|
||||
//-----------------------------------------
|
||||
// Are we only parsing one code?
|
||||
//-----------------------------------------
|
||||
@@ -1710,7 +1927,7 @@ class class_bbcode_core
|
||||
// Stop infinite loops
|
||||
//-----------------------------------------
|
||||
|
||||
if( $_iteration > 2000 )
|
||||
if( $_iteration > $this->settings['max_bbcodes_per_post'] )
|
||||
{
|
||||
break;
|
||||
}
|
||||
@@ -1790,46 +2007,76 @@ class class_bbcode_core
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------
|
||||
// If this is a single tag, that's it
|
||||
// Protect against XSS
|
||||
//-----------------------------------------
|
||||
|
||||
if( $_bbcode['bbcode_single_tag'] )
|
||||
$_optionStrLen = IPSText::mbstrlen( $_option );
|
||||
$_optionSlenstr = strlen($_option);
|
||||
$_option = $this->checkXss($_option, false, $_tag);
|
||||
|
||||
/* Not parsing URls? */
|
||||
if ( isset( $_bbcode['bbcode_no_auto_url_parse'] ) AND $_bbcode['bbcode_no_auto_url_parse'] )
|
||||
{
|
||||
$txt = substr_replace( $txt, $this->_bbcodeToHtml( $_bbcode, $_option, '' ), $this->cur_pos, ($open_length + strlen($_option) + 1) );
|
||||
$_option = preg_replace( "#(http|https|news|ftp)://#i", "\\1://", $_option );
|
||||
}
|
||||
|
||||
//-----------------------------------------
|
||||
// Otherwise replace out the content too
|
||||
//-----------------------------------------
|
||||
|
||||
else
|
||||
if ( $_option !== FALSE )
|
||||
{
|
||||
$close_tag = '[/' . $_tag . ']';
|
||||
|
||||
if( stripos( $txt, $close_tag, $new_pos ) !== false )
|
||||
//-----------------------------------------
|
||||
// If this is a single tag, that's it
|
||||
//-----------------------------------------
|
||||
|
||||
if( $_bbcode['bbcode_single_tag'] )
|
||||
{
|
||||
$_content = substr( $txt, ($this->cur_pos + $open_length + strlen($_option) + 1), (stripos( $txt, $close_tag, $this->cur_pos ) - ($this->cur_pos + $open_length + strlen($_option) + 1)) );
|
||||
$txt = substr_replace( $txt, $this->_bbcodeToHtml( $_bbcode, $_option /*? $_option : $_content*/, $_content ), $this->cur_pos, (stripos( $txt, $close_tag, $this->cur_pos ) + strlen($close_tag) - $this->cur_pos) );
|
||||
$txt = substr_replace( $txt, $this->_bbcodeToHtml( $_bbcode, $_option, '' ), $this->cur_pos, ($open_length + $_optionSlenstr + 1) );
|
||||
}
|
||||
|
||||
//-----------------------------------------
|
||||
// Otherwise replace out the content too
|
||||
//-----------------------------------------
|
||||
|
||||
else
|
||||
{
|
||||
//-----------------------------------------
|
||||
// If there's no close tag, no need to continue
|
||||
//-----------------------------------------
|
||||
|
||||
break;
|
||||
$close_tag = '[/' . $_tag . ']';
|
||||
|
||||
if( stripos( $txt, $close_tag, $new_pos ) !== false )
|
||||
{
|
||||
$_content = substr( $txt, ($this->cur_pos + $open_length + $_optionSlenstr + 1), (stripos( $txt, $close_tag, $this->cur_pos ) - ($this->cur_pos + $open_length + $_optionSlenstr + 1)) );
|
||||
|
||||
if( $_bbcode['bbcode_useoption'] AND $_bbcode['bbcode_optional_option'] AND !$_option )
|
||||
{
|
||||
$_option = $_content;
|
||||
$_option = $this->checkXss($_option, false, $_tag);
|
||||
}
|
||||
|
||||
/* Not parsing URls? */
|
||||
if ( isset( $_bbcode['bbcode_no_auto_url_parse'] ) AND $_bbcode['bbcode_no_auto_url_parse'] )
|
||||
{
|
||||
$_content = preg_replace( "#(http|https|news|ftp)://#i", "\\1://", $_content );
|
||||
}
|
||||
|
||||
$txt = substr_replace( $txt, $this->_bbcodeToHtml( $_bbcode, $_option /*? $_option : $_content*/, $_content ), $this->cur_pos, (stripos( $txt, $close_tag, $this->cur_pos ) + strlen($close_tag) - $this->cur_pos) );
|
||||
}
|
||||
else
|
||||
{
|
||||
//-----------------------------------------
|
||||
// If there's no close tag, no need to continue
|
||||
//-----------------------------------------
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------
|
||||
// And reset current position to end of open tag
|
||||
// Bug 14744 - if we jump to $new_pos it can skip the opening of the next bbcode tag
|
||||
// when the replacement HTML is shorter than the full bbcode representation...
|
||||
//-----------------------------------------
|
||||
|
||||
$this->cur_pos = strpos( $txt, $open_tag ) ? strpos( $txt, $open_tag ) : $this->cur_pos + 1; //$new_pos;
|
||||
$this->cur_pos = stripos( $txt, $open_tag ) ? stripos( $txt, $open_tag ) : $this->cur_pos + 1; //$new_pos;
|
||||
|
||||
if( $this->cur_pos > strlen($txt) )
|
||||
{
|
||||
@@ -1859,6 +2106,44 @@ class class_bbcode_core
|
||||
{
|
||||
$txt = $this->_parseNonParsed( $txt, $cur_method );
|
||||
}
|
||||
|
||||
//-----------------------------------------
|
||||
// Auto parse URLs (only if this is full sweep)
|
||||
//-----------------------------------------
|
||||
|
||||
if( !$_code AND $cur_method == 'display' )
|
||||
{
|
||||
/* If we parse <a href='http://site.com'>http://site[color=red].com[/color]</a>, it breaks
|
||||
* @link http://community.invisionpower.com/tracker/issue-24318-colors-in-urls-as-names-breaks-them/
|
||||
* Here we will extract <a></a> pairs, put in */
|
||||
$_storedLinks = array();
|
||||
$_counter = 0;
|
||||
|
||||
while( preg_match( "/<a href='(.+?)'(.*?)>(.+?)<\/a>/is", $txt, $matches ) )
|
||||
{
|
||||
$_counter++;
|
||||
$_storedLinks[ $_counter ] = $matches[0];
|
||||
|
||||
$txt = str_replace( $matches[0], '<!--LINKS_TEMP--' . $_counter . '-->', $txt );
|
||||
}
|
||||
|
||||
/* Capture 'href="' and '</a>' as [URL] is now parsed first, we discard these in _autoParseUrls */
|
||||
/**
|
||||
* @link http://community.invisionpower.com/tracker/issue-23726-parser-wrong-url-with-unicode-chars/
|
||||
* I had to add the /u modifier to correct this. Previously, the first byte sequence of the word was matching \s.
|
||||
* @link http://community.invisionpower.com/tracker/issue-24684-posts-are-blankmissing/
|
||||
* Reverting this fix as it's breaking in some environments - not really sure what we can do about this at this point
|
||||
*/
|
||||
//$opts = ( IPS_DOC_CHAR_SET == 'UTF-8' ) ? 'isu' : 'is';
|
||||
$opts = "is";
|
||||
$txt = preg_replace_callback( '#(^|\s|\)|\(|\{|\}|>|\]|\[|href=\S)((http|https|news|ftp)://(?:[^<>\)\[\"\s]+|[a-zA-Z0-9/\._\-!&\#;,%\+\?:=]+))(</a>)?#' . $opts, array( $this, '_autoParseUrls' ), $txt );
|
||||
|
||||
/* Now put back stored links */
|
||||
foreach( $_storedLinks as $_inc => $_storedLink )
|
||||
{
|
||||
$txt = str_replace( '<!--LINKS_TEMP--' . $_inc . '-->', $_storedLink, $txt );
|
||||
}
|
||||
}
|
||||
|
||||
return $txt;
|
||||
}
|
||||
@@ -1939,7 +2224,7 @@ class class_bbcode_core
|
||||
//-----------------------------------------
|
||||
|
||||
$replaceCode = $_bbcode['bbcode_replace'];
|
||||
$replaceCode = str_replace( '{base_url}', $this->settings['base_url'], $replaceCode );
|
||||
$replaceCode = str_replace( '{base_url}', $this->settings['board_url'] . '/index.php?', $replaceCode );
|
||||
$replaceCode = str_replace( '{image_url}', $this->settings['img_url'], $replaceCode );
|
||||
|
||||
preg_match( '/\{text\.(.+?)\}/i', $replaceCode, $matches );
|
||||
@@ -1998,6 +2283,7 @@ class class_bbcode_core
|
||||
$txt = str_replace( "&" , "&", $txt );
|
||||
$txt = str_replace( ">" , ">", $txt );
|
||||
$txt = str_replace( "<" , "<", $txt );
|
||||
$txt = str_replace( ">" , ">", $txt );
|
||||
$txt = str_replace( """, '"', $txt );
|
||||
|
||||
return $txt;
|
||||
@@ -2130,7 +2416,7 @@ class class_bbcode_core
|
||||
|
||||
else if( (strpos( $txt, ']', $_curPosition ) - ( $_curPosition + $open_length )) !== 0 )
|
||||
{
|
||||
$_curPosition = strpos( $txt, ']', $_curPosition );
|
||||
$_curPosition = ( strpos( $txt, ']', $_curPosition ) !== false ) ? strpos( $txt, ']', $_curPosition ) : $_curPosition + 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -2138,7 +2424,7 @@ class class_bbcode_core
|
||||
// Grab the new position to jump to
|
||||
//-----------------------------------------
|
||||
|
||||
$new_pos = strpos( $txt, ']', $_curPosition );
|
||||
$new_pos = ( strpos( $txt, ']', $_curPosition ) !== false ) ? strpos( $txt, ']', $_curPosition ) : $_curPosition + 1;
|
||||
|
||||
//-----------------------------------------
|
||||
// If this is a single tag, that's it
|
||||
@@ -2146,8 +2432,8 @@ class class_bbcode_core
|
||||
|
||||
if( $_bbcode['bbcode_single_tag'] )
|
||||
{
|
||||
$_currentContent = substr( $txt, $_curPosition, ($open_length + strlen($_option) + 1) );
|
||||
$txt = substr_replace( $txt, $_thisTag, $_curPosition, ($open_length + strlen($_option) + 1) );
|
||||
$_currentContent = substr( $txt, $_curPosition, ($open_length + IPSText::mbstrlen($_option) + 1) );
|
||||
$txt = substr_replace( $txt, $_thisTag, $_curPosition, ($open_length + IPSText::mbstrlen($_option) + 1) );
|
||||
}
|
||||
|
||||
//-----------------------------------------
|
||||
@@ -2170,7 +2456,7 @@ class class_bbcode_core
|
||||
}
|
||||
}
|
||||
|
||||
$this->noParseStorage[] = array(
|
||||
$this->noParseStorage[$this->_storedNoParsing] = array(
|
||||
'find' => $_thisTag,
|
||||
'replace' => $_currentContent,
|
||||
'code' => $_tag,
|
||||
@@ -2202,7 +2488,7 @@ class class_bbcode_core
|
||||
if( is_array( $this->noParseStorage ) AND count( $this->noParseStorage ) )
|
||||
{
|
||||
$this->resetPerPost();
|
||||
|
||||
|
||||
foreach( $this->noParseStorage as $replacement )
|
||||
{
|
||||
//-----------------------------------------
|
||||
@@ -2221,12 +2507,23 @@ class class_bbcode_core
|
||||
$replacement['replace'] = str_replace( "<", "<" , $replacement['replace'] );
|
||||
$replacement['replace'] = str_replace( '"', """, $replacement['replace'] );
|
||||
$replacement['replace'] = str_replace( '&#60;', "<", $replacement['replace'] );
|
||||
$replacement['replace'] = str_replace( '&#092;', "\", $replacement['replace'] );
|
||||
//$replacement['replace'] = str_replace( '<br />', "<br />", $replacement['replace'] );
|
||||
}
|
||||
|
||||
$_final = $this->parseBbcode( $replacement['replace'], $cur_method, $replacement['code'] );
|
||||
$_final = $this->preEditParse( $_final );
|
||||
|
||||
/* Bug fix: #20973 */
|
||||
if( preg_match( '/\<\!\-\-NoParse(\d+)\-\-\>/', $_final, $matches ) )
|
||||
{
|
||||
if( $matches[1] )
|
||||
{
|
||||
$_final = str_replace( "<!--NoParse{$matches[1]}-->", $this->noParseStorage[ $matches[1] ]['replace'], $_final );
|
||||
unset( $this->noParseStorage[ $matches[1] ] );
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------
|
||||
// We don't want any bbcodes to parse..
|
||||
//-----------------------------------------
|
||||
@@ -2252,7 +2549,88 @@ class class_bbcode_core
|
||||
*/
|
||||
private function _autoParseUrls( $matches )
|
||||
{
|
||||
return $this->parseBbcode( $matches[1] . '[url]' . $matches[2] . '[/url]', 'display', 'url' );
|
||||
$_extra = '';
|
||||
|
||||
/* Basic checking */
|
||||
if ( stristr( $matches[1], 'href' ) )
|
||||
{
|
||||
return $matches[0];
|
||||
}
|
||||
|
||||
if( strlen( $matches[2] ) < 12 )
|
||||
{
|
||||
return $matches[0];
|
||||
}
|
||||
|
||||
if ( isset( $matches[4] ) AND stristr( $matches[4], '</a>' ) )
|
||||
{
|
||||
return $matches[0];
|
||||
}
|
||||
|
||||
/* Check for XSS */
|
||||
if ( ! IPSText::xssCheckUrl( $matches[2] ) )
|
||||
{
|
||||
return $matches[0];
|
||||
}
|
||||
|
||||
if( substr( $matches[2], -1 ) == ',' )
|
||||
{
|
||||
$matches[2] = rtrim( $matches[2], ',' );
|
||||
$_extra = ',';
|
||||
}
|
||||
|
||||
/* Check for ! which is &#xx; at this point */
|
||||
if( preg_match( '/&#\d+?;$/', $matches[2], $_m ) )
|
||||
{
|
||||
$matches[2] = str_replace( $_m[0], '', $matches[2] );
|
||||
$_extra = $_m[0];
|
||||
}
|
||||
|
||||
/* Is this a media URL? */
|
||||
if( $this->settings['bbcode_automatic_media'] and isset( $this->_bbcodes['display']['media'] ) and ( $this->_bbcodes['display']['media']['bbcode_sections'] == 'all' or in_array( $this->parsing_section, explode( ',', $this->_bbcodes['display']['media']['bbcode_sections'] ) ) ) )
|
||||
{
|
||||
$media = $this->cache->getCache( 'mediatag' );
|
||||
|
||||
if( is_array($media) AND count($media) )
|
||||
{
|
||||
foreach( $media as $type => $r )
|
||||
{
|
||||
if( preg_match( "#^" . $r['match'] . "$#is", $matches[2] ) )
|
||||
{
|
||||
//-----------------------------------------
|
||||
// Do it this way so we can capture disable_flash
|
||||
//-----------------------------------------
|
||||
|
||||
$this->cache->updateCacheWithoutSaving( '_tmp_autoparse_media', 1 );
|
||||
$_result = $this->parseBbcode( $matches[1] . '[media]' . $matches[2] . '[/media]' . $_extra, 'display', 'media' );
|
||||
$this->cache->updateCacheWithoutSaving( '_tmp_autoparse_media', 0 );
|
||||
|
||||
return $_result;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* It's not media - so we'll use [url] - check we're allowed first */
|
||||
if( !isset( $this->_bbcodes['display']['url'] ) or ( $this->_bbcodes['display']['url']['bbcode_sections'] != 'all' and !in_array( $this->parsing_section, explode( ',', $this->_bbcodes['display']['url']['bbcode_sections'] ) ) ) )
|
||||
{
|
||||
// We're not allowed to use [url] here
|
||||
return $matches[0];
|
||||
}
|
||||
|
||||
/* Ensure bbcode is stripped for the actual URL */
|
||||
/* @link http://community.invisionpower.com/tracker/issue-22580-bbcode-breaks-link-add-bold-formatting-to-part-of-link/ */
|
||||
if ( preg_match( '#\[\w#', $matches[2] ) )
|
||||
{
|
||||
$wFormatting = $matches[2];
|
||||
$matches[2] = $this->stripAllTags( $matches[2] );
|
||||
|
||||
return $this->parseBbcode( $matches[1] . '[url="' . $matches[2] . '"]' . $wFormatting . '[/url]' . $_extra, 'display', 'url' );
|
||||
}
|
||||
else
|
||||
{
|
||||
return $this->parseBbcode( $matches[1] . '[url]' . $matches[2] . '[/url]' . $_extra, 'display', 'url' );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in new issue
Block a user