Invision Power Services, Inc. * @copyright (c) 2001 - SVN_YYYY Invision Power Services, Inc. * @license http://www.invisionpower.com/legal/standards/ * @package IPS Social Suite * @since 12 Jun 2013 * @version SVN_VERSION_NUMBER */ 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; } /** * Legacy Text Parser */ class _LegacyParser { /** * Maximum number of embeds we will try. * @note Attempting to pull too many during the rebuild process can easily time out */ public $maxEmbeds = 10; /** * Parse statically * * @param string $value The value to parse * @param \IPS\Member|null $member The member posting. NULL will use currently logged in member. * @param bool $allowHtml Allow HTML * @param string $attachClass Key to use for attachments * @param int $id1 ID1 to use for attachments * @param int $id2 ID2 to use for attachments * @param int|NULL $id3 ID3 to use for attachments * @param string $itemClass The *item* classname (e.g. IPS\forums\Topic) * @return string * @see __construct */ 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 ); return $obj->parse( $value ); } /** * @brief BBcodes */ public $bbcodes = NULL; /** * @brief Emoticons */ public $emoticons = NULL; /** * @brief Media tags */ public $media = NULL; /** * Can use plugin? * * @param \IPS\Member $member The member * @param string $bbcode BBCode * @return bool */ public static function canUse( \IPS\Member $member, $bbcode ) { 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_groups'] == 'all' ) { return true; } if( $member->inGroup( explode( ',', $bbcode['bbcode_groups'] ) ) ) { return true; } } } return false; } /** * @brief Member */ protected $member = NULL; /** * @brief Allow HTML */ protected $allowHtml = FALSE; /** * @brief Parser object */ protected $parser = NULL; /** * @brief Key for attachments */ protected $attachClass = NULL; /** * @brief Item classname */ protected $itemClass = NULL; /** * @brief ID1 to use for attachments */ protected $idOne = 0; /** * @brief ID2 to use for attachments */ protected $idTwo = 0; /** * @brief ID3 to use for attachments */ protected $idThree = 0; /** * Constructor * * @param \IPS\Member|null $member The member posting. NULL will use guest. * @param bool $allowHtml Allow HTML * @param string $attachClass Key to use for attachments * @param int $id1 ID1 to use for attachments * @param int $id2 ID2 to use for attachments * @param int|NULL $id3 ID3 to use for attachments * @param string $itemClass The *item* classname (e.g. IPS\forums\Topic) * @return void */ public function __construct( $member=NULL, $allowHtml=FALSE, $attachClass=null, $id1=0, $id2=0, $id3=NULL, $itemClass=NULL ) { /* Get member */ $this->member = $member === NULL ? \IPS\Member::load(0) : $member; /* Remember if we allow HTML */ $this->allowHtml = $allowHtml; /* Set attachment data */ $this->attachClass = $attachClass; $this->idOne = $id1; $this->idTwo = $id2; $this->idThree = $id3; /* And item class */ $this->itemClass = $itemClass; /* Grab legacy custom bbcodes */ try { $this->bbcodes = iterator_to_array( \IPS\Db::i()->select( '*', 'custom_bbcode' )->setKeyField( 'bbcode_tag' ) ); } catch( \IPS\Db\Exception $e ) { $this->bbcodes = array(); } /* Grab emoticons */ try { $this->emoticons = iterator_to_array( \IPS\Db::i()->select( '*', 'core_emoticons' )->setKeyField( 'typed' ) ); } catch( \IPS\Db\Exception $e ) { $this->emoticons = array(); } /* Grab a new parser object */ $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, 1 ); $updatedBbcodeTags = array_keys( $this->parser->bbcodeTags( $this->member, TRUE ) ); foreach( $updatedBbcodeTags as $tag ) { if( isset( $this->bbcodes[ $tag ] ) AND $tag != 'media' ) { unset( $this->bbcodes[ $tag ] ); } } if( isset( $this->bbcodes['media'] ) ) { $this->bbcodes['media']['bbcode_replace'] = '
{content}
'; } if( $this->media === null ) { try { $this->media = iterator_to_array( \IPS\Db::i()->select( '*', 'bbcode_mediatag' ) ); } catch( \IPS\Db\Exception $e ) { $this->media = array(); } } } /** * Parse * * @param string $value Text to parse * @return string */ public function parse( $value ) { /* We have to fix up newlines a little bit */ $value = str_replace( array( "\r\n", "\r" ), "\n", $value ); if ( ! \strstr( $value, "\n" ) && ( \stristr( $value, '(.+?)#is", $value ) ) { $value = preg_replace( "#
(.+?)#is" , "[indent]\\1[/indent]", $value ); } /* Capital inconsistency */ foreach( array_keys( $this->parser->bbcodeTags( $this->member, TRUE ) ) as $bbcode ) { $value = str_replace( '[' . mb_strtoupper( $bbcode ), '[' . $bbcode, $value ); $value = str_replace( '[/' . mb_strtoupper( $bbcode ), '[/' . $bbcode, $value ); } /* Convert quote tag */ $value = preg_replace_callback( "#
]*?)>#si", array( $this, '_parseOldBlockquote' ) , $value ); $value = preg_replace_callback( "#\[quote([^>]*?)\]#si" , array( $this, '_parseOldQuoteBbcode' ) , $value ); $value = str_replace( "", "", $value ); $value = str_replace( "[/quote]", "", $value ); /* Fix download manager embedded screenshot URLs */ $value = preg_replace_callback( "#
[attachment=' . $attachmentId . ':name]
'; } } } /* Now fix shared media */ $value = preg_replace_callback( "/\[sharedmedia=(.+?):(.+?):(.+?)\]/ims", function( $matches ) { switch( $matches[1] ) { case 'calendar': try { $event = \IPS\Db::i()->select( '*', 'calendar_events', array( 'event_id=?', (int) $matches[3] ) )->first(); $url = \IPS\Http\Url::internal( "app=calendar&module=events&controller=event&id={$event['event_id']}", 'front', 'calendar_event', $event['event_title_seo'] ); return ""; } catch( \Exception $e ) { return ""; } break; case 'gallery': if( $matches[2] == 'images' ) { try { $image = \IPS\Db::i()->select( '*', 'gallery_images', array( 'image_id=?', (int) $matches[3] ) )->first(); $url = \IPS\Http\Url::internal( "app=gallery&module=gallery&controller=view&id={$image['image_id']}", 'front', 'gallery_image', $image['image_caption_seo'] ); return ""; } catch( \Exception $e ) { return ""; } } else { try { $album = \IPS\Db::i()->select( '*', 'gallery_albums', array( 'album_id=?', (int) $matches[3] ) )->first(); $url = \IPS\Http\Url::internal( "app=gallery&module=gallery&controller=browse&album={$album['album_id']}", 'front', 'gallery_album', $album['album_name_seo'] ); return ""; } catch( \Exception $e ) { return ""; } } break; case 'downloads': try { $file = \IPS\Db::i()->select( '*', 'downloads_files', array( 'file_id=?', (int) $matches[3] ) )->first(); $url = \IPS\Http\Url::internal( "app=downloads&module=downloads&controller=view&id={$file['file_id']}", 'front', 'downloads_file', $file['file_name_furl'] ); return ""; } catch( \Exception $e ) { return ""; } break; case 'core': /* We'll just let the attachment parsing next take care of this */ return "[attachment={$matches[3]}:string]"; break; case 'blog': try { $entry = \IPS\Db::i()->select( '*', 'blog_entries', array( 'entry_id=?', (int) $matches[3] ) )->first(); $url = \IPS\Http\Url::internal( "app=blog&module=blogs&controller=entry&id={$entry['entry_id']}", 'front', 'blog_entry', $entry['entry_name_seo'] ); return ""; } catch( \Exception $e ) { return ""; } break; } /* Could be a third party app - just return original embed code if we are still here */ return $matches[0]; }, $value ); /* Some people may have tried to embed the direct youtube video...tsk tsk */ preg_match_all( '#youtube.com/v/([^ \[]+?)#is', $value, $matches ); foreach( $matches[0] as $idx => $m ) { $value = str_replace( $m, "youtube.com/watch?v=" . $matches[1][ $idx ], $value ); } /* Media */ $urls = array(); /* Parse [URL]url[/URL] bbcode */ preg_match_all( '#\[url]([^\[]+?)\[\/url\]#is', $value, $matches ); foreach( $matches[0] as $idx => $m ) { $value = str_replace( $m, "" . $matches[1][ $idx ] . "", $value ); } /* Parse [URL=url]text[/URL] bbcode */ preg_match_all( '#\[url=(?:\'|"|&\#039;)?(.+?)(?:\'|"|&\#039;)?\](.+?)\[\/url\]#is', $value, $matches ); foreach( $matches[0] as $idx => $m ) { $value = str_replace( $m, "" . $matches[2][ $idx ] . "", $value ); } /* Parse img bbcode */ preg_match_all( '#\[img\](.+?)\[\/img\]#is', $value, $matches ); foreach( $matches[0] as $idx => $m ) { $image = basename( $matches[1][ $idx ] ); $value = str_replace( $m, "