/**
* Custom event: Remove avatar
*
* @access public
* @author Matt Mecham
* @return string Processed HTML
*/
public function customEvent_removeAvatar()
Добавить после:
//-----------------------------------------
// Check secure hash...
//-----------------------------------------
if ( $this->request['secure_key'] != $this->member->form_hash )
{
$this->registry->output->showError( 'authorization_error', 100, true, null, 403 );
}
Найти:
/**
* Custom event: Remove photo
*
* @access public
* @author Matt Mecham
* @return string Processed HTML
*/
function customEvent_removePhoto()
{
Добавить после:
//-----------------------------------------
// Check secure hash...
//-----------------------------------------
if ( $this->request['secure_key'] != $this->member->form_hash )
{
$this->registry->output->showError( 'authorization_error', 100, true, null, 403 );
}
Найти:
//-----------------------------------------
// Reset forced form action?
//-----------------------------------------
if ( $is_reset )
{
$this->settings['base_url'] = $original;
}
Добавить после:
/* fix url */
$return = preg_replace( "#(area=removeavatar(&|&)do=remove)#", "\\1&secure_key=" . $this->member->form_hash, $return );
Найти:
$this->uploadFormMax = 5000000;
return $this->registry->getClass('output')->getTemplate('ucp')->membersPhotoForm( $cur_photo, $show_size, $p_max, 500000, $rand );
Заменить на:
$this->uploadFormMax = 5000000;
$return = $this->registry->getClass('output')->getTemplate('ucp')->membersPhotoForm( $cur_photo, $show_size, $p_max, 500000, $rand );
/* fix url */
$return = preg_replace( "#(area=removephoto(&|&)do=remove)#", "\\1&secure_key=" . $this->member->form_hash, $return );
return $return;
**В файле //admin/sources/classes/bbcode/core.php//** найти:
/**
* Check against XSS
*
* @access public
* @param string Original string
* @param boolean Fix script HTML tags
* @return string "Cleaned" text
*/
public function checkXss( $txt='', $fixScript=false )
{
//-----------------------------------------
// Opening script tags...
// Check for spaces and new lines...
//-----------------------------------------
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 );
}
//-----------------------------------------
// Here we can do some generic checking for XSS
// This should not be considered fool proof, though can provide
// a centralized point for maintenance and checking
//-----------------------------------------
$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" , "\\1xpression" , $txt );
$txt = preg_replace( "/(e)((\\\|\)*)x((\\\|\)*)p((\\\|\)*)r((\\\|\)*)e((\\\|\)*)s((\\\|\)*)s((\\\|\)*)i((\\\|\)*)o((\\\|\)*)n/is" , "\\1xpression" , $txt );
$txt = preg_replace( "/m((\\\|\)*)o((\\\|\)*)z((\\\|\)*)\-((\\\|\)*)b((\\\|\)*)i((\\\|\)*)n((\\\|\)*)d((\\\|\)*)i((\\\|\)*)n((\\\|\)*)g/is" , "moz-binding" , $txt );
$txt = str_ireplace( "about:" , "about:" , $txt );
$txt = str_ireplace( "
Заменить на:
public function checkXss( $txt='', $fixScript=false, $tag='' )
{
//-----------------------------------------
// Opening script tags...
// Check for spaces and new lines...
//-----------------------------------------
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 );
}
/* got a tag? */
if ( $tag )
{
$tag = strip_tags( $tag, '
' );
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 = 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;
}
/* 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, '
' );
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
// a centralized point for maintenance and checking
//-----------------------------------------
$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" , "\\1xpression" , $txt );
$txt = preg_replace( "/(e)((\\\|\)*)x((\\\|\)*)p((\\\|\)*)r((\\\|\)*)e((\\\|\)*)s((\\\|\)*)s((\\\|\)*)i((\\\|\)*)o((\\\|\)*)n/is" , "\\1xpression" , $txt );
$txt = preg_replace( "/m((\\\|\)*)o((\\\|\)*)z((\\\|\)*)\-((\\\|\)*)b((\\\|\)*)i((\\\|\)*)n((\\\|\)*)d((\\\|\)*)i((\\\|\)*)n((\\\|\)*)g/is" , "moz-binding" , $txt );
$txt = str_ireplace( "about:" , "about:" , $txt );
$txt = str_ireplace( "
Найти:
//-----------------------------------------
// If this is a single tag, that's it
//-----------------------------------------
if( $_bbcode['bbcode_single_tag'] )
{
$txt = substr_replace( $txt, $this->_bbcodeToHtml( $_bbcode, $_option, '' ), $this->cur_pos, ($open_length + strlen($_option) + 1) );
}
//-----------------------------------------
// Otherwise replace out the content too
//-----------------------------------------
else
{
$close_tag = '[/' . $_tag . ']';
if( stripos( $txt, $close_tag, $new_pos ) !== false )
{
$_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) );
}
else
{
//-----------------------------------------
// If there's no close tag, no need to continue
//-----------------------------------------
break;
}
}
Заменить на:
//-----------------------------------------
// Protect against XSS
//-----------------------------------------
$_optionStrLen = IPSText::mbstrlen( $_option );
$_option = $this->checkXss($_option, false, $_tag);
if ( $_option !== FALSE )
{
//-----------------------------------------
// If this is a single tag, that's it
//-----------------------------------------
if( $_bbcode['bbcode_single_tag'] )
{
$txt = substr_replace( $txt, $this->_bbcodeToHtml( $_bbcode, $_option, '' ), $this->cur_pos, ($open_length + $_optionStrLen + 1) );
}
//-----------------------------------------
// Otherwise replace out the content too
//-----------------------------------------
else
{
$close_tag = '[/' . $_tag . ']';
if( stripos( $txt, $close_tag, $new_pos ) !== false )
{
$_content = substr( $txt, ($this->cur_pos + $open_length + $_optionStrLen + 1), (stripos( $txt, $close_tag, $this->cur_pos ) - ($this->cur_pos + $open_length + $_optionStrLen + 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) );
}
else
{
//-----------------------------------------
// If there's no close tag, no need to continue
//-----------------------------------------
break;
}
}
}
**В файле //admin/sources/classes/bbcode/custom/defaults.php//** найти:
class bbcode_quote extends bbcode_parent_class implements bbcodePlugin
{
/**
* Constructor
*
* @access public
* @param object Registry object
* @return void
*/
public function __construct( ipsRegistry $registry )
{
$this->currentBbcode = 'quote';
parent::__construct( $registry );
}
/**
* Method that is run before the content is stored in the database
* You are responsible for ensuring you mark the replaced text appropriately so that you
* are able to unparse it, if you wish to have bbcode parsed on save
*
* @access public
* @param string $txt BBCode text from submission to be stored in database
* @return string Formatted content, ready for display
*/
public function preDbParse( $txt )
{
$this->cache->updateCacheWithoutSaving( '_tmp_bbcode_quotes', 0 );
return parent::preDbParse( $txt );
}
/**
* Method that is run before the content is displayed to the user
* This is the safest method of parsing, as the original submitted text is left in tact.
* No markers are necessary if you use parse on display.
*
* @access public
* @param string $txt BBCode/parsed text from database to be displayed
* @return string Formatted content, ready for display
*/
public function preDisplayParse( $txt )
{
$this->cache->updateCacheWithoutSaving( '_tmp_bbcode_quotes', 0 );
return parent::preDisplayParse( $txt );
}
/**
* Do the actual replacement
*
* @access protected
* @param string $txt Parsed text from database to be edited
* @return string BBCode content, ready for editing
*/
protected function _replaceText( $txt )
{
$_tags = $this->_retrieveTags();
foreach( $_tags as $_tag )
{
//-----------------------------------------
// Determine open and close tags
//-----------------------------------------
$open_tag = '[' . $_tag;
$close_tag = '[/' . $_tag . ']';
//-----------------------------------------
// Ok, quotes suck A LOT
// We have to first match the CLOSE tag, unlike other bbcode
// Then we back-track to find the matching opening tag
// Do the replacement, and repeat....
//-----------------------------------------
while( ( $this->end_pos = stripos( $txt, $close_tag, $this->end_pos ) ) !== false )
{
//-----------------------------------------
// Ok at this point, we have a closing quote tag
// Set start position to end position point
//-----------------------------------------
$this->cur_pos = $this->end_pos;
//-----------------------------------------
// We are at 0 or above still...
//-----------------------------------------
while( $this->cur_pos > 0 )
{
//-----------------------------------------
// Loop over characters moving backwards 1 by 1
//-----------------------------------------
$this->cur_pos = $this->cur_pos - 1;
//-----------------------------------------
// Shouldn't hit this, but if we do we're done
//-----------------------------------------
if( $this->cur_pos < 0 )
{
break;
}
//-----------------------------------------
// Have we finally hit the first preceeding open tag?
//-----------------------------------------
if( stripos( $txt, $open_tag, $this->cur_pos ) === $this->cur_pos )
{
//-----------------------------------------
// Start figuring out open tag length
//-----------------------------------------
$open_length = strlen($open_tag);
//-----------------------------------------
// Extract the options (like surgery)
//-----------------------------------------
$_option = '';
$quoteOptions = array();
//-----------------------------------------
// Does we haz it?
//-----------------------------------------
if( substr( $txt, $this->cur_pos + strlen($open_tag), 1 ) == ' ' )
{
$open_length += 1;
$_option = substr( $txt, $this->cur_pos + $open_length, (strpos( $txt, ']', $this->cur_pos ) - ($this->cur_pos + $open_length)) );
$quoteOptions = $this->_extractSurgicallyTehOptions( $_option );
}
//-----------------------------------------
// If not, [u] != [url] (for example)
//-----------------------------------------
else if( (strpos( $txt, ']', $this->cur_pos ) - ( $this->cur_pos + $open_length )) !== 0 )
{
continue;
}
//-----------------------------------------
// Otherwise replace out the content too
//-----------------------------------------
$_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)) );
//-----------------------------------------
// Turn attachments into links
// Prevents em from breaking on other pages
//-----------------------------------------
preg_match_all( "#\[attachment=(.+?):(.+?)\]#", $_content, $matches );
if( is_array( $matches[1] ) && count( $matches[1] ) )
{
foreach( $matches[1] as $idx => $attach_id )
{
$_content = str_replace( "[attachment={$attach_id}:{$matches[2][$idx]}]", $this->registry->getClass('output')->getReplacement('post_attach_link') . " {$matches[2][$idx]}", $_content );
}
}
//-----------------------------------------
// Trim off leading newlines / brs, etc
//-----------------------------------------
$_content = IPSText::br2nl( $_content );
$_content = trim( $_content );
$_content = nl2br( $_content );
//-----------------------------------------
// And replace...
//-----------------------------------------
$txt = substr_replace( $txt, $this->_buildOutput( $_content, $quoteOptions ? $quoteOptions : '' ), $this->cur_pos, (stripos( $txt, $close_tag, $this->cur_pos ) + strlen($close_tag) - $this->cur_pos) );
//-----------------------------------------
// Now we break since we've done the inner replacement
//-----------------------------------------
break;
}
}
//-----------------------------------------
// And reset end position to one char further
//-----------------------------------------
$this->end_pos += 1;
//-----------------------------------------
// If end_pos is greater than length of text we're done
//-----------------------------------------
if( $this->end_pos > strlen($txt) )
{
//-----------------------------------------
// Need to reset for next "tag"
//-----------------------------------------
$this->end_pos = 0;
break;
}
}
}
return $txt;
}
/**
* Raw options string
*
* @access private
* @param string $string The options submitted with the post as a string
* @return array Key => value Option pairs
*/
private function _extractSurgicallyTehOptions( $options='' )
{
if( !$options )
{
return array();
}
/**
* Strip tags removes any added tags
* @see http://community.invisionpower.com/tracker/issue-19960-problem-when-tags-is-put-inside-quote-starter-tag/
*/
$options = str_replace( ''', "'", strip_tags($options) );
$options = str_replace( '"', '"', $options );
$finalOpts = array();
// Need to push through string, pulling out keys/options
$pos = 0;
$options = trim($options);
$key = '';
$value = '';
$inKey = true;
$inValue = false;
while( $pos < strlen($options) )
{
if( $options{$pos} == ' ' AND !$inKey AND !$inValue )
{
$key = '';
$value = '';
$inKey = true;
}
else if( $options{$pos} == "'" OR $options{$pos} == '"' )
{
if( $inKey )
{
$inKey = false;
$inValue = true;
}
else
{
$inValue = false;
$finalOpts[ trim($key) ] = $value;
}
}
else
{
if( $inKey )
{
if( $options{$pos} != '=' )
{
$key .= $options{$pos};
}
}
else if( $inValue )
{
$value .= $options{$pos};
}
}
$pos++;
}
return $finalOpts;
}
/**
* Build the actual output to show
*
* @access private
* @param string $content This is the contents of the quote
* @param array $options [Optional] Quote options
* @return string Content to replace bbcode with
*/
private function _buildOutput( $content, $options=array() )
{
//-----------------------------------------
// Too many quotes?
//-----------------------------------------
$existing = $this->cache->getCache('_tmp_bbcode_quotes');
$existing = intval($existing) + 1;
if ( $this->settings['max_quotes_per_post'] )
{
if ($existing > $this->settings['max_quotes_per_post'])
{
$this->error = 'too_many_quotes';
return $content;
}
}
$this->cache->updateCacheWithoutSaving( '_tmp_bbcode_quotes', $existing );
//-----------------------------------------
// Build output and return it
//-----------------------------------------
$output = "";
$snapback = '';
if( $options['post'] )
{
$snapback = "" .
$this->registry->output->getReplacement( 'snapback' ) . "";
}
if( $options['name'] OR $options['date'] OR $options['timestamp'] )
{
// sort timestamp
if ( !$this->settings['cc_on'] AND $options['timestamp'] AND strlen( $options['timestamp'] ) == 10 AND ( intval($options['timestamp']) == $options['timestamp'] ) )
{
$options['date'] = $this->registry->getClass('class_localization')->getDate( $options['timestamp'], 'LONG' );
}
if( $options['name'] AND $options['date'] )
{
$output .= $snapback . sprintf( $this->lang->words['bbc_full_cite'], $options['name'], $options['date'] ) ;
}
else if( $options['name'] )
{
$output .= $snapback . sprintf( $this->lang->words['bbc_name_cite'], $options['name'] ) ;
}
else if( $options['date'] )
{
$output .= $snapback . sprintf( $this->lang->words['bbc_date_cite'], $options['date'] ) ;
}
}
else
{
$output .= $snapback . $this->lang->words['bbc_quote'];
}
$output .= "
";
$output .= '
Заменить на:
class bbcode_quote extends bbcode_parent_class implements bbcodePlugin
{
/**#@+
* Quote tracking
*
* @access protected
* @var int
*/
protected $quote_open = 0;
protected $quote_closed = 0;
protected $quote_error = 0;
/**#@-*/
/**
* Constructor
*
* @access public
* @param object Registry object
* @return void
*/
public function __construct( ipsRegistry $registry )
{
$this->currentBbcode = 'quote';
parent::__construct( $registry );
}
/**
* Method that is run before the content is stored in the database
* You are responsible for ensuring you mark the replaced text appropriately so that you
* are able to unparse it, if you wish to have bbcode parsed on save
*
* @access public
* @param string $txt BBCode text from submission to be stored in database
* @return string Formatted content, ready for display
*/
public function preDbParse( $txt )
{
return parent::preDbParse( $txt );
}
/**
* Method that is run before the content is displayed to the user
* This is the safest method of parsing, as the original submitted text is left in tact.
* No markers are necessary if you use parse on display.
*
* @access public
* @param string $txt BBCode/parsed text from database to be displayed
* @return string Formatted content, ready for display
*/
public function preDisplayParse( $txt )
{
return parent::preDisplayParse( $txt );
}
/**
* Do the actual replacement
*
* @access protected
* @param string $txt Parsed text from database to be edited
* @return string BBCode content, ready for editing
*/
protected function _replaceText( $txt )
{
$txt = preg_replace_callback( "#(\[quote([^\]]+?)?\].*\[/quote\])#is" , array( $this, '_parseQuote' ), $txt );
return $txt;
}
/**
* Build the actual output to show
*
* @access private
* @param array $options [Optional] Quote options
* @return string Content to replace bbcode with
*/
private function _buildOutput( $options=array() )
{
//-----------------------------------------
// Build output and return it
//-----------------------------------------
$output = "";
$snapback = '';
if( $options['post'] )
{
$snapback = "" .
$this->registry->output->getReplacement( 'snapback' ) . "";
}
if( $options['name'] OR $options['date'] OR $options['timestamp'] )
{
// sort timestamp
if ( !$this->settings['cc_on'] AND $options['timestamp'] AND strlen( $options['timestamp'] ) == 10 AND ( intval($options['timestamp']) == $options['timestamp'] ) )
{
$options['date'] = $this->registry->getClass('class_localization')->getDate( $options['timestamp'], 'LONG' );
}
if( $options['name'] AND $options['date'] )
{
$output .= $snapback . sprintf( $this->lang->words['bbc_full_cite'], $options['name'], $options['date'] ) ;
}
else if( $options['name'] )
{
$output .= $snapback . sprintf( $this->lang->words['bbc_name_cite'], $options['name'] ) ;
}
else if( $options['date'] )
{
$output .= $snapback . sprintf( $this->lang->words['bbc_date_cite'], $options['date'] ) ;
}
}
else
{
$output .= $snapback . $this->lang->words['bbc_quote'];
}
$output .= "
";
$output .= 'quote_open = 0;
$this->quote_closed = 0;
$this->quote_error = 0;
//-----------------------------------------
// Make sure we don't have too many embedded
//-----------------------------------------
if ( $this->settings['max_quotes_per_post'] )
{
if ( substr_count( strtolower($txt), '[quote' ) > $this->settings['max_quotes_per_post'] )
{
$this->error = 'too_many_quotes';
return $txt;
}
}
//-----------------------------------------
// Fix char 173
//-----------------------------------------
$txt = str_replace( chr(173).']', ']', $txt );
//-----------------------------------------
// Trim the quote content
//-----------------------------------------
$txt = preg_replace_callback( "#\[quote([^\]]+?)?\](.+?)\[/quote\]#si", array( $this, '_trimQuote' ), $txt );
//-----------------------------------------
// Clean usernames with brackets and quotes
//-----------------------------------------
$txt = preg_replace_callback( "#(name=(?:&\#39;|"|'|\"))(.+?)(&\#39;|"|'|\")#si", array( $this, '_makeQuoteSafe' ), $txt );
$txt = preg_replace_callback( "#name=(&\#39;|"|'|\")(.+?)(\\1)\s?(post|date)=#si", array( $this, '_makeNameSafe' ), $txt );
//-----------------------------------------
// Replace out end tag
//-----------------------------------------
$txt = str_ireplace( "[/quote]", "", $txt, $this->quote_closed );
//-----------------------------------------
// Replace the quote tag
//-----------------------------------------
$txt = preg_replace_callback( "#\[quote([^\]]+?)?\]#i", array( $this, '_replaceQuoteTag' ), $txt );
//-----------------------------------------
// Newlines
//-----------------------------------------
//$txt = str_replace( "\n", "
", $txt );
$txt = str_replace( "
", "", $txt );
//-----------------------------------------
// Swap name replacement (_makeNameSafe) back
//-----------------------------------------
$txt = str_replace( "'", "'", $txt );
//-----------------------------------------
// Turn attachments into links
// Prevents em from breaking on other pages
//-----------------------------------------
preg_match_all( "#\[attachment=(.+?):(.+?)\]#", $txt, $_matches );
if( is_array( $_matches[1] ) && count( $_matches[1] ) )
{
foreach( $_matches[1] as $idx => $attach_id )
{
$txt = str_replace( "[attachment={$attach_id}:{$_matches[2][$idx]}]", $this->registry->getClass('output')->getReplacement('post_attach_link') . " {$_matches[2][$idx]}", $txt );
}
}
//-----------------------------------------
// If open and close tags match, we're good.
// Otherwise, return an error.
//-----------------------------------------
if ( ( $this->quote_open == $this->quote_closed ) and ( $this->quote_error == 0 ) )
{
return $txt;
}
else
{
$this->error = 'quote_mismatch';
return $_orig;
}
}
/**
* Callback for triming quote
*
* @access protected
* @param array preg_replace_callback Matches
* @return string Output
*/
protected function _trimQuote( $matches )
{
$txt = $matches[2];
$extra = $matches[1];
if( $txt == "" )
{
return "[quote][/quote]";
}
else
{
$txt = trim( $txt );
return "[quote{$extra}]{$txt}[/quote]";
}
}
/**
* Make the quoted content safe for regex parsing
*
* @access protected
* @param array preg_replace_callback Matches
* @return string Output
*/
protected function _makeQuoteSafe( $matches )
{
//-----------------------------------------
// INIT
//-----------------------------------------
$begin = $matches[1];
$end = $matches[3];
$txt = $matches[2];
//-----------------------------------------
// Sort name
//-----------------------------------------
$txt = str_replace( "+", "+" , $txt );
$txt = str_replace( "-", "-" , $txt );
$txt = str_replace( ":", ":" , $txt );
$txt = str_replace( "[", "[" , $txt );
$txt = str_replace( "]", "]" , $txt );
$txt = str_replace( ")", ")" , $txt );
$txt = str_replace( "(", "(" , $txt );
$txt = str_replace( "'", "'" , $txt );
return $begin . $txt . $end;
}
/**
* Make the name used for the quote safe for regex parsing
*
* @access protected
* @param array preg_replace_callback Matches
* @return string Output
*/
protected function _makeNameSafe( $matches )
{
$quote = $matches[1];
$name = $matches[2];
$next = $matches[4];
# Squeeze past the parser...
$name = str_replace( ''', "'", $name );
return 'name=' . $quote . $name . $quote . ' ' . $next . '=';
}
/**
* Replace the quote tag
*
* @access protected
* @param array preg_replace_callback Matches
* @return string Output
*/
protected function _replaceQuoteTag( $matches )
{
//-----------------------------------------
// INIT
//-----------------------------------------
$extra = str_replace( ''', "'", $matches[1] );
$post_id = 0;
$date = '';
$timestamp = 0;
$name = '';
//-----------------------------------------
// Inc..
//-----------------------------------------
$this->quote_open++;
//-----------------------------------------
// Post?
//-----------------------------------------
preg_match( "#post=([\"']|"|&\#039;|&\#39;)?(\d+)([\"']|"|&\#039;|&\#39;)?#", $extra, $match );
if ( isset($match[2]) AND intval( $match[2] ) )
{
$post_id = intval( $match[2] );
}
//-----------------------------------------
// Name?
//-----------------------------------------
preg_match( "#name=([\"']|"|&\#039;|&\#39;)(.+?)([\"']|"|&\#039;|&\#39;)\s?(date|post)?#is", $extra, $match );
if ( isset($match[2]) AND $match[2] )
{
$name = $this->_makeQuoteSafe( array( 2 => $match[2] ) );
}
//-----------------------------------------
// Date?
//-----------------------------------------
preg_match( "#date=([\"']|"|&\#039;|&\#39;)(.+?)([\"']|"|&\#039;|&\#39;)#", $extra, $match );
if ( isset($match[2]) AND $match[2] )
{
$date = $this->_makeQuoteSafe( array( 2 => $match[2] ) );
}
//-----------------------------------------
// Timestamp?
//-----------------------------------------
preg_match( "#timestamp=([\"']|"|&\#039;|&\#39;)(.+?)([\"']|"|&\#039;|&\#39;)#", $extra, $match );
if ( isset($match[2]) AND $match[2] )
{
$timestamp = intval( $match[2] );
}
return $this->_buildOutput( array( 'name' => $name, 'date' => $date, 'post' => $post_id, 'timestamp' => $timestamp ) );
}
}
Найти:
//-----------------------------------------
// No closing tag
//-----------------------------------------
if( stripos( $txt, $close_tag, $new_pos ) === false )
{
break;
}
$_content = substr( $txt, ($this->cur_pos + strlen($open_tag) + strlen($_option) + 1), (stripos( $txt, $close_tag, $this->cur_pos ) - ($this->cur_pos + strlen($open_tag) + strlen($_option) + 1)) );
//-----------------------------------------
// If this is a single tag, that's it
//-----------------------------------------
if( $_content )
{
$txt = substr_replace( $txt, $this->_buildOutput( $_option, $_content ), $this->cur_pos, (stripos( $txt, $close_tag, $this->cur_pos ) + strlen($close_tag) - $this->cur_pos) );
}
else
{
$txt = substr_replace( $txt, '', $this->cur_pos, (stripos( $txt, $close_tag, $this->cur_pos ) + strlen($close_tag) - $this->cur_pos) );
}
Заменить на:
//-----------------------------------------
// Protect against XSS
//-----------------------------------------
/* Make sure it's clean */
$test = str_replace( array( '"', "'", '"', ''' ), "", $_option );
$test1 = IPSText::alphanumericalClean( $test, '.+ ' );
if ( $test1 != $test )
{
$_option = false;
}
//-----------------------------------------
// No closing tag
//-----------------------------------------
if ( $_option !== false AND stripos( $txt, $close_tag, $new_pos ) !== false )
{
$_content = substr( $txt, ($this->cur_pos + strlen($open_tag) + strlen($_option) + 1), (stripos( $txt, $close_tag, $this->cur_pos ) - ($this->cur_pos + strlen($open_tag) + strlen($_option) + 1)) );
//-----------------------------------------
// If this is a single tag, that's it
//-----------------------------------------
if( $_content )
{
$txt = substr_replace( $txt, $this->_buildOutput( $_option, $_content ), $this->cur_pos, (stripos( $txt, $close_tag, $this->cur_pos ) + strlen($close_tag) - $this->cur_pos) );
}
else
{
$txt = substr_replace( $txt, '', $this->cur_pos, (stripos( $txt, $close_tag, $this->cur_pos ) + strlen($close_tag) - $this->cur_pos) );
}
}
После установки исправления обязательно сделайте перестроение сообщений/подписей/личных сообщений через админ-центр форума.