Version 4.5.0
This commit is contained in:
1 parent
1a0c7fd3c2
commit
f79dcf067a
3791 files changed
+248032
-76372
No files matched your search
+16
-10
@@ -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( '/<fileStore\.([\d\w\_]+?)>/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( '<___base_url___>', '<___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
@@ -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 );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -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 );
|
||||
}
|
||||
|
||||
@@ -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 );
|
||||
}
|
||||
|
||||
@@ -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&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
File diff suppressed because it is too large.
Load diff
Reference in new issue
Block a user