Version 4.5.0

This commit is contained in:
Neo committed 2025-12-19 05:51:58 -08:00
1 parent 1a0c7fd3c2
commit f79dcf067a
3791 files changed
+248032 -76372

No files matched your search

+16 -10
View File
@@ -11,7 +11,7 @@
namespace IPS\Text;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
@@ -36,22 +36,27 @@ class _DOMParser
* Parse
*
* @param string $value Contents to parse
* @param callback $elementParser Callback to parse a DOMElement object. Is expected to call $parent->appendChild( $element ) after doing any parsing and call $parser->_parseDomNodeList(). function ( \DOMElement $element, \DOMNode $parent, \IPS\Text\DOMParser $parser )
* @param callback|NULL $textParser Callback to parse a DOMText object. Is expected to call $parent->appendChild( $element ) after doing any parsing. function ( \DOMText $textNode, \DOMNode $parent, \IPS\Text\DOMParser $parser )
* @retrun string
* @param callback $elementParser Callback to parse a DOMElement object. Is expected to call `$parent->appendChild( $element )` after doing any parsing and call `$parser->_parseDomNodeList()`. `function ( \DOMElement $element, \DOMNode $parent, \IPS\Text\DOMParser $parser )`
* @param callback|NULL $textParser Callback to parse a DOMText object. Is expected to call `$parent->appendChild( $element )` after doing any parsing. `function ( \DOMText $textNode, \DOMNode $parent, \IPS\Text\DOMParser $parser )`
* @return string
*/
public static function parse( $value, $elementParser, $textParser = NULL )
{
return static::getDocumentBodyContents( ( new static( $elementParser, $textParser ) )->parseValueIntoDocument( $value ) );
$content = static::getDocumentBodyContents( ( new static( $elementParser, $textParser ) )->parseValueIntoDocument( $value ) );
/* Replace file storage tags */
$content = preg_replace( '/&lt;fileStore\.([\d\w\_]+?)&gt;/i', '<fileStore.$1>', $content );
/* DOMDocument::saveHTML will encode the base_url brackets, so we need to make sure it's in the expected format. */
return str_replace( '&lt;___base_url___&gt;', '<___base_url___>', $content );
}
/**
* Constructor
*
* @param string $value
* @param callback $elementParser Callback to parse a DOMElement object. Is expected to call $parent->appendChild( $element ) after doing any parsing and call $parser->_parseDomNodeList(). function ( \DOMElement $element, \DOMNode $parent, \IPS\Text\DOMParser $parser )
* @param callback|NULL $textParser Callback to parse a DOMText object. Is expected to call $parent->appendChild( $element ) after doing any parsing. function ( \DOMText $textNode, \DOMNode $parent, \IPS\Text\DOMParser $parser )
* @retrun string
* @param callback $elementParser Callback to parse a DOMElement object. Is expected to call `$parent->appendChild( $element )` after doing any parsing and call `$parser->_parseDomNodeList()`. `function ( \DOMElement $element, \DOMNode $parent, \IPS\Text\DOMParser $parser )`
* @param callback|NULL $textParser Callback to parse a DOMText object. Is expected to call `$parent->appendChild( $element )` after doing any parsing. `function ( \DOMText $textNode, \DOMNode $parent, \IPS\Text\DOMParser $parser )`
* @return string
*/
public function __construct( $elementParser, $textParser = NULL )
{
@@ -99,7 +104,8 @@ class _DOMParser
/* This is a HTML element (e.g. <html>, <p>, <a>, etc.) represented as a DOMElement object. Parse it. */
case XML_ELEMENT_NODE:
call_user_func( $this->elementParser, $node, $parent, $this );
$function = $this->elementParser;
$function( $node, $parent, $this );
break;
/* This is text represented as a DOMText object. Parse it. */
+91 -18
View File
@@ -11,7 +11,7 @@
namespace IPS\Text;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
@@ -35,27 +35,56 @@ class _Encrypt
/**
* @brief Cipher
*/
public $cipher;
protected $cipher;
/**
* Constructor
*
* @return void
* @brief IV
*/
public function __construct()
{
require_once \IPS\ROOT_PATH . '/system/3rd_party/AES/AES.php';
}
protected $iv = NULL;
/**
* @brief Tag
*/
protected $tag = NULL;
/**
* @brief Hash of cipher
*/
protected $hmac = NULL;
/**
* From plaintext
*
* @param string $plaintext Plaintext
* @return \IPS\Text\Encrypt
* @return static
*/
public static function fromPlaintext( $plaintext )
{
$obj = new static;
/* Try to use OpenSSL if it's available... */
if ( \function_exists( 'openssl_get_cipher_methods' ) )
{
/* If GCM is available (PHP 7.1+), use that as if provides authenticated encryption natively */
if ( \in_array( 'aes-128-gcm', openssl_get_cipher_methods() ) )
{
$obj->iv = openssl_random_pseudo_bytes( openssl_cipher_iv_length( 'aes-128-gcm' ) );
$obj->cipher = openssl_encrypt( $plaintext, 'aes-128-gcm', static::key(), 0, $obj->iv, $obj->tag );
return $obj;
}
/* Otherwise, use CBC and store the hash so we can do our own authentication when decrypting */
elseif ( \in_array( 'aes-128-cbc', openssl_get_cipher_methods() ) )
{
$obj->iv = openssl_random_pseudo_bytes( openssl_cipher_iv_length( 'aes-128-cbc' ) );
$obj->cipher = openssl_encrypt( $plaintext, 'aes-128-cbc', static::key(), OPENSSL_RAW_DATA, $obj->iv );
$obj->hmac = hash_hmac( 'sha256', $obj->cipher, static::key(), TRUE );
return $obj;
}
}
/* If we're still here, fallback to the PHP library */
require_once \IPS\ROOT_PATH . '/system/3rd_party/AES/AES.php';
$obj->cipher = \AesCtr::encrypt( $plaintext, static::key(), 256 );
return $obj;
}
@@ -63,13 +92,19 @@ class _Encrypt
/**
* From plaintext
*
* @param string $cipher Cipher
* @return \IPS\Text\Encrypt
* @param string $cipher Cipher
* @param string|null $iv The IV, or if null, will use the PHP library rather than built-in openssl_*() methods
* @param string|null $tag The tag if using AES-128-GCM
* @param string|null $hash The hash if using AES-128-CBC
* @return static
*/
public static function fromCipher( $cipher )
public static function fromCipher( $cipher, $iv = NULL, $tag = NULL, $hash = NULL )
{
$obj = new static;
$obj->cipher = $cipher;
$obj->iv = $iv;
$obj->tag = $tag;
$obj->hmac = $hash;
return $obj;
}
@@ -77,11 +112,22 @@ class _Encrypt
* From tag
*
* @param string $tag Tag
* @return \IPS\Text\Encrypt
* @return static
*/
public static function fromTag( $tag )
{
if ( preg_match( '/^\[\!AES\[(.+?)\]\]/', $tag, $matches ) )
if ( preg_match( '/^\[\!AES128GCM\[(.+?)\]\[(.+?)\]\[(.+?)\]\]/', $tag, $matches ) )
{
return static::fromCipher( $matches[1], hex2bin( $matches[2] ), hex2bin( $matches[3] ) );
}
elseif ( preg_match( '/^\[\!AES128CBC\[(.+?)\]\]/', $tag, $matches ) )
{
$cipher = base64_decode( $matches[1] );
$ivLength = openssl_cipher_iv_length('aes-128-cbc');
return static::fromCipher( \substr( $cipher, $ivLength + 32 ), \substr( $cipher, 0, $ivLength ), NULL, \substr( $cipher, $ivLength, 32 ) );
}
elseif ( preg_match( '/^\[\!AES\[(.+?)\]\]/', $tag, $matches ) )
{
return static::fromCipher( $matches[1] );
}
@@ -93,13 +139,23 @@ class _Encrypt
/**
* Wrap in a tag to use later with fromTag
* Used for legacy areas which previously stored unencrypted values
*
* @return string
*/
public function tag()
{
return '[!AES[' . $this->cipher . ']]';
if ( $this->tag )
{
return '[!AES128GCM[' . $this->cipher . '][' . bin2hex( $this->iv ) . '][' . bin2hex( $this->tag ) . ']]';
}
elseif ( $this->hmac )
{
return '[!AES128CBC[' . base64_encode( $this->iv . $this->hmac . $this->cipher ) . ']]';
}
else
{
return '[!AES[' . $this->cipher . ']]';
}
}
/**
@@ -109,6 +165,23 @@ class _Encrypt
*/
public function decrypt()
{
return \AesCtr::decrypt( $this->cipher, static::key(), 256 );
if ( $this->tag )
{
return openssl_decrypt( $this->cipher, 'aes-128-gcm', static::key(), 0, $this->iv, $this->tag );
}
elseif ( $this->hmac )
{
$decrypted = openssl_decrypt( $this->cipher, 'aes-128-cbc', static::key(), OPENSSL_RAW_DATA, $this->iv );
if ( hash_equals( $this->hmac, hash_hmac( 'sha256', $this->cipher, static::key(), TRUE ) ) )
{
return $decrypted;
}
return '';
}
else
{
require_once \IPS\ROOT_PATH . '/system/3rd_party/AES/AES.php';
return \AesCtr::decrypt( $this->cipher, static::key(), 256 );
}
}
}
+1 -1
View File
@@ -10,7 +10,7 @@
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
+56
View File
@@ -0,0 +1,56 @@
<?php
/**
* @brief An HTMLPurifier image transformation that only allows HTTPS images
* @author <a href='https://www.invisioncommunity.com'>Invision Power Services, Inc.</a>
* @copyright (c) Invision Power Services, Inc.
* @license https://www.invisioncommunity.com/legal/standards/
* @package Invision Community
* @since 14 Jan 2020
*/
namespace IPS\Text;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
}
/**
* An HTMLPurifier image transformation that only allows HTTPS images
* @see https://stackoverflow.com/questions/34876151/htmlpurifier-allow-scheme-for-specific-tags
*/
class _HtmlPurifierHttpsImages extends \HTMLPurifier_URIFilter
{
public $name = 'HttpsEmbedScheme';
public $ourHost = '';
public function prepare( $config )
{
$this->ourHost = parse_url( \IPS\Settings::i()->base_url, \PHP_URL_HOST );
}
public function filter( &$uri, $config, $context )
{
/* We only care about embedded resources for this */
if ( !$context->get( 'EmbeddedURI', true ) )
{
return true;
}
/* If the image is on the same domain, we will allow it. This covers lazy loading as well as emoticons. */
if( !$uri->host OR $uri->host == $this->ourHost )
{
return true;
}
/* Don't allow anything but https */
if( $uri->scheme !== 'https' AND $uri->scheme !== NULL )
{
return false;
}
return true;
}
}
+1 -1
View File
@@ -11,7 +11,7 @@
namespace IPS\Text;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
+2 -2
View File
@@ -11,7 +11,7 @@
namespace IPS\Text;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
@@ -47,7 +47,7 @@ class _HtmlPurifierSrcsetDef extends \HTMLPurifier_AttrDef_URI
}
}
if ( count( $return ) )
if ( \count( $return ) )
{
return implode( ', ', $return );
}
+5 -2
View File
@@ -11,7 +11,7 @@
namespace IPS\Text;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
@@ -22,6 +22,9 @@ if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
*/
class _HtmlPurifierSwitchAttrDef extends \HTMLPurifier_AttrDef_Switch
{
/**
* @brief Is the attribute required
*/
public $required = FALSE;
/**
@@ -55,7 +58,7 @@ class _HtmlPurifierSwitchAttrDef extends \HTMLPurifier_AttrDef_Switch
{
$token = $context->get('CurrentToken', true);
if ( count( array_diff( $this->attributes, array_keys( $token->attr ) ) ) )
if ( \count( array_diff( $this->attributes, array_keys( $token->attr ) ) ) )
{
return $this->withoutTag->validate( $string, $config, $context );
}
+67 -28
View File
@@ -11,7 +11,7 @@
namespace IPS\Text;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
@@ -23,7 +23,7 @@ if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
class _LegacyParser
{
/**
* Maximum number of embeds we will try.
* @brief Maximum number of embeds we will try.
* @note Attempting to pull too many during the rebuild process can easily time out
*/
public $maxEmbeds = 10;
@@ -44,7 +44,7 @@ class _LegacyParser
*/
public static function parseStatic( $value, $member=NULL, $allowHtml=FALSE, $attachClass=null, $id1=0, $id2=0, $id3=NULL, $itemClass=NULL )
{
$obj = new self( $member, $allowHtml, $attachClass, $id1, $id2, $id3, $itemClass );
$obj = new static( $member, $allowHtml, $attachClass, $id1, $id2, $id3, $itemClass );
return $obj->parse( $value );
}
@@ -69,7 +69,7 @@ class _LegacyParser
{
foreach( static::$bbcodes as $code )
{
if( $code['bbcode_tag'] == $bbcode OR ( $code['bbcode_aliases'] AND in_array( $bbcode, explode( ',', $code['bbcode_aliases'] ) ) ) )
if( $code['bbcode_tag'] == $bbcode OR ( $code['bbcode_aliases'] AND \in_array( $bbcode, explode( ',', $code['bbcode_aliases'] ) ) ) )
{
if( $code['bbcode_groups'] == 'all' )
{
@@ -175,9 +175,27 @@ class _LegacyParser
$this->emoticons = array();
}
/* The `a_type` column is added in 4.5, so we need to account for this if running the legacy parser during an older upgrade */
$newAcronyms = \IPS\Db::i()->checkForColumn( 'core_acronyms', 'a_type' );
/* Grab a new parser object */
\IPS\Text\Parser::$requestTimeout = 1;
$this->parser = new \IPS\Text\Parser( TRUE, $this->idOne ? array( $this->idOne, $this->idTwo, $this->idThree ) : NULL, $this->member, $this->attachClass, TRUE, ( $this->allowHtml ? FALSE : TRUE ), NULL );
$this->parser = new \IPS\Text\Parser( TRUE, $this->idOne ? array( $this->idOne, $this->idTwo, $this->idThree ) : NULL, $this->member, $this->attachClass, TRUE, ( $this->allowHtml ? FALSE : TRUE ), NULL, $newAcronyms );
/* If we're in the upgrader and the new acronym support hasn't been added yet, populate acronyms manually */
if( !$newAcronyms )
{
$this->parser->caseSensitiveAcronyms = iterator_to_array( \IPS\Db::i()->select( array( 'a_short', 'a_long', "'acronym' as `a_type`" ), 'core_acronyms', array( 'a_casesensitive=1' ) )->setKeyField( 'a_short' ) );
$this->parser->caseInsensitiveAcronyms = array();
foreach ( \IPS\Db::i()->select( array( 'a_short', 'a_long', "'acronym' as `a_type`" ), 'core_acronyms', array( 'a_casesensitive=0' ) )->setKeyField( 'a_short' ) as $k => $v )
{
$this->parser->caseInsensitiveAcronyms[ mb_strtolower( $k ) ] = $v;
}
}
/* We need to force bbcode to parse for the legacy parser */
$this->parser->forceBbcodeEnabled = TRUE;
$updatedBbcodeTags = array_keys( $this->parser->bbcodeTags( $this->member, TRUE ) );
@@ -255,7 +273,7 @@ class _LegacyParser
preg_match_all( "#(<img(?:[^>]+?)class=['\"]bbc_emoticon[\"'](?:[^>]+?)alt=['\"](.+?)[\"'](?:[^>]+?)?>)#is", $value, $matches );
if( is_array($matches[1]) AND count($matches[1]) )
if( \is_array($matches[1]) AND \count($matches[1]) )
{
foreach( $matches[1] as $index => $match )
{
@@ -323,7 +341,7 @@ class _LegacyParser
foreach( $matches[0] as $k => $m )
{
$c = count( $codeboxes );
$c = \count( $codeboxes );
$codeboxes[ $c ] = $m;
$replacement = '<!--codeboxes{' . $c . '}-->';
@@ -335,7 +353,7 @@ class _LegacyParser
foreach( $matches[0] as $k => $m )
{
$c = count( $codeboxes );
$c = \count( $codeboxes );
$codeboxes[ $c ] = $m;
$replacement = '<!--codeboxes{' . $c . '}-->';
@@ -343,6 +361,19 @@ class _LegacyParser
$value = str_replace( $m, $replacement, $value );
}
preg_match_all( "/\<table([^>]*?)>(.+?)\<\/table\>/ims", $value, $matches );
$tables = array();
foreach( $matches[0] as $k => $m )
{
$c = \count( $tables );
$tables[ $c ] = \str_ireplace( '<td><br />', '<td>', $m ); // Fix up un-needed BRs added earlier in this method
$replacement = '<!--tables{' . $c . '}-->';
$value = str_replace( $m, $replacement, $value );
}
/* Nested spoilers do not parse correctly, so just do that manually here for now */
$value = str_replace( "[spoiler]", '</p><div class="ipsSpoiler" data-ipsSpoiler><div class="ipsSpoiler_header"><span></span></div><div class="ipsSpoiler_contents"><p>', $value );
$value = str_replace( "[/spoiler]", "</p></div></div><p>", $value );
@@ -471,6 +502,9 @@ class _LegacyParser
}
}
/* Really really old versions of IPB used to use [attachmentid=X] as markers for attachments */
$value = preg_replace( "/\[attachmentid=(.+?)\]/i", "[attachment=$1:name]", $value );
/* Figure out what attachments are missing so we can add them at the end */
if( $this->attachClass !== NULL AND $this->idOne !== 0 )
{
@@ -478,7 +512,7 @@ class _LegacyParser
preg_match_all( "/\[attachment=(.+?):(.+?)\]/ims", $value, $matches );
if( count( $matches[1] ) )
if( \count( $matches[1] ) )
{
foreach( $matches[1] as $id )
{
@@ -497,7 +531,7 @@ class _LegacyParser
foreach( $mappedAttachments as $attachmentId => $map )
{
if( !in_array( $attachmentId, $embeddedAttachments ) )
if( !\in_array( $attachmentId, $embeddedAttachments ) )
{
$value .= '<p>[attachment=' . $attachmentId . ':name]</p>';
}
@@ -546,7 +580,7 @@ class _LegacyParser
try
{
$album = \IPS\gallery\Album::constructFromData( \IPS\Db::i()->select( '*', 'gallery_albums', array( 'album_id=?', (int) $matches[3] ) )->first() );
return \IPS\Text\Parser::embeddableMedia( \IPS\Http\Url::createFromString( $album->url(), TRUE, TRUE ) );
return \IPS\Text\Parser::embeddableMedia( \IPS\Http\Url::createFromString( $album->url(), TRUE, TRUE ), FALSE, $this->member );
}
catch( \Exception $e )
{
@@ -700,7 +734,7 @@ class _LegacyParser
$url = preg_replace( "/#entry(\d+)/", $sep . "do=findComment&amp;comment=$1", $url );
}
$c = count( $urls );
$c = \count( $urls );
$urls[ $c ] = str_replace( $matches[1][ $k ], $url, $m );
$replacement = '<!--url{' . $c . '}-->';
@@ -708,7 +742,7 @@ class _LegacyParser
try
{
/* In 3.x, hyperlinked YouTube URLs did replace as long as a data attribute wasn't present */
if( ! mb_strpos( $matches[1][ $k ], \IPS\Settings::i()->base_url ) AND ( mb_strpos( $matches[0][ $k ], 'youtube.co' ) OR mb_strpos( $matches[0][ $k ], 'youtu.be' ) ) and ! mb_strpos( $matches[0][ $k ], 'nomediaparse' ) AND $response = \IPS\Text\Parser::embeddableMedia( \IPS\Http\Url::createFromString( $matches[1][ $k ], FALSE, TRUE ) ) )
if( ! mb_strpos( $matches[1][ $k ], \IPS\Settings::i()->base_url ) AND ( mb_strpos( $matches[0][ $k ], 'youtube.co' ) OR mb_strpos( $matches[0][ $k ], 'youtu.be' ) ) and ! mb_strpos( $matches[0][ $k ], 'nomediaparse' ) AND $response = \IPS\Text\Parser::embeddableMedia( \IPS\Http\Url::createFromString( $matches[1][ $k ], FALSE, TRUE ), FALSE, $this->member ) )
{
$urls[ $c ] = $response;
}
@@ -723,7 +757,7 @@ class _LegacyParser
foreach( $matches[0] as $m )
{
$c = count( $urls );
$c = \count( $urls );
$urls[ $c ] = $m;
$value = str_replace( $m, '<!--url{' . $c . '}-->', $value );
@@ -734,7 +768,7 @@ class _LegacyParser
foreach( $matches[1] as $k => $m )
{
$c = count( $urls );
$c = \count( $urls );
$urls[ $c ] = "<a href='{$m}'>{$m}</a>";
$value = str_replace( $matches[0][ $k ], '<!--url{' . $c . '}-->', $value );
@@ -767,7 +801,7 @@ class _LegacyParser
try
{
$me = \IPS\Text\Parser::embeddableMedia( \IPS\Http\Url::createFromString( $url, FALSE, TRUE ) );
$me = \IPS\Text\Parser::embeddableMedia( \IPS\Http\Url::createFromString( $url, FALSE, TRUE ), FALSE, $this->member );
}
catch( \Exception $e ){}
}
@@ -777,7 +811,7 @@ class _LegacyParser
$embedCount++;
}
$c = count( $urls );
$c = \count( $urls );
$urls[ $c ] = $me ?: "<a href='{$m}'>{$m}</a>";
$value = str_replace( $matches[1][ $k ], '<!--url{' . $c . '}-->', $value );
@@ -888,6 +922,11 @@ class _LegacyParser
{
$value = str_replace( '<!--codeboxes{' . $k . '}-->', $v, $value );
}
/* Put tables back */
foreach( $tables as $k => $v )
{
$value = str_replace( '<!--tables{' . $k . '}-->', $v, $value );
}
/* Block level tags */
$value = preg_replace( "/\[(code|codebox|sql|php|xml|html)(.*?)\](.+?)\[\/(code|codebox|sql|php|xml|html)\]/ims", "</p><div>[$1$2]$3[/$4]</div><p>", $value );
@@ -950,7 +989,7 @@ class _LegacyParser
/**
* Parse new quotes
*
* @param array Data from preg_replace callback
* @param array $matches Data from preg_replace callback
* @return string Converted text
*/
protected function _parseOldQuote( $matches=array() )
@@ -972,7 +1011,7 @@ class _LegacyParser
if ( $match[1] )
{
$return[] = " post='" . intval($match[1]) . "'";
$return[] = " post='" . \intval($match[1]) . "'";
}
if ( $match[2] )
@@ -987,14 +1026,14 @@ class _LegacyParser
/**
* Parse new quotes #2
*
* @param array Data from preg_replace callback
* @param array $matches Data from preg_replace callback
* @return string Converted text
*/
protected function _parseOldBlockquote( $matches=array() )
{
$parameters = array( 'data-ipsQuote' => '', 'class' => 'ipsQuote' );
if( count( $matches[1] ) )
if( \count( $matches ) )
{
preg_match( "/data-author=['\"](.+?)[\"']/i", static::_cleanQuoteName( $matches[1] ), $author );
preg_match( "/data-cid=['\"](.+?)[\"']/i", $matches[1], $cid );
@@ -1040,14 +1079,14 @@ class _LegacyParser
/**
* Parse new quotes #3
*
* @param array Data from preg_replace callback
* @param array $matches Data from preg_replace callback
* @return string Converted text
*/
protected function _parseOldQuoteBbcode( $matches=array() )
{
$parameters = array( 'data-ipsQuote' => '', 'class' => 'ipsQuote' );
if( count( $matches[1] ) )
if( \count( $matches ) )
{
preg_match( "/name=['\"](.+?)[\"']/i", $matches[1], $author );
preg_match( "/post=['\"](.+?)[\"']/i", $matches[1], $cid );
@@ -1101,7 +1140,7 @@ class _LegacyParser
/**
* Convert flash HTML back into BBCode
*
* @param array Data from preg_replace callback
* @param array $matches Data from preg_replace callback
* @return string Converted text
*/
protected function _parseOldFlash( $matches=array() )
@@ -1114,7 +1153,7 @@ class _LegacyParser
/**
* Convert old code tags back into bbcode
*
* @param array Data from preg_replace callback
* @param array $matches Data from preg_replace callback
* @return string Converted text
*/
protected function _parseOldCode( $matches=array() )
@@ -1125,7 +1164,7 @@ class _LegacyParser
/**
* Convert download manager screenshot URLs
*
* @param array Data from preg_replace callback
* @param array $matches Data from preg_replace callback
* @return string Converted text
*/
protected function _fixDownloadsScreenshots( $matches )
@@ -1152,7 +1191,7 @@ class _LegacyParser
/**
* Legacy names can have things like $ and ' which break new parser
*
* @param string Name
* @param string $name Name
* @return string Converted name
*/
protected static function _cleanQuoteName( $name )
@@ -1164,4 +1203,4 @@ class _LegacyParser
return $name;
}
}
}
+871 -376
View File
File diff suppressed because it is too large. Load diff