2015-04-07 20:39:42 +00:00
< ? php
2019-04-19 22:38:29 +00:00
2019-11-21 10:32:22 +00:00
use Zotlabs\Lib\Apps ;
2019-05-08 04:50:02 +00:00
use Zotlabs\Lib\Libzot ;
2019-11-05 19:10:49 +00:00
use Zotlabs\Lib\SvgSanitizer ;
2020-10-15 01:04:49 +00:00
use Michelf\MarkdownExtra ;
2019-05-08 04:50:02 +00:00
2015-04-07 20:39:42 +00:00
/**
* @ file include / bbcode . php
* @ brief BBCode related functions for parsing , etc .
*/
2011-06-10 03:02:48 +00:00
2015-04-07 20:39:42 +00:00
require_once ( 'include/oembed.php' );
2011-06-10 03:02:48 +00:00
require_once ( 'include/event.php' );
2017-08-03 05:11:46 +00:00
require_once ( 'include/html2plain.php' );
2011-07-19 02:17:16 +00:00
2017-05-31 01:36:19 +00:00
function get_bb_tag_pos ( $s , $name , $occurance = 1 ) {
if ( $occurance < 1 )
$occurance = 1 ;
$start_open = - 1 ;
for ( $i = 1 ; $i <= $occurance ; $i ++ ) {
if ( $start_open !== false )
$start_open = strpos ( $s , '[' . $name , $start_open + 1 ); // allow [name= type tags
}
if ( $start_open === false )
return false ;
$start_equal = strpos ( $s , '=' , $start_open );
$start_close = strpos ( $s , ']' , $start_open );
if ( $start_close === false )
return false ;
$start_close ++ ;
$end_open = strpos ( $s , '[/' . $name . ']' , $start_close );
if ( $end_open === false )
return false ;
$res = array ( 'start' => array ( 'open' => $start_open , 'close' => $start_close ),
'end' => array ( 'open' => $end_open , 'close' => $end_open + strlen ( '[/' . $name . ']' )) );
if ( $start_equal !== false )
$res [ 'start' ][ 'equal' ] = $start_equal + 1 ;
return $res ;
}
function bb_tag_preg_replace ( $pattern , $replace , $name , $s ) {
$string = $s ;
$occurance = 1 ;
$pos = get_bb_tag_pos ( $string , $name , $occurance );
while ( $pos !== false && $occurance < 1000 ) {
$start = substr ( $string , 0 , $pos [ 'start' ][ 'open' ]);
$subject = substr ( $string , $pos [ 'start' ][ 'open' ], $pos [ 'end' ][ 'close' ] - $pos [ 'start' ][ 'open' ]);
$end = substr ( $string , $pos [ 'end' ][ 'close' ]);
if ( $end === false )
$end = '' ;
$subject = preg_replace ( $pattern , $replace , $subject );
$string = $start . $subject . $end ;
$occurance ++ ;
$pos = get_bb_tag_pos ( $string , $name , $occurance );
}
return $string ;
}
2012-10-23 02:46:18 +00:00
function tryoembed ( $match ) {
2015-04-07 20:39:42 +00:00
$url = (( count ( $match ) == 2 ) ? $match [ 1 ] : $match [ 2 ]);
2012-02-19 19:36:59 +00:00
2011-10-24 12:30:11 +00:00
$o = oembed_fetch_url ( $url );
2016-09-24 12:15:06 +00:00
if ( $o [ 'type' ] == 'error' )
2015-04-07 20:39:42 +00:00
return $match [ 0 ];
2012-02-19 19:36:59 +00:00
2011-10-24 12:30:11 +00:00
$html = oembed_format_object ( $o );
2012-10-23 02:46:18 +00:00
return $html ;
2011-10-24 12:30:11 +00:00
}
2016-10-06 22:59:27 +00:00
function nakedoembed ( $match ) {
$url = (( count ( $match ) == 2 ) ? $match [ 1 ] : $match [ 2 ]);
2018-04-27 03:27:14 +00:00
$strip_url = strip_escaped_zids ( $url );
2019-05-10 21:39:55 +00:00
// this function no longer performs oembed on naked links
// because they author may have created naked links intentionally.
// Now it just strips zids on naked links.
return str_replace ( $url , $strip_url , $match [ 0 ]);
2016-10-06 22:59:27 +00:00
}
2014-01-24 07:46:43 +00:00
function tryzrlaudio ( $match ) {
$link = $match [ 1 ];
2014-07-14 08:38:16 +00:00
$zrl = is_matrix_url ( $link );
2014-01-24 07:46:43 +00:00
if ( $zrl )
$link = zid ( $link );
2015-04-07 20:39:42 +00:00
2015-10-30 03:50:52 +00:00
return '<audio src="' . str_replace ( ' ' , '%20' , $link ) . '" controls="controls" preload="none"><a href="' . str_replace ( ' ' , '%20' , $link ) . '">' . $link . '</a></audio>' ;
2014-01-24 07:46:43 +00:00
}
function tryzrlvideo ( $match ) {
$link = $match [ 1 ];
2014-07-14 08:38:16 +00:00
$zrl = is_matrix_url ( $link );
2014-01-24 07:46:43 +00:00
if ( $zrl )
$link = zid ( $link );
2018-01-29 04:35:05 +00:00
$static_link = get_config ( 'system' , 'video_default_poster' , 'images/video_poster.jpg' );
if ( $static_link )
$poster = 'poster="' . escape_tags ( $static_link ) . '" ' ;
return '<video ' . $poster . ' controls="controls" preload="none" src="' . str_replace ( ' ' , '%20' , $link ) . '" style="width:100%; max-width:' . App :: $videowidth . 'px"><a href="' . str_replace ( ' ' , '%20' , $link ) . '">' . $link . '</a></video>' ;
2014-01-24 07:46:43 +00:00
}
2019-03-18 03:49:54 +00:00
function videowithopts ( $match ) {
$link = $match [ 2 ];
$zrl = is_matrix_url ( $link );
if ( $zrl )
$link = zid ( $link );
$attributes = $match [ 1 ];
$poster = " " ;
preg_match ( " /poster='(.*?)'/ism " , $attributes , $matches );
if ( $matches [ 1 ] != " " )
2019-03-19 22:23:45 +00:00
$poster = 'poster="' . (( $zrl ) ? zid ( $matches [ 1 ]) : $matches [ 1 ]) . '"' ;
2019-04-01 19:23:48 +00:00
preg_match ( " /poster= \ " \ ;(.*?) \ " \ ;/ism " , $attributes , $matches );
if ( $matches [ 1 ] != " " )
$poster = 'poster="' . (( $zrl ) ? zid ( $matches [ 1 ]) : $matches [ 1 ]) . '"' ;
2019-03-18 03:49:54 +00:00
2021-02-08 00:13:33 +00:00
preg_match ( " /poster= \\ \" (.*?) \\ \" /ism " , $attributes , $matches );
if ( $matches [ 1 ] != " " )
$poster = 'poster="' . (( $zrl ) ? zid ( $matches [ 1 ]) : $matches [ 1 ]) . '"' ;
2019-03-18 03:49:54 +00:00
return '<video ' . $poster . ' controls="controls" preload="none" src="' . str_replace ( ' ' , '%20' , $link ) . '" style="width:100%; max-width:' . App :: $videowidth . 'px"><a href="' . str_replace ( ' ' , '%20' , $link ) . '">' . $link . '</a></video>' ;
}
2012-02-19 19:36:59 +00:00
// [noparse][i]italic[/i][/noparse] turns into
// [noparse][ i ]italic[ /i ][/noparse],
2012-02-12 22:35:29 +00:00
// to hide them from parser.
function bb_spacefy ( $st ) {
2015-04-07 20:39:42 +00:00
$whole_match = $st [ 0 ];
$captured = $st [ 1 ];
$spacefied = preg_replace ( " / \ [(.*?) \ ]/ " , " [ $ 1 ] " , $captured );
$new_str = str_replace ( $captured , $spacefied , $whole_match );
return $new_str ;
2012-02-12 22:35:29 +00:00
}
2012-02-19 19:36:59 +00:00
// The previously spacefied [noparse][ i ]italic[ /i ][/noparse],
2014-05-10 19:50:20 +00:00
// now turns back and the [noparse] tags are trimmed
2012-02-12 22:35:29 +00:00
// returning [i]italic[/i]
2011-10-24 12:30:11 +00:00
2012-02-12 22:35:29 +00:00
function bb_unspacefy_and_trim ( $st ) {
2015-04-07 20:39:42 +00:00
//$whole_match = $st[0];
$captured = $st [ 1 ];
$unspacefied = preg_replace ( " / \ [ (.*?) \ ]/ " , " [ $ 1] " , $captured );
return $unspacefied ;
2012-02-12 22:35:29 +00:00
}
2011-07-19 02:17:16 +00:00
2015-01-30 02:13:14 +00:00
2012-07-07 22:20:24 +00:00
function bb_extract_images ( $body ) {
$saved_image = array ();
$orig_body = $body ;
$new_body = '' ;
$cnt = 0 ;
$img_start = strpos ( $orig_body , '[img' );
$img_st_close = ( $img_start !== false ? strpos ( substr ( $orig_body , $img_start ), ']' ) : false );
$img_end = ( $img_start !== false ? strpos ( substr ( $orig_body , $img_start ), '[/img]' ) : false );
while (( $img_st_close !== false ) && ( $img_end !== false )) {
$img_st_close ++ ; // make it point to AFTER the closing bracket
$img_end += $img_start ;
if ( ! strcmp ( substr ( $orig_body , $img_start + $img_st_close , 5 ), 'data:' )) {
// This is an embedded image
2012-07-08 00:47:13 +00:00
$saved_image [ $cnt ] = substr ( $orig_body , $img_start + $img_st_close , $img_end - ( $img_start + $img_st_close ));
2012-07-07 22:20:24 +00:00
$new_body = $new_body . substr ( $orig_body , 0 , $img_start ) . '[$#saved_image' . $cnt . '#$]' ;
2012-07-08 00:47:13 +00:00
$cnt ++ ;
2012-07-07 22:20:24 +00:00
}
else
$new_body = $new_body . substr ( $orig_body , 0 , $img_end + strlen ( '[/img]' ));
$orig_body = substr ( $orig_body , $img_end + strlen ( '[/img]' ));
if ( $orig_body === false ) // in case the body ends on a closing image tag
$orig_body = '' ;
$img_start = strpos ( $orig_body , '[img' );
$img_st_close = ( $img_start !== false ? strpos ( substr ( $orig_body , $img_start ), ']' ) : false );
$img_end = ( $img_start !== false ? strpos ( substr ( $orig_body , $img_start ), '[/img]' ) : false );
}
$new_body = $new_body . $orig_body ;
return array ( 'body' => $new_body , 'images' => $saved_image );
2015-01-30 02:13:14 +00:00
}
2012-07-07 22:20:24 +00:00
function bb_replace_images ( $body , $images ) {
$newbody = $body ;
$cnt = 0 ;
2015-04-07 20:39:42 +00:00
2015-01-30 02:13:14 +00:00
if ( ! $images )
return $newbody ;
2012-07-07 22:20:24 +00:00
foreach ( $images as $image ) {
// We're depending on the property of 'foreach' (specified on the PHP website) that
// it loops over the array starting from the first element and going sequentially
// to the last element
2015-01-30 02:13:14 +00:00
$newbody = str_replace ( '[$#saved_image' . $cnt . '#$]' , '<img src="' . $image . '" alt="' . t ( 'Image/photo' ) . '" />' , $newbody );
2012-07-07 22:20:24 +00:00
$cnt ++ ;
}
2015-01-30 02:13:14 +00:00
// logger('replace_images: ' . $newbody);
2012-07-07 22:20:24 +00:00
return $newbody ;
2015-01-30 02:13:14 +00:00
}
2012-07-07 22:20:24 +00:00
2015-04-07 20:39:42 +00:00
/**
* @ brief Parses crypt BBCode .
*
* @ param array $match
* @ return string HTML code
*/
2020-08-23 09:28:38 +00:00
2013-11-08 04:18:52 +00:00
function bb_parse_crypt ( $match ) {
2020-08-23 09:28:38 +00:00
$matches = [];
2013-11-08 04:18:52 +00:00
$attributes = $match [ 1 ];
$algorithm = " " ;
2013-12-23 23:13:09 +00:00
2013-11-08 04:18:52 +00:00
preg_match ( " /alg='(.*?)'/ism " , $attributes , $matches );
if ( $matches [ 1 ] != " " )
2013-12-23 23:13:09 +00:00
$algorithm = $matches [ 1 ];
2013-11-08 04:18:52 +00:00
preg_match ( " /alg= \ " \ ;(.*?) \ " \ ;/ism " , $attributes , $matches );
if ( $matches [ 1 ] != " " )
2013-12-23 23:13:09 +00:00
$algorithm = $matches [ 1 ];
2013-11-08 04:18:52 +00:00
2021-02-08 00:13:33 +00:00
preg_match ( " /alg= \\ \" (.*?) \\ \" /ism " , $attributes , $matches );
if ( $matches [ 1 ] != " " )
$algorithm = $matches [ 1 ];
2013-12-23 23:13:09 +00:00
2021-02-08 00:13:33 +00:00
$hint = " " ;
$matches = [];
2013-11-08 04:18:52 +00:00
preg_match ( " /hint='(.*?)'/ism " , $attributes , $matches );
if ( $matches [ 1 ] != " " )
2013-12-23 23:13:09 +00:00
$hint = $matches [ 1 ];
2013-11-08 04:18:52 +00:00
preg_match ( " /hint= \ " \ ;(.*?) \ " \ ;/ism " , $attributes , $matches );
if ( $matches [ 1 ] != " " )
2013-12-23 23:13:09 +00:00
$hint = $matches [ 1 ];
2013-11-08 04:18:52 +00:00
2013-11-11 08:21:00 +00:00
$x = random_string ();
2020-08-23 09:28:38 +00:00
$f = 'hz_decrypt' ;
$onclick = 'onclick="' . $f . '(\'' . $algorithm . '\',\'' . $hint . '\',\'' . $match [ 2 ] . '\',\'#' . $x . '\');"' ;
$label = t ( 'Encrypted content' );
$Text = '<br /><div id="' . $x . '"><img class="cursor-pointer" src="' . z_root () . '/images/lock_icon.svg" ' . $onclick . ' alt="' . $label . '" title="' . $label . '" /></div><br />' ;
2013-11-08 04:18:52 +00:00
return $Text ;
}
2014-05-19 01:21:20 +00:00
function bb_parse_app ( $match ) {
2019-11-21 10:32:22 +00:00
$app = Apps :: app_decode ( $match [ 1 ]);
if ( $app ) {
return Apps :: app_render ( $app );
}
2014-05-19 01:21:20 +00:00
}
2019-11-25 23:48:14 +00:00
function bb_parse_app_ap ( $match ) {
$app = Apps :: app_decode ( $match [ 1 ]);
if ( $app ) {
2019-11-26 00:02:23 +00:00
return sprintf ( t ( '(Embedded app \'%s\' could not be displayed).' ), $app [ 'name' ]);
2019-11-25 23:48:14 +00:00
}
}
2019-11-05 05:45:16 +00:00
function bb_svg ( $match ) {
2019-11-05 08:48:09 +00:00
2019-11-06 05:34:47 +00:00
$params = str_replace ([ '<br>' , '"' ], [ '' , '"' ], $match [ 1 ]);
2019-11-06 23:42:27 +00:00
$Text = str_replace ([ '[' , ']' ], [ '<' , '>' ], $match [ 2 ]);
2019-11-06 05:34:47 +00:00
$output = '<svg' . (( $params ) ? $params : ' width="100%" height="480" ' ) . '>' . str_replace ([ '<br>' , '"' , ' ' ], [ '' , '"' , ' ' ], $Text ) . '</svg>' ;
2019-11-05 19:14:18 +00:00
2019-11-05 19:10:49 +00:00
$purify = new SvgSanitizer ();
$purify -> loadXML ( $output );
2019-11-06 05:34:47 +00:00
$purify -> sanitize ();
$output = $purify -> saveSVG ();
$output = preg_replace ( " / \ < \ ?xml(.*?) \ ? \ >/ " , '' , $output );
return $output ;
2019-11-05 05:45:16 +00:00
}
2020-01-15 04:02:13 +00:00
function bb_svg_export ( $match ) {
$params = str_replace ([ '<br>' , '"' ], [ '' , '"' ], $match [ 1 ]);
$Text = str_replace ([ '[' , ']' ], [ '<' , '>' ], $match [ 2 ]);
$output = '<svg' . (( $params ) ? $params : ' width="100%" height="480" ' ) . '>' . str_replace ([ '<br>' , '"' , ' ' ], [ '' , '"' , ' ' ], $Text ) . '</svg>' ;
$purify = new SvgSanitizer ();
$purify -> loadXML ( $output );
$purify -> sanitize ();
$output = $purify -> saveSVG ();
$output = preg_replace ( " / \ < \ ?xml(.*?) \ ? \ >/ " , '' , $output );
$output = '<img alt="svg" src="data:image/svg+xml,' . urlencode ( $output ) . '" >' ;
return $output ;
}
2014-10-07 00:47:17 +00:00
function bb_parse_element ( $match ) {
$j = json_decode ( base64url_decode ( $match [ 1 ]), true );
2015-05-19 19:09:35 +00:00
2015-07-11 23:36:58 +00:00
if ( $j && local_channel ()) {
2017-12-04 03:30:36 +00:00
$text = sprintf ( t ( 'Install %1$s element %2$s' ), translate_design_element ( $j [ 'type' ]), $j [ 'pagetitle' ]);
$o = EOL . '<button class="btn btn-primary" onclick="importElement(\'' . $match [ 1 ] . '\'); return false;" >' . $text . '</button>' . EOL ;
2014-10-07 00:47:17 +00:00
}
2015-07-11 23:36:58 +00:00
else {
$text = sprintf ( t ( 'This post contains an installable %s element, however you lack permissions to install it on this site.' ), translate_design_element ( $j [ 'type' ])) . $j [ 'pagetitle' ];
$o = EOL . $text . EOL ;
}
2015-04-07 20:39:42 +00:00
2014-10-07 00:47:17 +00:00
return $o ;
}
2015-05-20 06:34:40 +00:00
function translate_design_element ( $type ) {
switch ( $type ) {
case 'webpage' :
$ret = t ( 'webpage' );
break ;
case 'layout' :
$ret = t ( 'layout' );
break ;
case 'block' :
$ret = t ( 'block' );
break ;
2015-05-29 11:08:01 +00:00
case 'menu' :
$ret = t ( 'menu' );
break ;
2015-05-20 06:34:40 +00:00
}
return $ret ;
}
2018-10-25 02:01:43 +00:00
function bb_format_attachdata ( $body ) {
$data = getAttachmentData ( $body );
if ( $data ) {
$txt = '' ;
if ( $data [ 'url' ] && $data [ 'title' ]) {
$txt .= " \n \n " . '[url=' . $data [ 'url' ] . ']' . $data [ 'title' ] . '[/url]' ;
}
else {
if ( $data [ 'url' ]) {
$txt .= " \n \n " . $data [ 'url' ];
}
if ( $data [ 'title' ]) {
$txt .= " \n \n " . $data [ 'title' ];
}
}
if ( $data [ 'preview' ]) {
$txt .= " \n \n " . '[img]' . $data [ 'preview' ] . '[/img]' ;
}
2020-04-08 06:24:16 +00:00
if ( $data [ 'image' ]) {
$txt .= " \n \n " . '[img]' . $data [ 'image' ] . '[/img]' ;
}
2018-10-25 02:01:43 +00:00
$txt .= " \n \n " . $data [ 'text' ];
return preg_replace ( '/\[attachment(.*?)\](.*?)\[\/attachment\]/ism' , $txt , $body );
}
return $body ;
}
2013-11-08 04:18:52 +00:00
2018-10-17 22:51:23 +00:00
function getAttachmentData ( $body ) {
$data = [];
2018-10-25 02:01:43 +00:00
if ( ! preg_match ( " / \ [attachment(.*?) \ ](.*?) \ [ \ /attachment \ ]/ism " , $body , $match )) {
2018-10-17 22:51:23 +00:00
return null ;
}
2018-10-25 02:01:43 +00:00
$attributes = $match [ 1 ];
2018-10-17 22:51:23 +00:00
2018-10-25 02:01:43 +00:00
$data [ " text " ] = trim ( $match [ 2 ]);
2018-10-17 22:51:23 +00:00
$type = " " ;
preg_match ( " /type='(.*?)'/ism " , $attributes , $matches );
2018-10-25 02:01:43 +00:00
2018-10-17 22:51:23 +00:00
if ( x ( $matches , 1 )) {
$type = strtolower ( $matches [ 1 ]);
}
2018-10-25 02:01:43 +00:00
preg_match ( '/type=\"\;(.*?)\"\;/ism' , $attributes , $matches );
2018-10-17 22:51:23 +00:00
if ( x ( $matches , 1 )) {
$type = strtolower ( $matches [ 1 ]);
}
2021-02-08 00:13:33 +00:00
preg_match ( '/type=\\\"(.*?)\\\"/ism' , $attributes , $matches );
if ( x ( $matches , 1 )) {
$type = strtolower ( $matches [ 1 ]);
}
2018-10-17 22:51:23 +00:00
if ( $type == " " ) {
return [];
}
if ( ! in_array ( $type , [ " link " , " audio " , " photo " , " video " ])) {
return [];
}
if ( $type != " " ) {
$data [ " type " ] = $type ;
}
$url = " " ;
preg_match ( " /url='(.*?)'/ism " , $attributes , $matches );
if ( x ( $matches , 1 )) {
$url = $matches [ 1 ];
}
2018-10-25 02:01:43 +00:00
preg_match ( '/url=\"\;(.*?)\"\;/ism' , $attributes , $matches );
2018-10-17 22:51:23 +00:00
if ( x ( $matches , 1 )) {
$url = $matches [ 1 ];
}
2021-02-08 00:13:33 +00:00
preg_match ( '/url=\\\"(.*?)\\\"/ism' , $attributes , $matches );
if ( x ( $matches , 1 )) {
$url = $matches [ 1 ];
}
2018-10-17 22:51:23 +00:00
if ( $url != " " ) {
$data [ " url " ] = html_entity_decode ( $url , ENT_QUOTES , 'UTF-8' );
}
$title = " " ;
preg_match ( " /title='(.*?)'/ism " , $attributes , $matches );
if ( x ( $matches , 1 )) {
$title = $matches [ 1 ];
}
2018-10-25 02:01:43 +00:00
preg_match ( '/title=\"\;(.*?)\"\;/ism' , $attributes , $matches );
2018-10-17 22:51:23 +00:00
if ( x ( $matches , 1 )) {
$title = $matches [ 1 ];
}
2021-02-08 00:13:33 +00:00
preg_match ( '/title=\\\"(.*?)\\\"/ism' , $attributes , $matches );
if ( x ( $matches , 1 )) {
$title = $matches [ 1 ];
}
2018-10-17 22:51:23 +00:00
if ( $title != " " ) {
$title = html_entity_decode ( $title , ENT_QUOTES , 'UTF-8' );
$title = str_replace ([ " [ " , " ] " ], [ " [ " , " ] " ], $title );
$data [ " title " ] = $title ;
}
$image = " " ;
preg_match ( " /image='(.*?)'/ism " , $attributes , $matches );
if ( x ( $matches , 1 )) {
$image = $matches [ 1 ];
}
2018-10-25 02:01:43 +00:00
preg_match ( '/image=\"\;(.*?)\"\;/ism' , $attributes , $matches );
2018-10-17 22:51:23 +00:00
if ( x ( $matches , 1 )) {
$image = $matches [ 1 ];
}
2021-02-08 00:13:33 +00:00
preg_match ( '/image=\\\"(.*?)\\\"/ism' , $attributes , $matches );
if ( x ( $matches , 1 )) {
$image = $matches [ 1 ];
}
2018-10-17 22:51:23 +00:00
if ( $image != " " ) {
$data [ " image " ] = html_entity_decode ( $image , ENT_QUOTES , 'UTF-8' );
}
$preview = " " ;
preg_match ( " /preview='(.*?)'/ism " , $attributes , $matches );
if ( x ( $matches , 1 )) {
$preview = $matches [ 1 ];
}
2018-10-25 02:01:43 +00:00
preg_match ( '/preview=\"\;(.*?)\"\;/ism' , $attributes , $matches );
2018-10-17 22:51:23 +00:00
if ( x ( $matches , 1 )) {
$preview = $matches [ 1 ];
}
2021-02-08 00:13:33 +00:00
preg_match ( '/preview=\\\"(.*?)\\\"/ism' , $attributes , $matches );
if ( x ( $matches , 1 )) {
$preview = $matches [ 1 ];
}
2018-10-17 22:51:23 +00:00
if ( $preview != " " ) {
$data [ " preview " ] = html_entity_decode ( $preview , ENT_QUOTES , 'UTF-8' );
}
$data [ " description " ] = trim ( $match [ 3 ]);
$data [ " after " ] = trim ( $match [ 4 ]);
return $data ;
}
2013-02-26 03:06:31 +00:00
function bb_ShareAttributes ( $match ) {
2015-04-07 20:39:42 +00:00
$matches = array ();
2013-03-12 04:29:43 +00:00
$attributes = $match [ 1 ];
2013-02-26 03:06:31 +00:00
2013-03-12 04:29:43 +00:00
$author = " " ;
preg_match ( " /author='(.*?)'/ism " , $attributes , $matches );
if ( $matches [ 1 ] != " " )
2013-09-06 12:25:10 +00:00
$author = urldecode ( $matches [ 1 ]);
2013-02-26 03:06:31 +00:00
2013-03-12 04:29:43 +00:00
$link = " " ;
preg_match ( " /link='(.*?)'/ism " , $attributes , $matches );
if ( $matches [ 1 ] != " " )
$link = $matches [ 1 ];
2013-02-26 03:06:31 +00:00
2013-03-12 04:29:43 +00:00
$avatar = " " ;
preg_match ( " /avatar='(.*?)'/ism " , $attributes , $matches );
if ( $matches [ 1 ] != " " )
$avatar = $matches [ 1 ];
2013-02-26 03:06:31 +00:00
2013-03-12 04:29:43 +00:00
$profile = " " ;
preg_match ( " /profile='(.*?)'/ism " , $attributes , $matches );
if ( $matches [ 1 ] != " " )
$profile = $matches [ 1 ];
2013-02-26 03:06:31 +00:00
2013-03-12 04:29:43 +00:00
$posted = " " ;
preg_match ( " /posted='(.*?)'/ism " , $attributes , $matches );
if ( $matches [ 1 ] != " " )
$posted = $matches [ 1 ];
2013-02-26 03:06:31 +00:00
2018-03-16 00:51:24 +00:00
$auth = " " ;
preg_match ( " /auth='(.*?)'/ism " , $attributes , $matches );
if ( $matches [ 1 ] != " " ) {
if ( $matches [ 1 ] === 'true' )
$auth = true ;
else
$auth = false ;
}
if ( $auth === EMPTY_STR ) {
$auth = is_matrix_url ( $profile );
}
2015-04-07 20:39:42 +00:00
// message_id is never used, do we still need it?
2014-05-05 23:16:32 +00:00
$message_id = " " ;
preg_match ( " /message_id='(.*?)'/ism " , $attributes , $matches );
if ( $matches [ 1 ] != " " )
$message_id = $matches [ 1 ];
2016-06-14 02:58:24 +00:00
if ( ! $message_id ) {
preg_match ( " /guid='(.*?)'/ism " , $attributes , $matches );
if ( $matches [ 1 ] != " " )
$message_id = $matches [ 1 ];
}
2016-04-11 04:30:35 +00:00
$reldate = '<span class="autotime" title="' . datetime_convert ( 'UTC' , date_default_timezone_get (), $posted , 'c' ) . '" >' . datetime_convert ( 'UTC' , date_default_timezone_get (), $posted , 'r' ) . '</span>' ;
2013-02-26 03:06:31 +00:00
2013-10-02 04:03:09 +00:00
$headline = '<div class="shared_container"> <div class="shared_header">' ;
2013-02-26 03:06:31 +00:00
2013-03-12 04:29:43 +00:00
if ( $avatar != " " )
2019-10-12 20:09:18 +00:00
$headline .= '<a href="' . (( $auth ) ? zid ( $profile ) : $profile ) . '" ><img src="' . $avatar . '" alt="' . htmlspecialchars ( $author , ENT_COMPAT , 'UTF-8' , false ) . '" height="32" width="32" /></a>' ;
2013-02-26 03:06:31 +00:00
2017-09-05 04:02:44 +00:00
if ( strpos ( $link , '/cards/' ))
$type = t ( 'card' );
2017-11-22 23:39:06 +00:00
elseif ( strpos ( $link , '/articles/' ))
$type = t ( 'article' );
2017-09-05 04:02:44 +00:00
else
$type = t ( 'post' );
2013-03-12 04:29:43 +00:00
// Bob Smith wrote the following post 2 hours ago
2013-02-26 03:06:31 +00:00
2013-03-12 04:29:43 +00:00
$fmt = sprintf ( t ( '%1$s wrote the following %2$s %3$s' ),
2020-02-12 23:21:39 +00:00
'<a href="' . (( $auth ) ? zid ( $profile ) : $profile ) . '" ><bdi>' . $author . '</bdi></a>' ,
2018-03-16 00:51:24 +00:00
'<a href="' . (( $auth ) ? zid ( $link ) : $link ) . '" >' . $type . '</a>' ,
2013-03-12 04:29:43 +00:00
$reldate
);
2013-03-12 01:22:40 +00:00
2013-03-12 04:29:43 +00:00
$headline .= '<span>' . $fmt . '</span></div>' ;
2013-10-02 04:03:09 +00:00
$text = $headline . '<div class="reshared-content">' . trim ( $match [ 2 ]) . '</div></div>' ;
2013-03-12 04:29:43 +00:00
2015-04-07 20:39:42 +00:00
return $text ;
2013-02-26 03:06:31 +00:00
}
2014-01-23 23:43:35 +00:00
function bb_location ( $match ) {
// not yet implemented
}
2015-04-07 20:39:42 +00:00
/**
* @ brief Returns an iframe from $match [ 1 ] .
*
* @ param array $match
* @ return string HTML iframe with content of $match [ 1 ]
*/
function bb_iframe ( $match ) {
2014-03-17 03:34:21 +00:00
2016-03-31 23:06:03 +00:00
$sandbox = (( strpos ( $match [ 1 ], App :: get_hostname ())) ? ' sandbox="allow-scripts" ' : '' );
2014-03-31 22:56:58 +00:00
2016-03-31 23:06:03 +00:00
return '<iframe ' . $sandbox . ' src="' . $match [ 1 ] . '" width="' . App :: $videowidth . '" height="' . App :: $videoheight . '"><a href="' . $match [ 1 ] . '">' . $match [ 1 ] . '</a></iframe>' ;
2014-02-21 05:15:35 +00:00
}
2013-02-26 03:06:31 +00:00
function bb_ShareAttributesSimple ( $match ) {
2015-04-07 20:39:42 +00:00
$matches = array ();
2013-03-12 04:29:43 +00:00
$attributes = $match [ 1 ];
2013-02-26 03:06:31 +00:00
2013-03-12 04:29:43 +00:00
$author = " " ;
preg_match ( " /author='(.*?)'/ism " , $attributes , $matches );
if ( $matches [ 1 ] != " " )
$author = html_entity_decode ( $matches [ 1 ], ENT_QUOTES , 'UTF-8' );
2013-02-26 03:06:31 +00:00
2013-03-12 04:29:43 +00:00
preg_match ( '/author="(.*?)"/ism' , $attributes , $matches );
if ( $matches [ 1 ] != " " )
$author = $matches [ 1 ];
2013-02-26 03:06:31 +00:00
2013-03-12 04:29:43 +00:00
$profile = " " ;
preg_match ( " /profile='(.*?)'/ism " , $attributes , $matches );
if ( $matches [ 1 ] != " " )
$profile = $matches [ 1 ];
2013-02-26 03:06:31 +00:00
2013-03-12 04:29:43 +00:00
preg_match ( '/profile="(.*?)"/ism' , $attributes , $matches );
if ( $matches [ 1 ] != " " )
$profile = $matches [ 1 ];
2013-02-26 03:06:31 +00:00
2018-03-15 13:31:50 +00:00
$text = html_entity_decode ( " ♲ " , ENT_QUOTES , 'UTF-8' ) . ' <a href="' . $profile . '">' . $author . '</a>: <div class="reshared-content">' . $match [ 2 ] . '</div>' ;
2013-02-26 03:06:31 +00:00
2013-03-12 04:29:43 +00:00
return ( $text );
2013-02-26 03:06:31 +00:00
}
2012-07-07 22:20:24 +00:00
2013-10-30 01:46:51 +00:00
function rpost_callback ( $match ) {
2013-10-30 23:08:32 +00:00
if ( $match [ 2 ]) {
2019-05-08 04:50:02 +00:00
return str_replace ( $match [ 0 ], Libzot :: get_rpost_path ( App :: get_observer ()) . '&title=' . urlencode ( $match [ 2 ]) . '&body=' . urlencode ( $match [ 3 ]), $match [ 0 ]);
2013-10-30 21:29:25 +00:00
} else {
2019-05-08 04:50:02 +00:00
return str_replace ( $match [ 0 ], Libzot :: get_rpost_path ( App :: get_observer ()) . '&body=' . urlencode ( $match [ 3 ]), $match [ 0 ]);
2013-10-30 21:29:25 +00:00
}
2013-10-30 01:46:51 +00:00
}
2014-12-17 22:12:19 +00:00
function bb_map_coords ( $match ) {
// the extra space in the following line is intentional
return str_replace ( $match [ 0 ], '<div class="map" >' . generate_map ( str_replace ( '/' , ' ' , $match [ 1 ])) . '</div>' , $match [ 0 ]);
}
function bb_map_location ( $match ) {
// the extra space in the following line is intentional
return str_replace ( $match [ 0 ], '<div class="map" >' . generate_named_map ( $match [ 1 ]) . '</div>' , $match [ 0 ]);
}
2015-04-07 20:39:42 +00:00
function bb_opentag ( $match ) {
2016-04-26 09:41:08 +00:00
$openclose = (( $match [ 2 ]) ? '<span class="bb-open" title="' . t ( 'Click to open/close' ) . '">' . $match [ 1 ] . '</span>' : t ( 'Click to open/close' ));
$text = (( $match [ 2 ]) ? $match [ 2 ] : $match [ 1 ]);
2015-04-07 20:39:42 +00:00
$rnd = mt_rand ();
2016-04-26 09:41:08 +00:00
return '<div onclick="openClose(\'opendiv-' . $rnd . '\'); return false;" class="fakelink">' . $openclose . '</div><div id="opendiv-' . $rnd . '" style="display: none;">' . $text . '</div>' ;
}
function bb_spoilertag ( $match ) {
$openclose = (( $match [ 2 ]) ? '<span class="bb-spoiler" title="' . t ( 'Click to open/close' ) . '">' . $match [ 1 ] . ' ' . t ( 'spoiler' ) . '</span>' : t ( 'Click to open/close' ));
$text = (( $match [ 2 ]) ? $match [ 2 ] : $match [ 1 ]);
$rnd = mt_rand ();
return '<div onclick="openClose(\'opendiv-' . $rnd . '\'); return false;" class="fakelink">' . $openclose . '</div><blockquote id="opendiv-' . $rnd . '" style="display: none;">' . $text . '</blockquote>' ;
2015-04-07 04:26:40 +00:00
}
2018-01-16 04:47:32 +00:00
function bb_summary ( $match ) {
$rnd1 = mt_rand ();
$rnd2 = mt_rand ();
$rnd3 = mt_rand ();
$rnd4 = mt_rand ();
2018-11-12 01:44:01 +00:00
return $match [ 1 ] . $match [ 2 ] . EOL . EOL . $match [ 3 ];
// return $match[1] . '<div style="display: block;" id="opendiv-' . $rnd2 . '">' . $match[2] . '</div><div style="display: block;" id="opendiv-' . $rnd3 . '" onclick="openClose(\'opendiv-' . $rnd1 . '\'); openClose(\'opendiv-' . $rnd2 . '\'); openClose(\'opendiv-' . $rnd3 . '\'); openClose(\'opendiv-' . $rnd4 . '\'); return false;" class="fakelink view-article">' . t('View article') . '</div><div style="display: none;" id="opendiv-' . $rnd4 . '" onclick="openClose(\'opendiv-' . $rnd1 . '\'); openClose(\'opendiv-' . $rnd2 . '\'); openClose(\'opendiv-' . $rnd3 . '\'); openClose(\'opendiv-' . $rnd4 . '\'); return false;" class="fakelink view-summary">' . t('View summary') . '</div><div id="opendiv-' . $rnd1 . '" style="display: none;">' . $match[3] . '</div>';
2018-01-16 04:47:32 +00:00
}
2016-04-28 13:48:50 +00:00
function bb_definitionList ( $match ) {
// $match[1] is the markup styles for the "terms" in the definition list.
// $match[2] is the content between the [dl]...[/dl] tags
$classes = '' ;
if ( stripos ( $match [ 1 ], " b " ) !== false ) $classes .= 'dl-terms-bold ' ;
if ( stripos ( $match [ 1 ], " i " ) !== false ) $classes .= 'dl-terms-italic ' ;
if ( stripos ( $match [ 1 ], " u " ) !== false ) $classes .= 'dl-terms-underline ' ;
if ( stripos ( $match [ 1 ], " l " ) !== false ) $classes .= 'dl-terms-large ' ;
if ( stripos ( $match [ 1 ], " m " ) !== false ) $classes .= 'dl-terms-monospace ' ;
if ( stripos ( $match [ 1 ], " h " ) !== false ) $classes .= 'dl-horizontal ' ; // dl-horizontal is already provided by bootstrap
if ( strlen ( $classes ) === 0 ) $classes = " dl-terms-plain " ;
// The bbcode transformation will be:
// [*=term-text] description-text => </dd> <dt>term-text<dt><dd> description-text
2016-04-29 16:03:38 +00:00
// then after all replacements have been made, the extra </dd> at the start of the
// first line can be removed. HTML5 allows the tag to be missing from the end of the last line.
2016-04-28 13:48:50 +00:00
// Using '(?<!\\\)' to allow backslash-escaped closing braces to appear in the term-text.
$closeDescriptionTag = " </dd> \n " ;
2016-04-29 16:03:38 +00:00
$eatLeadingSpaces = '(?: |[ \t])*' ; // prevent spaces infront of [*= from adding another line to the previous element
2019-11-22 01:34:49 +00:00
$listElements = preg_replace ( '/^(\n|<br>)/' , '' , $match [ 2 ]); // ltrim the first newline
2016-04-28 13:48:50 +00:00
$listElements = preg_replace (
2017-05-15 04:04:34 +00:00
'/' . $eatLeadingSpaces . '\[\*=([[:print:]]*?)(?<!\\\)\]/uism' ,
2016-04-28 13:48:50 +00:00
$closeDescriptionTag . '<dt>$1</dt><dd>' ,
2016-04-29 16:03:38 +00:00
$listElements
2016-04-28 13:48:50 +00:00
);
// Unescape any \] inside the <dt> tags
$listElements = preg_replace_callback ( '/<dt>(.*?)<\/dt>/ism' , 'bb_definitionList_unescapeBraces' , $listElements );
// Remove the extra </dd> at the start of the string, if there is one.
$firstOpenTag = strpos ( $listElements , '<dd>' );
$firstCloseTag = strpos ( $listElements , $closeDescriptionTag );
if ( $firstCloseTag !== false && ( $firstOpenTag === false || ( $firstCloseTag < $firstOpenTag ))) {
$listElements = preg_replace ( '/<\/dd>/ism' , '' , $listElements , 1 );
}
return '<dl class="bb-dl ' . rtrim ( $classes ) . '">' . $listElements . '</dl>' ;;
}
function bb_definitionList_unescapeBraces ( $match ) {
return '<dt>' . str_replace ( '\]' , ']' , $match [ 1 ]) . '</dt>' ;
}
2016-11-16 19:49:58 +00:00
function bb_checklist ( $match ) {
$str = $match [ 1 ];
$str = str_replace ( " [] " , " <li><input type= \" checkbox \" disabled= \" disabled \" > " , $str );
$str = str_replace ( " [x] " , " <li><input type= \" checkbox \" checked= \" checked \" disabled= \" disabled \" > " , $str );
return '<ul class="checklist" style="list-style-type: none;">' . $str . '</ul>' ;
}
2015-04-07 20:39:42 +00:00
/**
* @ brief Sanitize style properties from BBCode to HTML .
*
2020-12-02 05:37:58 +00:00
* @ param array | string $input
2015-04-07 20:39:42 +00:00
* @ return string A HTML span tag with the styles .
*/
2020-12-02 05:37:58 +00:00
function bb_sanitize_style ( $input ) {
2015-04-07 20:39:42 +00:00
// whitelist array: property => limits (0 = no limitation)
$w = array (
// color properties
2018-10-17 22:51:23 +00:00
" color " => 0 ,
2015-04-07 20:39:42 +00:00
" background-color " => 0 ,
2014-02-05 13:34:25 +00:00
// box properties
2015-04-07 20:39:42 +00:00
" padding " => array ( " px " => 100 , " % " => 0 , " em " => 2 , " ex " => 2 , " mm " => 0 , " cm " => 0 , " in " => 0 , " pt " => 0 , " pc " => 0 ),
" margin " => array ( " px " => 100 , " % " => 0 , " em " => 2 , " ex " => 2 , " mm " => 0 , " cm " => 0 , " in " => 0 , " pt " => 0 , " pc " => 0 ),
" border " => array ( " px " => 100 , " % " => 0 , " em " => 2 , " ex " => 2 , " mm " => 0 , " cm " => 0 , " in " => 0 , " pt " => 0 , " pc " => 0 ),
" float " => 0 ,
" clear " => 0 ,
2014-02-05 13:34:25 +00:00
// text properties
2015-04-07 20:39:42 +00:00
" text-decoration " => 0 ,
2014-02-05 13:34:25 +00:00
);
2020-12-02 05:37:58 +00:00
// determine if input is string or array
$input_is_array = is_array ( $input );
2015-04-07 20:39:42 +00:00
$css = array ();
2020-12-02 05:39:21 +00:00
$css_string = (( $input_is_array ) ? $input [ 1 ] : $input );
2015-04-07 20:39:42 +00:00
$a = explode ( ';' , $css_string );
2014-02-05 13:34:25 +00:00
foreach ( $a as $parts ){
list ( $k , $v ) = explode ( ':' , $parts );
2015-04-07 20:39:42 +00:00
$css [ trim ( $k ) ] = trim ( $v );
2014-02-05 13:34:25 +00:00
}
// sanitize properties
$b = array_merge ( array_diff_key ( $css , $w ), array_diff_key ( $w , $css ));
$css = array_diff_key ( $css , $b );
2015-04-07 20:39:42 +00:00
$css_string_san = '' ;
2014-02-05 13:34:25 +00:00
2015-04-07 20:39:42 +00:00
foreach ( $css as $key => $value ) {
if ( $w [ $key ] != null ) {
foreach ( $w [ $key ] as $limit_key => $limit_value ) {
2014-02-05 13:34:25 +00:00
//sanitize values
2015-04-07 20:39:42 +00:00
if ( strpos ( $value , $limit_key )) {
2014-02-05 13:34:25 +00:00
$value = preg_replace_callback (
" /( \ S.*?) $limit_key /ism " ,
function ( $match ) use ( $limit_value , $limit_key ) {
2015-04-07 20:39:42 +00:00
if ( $match [ 1 ] > $limit_value ) {
2014-02-05 13:34:25 +00:00
return $limit_value . $limit_key ;
} else {
2015-04-07 20:39:42 +00:00
return $match [ 1 ] . $limit_key ;
2014-02-05 13:34:25 +00:00
}
},
$value
);
}
}
}
$css_string_san .= $key . " : " . $value . " ; " ;
}
2015-04-07 20:39:42 +00:00
2020-12-02 05:37:58 +00:00
if ( $input_is_array ) {
return '<span style="' . $css_string_san . '">' . $input [ 2 ] . '</span>' ;
2020-12-01 03:48:59 +00:00
}
2020-12-02 05:37:58 +00:00
return $css_string_san ;
2014-02-05 13:34:25 +00:00
}
2013-10-30 01:46:51 +00:00
2017-01-20 21:36:37 +00:00
function oblanguage_callback ( $matches ) {
if ( strlen ( $matches [ 1 ]) == 2 ) {
$compare = strtolower ( substr ( \App :: $language , 0 , 2 ));
}
else {
$compare = strtolower ( \App :: $language );
}
if ( $compare === strtolower ( $matches [ 1 ]))
return $matches [ 2 ];
return '' ;
}
2017-01-20 23:30:08 +00:00
function oblanguage_necallback ( $matches ) {
if ( strlen ( $matches [ 1 ]) == 2 ) {
$compare = strtolower ( substr ( \App :: $language , 0 , 2 ));
}
else {
$compare = strtolower ( \App :: $language );
}
if ( $compare !== strtolower ( $matches [ 1 ]))
return $matches [ 2 ];
return '' ;
}
2015-05-07 04:43:15 +00:00
function bb_observer ( $Text ) {
2016-03-31 23:06:03 +00:00
$observer = App :: get_observer ();
2015-05-07 04:43:15 +00:00
if (( strpos ( $Text , '[/observer]' ) !== false ) || ( strpos ( $Text , '[/rpost]' ) !== false )) {
2017-01-20 21:36:37 +00:00
2015-05-07 04:43:15 +00:00
if ( $observer ) {
$Text = preg_replace ( " / \ [observer \ =1 \ ](.*?) \ [ \ /observer \ ]/ism " , '$1' , $Text );
$Text = preg_replace ( " / \ [observer \ =0 \ ].*? \ [ \ /observer \ ]/ism " , '' , $Text );
$Text = preg_replace_callback ( " / \ [rpost(=(.*?))? \ ](.*?) \ [ \ /rpost \ ]/ism " , 'rpost_callback' , $Text );
} else {
$Text = preg_replace ( " / \ [observer \ =1 \ ].*? \ [ \ /observer \ ]/ism " , '' , $Text );
$Text = preg_replace ( " / \ [observer \ =0 \ ](.*?) \ [ \ /observer \ ]/ism " , '$1' , $Text );
$Text = preg_replace ( " / \ [rpost(=.*?)? \ ](.*?) \ [ \ /rpost \ ]/ism " , '' , $Text );
}
}
2016-03-31 23:06:03 +00:00
$channel = App :: get_channel ();
2015-05-07 04:43:15 +00:00
if ( strpos ( $Text , '[/channel]' ) !== false ) {
if ( $channel ) {
$Text = preg_replace ( " / \ [channel \ =1 \ ](.*?) \ [ \ /channel \ ]/ism " , '$1' , $Text );
$Text = preg_replace ( " / \ [channel \ =0 \ ].*? \ [ \ /channel \ ]/ism " , '' , $Text );
} else {
$Text = preg_replace ( " / \ [channel \ =1 \ ].*? \ [ \ /channel \ ]/ism " , '' , $Text );
$Text = preg_replace ( " / \ [channel \ =0 \ ](.*?) \ [ \ /channel \ ]/ism " , '$1' , $Text );
}
}
return $Text ;
}
2020-02-27 03:10:43 +00:00
function bb_imgoptions ( $match ) {
// $Text = preg_replace_callback("/\[([zi])mg([ \=])(.*?)\](.*?)\[\/[zi]mg\]/ism",'bb_imgoptions',$Text);
// alt text cannot contain ']'
// [img|zmg=wwwxhhh float=left|right alt=alt text]url[/img|zmg]
2020-03-02 19:54:29 +00:00
// [img|zmg width="nnn" height="nnn" alt="xyz" style="float: abc;"]url[/img|zmg]
2020-02-27 03:10:43 +00:00
$local_match = null ;
$width = 0 ;
$float = false ;
$alt = false ;
$style = EMPTY_STR ;
2020-02-29 21:03:28 +00:00
$attributes = $match [ 3 ];
$x = preg_match ( " /alt='(.*?)'/ism " , $attributes , $matches );
if ( $x ) {
$alt = $matches [ 1 ];
}
$x = preg_match ( " /alt= \ " \ ;(.*?) \ " \ ;/ism " , $attributes , $matches );
if ( $x ) {
$alt = $matches [ 1 ];
}
2021-02-08 00:13:33 +00:00
$x = preg_match ( " /alt= \\ \" (.*?) \\ \" /ism " , $attributes , $matches );
if ( $x ) {
$alt = $matches [ 1 ];
}
2020-03-02 19:54:29 +00:00
$x = preg_match ( " /width=([0-9]*)/ism " , $attributes , $matches );
if ( $x ) {
2020-12-01 03:48:59 +00:00
$width = bb_xss ( $matches [ 1 ]);
2020-03-02 19:54:29 +00:00
}
2020-02-29 21:03:28 +00:00
$x = preg_match ( " /width='(.*?)'/ism " , $attributes , $matches );
if ( $x ) {
2020-12-01 03:48:59 +00:00
$width = bb_xss ( $matches [ 1 ]);
2020-02-29 21:03:28 +00:00
}
$x = preg_match ( " /width= \ " \ ;(.*?) \ " \ ;/ism " , $attributes , $matches );
if ( $x ) {
2020-12-01 03:48:59 +00:00
$width = bb_xss ( $matches [ 1 ]);
2020-02-29 21:03:28 +00:00
}
2021-02-08 00:13:33 +00:00
$x = preg_match ( " /width= \\ \" (.*?) \\ \" /ism " , $attributes , $matches );
if ( $x ) {
$width = bb_xss ( $matches [ 1 ]);
}
2020-03-02 19:54:29 +00:00
$x = preg_match ( " /height=([0-9]*)/ism " , $attributes , $matches );
if ( $x ) {
2020-12-01 03:48:59 +00:00
$height = bb_xss ( $matches [ 1 ]);
2020-03-02 19:54:29 +00:00
}
2020-02-29 21:03:28 +00:00
$x = preg_match ( " /height='(.*?)'/ism " , $attributes , $matches );
if ( $x ) {
2020-12-01 03:48:59 +00:00
$height = bb_xss ( $matches [ 1 ]);
2020-02-29 21:03:28 +00:00
}
$x = preg_match ( " /height= \ " \ ;(.*?) \ " \ ;/ism " , $attributes , $matches );
if ( $x ) {
2020-12-01 03:48:59 +00:00
$height = bb_xss ( $matches [ 1 ]);
2020-02-29 21:03:28 +00:00
}
2021-02-08 00:13:33 +00:00
$x = preg_match ( " /height= \\ \" (.*?) \\ \" /ism " , $attributes , $matches );
if ( $x ) {
$height = bb_xss ( $matches [ 1 ]);
}
2020-02-29 21:03:28 +00:00
$x = preg_match ( " /style='(.*?)'/ism " , $attributes , $matches );
if ( $x ) {
2020-12-02 05:37:58 +00:00
$style = bb_sanitize_style ( $matches [ 1 ]);
2020-02-29 21:03:28 +00:00
}
$x = preg_match ( " /style= \ " \ ;(.*?) \ " \ ;/ism " , $attributes , $matches );
if ( $x ) {
2020-12-02 05:37:58 +00:00
$style = bb_sanitize_style ( $matches [ 1 ]);
2021-02-08 00:13:33 +00:00
}
$x = preg_match ( " /style= \\ \" (.*?) \\ \" /ism " , $attributes , $matches );
if ( $x ) {
$style = bb_sanitize_style ( $matches [ 1 ]);
2020-02-29 21:03:28 +00:00
}
// legacy img options
2020-02-27 03:10:43 +00:00
if ( $match [ 2 ] === '=' ) {
2020-02-29 21:03:28 +00:00
// pull out (optional) legacy size declarations first
2020-02-27 03:10:43 +00:00
if ( preg_match ( " /([0-9]*)x([0-9]*)/ism " , $match [ 3 ], $local_match )) {
$width = intval ( $local_match [ 1 ]);
}
$match [ 3 ] = substr ( $match [ 3 ], strpos ( $match [ 3 ], ' ' ));
}
2020-02-29 21:03:28 +00:00
// then (optional) legacy float specifiers
2020-02-27 03:10:43 +00:00
if ( $n = strpos ( $match [ 3 ], 'float=left' ) !== false ) {
$float = 'left' ;
$match [ 3 ] = substr ( $match [ 3 ], $n + 10 );
}
if ( $n = strpos ( $match [ 3 ], 'float=right' ) !== false ) {
$float = 'right' ;
$match [ 3 ] = substr ( $match [ 3 ], $n + 11 );
}
2020-02-29 21:03:28 +00:00
2020-02-27 03:10:43 +00:00
// finally alt text which extends to the close of the tag
2020-02-29 21:03:28 +00:00
if (( ! $alt ) && ( $n = strpos ( $match [ 3 ], 'alt=' ) !== false )) {
2020-02-27 03:10:43 +00:00
$alt = substr ( $match [ 3 ], $n + 4 );
}
// now assemble the resulting img tag from these components
$output = '<img ' . (( $match [ 1 ] === 'z' ) ? 'class="zrl" ' : '' ) . ' ' ;
if ( $width ) {
$style .= 'width: 100%; max-width: ' . $width . 'px; ' ;
}
else {
$style .= 'max-width: 100%; ' ;
}
if ( $float ) {
$style .= 'float: ' . $float . '; ' ;
}
$output .= (( $style ) ? 'style="' . $style . '" ' : '' ) . 'alt="' . htmlentities (( $alt ) ? $alt : t ( 'Image/photo' ), ENT_COMPAT , 'UTF-8' ) . '" ' ;
$output .= 'src="' . $match [ 4 ] . '" >' ;
return $output ;
}
2021-02-11 01:55:10 +00:00
function multicode_purify ( $s ) {
$s = preg_replace_callback ( " / \ [code(.*?) \ ](.*?) \ [ \ /code \ ]/ism " , function ( $match ) {
return '[code' . $match [ 1 ] . ']' . bb_code_protect ( $match [ 2 ]) . '[/code]' ;
}, $s );
$s = preg_replace_callback ( '#(^|\n)([`~]{3,})(?: *\.?([a-zA-Z0-9\-.]+))?\n+([\s\S]+?)\n+\2(\n|$)#' , function ( $match ) {
return $match [ 1 ] . $match [ 2 ] . " \n " . bb_code_protect ( $match [ 4 ]) . " \n " . $match [ 2 ] . (( $match [ 5 ]) ? $match [ 5 ] : " \n " );
}, $s );
$s = purify_html ( $s , [ 'escape' ]);
return bb_code_unprotect ( $s );
}
2020-11-01 00:10:22 +00:00
function bb_code_preprotect ( $matches ) {
2021-02-02 22:49:11 +00:00
return '[code' . $matches [ 1 ] . ']' . 'b64.^8e%.' . base64_encode ( str_replace ( '<br>' , '|+br+|' , $matches [ 2 ])) . '.b64.$8e%' . '[/code]' ;
2020-11-01 00:10:22 +00:00
}
function bb_code_preunprotect ( $s ) {
return preg_replace_callback ( '|b64\.\^8e\%\.(.*?)\.b64\.\$8e\%|ism' , 'bb_code_unprotect_sub' , $s );
}
2018-01-26 00:16:55 +00:00
function bb_code_protect ( $s ) {
2021-02-02 22:49:11 +00:00
return 'b64.^9e%.' . base64_encode ( str_replace ( '<br>' , '|+br+|' , $s )) . '.b64.$9e%' ;
2018-01-26 00:16:55 +00:00
}
function bb_code_unprotect ( $s ) {
return preg_replace_callback ( '|b64\.\^9e\%\.(.*?)\.b64\.\$9e\%|ism' , 'bb_code_unprotect_sub' , $s );
}
function bb_code_unprotect_sub ( $match ) {
2021-02-02 22:49:11 +00:00
$x = str_replace ( [ '<' , '>' ], [ '<' , '>' ], base64_decode ( $match [ 1 ]));
return str_replace ( '|+br+|' , '<br>' , $x );
2018-01-26 00:16:55 +00:00
}
2019-09-23 23:11:36 +00:00
function bb_colorbox ( $match ) {
if ( strpos ( $match [ 1 ], 'zrl' )) {
$url = zid ( $match [ 2 ]);
}
else {
$url = $match [ 2 ];
}
return '<a href="' . $url . '" target="censored"><img src="' . $url . '" alt="censored" style="opacity: 0.03;"></a>' ;
}
2016-05-30 14:12:48 +00:00
function bb_code ( $match ) {
2019-11-22 01:34:49 +00:00
if ( strpos ( $match [ 0 ], " <br> " ))
2018-02-18 15:09:05 +00:00
return '<pre><code>' . bb_code_protect ( trim ( $match [ 1 ])) . '</code></pre>' ;
2016-05-30 14:12:48 +00:00
else
2018-01-26 00:16:55 +00:00
return '<code class="inline-code">' . bb_code_protect ( trim ( $match [ 1 ])) . '</code>' ;
2016-05-30 14:12:48 +00:00
}
2015-05-07 04:43:15 +00:00
2016-12-28 19:58:25 +00:00
function bb_code_options ( $match ) {
2019-11-22 01:34:49 +00:00
if ( strpos ( $match [ 0 ], " <br> " )) {
2016-12-28 19:58:25 +00:00
$class = " " ;
2018-02-18 15:09:05 +00:00
$pre = true ;
2016-12-28 19:58:25 +00:00
} else {
$class = " inline-code " ;
2018-02-18 15:09:05 +00:00
$pre = false ;
2016-12-28 19:58:25 +00:00
}
if ( strpos ( $match [ 1 ], 'nowrap' )) {
$style = " overflow-x: auto; white-space: pre; " ;
} else {
$style = " " ;
}
2018-02-18 15:09:05 +00:00
if ( $pre ) {
return '<pre><code class="' . $class . '" style="' . $style . '">' . bb_code_protect ( trim ( $match [ 2 ])) . '</code></pre>' ;
} else {
return '<code class="' . $class . '" style="' . $style . '">' . bb_code_protect ( trim ( $match [ 2 ])) . '</code>' ;
}
2016-12-28 19:58:25 +00:00
}
2020-10-16 00:48:36 +00:00
function md_header ( $content ) {
$headingLevel = \strlen ( $content [ 1 ]);
$header = trim ( $content [ 2 ]);
// Build anker without space, numbers.
$anker = preg_replace ( '#[^a-z?!]#' , '' , strtolower ( $header ));
return sprintf ( '<h%d id="%s">%s</h%d>' , $headingLevel , $anker , $header , $headingLevel );
}
function md_codeblock ( $content ) {
$language = ! empty ( $content [ 3 ]) ? filter_var ( $content [ 3 ], FILTER_SANITIZE_STRING ) : '' ;
$class = ! empty ( $language ) ? sprintf ( ' class="%s language-%s"' , $language , $language ) : '' ;
2021-02-11 01:55:10 +00:00
// Build one block so that we not render each paragraph separately.
2020-10-16 00:48:36 +00:00
$content = str_replace ( " \n " , '<br>' , $content [ 4 ]);
2020-10-22 02:21:33 +00:00
return sprintf ( '<pre><code%s>%s</code></pre>' , $class , bb_code_protect ( $content ));
2020-10-16 00:48:36 +00:00
}
2020-10-16 05:46:48 +00:00
function md_italic ( $content ) {
2020-10-17 03:40:27 +00:00
return '<em>' . $content [ 1 ] . $content [ 3 ] . '</em>' ;
2020-10-16 05:46:48 +00:00
}
2020-10-16 00:48:36 +00:00
function md_image ( $content ) {
$url = filter_var ( $content [ 1 ], FILTER_SANITIZE_URL );
$alt = '' ;
if ( isset ( $content [ 2 ])) {
$content [ 2 ] = str_replace ( '"' , '' , $content [ 2 ]);
$alt = ' alt="' . filter_var ( $content [ 2 ], FILTER_SANITIZE_STRING ) . '"' ;
}
return sprintf ( '<img src="%s"%s>' , $url , $alt );
}
function md_topheader ( $matches ) {
// Terrible hack to check we haven't found an empty list item.
if ( $matches [ 2 ] == '-' && preg_match ( '{^-(?: |$)}' , $matches [ 1 ])) {
return $matches [ 0 ];
}
$level = $matches [ 2 ][ 0 ] == '=' ? 1 : 2 ;
return " <h $level > " . $matches [ 1 ] . " </h $level > " . " \n " ;
}
2015-05-07 04:43:15 +00:00
2016-06-27 03:15:42 +00:00
function bb_fixtable_lf ( $match ) {
// remove extraneous whitespace between table element tags since newlines will all
2019-11-22 01:34:49 +00:00
// be converted to '<br>' and turn your neatly crafted tables into a whole lot of
2016-06-27 03:15:42 +00:00
// empty space.
$x = preg_replace ( " / \ ] \ s+ \ [/ " , '][' , $match [ 1 ]);
return '[table]' . $x . '[/table]' ;
}
2020-12-01 03:48:59 +00:00
function bb_colortag ( $matches ) {
return '<span style="color: ' . bb_xss ( $matches [ 1 ]) . ';">' . $matches [ 2 ] . '</span>' ;
}
function bb_fonttag ( $matches ) {
return '<span style="font-family: ' . bb_xss ( $matches [ 1 ]) . ';">' . $matches [ 2 ] . '</span>' ;
}
2020-12-01 19:07:17 +00:00
function bb_sizetag ( $matches ) {
2020-12-01 19:08:20 +00:00
return '<span style="font-size: ' . bb_xss ( $matches [ 1 ]) . ';">' . $matches [ 2 ] . '</span>' ;
2020-12-01 19:07:17 +00:00
}
2020-12-01 03:48:59 +00:00
2020-12-02 00:20:46 +00:00
function bb_hltag ( $matches ) {
return '<span style="background-color: ' . bb_xss ( $matches [ 1 ]) . ';">' . $matches [ 2 ] . '</span>' ;
}
2020-12-01 03:48:59 +00:00
function bb_xss ( $s ) {
// don't allow functions of any kind
$s = str_replace ( [ '(' , ')' ], [ '' , '' ], $s );
// don't allow injection of multiple params
if ( strpos ( $s , ';' ) !== false ) {
return substr ( $s , 0 , strpos ( $s , ';' ));
}
return $s ;
}
2018-03-03 21:52:55 +00:00
function bbtopoll ( $s ) {
$pl = [];
$match = '' ;
if ( ! preg_match ( " / \ [poll=(.*?) \ ](.*?) \ [ \ /poll \ ]/ism " , $s , $match )) {
return null ;
}
$pl [ 'poll_id' ] = $match [ 1 ];
$pl [ 'poll_question' ] = $match [ 2 ];
$match = '' ;
if ( preg_match_all ( " / \ [poll \ -answer=(.*?) \ ](.*?) \ [ \ /poll \ -answer \ ]/is " , $s , $match , PREG_SET_ORDER )) {
$pl [ 'answer' ] = [];
foreach ( $match as $m ) {
$ans = [ 'answer_id' => $m [ 1 ], 'answer_text' => $m [ 2 ] ];
$pl [ 'answer' ][] = $ans ;
}
}
return $pl ;
}
2016-11-27 21:48:06 +00:00
function parseIdentityAwareHTML ( $Text ) {
2016-12-26 13:58:40 +00:00
// Hide all [noparse] contained bbtags by spacefying them
if ( strpos ( $Text , '[noparse]' ) !== false ) {
$Text = preg_replace_callback ( " / \ [noparse \ ](.*?) \ [ \ /noparse \ ]/ism " , 'bb_spacefy' , $Text );
}
if ( strpos ( $Text , '[nobb]' ) !== false ) {
$Text = preg_replace_callback ( " / \ [nobb \ ](.*?) \ [ \ /nobb \ ]/ism " , 'bb_spacefy' , $Text );
}
if ( strpos ( $Text , '[pre]' ) !== false ) {
$Text = preg_replace_callback ( " / \ [pre \ ](.*?) \ [ \ /pre \ ]/ism " , 'bb_spacefy' , $Text );
}
2016-11-27 21:48:06 +00:00
// process [observer] tags before we do anything else because we might
// be stripping away stuff that then doesn't need to be worked on anymore
2016-06-27 03:15:42 +00:00
2016-11-27 21:48:06 +00:00
$observer = App :: get_observer ();
if (( strpos ( $Text , '[/observer]' ) !== false ) || ( strpos ( $Text , '[/rpost]' ) !== false )) {
2017-01-20 21:36:37 +00:00
$Text = preg_replace_callback ( " / \ [observer \ .language \ =(.*?) \ ](.*?) \ [ \ /observer \ ]/ism " , 'oblanguage_callback' , $Text );
2017-01-20 23:30:08 +00:00
$Text = preg_replace_callback ( " / \ [observer \ .language \ ! \ =(.*?) \ ](.*?) \ [ \ /observer \ ]/ism " , 'oblanguage_necallback' , $Text );
2016-11-27 21:48:06 +00:00
if ( $observer ) {
$Text = preg_replace ( " / \ [observer \ =1 \ ](.*?) \ [ \ /observer \ ]/ism " , '$1' , $Text );
$Text = preg_replace ( " / \ [observer \ =0 \ ].*? \ [ \ /observer \ ]/ism " , '' , $Text );
$Text = preg_replace_callback ( " / \ [rpost(=(.*?))? \ ](.*?) \ [ \ /rpost \ ]/ism " , 'rpost_callback' , $Text );
} else {
$Text = preg_replace ( " / \ [observer \ =1 \ ].*? \ [ \ /observer \ ]/ism " , '' , $Text );
$Text = preg_replace ( " / \ [observer \ =0 \ ](.*?) \ [ \ /observer \ ]/ism " , '$1' , $Text );
$Text = preg_replace ( " / \ [rpost(=.*?)? \ ](.*?) \ [ \ /rpost \ ]/ism " , '' , $Text );
}
}
// replace [observer.baseurl]
if ( $observer ) {
$s1 = '<span class="bb_observer" title="' . t ( 'Different viewers will see this text differently' ) . '">' ;
$s2 = '</span>' ;
$obsBaseURL = $observer [ 'xchan_connurl' ];
$obsBaseURL = preg_replace ( " / \ /poco \ /.* $ / " , '' , $obsBaseURL );
$Text = str_replace ( '[observer.baseurl]' , $obsBaseURL , $Text );
$Text = str_replace ( '[observer.url]' , $observer [ 'xchan_url' ], $Text );
$Text = str_replace ( '[observer.name]' , $s1 . $observer [ 'xchan_name' ] . $s2 , $Text );
$Text = str_replace ( '[observer.address]' , $s1 . $observer [ 'xchan_addr' ] . $s2 , $Text );
$Text = str_replace ( '[observer.webname]' , substr ( $observer [ 'xchan_addr' ], 0 , strpos ( $observer [ 'xchan_addr' ], '@' )), $Text );
$Text = str_replace ( '[observer.photo]' , $s1 . '[zmg]' . $observer [ 'xchan_photo_l' ] . '[/zmg]' . $s2 , $Text );
2019-11-07 05:29:00 +00:00
$Text = str_replace ( '[observer.baseurl/]' , $obsBaseURL , $Text );
$Text = str_replace ( '[observer.url/]' , $observer [ 'xchan_url' ], $Text );
$Text = str_replace ( '[observer.name/]' , $s1 . $observer [ 'xchan_name' ] . $s2 , $Text );
$Text = str_replace ( '[observer.address/]' , $s1 . $observer [ 'xchan_addr' ] . $s2 , $Text );
$Text = str_replace ( '[observer.webname/]' , substr ( $observer [ 'xchan_addr' ], 0 , strpos ( $observer [ 'xchan_addr' ], '@' )), $Text );
$Text = str_replace ( '[observer.photo/]' , $s1 . '[zmg]' . $observer [ 'xchan_photo_l' ] . '[/zmg]' . $s2 , $Text );
2016-11-27 21:48:06 +00:00
} else {
$Text = str_replace ( '[observer.baseurl]' , '' , $Text );
$Text = str_replace ( '[observer.url]' , '' , $Text );
$Text = str_replace ( '[observer.name]' , '' , $Text );
$Text = str_replace ( '[observer.address]' , '' , $Text );
$Text = str_replace ( '[observer.webname]' , '' , $Text );
$Text = str_replace ( '[observer.photo]' , '' , $Text );
2019-11-07 05:29:00 +00:00
$Text = str_replace ( '[observer.baseurl/]' , '' , $Text );
$Text = str_replace ( '[observer.url/]' , '' , $Text );
$Text = str_replace ( '[observer.name/]' , '' , $Text );
$Text = str_replace ( '[observer.address/]' , '' , $Text );
$Text = str_replace ( '[observer.webname/]' , '' , $Text );
$Text = str_replace ( '[observer.photo/]' , '' , $Text );
2016-11-27 21:48:06 +00:00
}
2016-11-27 23:46:24 +00:00
2019-11-07 05:29:00 +00:00
$Text = str_replace ( array ( '[baseurl]' , '[baseurl/]' , '[sitename]' , '[sitename/]' ), array ( z_root (), z_root (), get_config ( 'system' , 'sitename' ), get_config ( 'system' , 'sitename' )), $Text );
2016-11-27 23:46:24 +00:00
2016-12-26 13:58:40 +00:00
// Unhide all [noparse] contained bbtags unspacefying them
// and triming the [noparse] tag.
if ( strpos ( $Text , '[noparse]' ) !== false ) {
$Text = preg_replace_callback ( " / \ [noparse \ ](.*?) \ [ \ /noparse \ ]/ism " , 'bb_unspacefy_and_trim' , $Text );
}
if ( strpos ( $Text , '[nobb]' ) !== false ) {
$Text = preg_replace_callback ( " / \ [nobb \ ](.*?) \ [ \ /nobb \ ]/ism " , 'bb_unspacefy_and_trim' , $Text );
}
if ( strpos ( $Text , '[pre]' ) !== false ) {
$Text = preg_replace_callback ( " / \ [pre \ ](.*?) \ [ \ /pre \ ]/ism " , 'bb_unspacefy_and_trim' , $Text );
}
return $Text ;
2016-11-27 21:48:06 +00:00
}
2015-05-07 04:43:15 +00:00
2010-08-20 03:52:49 +00:00
2017-11-23 23:21:50 +00:00
function bbcode ( $Text , $options = []) {
2018-04-05 06:14:41 +00:00
if ( ! is_array ( $options )) {
$options = [];
}
2018-08-17 06:01:31 +00:00
if ( is_array ( $Text )) {
btlogger ( 'Text is array: ' . print_r ( $Text , true ));
}
2017-11-23 23:21:50 +00:00
$cache = (( array_key_exists ( 'cache' , $options )) ? $options [ 'cache' ] : false );
2018-04-04 23:33:11 +00:00
$newwin = (( array_key_exists ( 'newwin' , $options )) ? $options [ 'newwin' ] : true );
2018-07-06 05:27:44 +00:00
$export = (( array_key_exists ( 'export' , $options )) ? $options [ 'export' ] : false );
2019-11-25 23:48:14 +00:00
$activitypub = (( array_key_exists ( 'activitypub' , $options )) ? $options [ 'activitypub' ] : false );
2019-08-01 01:15:38 +00:00
$censored = (( array_key_exists ( 'censored' , $options )) ? $options [ 'censored' ] : false );
2020-01-07 23:47:27 +00:00
$plain = (( array_key_exists ( 'plain' , $options )) ? $options [ 'plain' ] : false );
2021-01-22 02:36:44 +00:00
$bbonly = (( array_key_exists ( 'bbonly' , $options )) ? $options [ 'bbonly' ] : false );
2020-01-07 23:47:27 +00:00
2019-11-25 23:48:14 +00:00
if ( $activitypub ) {
$export = true ;
}
2018-04-04 23:33:11 +00:00
$target = (( $newwin ) ? ' target="_blank" ' : '' );
2016-10-06 00:21:32 +00:00
call_hooks ( 'bbcode_filter' , $Text );
2020-09-24 00:59:09 +00:00
2012-07-07 22:20:24 +00:00
// Hide all [noparse] contained bbtags by spacefying them
2013-07-28 00:28:35 +00:00
if ( strpos ( $Text , '[noparse]' ) !== false ) {
$Text = preg_replace_callback ( " / \ [noparse \ ](.*?) \ [ \ /noparse \ ]/ism " , 'bb_spacefy' , $Text );
}
if ( strpos ( $Text , '[nobb]' ) !== false ) {
$Text = preg_replace_callback ( " / \ [nobb \ ](.*?) \ [ \ /nobb \ ]/ism " , 'bb_spacefy' , $Text );
}
if ( strpos ( $Text , '[pre]' ) !== false ) {
$Text = preg_replace_callback ( " / \ [pre \ ](.*?) \ [ \ /pre \ ]/ism " , 'bb_spacefy' , $Text );
}
2012-02-12 22:35:29 +00:00
2018-10-25 02:01:43 +00:00
$Text = bb_format_attachdata ( $Text );
2011-09-11 22:44:07 +00:00
// If we find any event code, turn it into an event.
2012-02-19 19:36:59 +00:00
// After we're finished processing the bbcode we'll
2011-09-11 22:44:07 +00:00
// replace all of the event code with a reformatted version.
$ev = bbtoevent ( $Text );
2018-03-03 21:52:55 +00:00
// and the same with polls
$pl = bbtopoll ( $Text );
2013-09-23 11:26:23 +00:00
// process [observer] tags before we do anything else because we might
// be stripping away stuff that then doesn't need to be worked on anymore
2014-01-23 23:43:35 +00:00
2018-07-06 05:27:44 +00:00
if ( $cache || $export )
2015-05-01 00:52:34 +00:00
$observer = false ;
else
2016-03-31 23:06:03 +00:00
$observer = App :: get_observer ();
2015-05-01 00:52:34 +00:00
2013-10-30 01:46:51 +00:00
if (( strpos ( $Text , '[/observer]' ) !== false ) || ( strpos ( $Text , '[/rpost]' ) !== false )) {
2017-01-20 21:36:37 +00:00
$Text = preg_replace_callback ( " / \ [observer \ .language \ =(.*?) \ ](.*?) \ [ \ /observer \ ]/ism " , 'oblanguage_callback' , $Text );
2017-01-20 23:30:08 +00:00
$Text = preg_replace_callback ( " / \ [observer \ .language \ ! \ =(.*?) \ ](.*?) \ [ \ /observer \ ]/ism " , 'oblanguage_necallback' , $Text );
2017-01-20 21:36:37 +00:00
2013-09-23 11:26:23 +00:00
if ( $observer ) {
2013-09-24 12:35:47 +00:00
$Text = preg_replace ( " / \ [observer \ =1 \ ](.*?) \ [ \ /observer \ ]/ism " , '$1' , $Text );
2013-09-23 11:26:23 +00:00
$Text = preg_replace ( " / \ [observer \ =0 \ ].*? \ [ \ /observer \ ]/ism " , '' , $Text );
2013-10-30 23:08:32 +00:00
$Text = preg_replace_callback ( " / \ [rpost(=(.*?))? \ ](.*?) \ [ \ /rpost \ ]/ism " , 'rpost_callback' , $Text );
2013-09-23 11:26:23 +00:00
} else {
2013-09-24 12:35:47 +00:00
$Text = preg_replace ( " / \ [observer \ =1 \ ].*? \ [ \ /observer \ ]/ism " , '' , $Text );
2013-09-23 11:26:23 +00:00
$Text = preg_replace ( " / \ [observer \ =0 \ ](.*?) \ [ \ /observer \ ]/ism " , '$1' , $Text );
2013-10-30 23:08:32 +00:00
$Text = preg_replace ( " / \ [rpost(=.*?)? \ ](.*?) \ [ \ /rpost \ ]/ism " , '' , $Text );
2013-09-23 11:26:23 +00:00
}
2015-04-07 20:39:42 +00:00
}
2011-09-11 22:44:07 +00:00
2018-07-06 05:27:44 +00:00
if ( $cache || $export )
2015-05-01 00:52:34 +00:00
$channel = false ;
else
2016-03-31 23:06:03 +00:00
$channel = App :: get_channel ();
2015-05-01 00:52:34 +00:00
2014-02-12 21:45:11 +00:00
if ( strpos ( $Text , '[/channel]' ) !== false ) {
if ( $channel ) {
$Text = preg_replace ( " / \ [channel \ =1 \ ](.*?) \ [ \ /channel \ ]/ism " , '$1' , $Text );
$Text = preg_replace ( " / \ [channel \ =0 \ ].*? \ [ \ /channel \ ]/ism " , '' , $Text );
} else {
$Text = preg_replace ( " / \ [channel \ =1 \ ].*? \ [ \ /channel \ ]/ism " , '' , $Text );
$Text = preg_replace ( " / \ [channel \ =0 \ ](.*?) \ [ \ /channel \ ]/ism " , '$1' , $Text );
}
2015-04-07 20:39:42 +00:00
}
2014-02-12 21:45:11 +00:00
2015-01-30 02:13:14 +00:00
$x = bb_extract_images ( $Text );
$Text = $x [ 'body' ];
$saved_images = $x [ 'images' ];
2018-07-06 05:27:44 +00:00
if ( ! $export )
2019-11-07 05:29:00 +00:00
$Text = str_replace ( array ( '[baseurl]' , '[baseurl/]' , '[sitename]' , '[sitename/]' ), array ( z_root (), z_root (), get_config ( 'system' , 'sitename' ), get_config ( 'system' , 'sitename' )), $Text );
2014-01-08 04:36:16 +00:00
2015-04-07 20:39:42 +00:00
2010-08-20 03:52:49 +00:00
// Replace any html brackets with HTML Entities to prevent executing HTML or script
// Don't use strip_tags here because it breaks [url] search by replacing & with amp
2010-12-30 22:21:05 +00:00
2021-02-04 22:45:07 +00:00
// These are no longer needed since we run the content through purify_html()
// $Text = str_replace("<", "<", $Text);
// $Text = str_replace(">", ">", $Text);
2010-08-20 03:52:49 +00:00
2015-04-07 20:39:42 +00:00
2016-06-16 02:44:15 +00:00
// Check for [code] text here, before the linefeeds are messed with.
// The highlighter will unescape and re-escape the content.
if ( strpos ( $Text , '[code=' ) !== false ) {
2018-07-17 01:12:03 +00:00
$Text = preg_replace_callback ( " / \ [code=(.*?) \ ](.*?) \ [ \ /code \ ]/ism " , function ( $match ) use ( $options ) {
return bb_code_protect ( text_highlight ( $match [ 2 ], strtolower ( $match [ 1 ]), $options ));
}, $Text );
2016-06-16 02:44:15 +00:00
}
2016-06-27 03:15:42 +00:00
$Text = preg_replace_callback ( " / \ [table \ ](.*?) \ [ \ /table \ ]/ism " , 'bb_fixtable_lf' , $Text );
2016-06-16 02:44:15 +00:00
2020-10-16 00:48:36 +00:00
$Text = str_replace ( " \r \n " , " \n " , $Text );
2021-02-02 22:49:11 +00:00
if ( $bbonly ) {
$Text = purify_html ( $Text );
}
else {
2021-01-22 02:36:44 +00:00
2021-02-02 04:42:39 +00:00
// escape some frequently encountered false positives with a zero-width space
// Here we are catching things like [quote](something)[/quote] and [b](something)[/b] and preventing them from turning into broken markdown links [text](url)
// We'll do this with a zero-width space between ] and (
$Text = preg_replace ( " / \ [(.*?) \ ] \ ((.*?) \ ) \ [ \ /(.*?) \ ]/ism " , '[$1]' . html_entity_decode ( '​' ) . '($2)[/$3]' , $Text );
2021-01-22 02:36:44 +00:00
// save code blocks from being interpreted as markdown
2020-10-16 00:48:36 +00:00
2021-01-22 02:36:44 +00:00
$Text = preg_replace_callback ( " / \ [code(.*?) \ ](.*?) \ [ \ /code \ ]/ism " , 'bb_code_preprotect' , $Text );
2020-10-16 02:01:43 +00:00
2021-02-10 22:04:57 +00:00
// Quick but flawed fix for performance regression after purification
// was moved to rendering code to allow multiple code formats
// A proper fix would be to escape any code blocks before purification,
// restore them and store the resultant intermediate multicode.
2021-02-11 01:55:10 +00:00
// This is now accomplished using multicode_purify()
2021-02-10 22:04:57 +00:00
2021-02-11 01:55:10 +00:00
// if (strpbrk($Text,'<>') !== false) {
// $Text = purify_html($Text, [ 'escape' ]);
// }
2021-02-02 22:49:11 +00:00
2021-01-22 02:36:44 +00:00
// Perform some markdown conversions before translating linefeeds so as to keep the regexes manageable
2020-10-16 02:01:43 +00:00
2021-01-22 02:36:44 +00:00
$Text = preg_replace ( '#(?<!\\\)([*_]{3})([^\n]+?)\1#' , '<strong><em>$2</em></strong>' , $Text );
$Text = preg_replace ( '#(?<!\\\)([*_]{2})([^\n]+?)\1#' , '<strong>$2</strong>' , $Text );
// The character check is so we don't mistake underscore in the middle of a code variable as an italic trigger.
$Text = preg_replace_callback ( '#(^| )(?<!\\\)([*_])([^\n|`]+?)\2#m' , 'md_italic' , $Text );
$Text = preg_replace_callback ( '{ ^(.+?)[ ]*\n(=+|-+)[ ]*\n+ }mx' , 'md_topheader' , $Text );
$Text = preg_replace_callback ( '#^(\#{1,6})\s+([^\#]+?)\s*\#*$#m' , 'md_header' , $Text );
$Text = preg_replace_callback ( '#(^|\n)([`~]{3,})(?: *\.?([a-zA-Z0-9\-.]+))?\n+([\s\S]+?)\n+\2(\n|$)#' , 'md_codeblock' , $Text );
$Text = preg_replace ( '#^(?:\0(.*?)\0\n)?( {4}|\t)(.*?)$#m' , '<pre><code>$3</code></pre>' , $Text );
$Text = preg_replace ( '#(?<!\\\)`([^\n]+?)`#' , '<pre><code>$1</code></pre>' , $Text );
$Text = preg_replace ( '#<\/code><\/pre>\n<pre><code(>| .*?>)#' , '<br>' , $Text );
2020-10-16 02:01:43 +00:00
2021-01-22 02:36:44 +00:00
// blockquotes
$Text = preg_replace ( '#^(>)+ +(.*?)$#m' , '<blockquote>$2</blockquote>' , $Text );
$Text = preg_replace ( '#</blockquote>\n<blockquote>#' , " \n " , $Text );
2020-11-01 00:10:22 +00:00
2021-01-22 02:36:44 +00:00
// links
$Text = preg_replace_callback ( '#!\[[^\]]*\]\((.*?)(?=\"|\))(\".*\")?\)(?!`)#' , 'md_image' , $Text );
$Text = preg_replace ( '#\[([^\[]+)\]\((?:javascript:)?([^\)]+)\)(?!`)#' , '<a href="$2">$1</a>' , $Text );
2020-10-16 00:48:36 +00:00
2021-01-22 02:36:44 +00:00
// unordered lists
$Text = preg_replace ( '#^ *[*\-+] +(.*?)$#m' , '<ul><li>$1</li></ul>' , $Text );
// order lists
$Text = preg_replace ( '#^\d+[\.] +(.*?)$#m' , '<ol><li>$1</li></ol>' , $Text );
$Text = preg_replace ( '/\s*<\/(ol|ul)>\n+<\1>\s*/' , " \n " , $Text );
$Text = bb_code_preunprotect ( $Text );
}
2020-10-16 00:48:36 +00:00
2020-11-01 00:10:22 +00:00
2019-11-22 01:34:49 +00:00
// Convert new line chars to html <br> tags
2011-04-10 10:00:29 +00:00
2020-10-15 02:20:29 +00:00
$Text = str_replace ( array ( " \r " , " \n " ), array ( '<br>' , '<br>' ), $Text );
$Text = str_replace ( array ( " \t " , " " ), array ( " " , " " ), $Text );
2018-01-26 00:16:55 +00:00
// Check for [code] text
if ( strpos ( $Text , '[code]' ) !== false ) {
$Text = preg_replace_callback ( " / \ [code \ ](.*?) \ [ \ /code \ ]/ism " , 'bb_code' , $Text );
}
// Check for [code options] text
if ( strpos ( $Text , '[code ' ) !== false ) {
$Text = preg_replace_callback ( " / \ [code(.*?) \ ](.*?) \ [ \ /code \ ]/ism " , 'bb_code_options' , $Text );
}
2010-08-20 03:52:49 +00:00
// Set up the parameters for a URL search string
2011-02-10 00:55:31 +00:00
$URLSearchString = " ^ \ [ \ ] " ;
2010-08-20 03:52:49 +00:00
// Set up the parameters for a MAIL search string
2011-02-10 00:55:31 +00:00
$MAILSearchString = $URLSearchString ;
2010-08-20 03:52:49 +00:00
2013-09-23 11:26:23 +00:00
// replace [observer.baseurl]
if ( $observer ) {
2015-01-06 13:00:31 +00:00
$s1 = '<span class="bb_observer" title="' . t ( 'Different viewers will see this text differently' ) . '">' ;
2014-11-25 02:02:36 +00:00
$s2 = '</span>' ;
2014-06-30 15:23:42 +00:00
$obsBaseURL = $observer [ 'xchan_connurl' ];
$obsBaseURL = preg_replace ( " / \ /poco \ /.* $ / " , '' , $obsBaseURL );
2013-09-23 11:26:23 +00:00
$Text = str_replace ( '[observer.baseurl]' , $obsBaseURL , $Text );
2013-09-24 01:38:08 +00:00
$Text = str_replace ( '[observer.url]' , $observer [ 'xchan_url' ], $Text );
2014-11-25 02:02:36 +00:00
$Text = str_replace ( '[observer.name]' , $s1 . $observer [ 'xchan_name' ] . $s2 , $Text );
$Text = str_replace ( '[observer.address]' , $s1 . $observer [ 'xchan_addr' ] . $s2 , $Text );
2015-04-10 05:35:04 +00:00
$Text = str_replace ( '[observer.webname]' , substr ( $observer [ 'xchan_addr' ], 0 , strpos ( $observer [ 'xchan_addr' ], '@' )), $Text );
2015-04-07 20:39:42 +00:00
$Text = str_replace ( '[observer.photo]' , $s1 . '[zmg]' . $observer [ 'xchan_photo_l' ] . '[/zmg]' . $s2 , $Text );
2019-11-07 05:29:00 +00:00
$Text = str_replace ( '[observer.baseurl/]' , $obsBaseURL , $Text );
$Text = str_replace ( '[observer.url/]' , $observer [ 'xchan_url' ], $Text );
$Text = str_replace ( '[observer.name/]' , $s1 . $observer [ 'xchan_name' ] . $s2 , $Text );
$Text = str_replace ( '[observer.address/]' , $s1 . $observer [ 'xchan_addr' ] . $s2 , $Text );
$Text = str_replace ( '[observer.webname/]' , substr ( $observer [ 'xchan_addr' ], 0 , strpos ( $observer [ 'xchan_addr' ], '@' )), $Text );
$Text = str_replace ( '[observer.photo/]' , $s1 . '[zmg]' . $observer [ 'xchan_photo_l' ] . '[/zmg]' . $s2 , $Text );
2013-09-23 11:26:23 +00:00
} else {
$Text = str_replace ( '[observer.baseurl]' , '' , $Text );
2013-09-24 01:38:08 +00:00
$Text = str_replace ( '[observer.url]' , '' , $Text );
$Text = str_replace ( '[observer.name]' , '' , $Text );
$Text = str_replace ( '[observer.address]' , '' , $Text );
2014-06-30 03:09:06 +00:00
$Text = str_replace ( '[observer.webname]' , '' , $Text );
2015-04-07 20:39:42 +00:00
$Text = str_replace ( '[observer.photo]' , '' , $Text );
2019-11-07 05:29:00 +00:00
$Text = str_replace ( '[observer.baseurl/]' , '' , $Text );
$Text = str_replace ( '[observer.url/]' , '' , $Text );
$Text = str_replace ( '[observer.name/]' , '' , $Text );
$Text = str_replace ( '[observer.address/]' , '' , $Text );
$Text = str_replace ( '[observer.webname/]' , '' , $Text );
$Text = str_replace ( '[observer.photo/]' , '' , $Text );
2013-09-23 11:26:23 +00:00
}
2011-01-22 13:19:53 +00:00
2014-06-30 03:09:06 +00:00
2011-10-24 12:30:11 +00:00
// Perform URL Search
2011-10-26 02:59:57 +00:00
2017-11-10 05:26:18 +00:00
$urlchars = '[a-zA-Z0-9\pL\:\/\-\?\&\;\.\=\_\~\#\%\$\!\+\,\@\(\)]' ;
2012-02-19 19:36:59 +00:00
2013-07-28 00:28:35 +00:00
if ( strpos ( $Text , 'http' ) !== false ) {
2019-11-06 05:34:47 +00:00
$Text = preg_replace ( " /([^ \ ] \ =' " . '"' . " \ ; \ /])(https? \ : \ / \ / $urlchars +)/ismu " , '$1<a href="$2" ' . $target . ' rel="nofollow noopener">$2</a>' , $Text );
2013-07-28 00:28:35 +00:00
}
2014-01-08 04:36:16 +00:00
2013-07-28 00:28:35 +00:00
if ( strpos ( $Text , '[/share]' ) !== false ) {
2015-04-07 20:39:42 +00:00
$Text = preg_replace_callback ( " / \ [share(.*?) \ ](.*?) \ [ \ /share \ ]/ism " , 'bb_ShareAttributes' , $Text );
2013-07-28 00:28:35 +00:00
}
2018-08-14 06:11:10 +00:00
2013-07-28 00:28:35 +00:00
if ( strpos ( $Text , '[/url]' ) !== false ) {
2018-04-04 23:33:11 +00:00
$Text = preg_replace ( " / \ [url \ ]([ $URLSearchString ]*) \ [ \ /url \ ]/ism " , '<a href="$1" ' . $target . ' rel="nofollow noopener" >$1</a>' , $Text );
2019-09-18 04:25:26 +00:00
$Text = preg_replace ( " / \ @( \ !?) \ [url \ =([ $URLSearchString ]*) \ ](.*?) \ [ \ /url \ ]/ism " , '@$1<span class="h-card"><a class="u-url mention" href="$2" ' . $target . ' rel="nofollow noopener" >$3</a></span>' , $Text );
2018-04-04 23:33:11 +00:00
$Text = preg_replace ( " / \ [url \ =([ $URLSearchString ]*) \ ](.*?) \ [ \ /url \ ]/ism " , '<a href="$1" ' . $target . ' rel="nofollow noopener" >$2</a>' , $Text );
2015-04-07 20:39:42 +00:00
}
2018-08-14 06:11:10 +00:00
2013-07-28 00:28:35 +00:00
if ( strpos ( $Text , '[/zrl]' ) !== false ) {
2019-09-21 23:20:04 +00:00
// render hubzilla bookmarks as normal links
$Text = preg_replace ( " / \ # \ ^ \ [zrl \ ]([ $URLSearchString ]*) \ [ \ /zrl \ ]/ism " , '<a class="zrl bookmark" href="$1" ' . $target . ' rel="nofollow noopener" >$1</a>' , $Text );
$Text = preg_replace ( " / \ # \ ^ \ [zrl \ =([ $URLSearchString ]*) \ ](.*?) \ [ \ /zrl \ ]/ism " , '<a class="zrl bookmark" href="$1" ' . $target . ' rel="nofollow noopener" >$2</a>' , $Text );
2018-04-04 23:33:11 +00:00
$Text = preg_replace ( " / \ [zrl \ ]([ $URLSearchString ]*) \ [ \ /zrl \ ]/ism " , '<a class="zrl" href="$1" ' . $target . ' rel="nofollow noopener" >$1</a>' , $Text );
2019-09-18 04:25:26 +00:00
$Text = preg_replace ( " / \ @( \ !?) \ [zrl \ =([ $URLSearchString ]*) \ ](.*?) \ [ \ /zrl \ ]/ism " , '@$1<span class="h-card"><a class="zrl u-url mention" href="$2" ' . $target . ' rel="nofollow noopener" >$3</a></span>' , $Text );
2018-04-04 23:33:11 +00:00
$Text = preg_replace ( " / \ [zrl \ =([ $URLSearchString ]*) \ ](.*?) \ [ \ /zrl \ ]/ism " , '<a class="zrl" href="$1" ' . $target . ' rel="nofollow noopener" >$2</a>' , $Text );
2015-04-07 20:39:42 +00:00
}
2016-03-10 18:39:38 +00:00
2019-04-16 00:34:29 +00:00
// named anchors do not work well in conversational text, as it is often collapsed by a "showmore" script.
// Included here for completeness.
if ( strpos ( $Text , '[/anchor]' ) !== false ) {
$Text = preg_replace ( " / \ [anchor \ ](.*?) \ [ \ /anchor \ ]/ism " , '<a name="$1"></a>' , $Text );
}
if ( strpos ( $Text , '[/goto]' ) !== false ) {
$Text = preg_replace ( " / \ [goto=(.*?) \ ](.*?) \ [ \ /goto \ ]/ism " , '<a href="#$1">$2</a>' , $Text );
}
2016-03-10 18:39:38 +00:00
2010-08-20 03:52:49 +00:00
// Perform MAIL Search
2015-04-07 20:39:42 +00:00
if ( strpos ( $Text , '[/mail]' ) !== false ) {
2018-04-04 23:33:11 +00:00
$Text = preg_replace ( " / \ [mail \ ]([ $MAILSearchString ]*) \ [ \ /mail \ ]/ " , '<a href="mailto:$1" ' . $target . ' rel="nofollow noopener" >$1</a>' , $Text );
$Text = preg_replace ( " / \ [mail \ =([ $MAILSearchString ]*) \ ](.*?) \ [ \ /mail \ ]/ " , '<a href="mailto:$1" ' . $target . ' rel="nofollow noopener" >$2</a>' , $Text );
2013-07-28 00:28:35 +00:00
}
2014-12-16 23:50:20 +00:00
2015-11-06 00:08:18 +00:00
2014-12-16 23:50:20 +00:00
// leave open the posibility of [map=something]
// this is replaced in prepare_body() which has knowledge of the item location
2019-05-14 03:28:56 +00:00
if ( $export ) {
$Text = str_replace ( [ '[map]' , '[/map]' ], [ '' , '' ] , $Text );
2020-09-23 02:57:28 +00:00
$Text = preg_replace ( " / \ [map=(.*?)[, ](.*?) \ ]/ism " , 'geo:$1,$2' , $Text );
2019-05-14 03:28:56 +00:00
}
else {
2018-07-06 05:27:44 +00:00
if ( strpos ( $Text , '[/map]' ) !== false ) {
$Text = preg_replace_callback ( " / \ [map \ ](.*?) \ [ \ /map \ ]/ism " , 'bb_map_location' , $Text );
}
if ( strpos ( $Text , '[map=' ) !== false ) {
2019-11-07 05:29:00 +00:00
$Text = preg_replace_callback ( " / \ [map=(.*?) \ / \ ]/ism " , 'bb_map_coords' , $Text );
2018-07-06 05:27:44 +00:00
$Text = preg_replace_callback ( " / \ [map=(.*?) \ ]/ism " , 'bb_map_coords' , $Text );
}
if ( strpos ( $Text , '[map]' ) !== false ) {
2019-11-07 05:29:00 +00:00
$Text = preg_replace ( " / \ [map \ / \ ]/ " , '<div class="map"></div>' , $Text );
2018-07-06 05:27:44 +00:00
$Text = preg_replace ( " / \ [map \ ]/ " , '<div class="map"></div>' , $Text );
}
2014-12-16 23:50:20 +00:00
}
2010-08-20 03:52:49 +00:00
// Check for bold text
2015-04-07 20:39:42 +00:00
if ( strpos ( $Text , '[b]' ) !== false ) {
$Text = preg_replace ( " ( \ [b \ ](.*?) \ [ \ /b \ ])ism " , '<strong>$1</strong>' , $Text );
2013-07-28 00:28:35 +00:00
}
2010-08-20 03:52:49 +00:00
// Check for Italics text
2015-04-07 20:39:42 +00:00
if ( strpos ( $Text , '[i]' ) !== false ) {
$Text = preg_replace ( " ( \ [i \ ](.*?) \ [ \ /i \ ])ism " , '<em>$1</em>' , $Text );
2013-07-28 00:28:35 +00:00
}
2010-08-20 03:52:49 +00:00
// Check for Underline text
2015-04-07 20:39:42 +00:00
if ( strpos ( $Text , '[u]' ) !== false ) {
$Text = preg_replace ( " ( \ [u \ ](.*?) \ [ \ /u \ ])ism " , '<u>$1</u>' , $Text );
2013-07-28 00:28:35 +00:00
}
2010-08-20 03:52:49 +00:00
// Check for strike-through text
2013-07-28 00:28:35 +00:00
if ( strpos ( $Text , '[s]' ) !== false ) {
2018-04-12 00:40:04 +00:00
$Text = preg_replace ( " ( \ [s \ ](.*?) \ [ \ /s \ ])ism " , '<span style="text-decoration: line-through;">$1</span>' , $Text );
2013-07-28 00:28:35 +00:00
}
2010-08-20 03:52:49 +00:00
// Check for over-line text
2015-04-07 20:39:42 +00:00
if ( strpos ( $Text , '[o]' ) !== false ) {
2018-04-12 00:40:04 +00:00
$Text = preg_replace ( " ( \ [o \ ](.*?) \ [ \ /o \ ])ism " , '<span style="text-decoration: overline;">$1</span>' , $Text );
2013-07-28 00:28:35 +00:00
}
2015-04-07 20:39:42 +00:00
if ( strpos ( $Text , '[sup]' ) !== false ) {
$Text = preg_replace ( " ( \ [sup \ ](.*?) \ [ \ /sup \ ])ism " , '<sup>$1</sup>' , $Text );
2014-08-05 11:32:48 +00:00
}
2015-04-07 20:39:42 +00:00
if ( strpos ( $Text , '[sub]' ) !== false ) {
$Text = preg_replace ( " ( \ [sub \ ](.*?) \ [ \ /sub \ ])ism " , '<sub>$1</sub>' , $Text );
2014-08-05 11:32:48 +00:00
}
2015-04-07 20:39:42 +00:00
2010-08-20 03:52:49 +00:00
// Check for colored text
2015-04-07 20:39:42 +00:00
if ( strpos ( $Text , '[/color]' ) !== false ) {
2020-12-01 03:48:59 +00:00
$Text = preg_replace_callback ( " ( \ [color=(.*?) \ ](.*?) \ [ \ /color \ ])ism " , 'bb_colortag' , $Text );
2013-07-28 00:28:35 +00:00
}
2020-12-01 03:48:59 +00:00
// Check for highlighted text
2016-11-29 22:09:01 +00:00
if ( strpos ( $Text , '[/hl]' ) !== false ) {
$Text = preg_replace ( " ( \ [hl \ ](.*?) \ [ \ /hl \ ])ism " , " <span style= \" background-color: yellow; \" > $ 1</span> " , $Text );
2020-12-02 00:20:46 +00:00
$Text = preg_replace_callback ( " ( \ [hl=(.*?) \ ](.*?) \ [ \ /hl \ ])ism " , 'bb_hltag' , $Text );
2016-11-29 22:09:01 +00:00
}
2010-08-20 03:52:49 +00:00
// Check for sized text
2015-04-07 20:39:42 +00:00
// [size=50] --> font-size: 50px (with the unit).
if ( strpos ( $Text , '[/size]' ) !== false ) {
$Text = preg_replace ( " ( \ [size=( \ d*?) \ ](.*?) \ [ \ /size \ ])ism " , " <span style= \" font-size: $ 1px; \" > $ 2</span> " , $Text );
2020-12-01 19:07:17 +00:00
$Text = preg_replace_callback ( " ( \ [size=(.*?) \ ](.*?) \ [ \ /size \ ])ism " , 'bb_sizetag' , $Text );
2013-07-28 00:28:35 +00:00
}
2014-05-10 04:54:59 +00:00
// Check for h1
if ( strpos ( $Text , '[h1]' ) !== false ) {
$Text = preg_replace ( " ( \ [h1 \ ](.*?) \ [ \ /h1 \ ])ism " , '<h1>$1</h1>' , $Text );
2019-11-22 01:34:49 +00:00
$Text = str_replace ( '</h1><br>' , '</h1>' , $Text );
2014-05-10 04:54:59 +00:00
}
// Check for h2
if ( strpos ( $Text , '[h2]' ) !== false ) {
$Text = preg_replace ( " ( \ [h2 \ ](.*?) \ [ \ /h2 \ ])ism " , '<h2>$1</h2>' , $Text );
2019-11-22 01:34:49 +00:00
$Text = str_replace ( '</h2><br>' , '</h2>' , $Text );
2014-05-10 04:54:59 +00:00
}
// Check for h3
if ( strpos ( $Text , '[h3]' ) !== false ) {
$Text = preg_replace ( " ( \ [h3 \ ](.*?) \ [ \ /h3 \ ])ism " , '<h3>$1</h3>' , $Text );
2019-11-22 01:34:49 +00:00
$Text = str_replace ( '</h3><br>' , '</h3>' , $Text );
2014-05-10 04:54:59 +00:00
}
// Check for h4
if ( strpos ( $Text , '[h4]' ) !== false ) {
$Text = preg_replace ( " ( \ [h4 \ ](.*?) \ [ \ /h4 \ ])ism " , '<h4>$1</h4>' , $Text );
2019-11-22 01:34:49 +00:00
$Text = str_replace ( '</h4><br>' , '</h4>' , $Text );
2014-05-10 04:54:59 +00:00
}
// Check for h5
if ( strpos ( $Text , '[h5]' ) !== false ) {
$Text = preg_replace ( " ( \ [h5 \ ](.*?) \ [ \ /h5 \ ])ism " , '<h5>$1</h5>' , $Text );
2019-11-22 01:34:49 +00:00
$Text = str_replace ( '</h5><br>' , '</h5>' , $Text );
2014-05-10 04:54:59 +00:00
}
// Check for h6
if ( strpos ( $Text , '[h6]' ) !== false ) {
$Text = preg_replace ( " ( \ [h6 \ ](.*?) \ [ \ /h6 \ ])ism " , '<h6>$1</h6>' , $Text );
2019-11-22 01:34:49 +00:00
$Text = str_replace ( '</h6><br>' , '</h6>' , $Text );
2014-05-10 04:54:59 +00:00
}
2017-12-21 08:07:37 +00:00
2015-02-14 19:33:51 +00:00
// Check for table of content without params
2016-12-04 11:51:23 +00:00
while ( strpos ( $Text , '[toc]' ) !== false ) {
$toc_id = 'toc-' . random_string ( 10 );
2016-12-04 13:31:45 +00:00
$Text = preg_replace ( " / \ [toc \ ]/ism " , '<ul id="' . $toc_id . '" class="toc" data-toc=".section-content-wrapper"></ul><script>$("#' . $toc_id . '").toc();</script>' , $Text , 1 );
2019-11-07 05:29:00 +00:00
$Text = preg_replace ( " / \ [toc \ / \ ]/ism " , '<ul id="' . $toc_id . '" class="toc" data-toc=".section-content-wrapper"></ul><script>$("#' . $toc_id . '").toc();</script>' , $Text , 1 );
2015-02-14 19:33:51 +00:00
}
// Check for table of content with params
2016-12-04 11:51:23 +00:00
while ( strpos ( $Text , '[toc' ) !== false ) {
$toc_id = 'toc-' . random_string ( 10 );
2019-11-07 05:29:00 +00:00
$Text = preg_replace ( " / \ [toc([^ \ ]]+?) \ / \ ]/ism " , '<ul id="' . $toc_id . '" class="toc"$1></ul><script>$("#' . $toc_id . '").toc();</script>' , $Text , 1 );
2016-12-04 13:31:45 +00:00
$Text = preg_replace ( " / \ [toc([^ \ ]]+?) \ ]/ism " , '<ul id="' . $toc_id . '" class="toc"$1></ul><script>$("#' . $toc_id . '").toc();</script>' , $Text , 1 );
2015-01-12 23:06:44 +00:00
}
2012-02-12 23:51:17 +00:00
// Check for centered text
2015-04-07 20:39:42 +00:00
if ( strpos ( $Text , '[/center]' ) !== false ) {
2016-02-29 22:58:32 +00:00
$Text = preg_replace ( " ( \ [center \ ](.*?) \ [ \ /center \ ])ism " , " <div style= \" text-align:center; \" > $ 1</div> " , $Text );
}
// Check for footer
if ( strpos ( $Text , '[/footer]' ) !== false ) {
$Text = preg_replace ( " ( \ [footer \ ](.*?) \ [ \ /footer \ ])ism " , " <div class= \" wall-item-footer \" > $ 1</div> " , $Text );
2013-07-28 00:28:35 +00:00
}
2020-02-12 23:21:39 +00:00
// Check for bdi
if ( strpos ( $Text , '[/bdi]' ) !== false ) {
$Text = preg_replace ( " ( \ [bdi \ ](.*?) \ [ \ /bdi \ ])ism " , " <bdi> $ 1</bdi> " , $Text );
}
2010-08-20 03:52:49 +00:00
// Check for list text
2016-10-12 22:25:48 +00:00
2019-11-22 01:34:49 +00:00
$Text = preg_replace ( " /<br> \ [ \ * \ / \ ]/ism " , '[*/]' , $Text );
$Text = preg_replace ( " /<br> \ [ \ * \ ]/ism " , '[*/]' , $Text );
2016-10-12 22:25:48 +00:00
2019-11-07 05:29:00 +00:00
$Text = str_replace ( " [*/] " , " <li> " , $Text );
2012-02-13 01:10:06 +00:00
$Text = str_replace ( " [*] " , " <li> " , $Text );
2011-11-10 03:32:54 +00:00
2012-02-19 20:07:45 +00:00
// handle nested lists
$endlessloop = 0 ;
2012-06-25 23:05:42 +00:00
2012-06-28 03:21:26 +00:00
while (((( strpos ( $Text , " [/list] " ) !== false ) && ( strpos ( $Text , " [list " ) !== false )) ||
2015-04-07 20:39:42 +00:00
(( strpos ( $Text , " [/ol] " ) !== false ) && ( strpos ( $Text , " [ol] " ) !== false )) ||
(( strpos ( $Text , " [/ul] " ) !== false ) && ( strpos ( $Text , " [ul] " ) !== false )) ||
2016-04-28 13:48:50 +00:00
(( strpos ( $Text , " [/dl] " ) !== false ) && ( strpos ( $Text , " [dl " ) !== false )) ||
2015-04-07 20:39:42 +00:00
(( strpos ( $Text , " [/li] " ) !== false ) && ( strpos ( $Text , " [li] " ) !== false ))) && ( ++ $endlessloop < 20 )) {
$Text = preg_replace ( " / \ [list \ ](.*?) \ [ \ /list \ ]/ism " , '<ul class="listbullet" style="list-style-type: circle;">$1</ul>' , $Text );
$Text = preg_replace ( " / \ [list= \ ](.*?) \ [ \ /list \ ]/ism " , '<ul class="listnone" style="list-style-type: none;">$1</ul>' , $Text );
$Text = preg_replace ( " / \ [list=1 \ ](.*?) \ [ \ /list \ ]/ism " , '<ul class="listdecimal" style="list-style-type: decimal;">$1</ul>' , $Text );
$Text = preg_replace ( " / \ [list=((?-i)i) \ ](.*?) \ [ \ /list \ ]/ism " , '<ul class="listlowerroman" style="list-style-type: lower-roman;">$2</ul>' , $Text );
$Text = preg_replace ( " / \ [list=((?-i)I) \ ](.*?) \ [ \ /list \ ]/ism " , '<ul class="listupperroman" style="list-style-type: upper-roman;">$2</ul>' , $Text );
$Text = preg_replace ( " / \ [list=((?-i)a) \ ](.*?) \ [ \ /list \ ]/ism " , '<ul class="listloweralpha" style="list-style-type: lower-alpha;">$2</ul>' , $Text );
$Text = preg_replace ( " / \ [list=((?-i)A) \ ](.*?) \ [ \ /list \ ]/ism " , '<ul class="listupperalpha" style="list-style-type: upper-alpha;">$2</ul>' , $Text );
$Text = preg_replace ( " / \ [ul \ ](.*?) \ [ \ /ul \ ]/ism " , '<ul class="listbullet" style="list-style-type: circle;">$1</ul>' , $Text );
$Text = preg_replace ( " / \ [ol \ ](.*?) \ [ \ /ol \ ]/ism " , '<ul class="listdecimal" style="list-style-type: decimal;">$1</ul>' , $Text );
2019-11-22 01:34:49 +00:00
$Text = preg_replace ( " / \ [ \ /li \ ]<br> \ [li \ ]/ism " , '[/li][li]' , $Text );
2015-04-07 20:39:42 +00:00
$Text = preg_replace ( " / \ [li \ ](.*?) \ [ \ /li \ ]/ism " , '<li>$1</li>' , $Text );
2016-04-28 13:48:50 +00:00
// [dl] tags have an optional [dl terms="bi"] form where bold/italic/underline/mono/large
// etc. style may be specified for the "terms" in the definition list. The quotation marks
// are also optional. The regex looks intimidating, but breaks down as:
// "[dl" <optional-whitespace> <optional-termStyles> "]" <matchGroup2> "[/dl]"
// where optional-termStyles are: "terms=" <optional-quote> <matchGroup1> <optional-quote>
$Text = preg_replace_callback ( '/\[dl[[:space:]]*(?:terms=(?:"|")?([a-zA-Z]+)(?:"|")?)?\](.*?)\[\/dl\]/ism' , 'bb_definitionList' , $Text );
2016-11-16 19:49:58 +00:00
}
2020-06-01 03:42:30 +00:00
// Friendica generates this
if ( strpos ( $Text , '[/abstract]' ) !== false ) {
2020-06-01 06:04:14 +00:00
$Text = preg_replace ( " / \ [abstract \ ](.*?) \ [ \ /abstract \ ]/ism " , '<h3>$1</h3>' , $Text );
2020-06-01 03:42:30 +00:00
}
2016-11-16 19:49:58 +00:00
if ( strpos ( $Text , '[checklist]' ) !== false ) {
$Text = preg_replace_callback ( " / \ [checklist \ ](.*?) \ [ \ /checklist \ ]/ism " , 'bb_checklist' , $Text );
2015-04-07 20:39:42 +00:00
}
2016-11-16 19:49:58 +00:00
2015-04-07 20:39:42 +00:00
if ( strpos ( $Text , '[th]' ) !== false ) {
$Text = preg_replace ( " / \ [th \ ](.*?) \ [ \ /th \ ]/sm " , '<th>$1</th>' , $Text );
2013-07-28 00:28:35 +00:00
}
if ( strpos ( $Text , '[td]' ) !== false ) {
2015-04-07 20:39:42 +00:00
$Text = preg_replace ( " / \ [td \ ](.*?) \ [ \ /td \ ]/sm " , '<td>$1</td>' , $Text );
2013-07-28 00:28:35 +00:00
}
2015-04-07 20:39:42 +00:00
if ( strpos ( $Text , '[tr]' ) !== false ) {
$Text = preg_replace ( " / \ [tr \ ](.*?) \ [ \ /tr \ ]/sm " , '<tr>$1</tr>' , $Text );
2013-07-28 00:28:35 +00:00
}
2015-04-07 20:39:42 +00:00
if ( strpos ( $Text , '[/table]' ) !== false ) {
$Text = preg_replace ( " / \ [table \ ](.*?) \ [ \ /table \ ]/sm " , '<table>$1</table>' , $Text );
2016-12-26 13:58:40 +00:00
$Text = preg_replace ( " / \ [table border=1 \ ](.*?) \ [ \ /table \ ]/sm " , '<table class="table table-responsive table-bordered" >$1</table>' , $Text );
$Text = preg_replace ( " / \ [table border=0 \ ](.*?) \ [ \ /table \ ]/sm " , '<table class="table table-responsive" >$1</table>' , $Text );
2013-07-28 00:28:35 +00:00
}
2019-11-22 01:34:49 +00:00
$Text = str_replace ( '</tr><br><tr>' , " </tr> \n <tr> " , $Text );
2019-11-07 05:29:00 +00:00
$Text = str_replace ( '[hr]' , '<hr>' , $Text );
$Text = str_replace ( '[hr/]' , '<hr>' , $Text );
2012-02-15 07:13:18 +00:00
// This is actually executed in prepare_body()
2015-04-07 20:39:42 +00:00
$Text = str_replace ( '[nosmile]' , '' , $Text );
2019-11-07 05:29:00 +00:00
$Text = str_replace ( '[nosmile/]' , '' , $Text );
2010-08-20 03:52:49 +00:00
// Check for font change text
2015-04-07 20:39:42 +00:00
if ( strpos ( $Text , '[/font]' ) !== false ) {
2020-12-01 03:52:46 +00:00
$Text = preg_replace_callback ( " / \ [font=(.*?) \ ](.*?) \ [ \ /font \ ]/sm " , 'bb_fonttag' , $Text );
2013-07-28 00:28:35 +00:00
}
2011-07-19 02:17:16 +00:00
2018-01-16 04:47:32 +00:00
if ( strpos ( $Text , '[/summary]' ) !== false ) {
$Text = preg_replace_callback ( " /^(.*?) \ [summary \ ](.*?) \ [ \ /summary \ ](.*?) $ /ism " , 'bb_summary' , $Text );
}
2012-03-17 10:07:49 +00:00
// Check for [spoiler] text
$endlessloop = 0 ;
2016-04-26 09:41:08 +00:00
while (( strpos ( $Text , " [/spoiler] " ) !== false ) and ( strpos ( $Text , " [spoiler] " ) !== false ) and ( ++ $endlessloop < 20 )) {
$Text = preg_replace_callback ( " / \ [spoiler \ ](.*?) \ [ \ /spoiler \ ]/ism " , 'bb_spoilertag' , $Text );
}
2012-03-17 10:07:49 +00:00
2012-03-17 11:15:59 +00:00
// Check for [spoiler=Author] text
$endlessloop = 0 ;
2016-04-26 09:41:08 +00:00
while (( strpos ( $Text , " [/spoiler] " ) !== false ) and ( strpos ( $Text , " [spoiler= " ) !== false ) and ( ++ $endlessloop < 20 )) {
$Text = preg_replace_callback ( " / \ [spoiler=(.*?) \ ](.*?) \ [ \ /spoiler \ ]/ism " , 'bb_spoilertag' , $Text );
}
2012-03-17 11:15:59 +00:00
2016-04-26 09:41:08 +00:00
// Check for [open] text
$endlessloop = 0 ;
while (( strpos ( $Text , " [/open] " ) !== false ) and ( strpos ( $Text , " [open] " ) !== false ) and ( ++ $endlessloop < 20 )) {
$Text = preg_replace_callback ( " / \ [open \ ](.*?) \ [ \ /open \ ]/ism " , 'bb_opentag' , $Text );
}
2015-04-01 19:30:03 +00:00
2016-04-26 09:41:08 +00:00
// Check for [open=Title] text
2015-04-01 19:30:03 +00:00
$endlessloop = 0 ;
while (( strpos ( $Text , " [/open] " ) !== false ) and ( strpos ( $Text , " [open= " ) !== false ) and ( ++ $endlessloop < 20 )) {
2015-04-07 20:39:42 +00:00
$Text = preg_replace_callback ( " / \ [open=(.*?) \ ](.*?) \ [ \ /open \ ]/ism " , 'bb_opentag' , $Text );
2015-04-01 19:30:03 +00:00
}
2010-08-20 03:52:49 +00:00
// Declare the format for [quote] layout
2012-02-19 19:36:59 +00:00
$QuoteLayout = '<blockquote>$1</blockquote>' ;
2012-03-17 10:07:49 +00:00
2020-01-07 23:47:27 +00:00
2010-08-20 03:52:49 +00:00
// Check for [quote] text
2012-02-19 19:36:59 +00:00
// handle nested quotes
$endlessloop = 0 ;
2012-02-23 19:51:44 +00:00
while (( strpos ( $Text , " [/quote] " ) !== false ) and ( strpos ( $Text , " [quote] " ) !== false ) and ( ++ $endlessloop < 20 ))
2015-04-07 20:39:42 +00:00
$Text = preg_replace ( " / \ [quote \ ](.*?) \ [ \ /quote \ ]/ism " , " $QuoteLayout " , $Text );
2012-02-13 00:18:58 +00:00
// Check for [quote=Author] text
2012-02-13 04:56:44 +00:00
$t_wrote = t ( '$1 wrote:' );
2012-02-19 19:36:59 +00:00
// handle nested quotes
$endlessloop = 0 ;
2012-02-23 19:51:44 +00:00
while (( strpos ( $Text , " [/quote] " ) !== false ) and ( strpos ( $Text , " [quote= " ) !== false ) and ( ++ $endlessloop < 20 ))
2012-02-19 19:36:59 +00:00
$Text = preg_replace ( " / \ [quote=[ \" \ ']*(.*?)[ \" \ ']* \ ](.*?) \ [ \ /quote \ ]/ism " ,
2016-04-26 09:41:08 +00:00
" <span class= " . '"bb-quote"' . " > " . $t_wrote . " </span><blockquote> $ 2</blockquote> " ,
2013-03-12 04:29:43 +00:00
$Text );
2012-02-13 00:18:58 +00:00
2020-01-07 23:47:27 +00:00
if ( $plain ) {
$Text = str_replace ([ '<blockquote>' , '</blockquote>' ], [ '“' , '”' ], $Text );
}
2010-08-20 03:52:49 +00:00
// Images
2019-08-01 01:15:38 +00:00
2010-08-20 03:52:49 +00:00
// [img]pathtoimage[/img]
2014-01-29 23:01:19 +00:00
if ( strpos ( $Text , '[/img]' ) !== false ) {
2020-12-01 19:48:05 +00:00
$Text = preg_replace ( " / \ [img \ ](.*?) \ [ \ /img \ ]/ism " , '<img style="max-width: 100%;" src="$1" alt="' . t ( 'Image/photo' ) . '" />' , $Text );
2019-12-06 04:37:43 +00:00
// Friendica's modified bbcode img tags
2020-12-01 19:48:05 +00:00
$Text = preg_replace ( " / \ [img=http(.*?) \ ](.*?) \ [ \ /img \ ]/ism " , '<img style="max-width: 100%;" src="http$1" alt="' . t ( 'Image/photo' ) . '" />' , $Text );
2013-07-28 00:28:35 +00:00
}
2014-01-29 23:01:19 +00:00
if ( strpos ( $Text , '[/zmg]' ) !== false ) {
2020-12-01 19:48:05 +00:00
$Text = preg_replace ( " / \ [zmg \ ](.*?) \ [ \ /zmg \ ]/ism " , '<img class="zrl" style="max-width: 100%;" src="$1" alt="' . t ( 'Image/photo' ) . '" />' , $Text );
2013-07-28 00:28:35 +00:00
}
2012-08-13 03:56:23 +00:00
2020-02-27 03:10:43 +00:00
$Text = preg_replace_callback ( " / \ [([zi])mg([ \ =])(.*?) \ ](.*?) \ [ \ /[zi]mg \ ]/ism " , 'bb_imgoptions' , $Text );
2019-08-01 04:46:19 +00:00
if ( $censored ) {
$Text = separate_img_links ( $Text );
2019-09-23 23:11:36 +00:00
$Text = preg_replace_callback ( " / \ <img(.*?)src= \" (.*?) \" (.*?) \ >/ism " , " bb_colorbox " , $Text );
2014-01-29 23:01:19 +00:00
}
2014-02-05 13:34:25 +00:00
// style (sanitized)
if ( strpos ( $Text , '[/style]' ) !== false ) {
$Text = preg_replace_callback ( " ( \ [style=(.*?) \ ](.*?) \ [ \ /style \ ])ism " , " bb_sanitize_style " , $Text );
}
2014-01-29 23:01:19 +00:00
// crypt
2015-04-07 20:39:42 +00:00
if ( strpos ( $Text , '[/crypt]' ) !== false ) {
2020-10-19 01:21:31 +00:00
if ( ! $activitypub ) {
2020-08-23 09:28:38 +00:00
$Text = preg_replace_callback ( " / \ [crypt (.*?) \ ](.*?) \ [ \ /crypt \ ]/ism " , 'bb_parse_crypt' , $Text );
}
2013-07-28 00:28:35 +00:00
}
2014-01-24 07:46:43 +00:00
2019-11-25 23:48:14 +00:00
if ( strpos ( $Text , '[/app]' ) !== false ) {
if ( $activitypub ) {
$Text = preg_replace_callback ( " / \ [app \ ](.*?) \ [ \ /app \ ]/ism " , 'bb_parse_app_ap' , $Text );
}
else {
$Text = preg_replace_callback ( " / \ [app \ ](.*?) \ [ \ /app \ ]/ism " , 'bb_parse_app' , $Text );
}
2014-05-19 01:21:20 +00:00
}
2014-10-07 00:47:17 +00:00
if ( strpos ( $Text , '[/element]' ) !== false ) {
$Text = preg_replace_callback ( " / \ [element \ ](.*?) \ [ \ /element \ ]/ism " , 'bb_parse_element' , $Text );
}
2014-01-24 07:46:43 +00:00
// html5 video and audio
2015-04-07 20:39:42 +00:00
if ( strpos ( $Text , '[/video]' ) !== false ) {
2019-07-07 23:32:48 +00:00
$Text = preg_replace_callback ( " / \ [video (.*?) \ ](.*? \ .(ogg|ogv|oga|ogm|webm|mp4|mpeg|mpg|mov)) \ [ \ /video \ ]/ism " , 'videowithopts' , $Text );
$Text = preg_replace_callback ( " / \ [video \ ](.*? \ .(ogg|ogv|oga|ogm|webm|mp4|mpeg|mpg|mov)) \ [ \ /video \ ]/ism " , 'tryzrlvideo' , $Text );
2014-01-24 07:46:43 +00:00
}
2015-04-07 20:39:42 +00:00
if ( strpos ( $Text , '[/audio]' ) !== false ) {
2016-09-30 02:26:58 +00:00
$Text = preg_replace_callback ( " / \ [audio \ ](.*? \ .(ogg|ogv|oga|ogm|webm|mp4|mp3|opus|m4a)) \ [ \ /audio \ ]/ism " , 'tryzrlaudio' , $Text );
2014-01-24 07:46:43 +00:00
}
2015-04-07 20:39:42 +00:00
if ( strpos ( $Text , '[/zvideo]' ) !== false ) {
2019-07-07 23:32:48 +00:00
$Text = preg_replace_callback ( " / \ [zvideo (.*?) \ ](.*? \ .(ogg|ogv|oga|ogm|webm|mp4|mpeg|mpg|mov)) \ [ \ /zvideo \ ]/ism " , 'videowithopts' , $Text );
$Text = preg_replace_callback ( " / \ [zvideo \ ](.*? \ .(ogg|ogv|oga|ogm|webm|mp4|mpeg|mpg|mov)) \ [ \ /zvideo \ ]/ism " , 'tryzrlvideo' , $Text );
2015-03-12 01:04:43 +00:00
}
2015-04-07 20:39:42 +00:00
if ( strpos ( $Text , '[/zaudio]' ) !== false ) {
2016-09-30 02:26:58 +00:00
$Text = preg_replace_callback ( " / \ [zaudio \ ](.*? \ .(ogg|ogv|oga|ogm|webm|mp4|mp3|opus|m4a)) \ [ \ /zaudio \ ]/ism " , 'tryzrlaudio' , $Text );
2015-03-12 01:04:43 +00:00
}
2014-01-24 07:46:43 +00:00
2013-06-22 04:39:06 +00:00
// if video couldn't be embedded, link to it instead.
2013-07-28 00:28:35 +00:00
if ( strpos ( $Text , '[/video]' ) !== false ) {
2018-04-04 23:33:11 +00:00
$Text = preg_replace ( " / \ [video \ ](.*?) \ [ \ /video \ ]/ " , '<a href="$1" ' . $target . ' rel="nofollow noopener" >$1</a>' , $Text );
2013-07-28 00:28:35 +00:00
}
if ( strpos ( $Text , '[/audio]' ) !== false ) {
2018-04-04 23:33:11 +00:00
$Text = preg_replace ( " / \ [audio \ ](.*?) \ [ \ /audio \ ]/ " , '<a href="$1" ' . $target . ' rel="nofollow noopener" >$1</a>' , $Text );
2013-07-28 00:28:35 +00:00
}
2013-06-22 04:39:06 +00:00
2015-03-12 01:04:43 +00:00
if ( strpos ( $Text , '[/zvideo]' ) !== false ) {
2018-04-04 23:33:11 +00:00
$Text = preg_replace ( " / \ [zvideo \ ](.*?) \ [ \ /zvideo \ ]/ " , '<a class="zid" href="$1" ' . $target . ' rel="nofollow noopener" >$1</a>' , $Text );
2015-03-12 01:04:43 +00:00
}
if ( strpos ( $Text , '[/zaudio]' ) !== false ) {
2018-04-04 23:33:11 +00:00
$Text = preg_replace ( " / \ [zaudio \ ](.*?) \ [ \ /zaudio \ ]/ " , '<a class="zid" href="$1" ' . $target . ' rel="nofollow noopener" >$1</a>' , $Text );
}
2015-04-07 20:39:42 +00:00
2019-11-05 05:45:16 +00:00
// SVG stuff
2020-01-15 04:02:13 +00:00
if ( $activitypub ) {
$Text = preg_replace_callback ( " / \ [svg(.*?) \ ](.*?) \ [ \ /svg \ ]/ism " , 'bb_svg_export' , $Text );
}
else {
$Text = preg_replace_callback ( " / \ [svg(.*?) \ ](.*?) \ [ \ /svg \ ]/ism " , 'bb_svg' , $Text );
}
2019-11-05 05:45:16 +00:00
2011-01-31 09:38:49 +00:00
// oembed tag
2018-07-06 05:27:44 +00:00
if ( ! $export )
$Text = oembed_bbcode2html ( $Text );
2011-06-10 03:02:48 +00:00
2012-07-19 00:08:03 +00:00
// Avoid triple linefeeds through oembed
2019-11-22 01:34:49 +00:00
$Text = str_replace ( " <br style='clear:left'></span><br><br> " , " <br style='clear:left'></span><br> " , $Text );
2012-07-19 00:08:03 +00:00
2011-06-10 03:02:48 +00:00
// If we found an event earlier, strip out all the event code and replace with a reformatted version.
2012-06-26 04:27:34 +00:00
// Replace the event-start section with the entire formatted event. The other bbcode is stripped.
// Summary (e.g. title) is required, earlier revisions only required description (in addition to
// start which is always required). Allow desc with a missing summary for compatibility.
2011-06-10 03:02:48 +00:00
2016-11-01 04:48:00 +00:00
if (( x ( $ev , 'desc' ) || x ( $ev , 'summary' )) && x ( $ev , 'dtstart' )) {
2015-07-31 05:29:10 +00:00
2011-06-10 03:02:48 +00:00
$sub = format_event_html ( $ev );
2015-07-31 05:29:10 +00:00
$sub = str_replace ( '$' , " \0 " , $sub );
$Text = preg_replace ( " / \ [event \ -start \ ](.*?) \ [ \ /event \ -start \ ]/ism " , $sub , $Text );
2017-05-02 05:56:11 +00:00
$Text = preg_replace ( " / \ [event \ ](.*?) \ [ \ /event \ ]/ism " , '' , $Text );
2012-06-26 03:55:27 +00:00
$Text = preg_replace ( " / \ [event \ -summary \ ](.*?) \ [ \ /event \ -summary \ ]/ism " , '' , $Text );
2012-06-26 04:20:08 +00:00
$Text = preg_replace ( " / \ [event \ -description \ ](.*?) \ [ \ /event \ -description \ ]/ism " , '' , $Text );
2011-09-03 11:36:45 +00:00
$Text = preg_replace ( " / \ [event \ -finish \ ](.*?) \ [ \ /event \ -finish \ ]/ism " , '' , $Text );
2016-05-26 03:06:21 +00:00
$Text = preg_replace ( " / \ [event \ -id \ ](.*?) \ [ \ /event \ -id \ ]/ism " , '' , $Text );
2011-09-03 11:36:45 +00:00
$Text = preg_replace ( " / \ [event \ -location \ ](.*?) \ [ \ /event \ -location \ ]/ism " , '' , $Text );
2019-10-04 21:36:08 +00:00
$Text = preg_replace ( " / \ [event \ -timezone \ ](.*?) \ [ \ /event \ -timezone \ ]/ism " , '' , $Text );
2011-09-03 11:36:45 +00:00
$Text = preg_replace ( " / \ [event \ -adjust \ ](.*?) \ [ \ /event \ -adjust \ ]/ism " , '' , $Text );
2015-07-31 05:29:10 +00:00
$Text = str_replace ( " \0 " , '$' , $Text );
2011-06-10 03:02:48 +00:00
}
2012-02-12 22:35:29 +00:00
// Unhide all [noparse] contained bbtags unspacefying them
// and triming the [noparse] tag.
2013-07-28 00:28:35 +00:00
if ( strpos ( $Text , '[noparse]' ) !== false ) {
2015-04-07 20:39:42 +00:00
$Text = preg_replace_callback ( " / \ [noparse \ ](.*?) \ [ \ /noparse \ ]/ism " , 'bb_unspacefy_and_trim' , $Text );
2013-07-28 00:28:35 +00:00
}
if ( strpos ( $Text , '[nobb]' ) !== false ) {
2015-04-07 20:39:42 +00:00
$Text = preg_replace_callback ( " / \ [nobb \ ](.*?) \ [ \ /nobb \ ]/ism " , 'bb_unspacefy_and_trim' , $Text );
2013-07-28 00:28:35 +00:00
}
if ( strpos ( $Text , '[pre]' ) !== false ) {
2015-04-07 20:39:42 +00:00
$Text = preg_replace_callback ( " / \ [pre \ ](.*?) \ [ \ /pre \ ]/ism " , 'bb_unspacefy_and_trim' , $Text );
2013-07-28 00:28:35 +00:00
}
2012-04-23 12:42:46 +00:00
2017-08-30 03:07:26 +00:00
// replace escaped links in code= blocks
$Text = str_replace ( '%eY9-!' , 'http' , $Text );
2018-01-26 00:16:55 +00:00
$Text = bb_code_unprotect ( $Text );
2017-08-30 03:07:26 +00:00
2020-11-25 03:22:59 +00:00
// This lets you use HTML entities in posts - just wrap them in brackets. For instance [©] to display a copyright symbol.
2015-04-07 20:39:42 +00:00
$Text = preg_replace ( '/\[\&\;([#a-z0-9]+)\;\]/' , '&$1;' , $Text );
2012-04-23 12:42:46 +00:00
2011-09-15 03:47:49 +00:00
// fix any escaped ampersands that may have been converted into links
2015-11-06 00:08:18 +00:00
if ( strpos ( $Text , '&' ) !== false )
$Text = preg_replace ( " / \ <(.*?)(src|href)=(.*?) \ & \ ;(.*?) \ >/ism " , '<$1$2=$3&$4>' , $Text );
// This is subtle - it's an XSS filter. It only accepts links with a protocol scheme and where
2021-02-11 01:55:10 +00:00
// the scheme begins with z (zhttp), h (http(s)), f (ftp(s)), g (gemini), m (mailto|magnet), t (tel) and named anchors.
2020-01-15 05:48:28 +00:00
// data: urls are allowed if exporting to activitypub which allows inline svg to federate, but not
// to be used for local display
2012-07-07 22:20:24 +00:00
2020-01-15 05:48:28 +00:00
if ( $activitypub ) {
2020-11-25 03:22:59 +00:00
$Text = preg_replace ( " / \ <(.*?)(src|href)= \" [^dzghfmt#](.*?) \ >/ism " , '<$1$2="">' , $Text );
2020-01-15 05:48:28 +00:00
}
else {
2020-11-25 03:22:59 +00:00
$Text = preg_replace ( " / \ <(.*?)(src|href)= \" [^zhgfmt#](.*?) \ >/ism " , '<$1$2="">' , $Text );
2020-01-15 05:48:28 +00:00
}
2012-07-18 05:11:24 +00:00
2015-04-07 20:39:42 +00:00
$Text = bb_replace_images ( $Text , $saved_images );
2015-01-30 02:13:14 +00:00
2020-05-03 06:20:00 +00:00
$args = [ 'text' => $Text , 'options' => $options ];
call_hooks ( 'bbcode' , $args );
2010-12-30 22:21:05 +00:00
2020-05-03 06:20:00 +00:00
return $args [ 'text' ];
2010-08-20 03:52:49 +00:00
}
2015-05-30 22:03:44 +00:00