Version 4.2.0
This commit is contained in:
1 parent
0dc2aee5ed
commit
96997ddd8e
2074 files changed
+125454
-55780
No files matched your search
+320
-223
@@ -1,12 +1,11 @@
|
||||
<?php
|
||||
/**
|
||||
* @brief Text Parser
|
||||
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
|
||||
* @copyright (c) 2001 - 2016 Invision Power Services, Inc.
|
||||
* @license http://www.invisionpower.com/legal/standards/
|
||||
* @package IPS Community Suite
|
||||
* @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 12 Jun 2013
|
||||
* @version SVN_VERSION_NUMBER
|
||||
*/
|
||||
|
||||
namespace IPS\Text;
|
||||
@@ -204,6 +203,52 @@ class _Parser
|
||||
/* Return */
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse content to add or remove image proxy URLs
|
||||
*
|
||||
* @param string $content HTML to parse
|
||||
* @param bool $status Add or remove image proxy
|
||||
* @return stinrg
|
||||
*/
|
||||
public static function parseImageProxy( $content, $status=TRUE )
|
||||
{
|
||||
$source = new \IPS\Xml\DOMDocument( '1.0', 'UTF-8' );
|
||||
$source->loadHTML( \IPS\Xml\DOMDocument::wrapHtml( $content ) );
|
||||
|
||||
/* Get document images */
|
||||
$contentImages = $source->getElementsByTagName( 'img' );
|
||||
|
||||
foreach( $contentImages as $element )
|
||||
{
|
||||
if( $status )
|
||||
{
|
||||
\IPS\Text\Parser::_parseImageProxySrc( $element );
|
||||
|
||||
/* Replace srcset also */
|
||||
if ( $element->getAttribute('srcset') )
|
||||
{
|
||||
\IPS\Text\Parser::_parseImageProxySrcSet( $element );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
\IPS\Text\Parser::_removeImageProxy( $element );
|
||||
}
|
||||
}
|
||||
|
||||
$proxyUrl = \IPS\Http\Url::createFromString( \IPS\Settings::i()->base_url . "applications/core/interface/imageproxy/imageproxy.php" );
|
||||
$genericUrl = '<___base_url___>/applications/core/interface/imageproxy/imageproxy.php';
|
||||
|
||||
/* Get DOMDocument output */
|
||||
$content = \IPS\Text\DOMParser::getDocumentBodyContents( $source );
|
||||
|
||||
/* 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( $proxyUrl, $genericUrl, str_replace( '<___base_url___>', '<___base_url___>', $content ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace {fileStore.xxx} with <fileStore.xxx>
|
||||
@@ -340,7 +385,8 @@ class _Parser
|
||||
$def->addAttribute( 'a', 'data-extension', 'Text' );
|
||||
|
||||
/* iFrames (used by embeddableMedia) */
|
||||
$def->addAttribute( 'iframe', 'data-controller', new \HTMLPurifier_AttrDef_Enum( array( 'core.front.core.autosizeiframe' ) ) ); // used in core/global/embed/oframe.phtml
|
||||
$def->addAttribute( 'iframe', 'data-controller', new \HTMLPurifier_AttrDef_Enum( array( 'core.front.core.autosizeiframe' ) ) ); // used in core/global/embed/iframe.phtml
|
||||
$def->addAttribute( 'iframe', 'data-embedid', 'Text' ); // used in core/global/embed/iframe.phtml
|
||||
$def->addAttribute( 'iframe', 'data-embedcontent', 'Text' ); // used in embeddableMedia
|
||||
$def->addAttribute( 'iframe', 'allowfullscreen', 'Text' ); // Some services will specify this property
|
||||
|
||||
@@ -453,7 +499,8 @@ class _Parser
|
||||
'www.ustream.tv/embed/',
|
||||
'api.smugmug.com/services/embed/',
|
||||
'www.google.com/maps/',
|
||||
'www.screencast.com/users/'
|
||||
'www.screencast.com/users/',
|
||||
'fast.wistia.net/embed/',
|
||||
) );
|
||||
|
||||
/* Extra admin-defined options */
|
||||
@@ -712,6 +759,16 @@ class _Parser
|
||||
$parent->replaceChild( $replace, $img );
|
||||
}
|
||||
}
|
||||
|
||||
/* Swap out blacklisted image URLs */
|
||||
foreach( $parent->getElementsByTagName( 'img' ) AS $img )
|
||||
{
|
||||
if ( $img->hasAttribute( 'data-ipsplaintext-img' ) )
|
||||
{
|
||||
$replace = $parent->appendChild( new \DOMText( $img->getAttribute( 'data-ipsplaintext-img' ) ) );
|
||||
$parent->replaceChild( $replace, $img );
|
||||
}
|
||||
}
|
||||
|
||||
/* <pre> tags don't parse BBCode inside */
|
||||
$resumeBBCodeAfterPre = FALSE;
|
||||
@@ -1169,13 +1226,15 @@ class _Parser
|
||||
/**
|
||||
* Adjust for Block-Level BBCode if necessary at end of the node
|
||||
*
|
||||
* @param \DOMNode $parent The node from the new document which will be the working node's parent. Passed by reference and will be modified if there is an open block-level BBCode
|
||||
* @return void
|
||||
*/
|
||||
protected function _adjustParentForBlockBBCodeAtEndOfNode()
|
||||
protected function _adjustParentForBlockBBCodeAtEndOfNode( \DOMNode &$parent )
|
||||
{
|
||||
/* If we have an open block-level BBCode element, decrease the depth we're at */
|
||||
if ( $this->openBlockDepth )
|
||||
{
|
||||
$parent = $parent->parentNode;
|
||||
$this->openBlockDepth--;
|
||||
}
|
||||
}
|
||||
@@ -1249,7 +1308,7 @@ class _Parser
|
||||
}
|
||||
|
||||
/* If it's not allowed, remove the href */
|
||||
if ( !$this->isAllowedUrl( $element->getAttribute('href') ) )
|
||||
if ( !static::isAllowedUrl( $element->getAttribute('href') ) )
|
||||
{
|
||||
$element->removeAttribute( 'href' );
|
||||
$element->setAttribute( 'class', 'ipsType_noLinkStyling' );
|
||||
@@ -1302,8 +1361,9 @@ class _Parser
|
||||
$this->_removeMunge( $element );
|
||||
|
||||
/* If it's not allowed, remove the src */
|
||||
if ( !$this->isAllowedUrl( $element->getAttribute('src') ) )
|
||||
if ( !static::isAllowedUrl( $element->getAttribute('src') ) )
|
||||
{
|
||||
$element->setAttribute( 'data-ipsplaintext-img', $element->getAttribute('src') );
|
||||
$element->removeAttribute('src');
|
||||
return;
|
||||
}
|
||||
@@ -1315,6 +1375,7 @@ class _Parser
|
||||
{
|
||||
$element->setAttribute( 'src', str_replace( static::$fileObjectClasses['core_Emoticons']->baseUrl(), '{fileStore.core_Emoticons}', $element->getAttribute('src') ) );
|
||||
$element->setAttribute( 'alt', $emoticon['typed'] );
|
||||
$element->setAttribute( 'data-emoticon', TRUE );
|
||||
|
||||
if( $emoticon['image_2x'] and $emoticon['width'] and $emoticon['height'] )
|
||||
{
|
||||
@@ -1367,7 +1428,90 @@ class _Parser
|
||||
/* Image proxy */
|
||||
if ( \IPS\Settings::i()->remote_image_proxy or !\IPS\Settings::i()->allow_remote_images )
|
||||
{
|
||||
$imageSrc = $element->getAttribute('src');
|
||||
static::_parseImageProxySrc( $element );
|
||||
|
||||
/* Replace srcset also */
|
||||
if ( $element->getAttribute('srcset') )
|
||||
{
|
||||
static::_parseImageProxySrcSet( $element );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Image Proxy SRC Attributes
|
||||
*
|
||||
* @param \DOMElement $element
|
||||
* @return void
|
||||
*/
|
||||
protected static function _parseImageProxySrc( \DOMElement $element )
|
||||
{
|
||||
/* If for some reason we're processing an existing imageproxy URL, set the full URL. */
|
||||
$imageSrc = str_replace( '<___base_url___>', rtrim( \IPS\Settings::i()->base_url, '/' ), $element->getAttribute('src') );
|
||||
|
||||
/* Check for file store tags */
|
||||
if( mb_stristr( $imageSrc, 'fileStore.') )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
$imageSrc = \IPS\Http\Url::createFromString( $imageSrc );
|
||||
$useProxy = !$imageSrc->isInternal and !$imageSrc->isLocalhost(); // We don't use the image proxy for internal resources as it may cause protected resources to be exposed because the server thinks it's an internal request
|
||||
}
|
||||
catch ( \IPS\Http\Url\Exception $e )
|
||||
{
|
||||
$useProxy = TRUE;
|
||||
}
|
||||
|
||||
if ( $useProxy )
|
||||
{
|
||||
if ( !\IPS\Settings::i()->allow_remote_images )
|
||||
{
|
||||
$element->setAttribute( 'src', '' );
|
||||
}
|
||||
else
|
||||
{
|
||||
$newUrl = \IPS\Http\Url::createFromString( \IPS\Settings::i()->base_url . "applications/core/interface/imageproxy/imageproxy.php" );
|
||||
$newUrl = $newUrl->setQueryString( array(
|
||||
'img' => (string) $imageSrc,
|
||||
'key' => hash_hmac( "sha256", (string) $imageSrc, \IPS\Settings::i()->site_secret_key )
|
||||
) );
|
||||
|
||||
$element->setAttribute( 'src', (string) $newUrl );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Image Proxy SRCSET Attributes
|
||||
*
|
||||
* @param \DOMElement $element
|
||||
* @return void
|
||||
*/
|
||||
protected static function _parseImageProxySrcSet( \DOMElement $element )
|
||||
{
|
||||
$urls = explode( ',', $element->getAttribute('srcset') );
|
||||
$fixedUrls = array();
|
||||
|
||||
foreach( $urls as $url )
|
||||
{
|
||||
/* Format is: http://url.com/img.png size */
|
||||
$data = explode( ' ', trim( $url ) );
|
||||
|
||||
if ( count( $data ) <= 2 )
|
||||
{
|
||||
/* If for some reason we're processing an existing imageproxy URL, set the full URL. */
|
||||
$imageSrc = str_replace( '<___base_url___>', rtrim( \IPS\Settings::i()->base_url, '/' ), $data[0] );
|
||||
|
||||
/* Check for file store tags */
|
||||
if( mb_stristr( $imageSrc, 'fileStore.') )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
$imageSrc = \IPS\Http\Url::createFromString( $imageSrc );
|
||||
@@ -1377,78 +1521,42 @@ class _Parser
|
||||
{
|
||||
$useProxy = TRUE;
|
||||
}
|
||||
|
||||
/* Image Proxy base URL */
|
||||
$newUrl = \IPS\Http\Url::createFromString( \IPS\Settings::i()->base_url . "applications/core/interface/imageproxy/imageproxy.php" );
|
||||
|
||||
if ( $useProxy )
|
||||
{
|
||||
if ( !\IPS\Settings::i()->allow_remote_images )
|
||||
{
|
||||
$element->setAttribute( 'src', '' );
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
$newUrl = \IPS\Http\Url::createFromString( \IPS\Settings::i()->base_url . "applications/core/interface/imageproxy/imageproxy.php" );
|
||||
{
|
||||
$newUrl = $newUrl->setQueryString( array(
|
||||
'img' => (string) $imageSrc,
|
||||
'key' => hash_hmac( "sha256", (string) $imageSrc, \IPS\Settings::i()->site_secret_key )
|
||||
'img' => str_replace( ',', '%2C', $imageSrc ), /* srcset URLs can have a param like resize=150,150 and the comma breaks the URLs */
|
||||
'key' => hash_hmac( "sha256", (string) $data[0], \IPS\Settings::i()->site_secret_key )
|
||||
) );
|
||||
|
||||
$element->setAttribute( 'src', (string) $newUrl );
|
||||
|
||||
$fixedUrls[] = (string) $newUrl . ( ! empty( $data[1] ) ? ' ' . $data[1] : '' );
|
||||
}
|
||||
}
|
||||
|
||||
/* Replace srcset also */
|
||||
if ( $element->getAttribute('srcset') )
|
||||
/* Srcset may already contain ImageProxy URLs if content is being rebuilt, we want to retain these */
|
||||
elseif( mb_stristr( $imageSrc, (string) $newUrl ) )
|
||||
{
|
||||
$urls = explode( ',', $element->getAttribute('srcset') );
|
||||
$fixedUrls = array();
|
||||
|
||||
foreach( $urls as $url )
|
||||
{
|
||||
/* Format is: http://url.com/img.png size */
|
||||
$data = explode( ' ', trim( $url ) );
|
||||
|
||||
if ( count( $data ) <= 2 )
|
||||
{
|
||||
$imageSrc = $data[0];
|
||||
try
|
||||
{
|
||||
$imageSrc = \IPS\Http\Url::createFromString( $data[0] );
|
||||
$useProxy = !$imageSrc->isInternal and !$imageSrc->isLocalhost(); // We don't use the image proxy for internal resources as it may cause protected resources to be exposed because the server thinks it's an internal request
|
||||
}
|
||||
catch ( \IPS\Http\Url\Exception $e )
|
||||
{
|
||||
$useProxy = TRUE;
|
||||
}
|
||||
if ( $useProxy )
|
||||
{
|
||||
if ( !\IPS\Settings::i()->allow_remote_images )
|
||||
{
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
$newUrl = \IPS\Http\Url::createFromString( \IPS\Settings::i()->base_url . "applications/core/interface/imageproxy/imageproxy.php" );
|
||||
$newUrl = $newUrl->setQueryString( array(
|
||||
'img' => str_replace( ',', '%2C', (string) $imageSrc ), /* srcset URLs can have a param like resize=150,150 and the comma breaks the URLs */
|
||||
'key' => hash_hmac( "sha256", (string) $data[0], \IPS\Settings::i()->site_secret_key )
|
||||
) );
|
||||
|
||||
$fixedUrls[] = (string) $newUrl . ( ! empty( $data[1] ) ? ' ' . $data[1] : '' );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( count( $fixedUrls ) )
|
||||
{
|
||||
$element->setAttribute( 'srcset', implode( ', ', $fixedUrls ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
$element->setAttribute( 'srcset', '' );
|
||||
}
|
||||
$fixedUrls[] = $imageSrc;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( count( $fixedUrls ) )
|
||||
{
|
||||
$element->setAttribute( 'srcset', implode( ', ', $fixedUrls ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
$element->setAttribute( 'srcset', '' );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1474,6 +1582,59 @@ class _Parser
|
||||
|
||||
$this->_removeMunge( $element );
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove Image Proxy URL
|
||||
*
|
||||
* @param \DOMElement $element
|
||||
* @return void
|
||||
*/
|
||||
protected static function _removeImageProxy( \DOMElement $element )
|
||||
{
|
||||
$imageProxyUrl = "<___base_url___>/applications/core/interface/imageproxy/imageproxy.php";
|
||||
|
||||
$imageSrc = $element->getAttribute( 'src' );
|
||||
|
||||
/* If it's a local placeholder, we don't need to process it. */
|
||||
if( mb_stristr( $imageSrc, 'fileStore.' ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
elseif( mb_stristr( $imageSrc, (string) $imageProxyUrl ) )
|
||||
{
|
||||
$srcUrl = \IPS\Http\Url::createFromString( str_replace( '<___base_url___>', rtrim( \IPS\Settings::i()->base_url, '/' ), $imageSrc ) );
|
||||
$element->setAttribute( 'src', $srcUrl->queryString['img'] );
|
||||
}
|
||||
|
||||
if( $element->getAttribute('srcset') )
|
||||
{
|
||||
$urls = explode( ',', $element->getAttribute('srcset') );
|
||||
$fixedUrls = array();
|
||||
|
||||
foreach( $urls as $url )
|
||||
{
|
||||
/* Format is: http://url.com/img.png size */
|
||||
$data = explode( ' ', trim( $url ) );
|
||||
|
||||
if( count( $data ) <= 2 )
|
||||
{
|
||||
/* If for some reason we're processing an existing imageproxy URL, set the full URL. */
|
||||
$imageSrcUrl = \IPS\Http\Url::createFromString( str_replace( '<___base_url___>', rtrim( \IPS\Settings::i()->base_url, '/' ), $data[0] ) );
|
||||
|
||||
if( !isset( $imageSrcUrl->queryString['img'] ) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
$fixedUrls[] = $imageSrcUrl->queryString['img'] . ( ! empty( $data[1] ) ? ' ' . $data[1] : '' );
|
||||
}
|
||||
}
|
||||
|
||||
if ( count( $fixedUrls ) )
|
||||
{
|
||||
$element->setAttribute( 'srcset', implode( ', ', $fixedUrls ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* When editing content in the AdminCP, images and iframes get the src munged. When we save, we need to put that back
|
||||
@@ -1532,7 +1693,7 @@ class _Parser
|
||||
* @param string $url The URL
|
||||
* @return bool
|
||||
*/
|
||||
public function isAllowedUrl( $url )
|
||||
static public function isAllowedUrl( $url )
|
||||
{
|
||||
if ( \IPS\Settings::i()->url_filter_action == 'moderate' )
|
||||
{
|
||||
@@ -1558,29 +1719,32 @@ class _Parser
|
||||
if ( !empty( $linkValues ) )
|
||||
{
|
||||
$goodUrl = FALSE;
|
||||
|
||||
foreach( $linkValues as $link )
|
||||
|
||||
if ( count( $linkValues ) )
|
||||
{
|
||||
if( !trim($link) )
|
||||
foreach( $linkValues as $link )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
$link = preg_quote( $link, '/' );
|
||||
$link = str_replace( '\*', "(.*?)", $link );
|
||||
|
||||
if ( \IPS\Settings::i()->ipb_url_filter_option == "black" )
|
||||
{
|
||||
if( preg_match( '/' . $link . '/i', $url ) )
|
||||
if( !trim($link) )
|
||||
{
|
||||
return false;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( preg_match( '/' . $link . '/i', $url ) )
|
||||
|
||||
$link = preg_quote( $link, '/' );
|
||||
$link = str_replace( '\*', "(.*?)", $link );
|
||||
|
||||
if ( \IPS\Settings::i()->ipb_url_filter_option == "black" )
|
||||
{
|
||||
$goodUrl = TRUE;
|
||||
if( preg_match( '/' . $link . '/i', $url ) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( preg_match( '/' . $link . '/i', $url ) )
|
||||
{
|
||||
$goodUrl = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1638,7 +1802,13 @@ class _Parser
|
||||
* @return array|NULL
|
||||
*/
|
||||
protected function _getAttachment( $url )
|
||||
{
|
||||
{
|
||||
/* De-munge it */
|
||||
if ( preg_match( '#^(?:http:|https:)?' . preg_quote( rtrim( str_replace( array( 'http://', 'https://' ), '//', \IPS\Settings::i()->base_url ), '/' ), '#' ) . '/index.php\?app=core&module=system&controller=redirect&url=(.+?)&key=.+?(?:&resource=[01])?$#', $url, $matches ) )
|
||||
{
|
||||
$url = urldecode( $matches[1] );
|
||||
}
|
||||
|
||||
/* We need the storage extension */
|
||||
if ( !isset( static::$fileObjectClasses['core_Attachment'] ) )
|
||||
{
|
||||
@@ -2416,6 +2586,8 @@ class _Parser
|
||||
'slideshare.net' => array( 'http://www.slideshare.net/api/oembed/2', static::EMBED_VIDEO ),
|
||||
'*.smugmug.com' => array( 'http://api.smugmug.com/services/oembed', static::EMBED_IMAGE ),
|
||||
'ustream.tv' => array( 'https://www.ustream.tv/oembed', static::EMBED_VIDEO ),
|
||||
'*.wistia.com' => array( 'http://fast.wistia.com/oembed', static::EMBED_VIDEO ),
|
||||
'*.wi.st' => array( 'http://fast.wistia.com/oembed', static::EMBED_VIDEO ),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -2441,12 +2613,6 @@ class _Parser
|
||||
{
|
||||
return $embedCode;
|
||||
}
|
||||
|
||||
/* Image? */
|
||||
if ( $embedCode = static::_imageEmbed( $url, $iframe ) )
|
||||
{
|
||||
return $embedCode;
|
||||
}
|
||||
}
|
||||
|
||||
/* External */
|
||||
@@ -2463,12 +2629,6 @@ class _Parser
|
||||
{
|
||||
return $embedCode;
|
||||
}
|
||||
|
||||
/* Image? */
|
||||
if ( \IPS\Settings::i()->allow_remote_images and $embedCode = static::_imageEmbed( $url, $iframe ) )
|
||||
{
|
||||
return $embedCode;
|
||||
}
|
||||
}
|
||||
|
||||
/* Still here? It's not embeddable */
|
||||
@@ -2609,6 +2769,15 @@ class _Parser
|
||||
{
|
||||
$response['html'] = preg_replace( '/data\-width="\d*"/', 'data-width="auto"', $response['html'] );
|
||||
}
|
||||
|
||||
/* For Youtube, we need to be a bit hacky to pass rel=0 */
|
||||
if ( $domain == 'youtube.com' or $domain == 'm.youtube.com' or $domain == 'youtu.be' )
|
||||
{
|
||||
if ( isset( $url->queryString['rel'] ) )
|
||||
{
|
||||
$response['html'] = str_replace( '?feature=oembed', '?feature=oembed&rel=0', $response['html'] );
|
||||
}
|
||||
}
|
||||
|
||||
/* We need a type otherwise we can't embed */
|
||||
if( !isset( $response['type'] ) )
|
||||
@@ -2665,7 +2834,7 @@ class _Parser
|
||||
{
|
||||
if ( $iframe )
|
||||
{
|
||||
return \IPS\Theme::i()->getTemplate( 'global', 'core', 'front' )->blankTemplate( \IPS\Theme::i()->getTemplate( 'embed', 'core', 'global' )->google( (string) $url ) );
|
||||
return \IPS\Theme::i()->getTemplate( 'embed', 'core', 'global' )->google( (string) $url );
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -2885,19 +3054,27 @@ class _Parser
|
||||
/* Extract the address and gps coordinates from the query string */
|
||||
$qbits = explode( "/", $matches[2] );
|
||||
|
||||
/* Place names are easy */
|
||||
if( $qbits[0] == 'place' )
|
||||
switch ( $qbits[0] )
|
||||
{
|
||||
/* This seems odd but sometimes the place names can already be url encoded and we don't want to double encode */
|
||||
return \IPS\Theme::i()->getTemplate( 'embed', 'core', 'global' )->googleMaps( urlencode( urldecode( $qbits[1] ) ), 'place' );
|
||||
}
|
||||
/* GPS Coordinate views need a little more work */
|
||||
else
|
||||
{
|
||||
$params = explode( ",", mb_substr( $qbits[0], 1, -1 ) );
|
||||
$coordinates = implode( "," , array( $params[0], $params[1]) );
|
||||
case 'place':
|
||||
/* This seems odd but sometimes the place names can already be url encoded and we don't want to double encode */
|
||||
return \IPS\Theme::i()->getTemplate( 'embed', 'core', 'global' )->googleMaps( urlencode( urldecode( $qbits[1] ) ), 'place' );
|
||||
break;
|
||||
|
||||
return \IPS\Theme::i()->getTemplate( 'embed', 'core', 'global' )->googleMaps( $coordinates, 'coordinates', $params[2] );
|
||||
case 'dir':
|
||||
$params = array( 'origin' => $qbits[1], 'destination' => $qbits[2] );
|
||||
return \IPS\Theme::i()->getTemplate( 'embed', 'core', 'global' )->googleMaps( $params, 'dir' );
|
||||
break;
|
||||
|
||||
case 'search':
|
||||
return \IPS\Theme::i()->getTemplate( 'embed', 'core', 'global' )->googleMaps( urlencode( urldecode( $qbits[1] ) ), 'search' );
|
||||
break;
|
||||
|
||||
default:
|
||||
$params = explode( ",", mb_substr( $qbits[0], 1, -1 ) );
|
||||
$coordinates = implode( "," , array( $params[0], $params[1]) );
|
||||
return \IPS\Theme::i()->getTemplate( 'embed', 'core', 'global' )->googleMaps( $coordinates, 'coordinates', $params[2] );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3006,7 +3183,8 @@ class _Parser
|
||||
throw new \UnexpectedValueException( 'embed__fail_500', static::EMBED_LINK );
|
||||
}
|
||||
|
||||
$preview = $preview->setQueryString( 'do', 'embed' );
|
||||
/* Strip the CSRF key if present - normally shouldnt't be, but just in case..*/
|
||||
$preview = $preview->setQueryString( 'do', 'embed' )->stripQueryString( 'csrfKey' );
|
||||
if( isset( $url->queryString['do'] ) and $url->queryString['do'] == 'findComment' )
|
||||
{
|
||||
$preview = $preview->setQueryString( 'embedComment', $url->queryString['comment'] );
|
||||
@@ -3025,7 +3203,7 @@ class _Parser
|
||||
}
|
||||
|
||||
/* And return */
|
||||
return "<iframe src='{$preview}' frameborder='0' data-embedContent></iframe>";
|
||||
return "<iframe src='{$preview}' data-embedContent data-controller='core.front.core.autosizeiframe' allowfullscreen=''></iframe>";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3036,130 +3214,49 @@ class _Parser
|
||||
/**
|
||||
* Image Embed Code
|
||||
*
|
||||
* @param \IPS\Http\Url $url URL
|
||||
* @param bool $iframe Some services need to be in iFrames so they cannot be edited in the editor. If TRUE, will return contents for iframe, if FALSE, return the iframe.
|
||||
* @param bool $bypassExtensionCheck If TRUE, will not check if the URL ends in ".gif", ".png", etc
|
||||
* @param \IPS\Http\Url $url URL to image (that you know is an image)
|
||||
* @param int $width Image width (the actual value, which this method will auto-adjust if it exceeds our allowed size)
|
||||
* @param int $height Image height (the actual value, which this method will auto-adjust if it exceeds our allowed size)
|
||||
* @return string|null
|
||||
*/
|
||||
public static function _imageEmbed( \IPS\Http\Url $url, $iframe=FALSE, $bypassExtensionCheck=FALSE )
|
||||
public static function imageEmbed( \IPS\Http\Url $url, $width, $height )
|
||||
{
|
||||
/* Extension check */
|
||||
if ( !$bypassExtensionCheck )
|
||||
/* If the URL is blacklisted, just return it */
|
||||
if( !static::isAllowedUrl( $url ) )
|
||||
{
|
||||
/* What's the extension? */
|
||||
$extension = mb_substr( $url, mb_strrpos( $url, '.' ) + 1 );
|
||||
$questionPos = mb_strpos( $extension, '?' );
|
||||
if ( $questionPos !== FALSE )
|
||||
{
|
||||
$extension = mb_substr( $extension, 0, $questionPos );
|
||||
}
|
||||
$hashPos = mb_strpos( $extension, '#' );
|
||||
if ( $hashPos !== FALSE )
|
||||
{
|
||||
$extension = mb_substr( $extension, 0, $hashPos );
|
||||
}
|
||||
|
||||
/* Is that an image extension? */
|
||||
if ( !in_array( mb_strtolower( $extension ), \IPS\Image::$imageExtensions ) )
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Get the image */
|
||||
try
|
||||
{
|
||||
$imageContents = $url->request()->get();
|
||||
}
|
||||
/* If it times out or we can't connect, we can't embed */
|
||||
catch ( \IPS\Http\Request\Exception $e )
|
||||
{
|
||||
throw new \UnexpectedValueException( 'embed__fail_500', static::EMBED_IMAGE );
|
||||
return (string) $url;
|
||||
}
|
||||
|
||||
/* If the response wasn't 200, then it failed */
|
||||
if( $imageContents->httpResponseCode != '200' )
|
||||
{
|
||||
switch( $imageContents->httpResponseCode )
|
||||
{
|
||||
case '404':
|
||||
throw new \UnexpectedValueException( 'embed__fail_404', static::EMBED_IMAGE );
|
||||
break;
|
||||
$maxImageDims = \IPS\Settings::i()->attachment_image_size ? explode( 'x', \IPS\Settings::i()->attachment_image_size ) : array( 1000, 750 );
|
||||
$widthToUse = $width;
|
||||
$heightToUse = $height;
|
||||
|
||||
case '401':
|
||||
case '403':
|
||||
throw new \UnexpectedValueException( 'embed__fail_403', static::EMBED_IMAGE );
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new \UnexpectedValueException( 'embed__fail_500', static::EMBED_IMAGE );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Get the image dimension - try getimagesize first, as it is more efficient when available */
|
||||
try
|
||||
{
|
||||
/* Need to write a temporary file */
|
||||
$temporary = tempnam( \IPS\TEMP_DIRECTORY, 'image' );
|
||||
\file_put_contents( $temporary, $imageContents );
|
||||
|
||||
/* Then we can use getimagesize */
|
||||
$dims = @getimagesize( $temporary );
|
||||
|
||||
/* And delete it */
|
||||
if ( @is_file( $temporary ) )
|
||||
{
|
||||
@unlink( $temporary );
|
||||
}
|
||||
|
||||
/* Check that the dimensions returned were valid */
|
||||
if( $dims === FALSE OR !isset( $dims[0] ) OR !$dims[0] )
|
||||
{
|
||||
throw new \RuntimeException;
|
||||
}
|
||||
}
|
||||
/* If that fails, then we'll create an image object */
|
||||
catch( \RuntimeException $e )
|
||||
{
|
||||
/* Try to create the image object */
|
||||
try
|
||||
{
|
||||
$image = \IPS\Image::create( $imageContents );
|
||||
}
|
||||
/* If it fails, it's not a valid image */
|
||||
catch ( \Exception $e )
|
||||
{
|
||||
throw new \UnexpectedValueException( 'embed_bad_image_dims', static::EMBED_IMAGE );
|
||||
}
|
||||
|
||||
/* Set the dimensions */
|
||||
$dims = array( 0 => $image->width, 1 => $image->height );
|
||||
}
|
||||
|
||||
/* Adjust the width/height according to our maximum dimensions */
|
||||
$maxImageDims = \IPS\Settings::i()->attachment_image_size ? explode( 'x', \IPS\Settings::i()->attachment_image_size ) : array( 1000, 750 );
|
||||
$width = NULL;
|
||||
$height = NULL;
|
||||
if ( is_array( $dims ) AND ( $dims[0] > 0 AND $dims[1] > 0 ) )
|
||||
if ( $width > $maxImageDims[0] )
|
||||
{
|
||||
/* Check width first */
|
||||
if ( $dims[0] > $maxImageDims[0] )
|
||||
$widthToUse = $maxImageDims[0];
|
||||
$heightToUse = floor( $height / $width * $widthToUse );
|
||||
|
||||
if ( $heightToUse > $maxImageDims[1] )
|
||||
{
|
||||
$width = $maxImageDims[0];
|
||||
$height = floor( $dims[1] / $dims[0] * $width );
|
||||
$widthToUse = floor( $maxImageDims[1] * ( $widthToUse / $heightToUse ) );
|
||||
$heightToUse = $maxImageDims[1];
|
||||
}
|
||||
|
||||
/* Then height */
|
||||
if ( $height > $maxImageDims[1] )
|
||||
}
|
||||
elseif( $height > $maxImageDims[1] )
|
||||
{
|
||||
$heightToUse = $maxImageDims[1];
|
||||
$widthToUse = floor( $width / $height * $heightToUse );
|
||||
|
||||
if ( $widthToUse > $maxImageDims[0] )
|
||||
{
|
||||
$width = floor( $maxImageDims[1] * ( $width / $height ) );
|
||||
$height = $maxImageDims[1];
|
||||
$heightToUse = floor( $maxImageDims[0] * ( $heightToUse / $widthToUse ) );
|
||||
$widthToUse = $maxImageDims[0];
|
||||
}
|
||||
}
|
||||
|
||||
/* And return the embed */
|
||||
return \IPS\Theme::i()->getTemplate( 'embed', 'core', 'global' )->photo( $url, NULL, NULL, $width, $height );
|
||||
return \IPS\Theme::i()->getTemplate( 'embed', 'core', 'global' )->photo( $url, NULL, NULL, $widthToUse, $heightToUse );
|
||||
}
|
||||
|
||||
/* !Utility Methods */
|
||||
|
||||
Reference in new issue
Block a user