]> git.mxchange.org Git - friendica.git/blobdiff - src/Content/Text/BBCode.php
Merge pull request #8657 from MrPetovan/bug/8653-catch-template-engine-errors
[friendica.git] / src / Content / Text / BBCode.php
index 601bf63b25e23dc2ee1250fbe7473da736052424..67dbe3b19aa05a3e347f0d9cb6c170a5e4e46425 100644 (file)
@@ -48,6 +48,15 @@ use Friendica\Util\XML;
 
 class BBCode
 {
+       const INTERNAL = 0;
+       const API = 2;
+       const DIASPORA = 3;
+       const CONNECTORS = 4;
+       const OSTATUS = 7;
+       const TWITTER = 8;
+       const BACKLINK = 8;
+       const ACTIVITYPUB = 9;
+
        /**
         * Fetches attachment data that were generated the old way
         *
@@ -434,28 +443,35 @@ class BBCode
         */
        public static function toPlaintext($text, $keep_urls = true)
        {
-               $naked_text = HTML::toPlaintext(BBCode::convert($text, false, 0, true), 0, !$keep_urls);
+               $naked_text = HTML::toPlaintext(self::convert($text, false, 0, true), 0, !$keep_urls);
 
                return $naked_text;
        }
 
-       private static function proxyUrl($image, $simplehtml = false)
+       private static function proxyUrl($image, $simplehtml = self::INTERNAL)
        {
                // Only send proxied pictures to API and for internal display
-               if (in_array($simplehtml, [false, 2])) {
+               if (in_array($simplehtml, [self::INTERNAL, self::API])) {
                        return ProxyUtils::proxifyUrl($image);
                } else {
                        return $image;
                }
        }
 
-       public static function scaleExternalImages($srctext)
+       /**
+        * This function changing the visual size (not the real size) of images.
+        * The function does not work for pictures with an alternate text description.
+        * This could only be changed by using some new "img" BBCode format.
+        *
+        * @param string $srctext The body with images
+        * @return string The body with possibly scaled images
+        */
+       public static function scaleExternalImages(string $srctext)
        {
                $s = $srctext;
 
                // Simplify image links
                $s = preg_replace("/\[img\=([0-9]*)x([0-9]*)\](.*?)\[\/img\]/ism", '[img]$3[/img]', $s);
-               $s = preg_replace("/\[img\=(.*?)\](.*?)\[\/img\]/ism", '[img]$1[/img]', $s);
 
                $matches = null;
                $c = preg_match_all('/\[img.*?\](.*?)\[\/img\]/ism', $s, $matches, PREG_SET_ORDER);
@@ -598,13 +614,13 @@ class BBCode
         *
         * Note: Can produce a [bookmark] tag in the returned string
         *
-        * @param string   $text
-        * @param bool|int $simplehtml
-        * @param bool     $tryoembed
+        * @param string  $text
+        * @param integer $simplehtml
+        * @param bool    $tryoembed
         * @return string
         * @throws \Friendica\Network\HTTPException\InternalServerErrorException
         */
-       private static function convertAttachment($text, $simplehtml = false, $tryoembed = true)
+       private static function convertAttachment($text, $simplehtml = self::INTERNAL, $tryoembed = true)
        {
                $data = self::getAttachmentData($text);
                if (empty($data) || empty($data['url'])) {
@@ -633,7 +649,7 @@ class BBCode
                } catch (Exception $e) {
                        $data['title'] = ($data['title'] ?? '') ?: $data['url'];
 
-                       if ($simplehtml != 4) {
+                       if ($simplehtml != self::CONNECTORS) {
                                $return = sprintf('<div class="type-%s">', $data['type']);
                        }
 
@@ -660,7 +676,7 @@ class BBCode
                                $return .= sprintf('<sup><a href="%s">%s</a></sup>', $data['url'], parse_url($data['url'], PHP_URL_HOST));
                        }
 
-                       if ($simplehtml != 4) {
+                       if ($simplehtml != self::CONNECTORS) {
                                $return .= '</div>';
                        }
                }
@@ -1018,13 +1034,10 @@ class BBCode
                $mention = Protocol::formatMention($attributes['profile'], $attributes['author']);
 
                switch ($simplehtml) {
-                       case 1:
-                               $text = ($is_quote_share? '<br />' : '') . '<p>' . html_entity_decode('&#x2672; ', ENT_QUOTES, 'UTF-8') . ' <a href="' . $attributes['profile'] . '">' . $mention . '</a>: </p>' . "\n" . '«' . $content . '»';
-                               break;
-                       case 2:
+                       case self::API:
                                $text = ($is_quote_share? '<br />' : '') . '<p>' . html_entity_decode('&#x2672; ', ENT_QUOTES, 'UTF-8') . ' ' . $author_contact['addr'] . ': </p>' . "\n" . $content;
                                break;
-                       case 3: // Diaspora
+                       case self::DIASPORA:
                                if (stripos(Strings::normaliseLink($attributes['link']), 'http://twitter.com/') === 0) {
                                        $text = ($is_quote_share? '<hr />' : '') . '<p><a href="' . $attributes['link'] . '">' . $attributes['link'] . '</a></p>' . "\n";
                                } else {
@@ -1042,7 +1055,7 @@ class BBCode
                                }
 
                                break;
-                       case 4:
+                       case self::CONNECTORS:
                                $headline = '<p><b>' . html_entity_decode('&#x2672; ', ENT_QUOTES, 'UTF-8');
                                $headline .= DI::l10n()->t('<a href="%1$s" target="_blank" rel="noopener noreferrer">%2$s</a> %3$s', $attributes['link'], $mention, $attributes['posted']);
                                $headline .= ':</b></p>' . "\n";
@@ -1050,13 +1063,10 @@ class BBCode
                                $text = ($is_quote_share? '<hr />' : '') . $headline . '<blockquote class="shared_content">' . trim($content) . '</blockquote>' . "\n";
 
                                break;
-                       case 5:
-                               $text = ($is_quote_share? '<br />' : '') . '<p>' . html_entity_decode('&#x2672; ', ENT_QUOTES, 'UTF-8') . ' ' . $author_contact['addr'] . ': </p>' . "\n" . $content;
-                               break;
-                       case 7: // statusnet/GNU Social
+                       case self::OSTATUS:
                                $text = ($is_quote_share? '<br />' : '') . '<p>' . html_entity_decode('&#x2672; ', ENT_QUOTES, 'UTF-8') . ' @' . $author_contact['addr'] . ': ' . $content . '</p>' . "\n";
                                break;
-                       case 9: // ActivityPub
+                       case self::ACTIVITYPUB:
                                $author = '@<span class="vcard"><a href="' . $author_contact['url'] . '" class="url u-url mention" title="' . $author_contact['addr'] . '"><span class="fn nickname mention">' . $author_contact['addr'] . '</span></a>:</span>';
                                $text = '<div><a href="' . $attributes['link'] . '">' . html_entity_decode('&#x2672;', ENT_QUOTES, 'UTF-8') . '</a> ' . $author . '<blockquote>' . $content . '</blockquote></div>' . "\n";
                                break;
@@ -1251,7 +1261,7 @@ class BBCode
         * @return string
         * @throws \Friendica\Network\HTTPException\InternalServerErrorException
         */
-       public static function convert($text, $try_oembed = true, $simple_html = 0, $for_plaintext = false)
+       public static function convert($text, $try_oembed = true, $simple_html = self::INTERNAL, $for_plaintext = false)
        {
                $a = DI::app();
 
@@ -1379,9 +1389,9 @@ class BBCode
 
                /// @todo Have a closer look at the different html modes
                // Handle attached links or videos
-               if (in_array($simple_html, [9])) {
+               if ($simple_html == self::ACTIVITYPUB) {
                        $text = self::removeAttachment($text);
-               } elseif (!in_array($simple_html, [0, 4])) {
+               } elseif (!in_array($simple_html, [self::INTERNAL, self::CONNECTORS])) {
                        $text = self::removeAttachment($text, true);
                } else {
                        $text = self::convertAttachment($text, $simple_html, $try_oembed);
@@ -1444,7 +1454,7 @@ class BBCode
 
                // Check for sized text
                // [size=50] --> font-size: 50px (with the unit).
-               if ($simple_html != 3) {
+               if ($simple_html != self::DIASPORA) {
                        $text = preg_replace("(\[size=(\d*?)\](.*?)\[\/size\])ism", "<span style=\"font-size: $1px; line-height: initial;\">$2</span>", $text);
                        $text = preg_replace("(\[size=(.*?)\](.*?)\[\/size\])ism", "<span style=\"font-size: $1; line-height: initial;\">$2</span>", $text);
                } else {
@@ -1714,11 +1724,19 @@ class BBCode
 
                // Replace non graphical smilies for external posts
                if (!$nosmile && !$for_plaintext) {
-                       $text = Smilies::replace($text);
+                       $text = Smilies::replace($text);                        
+               }
+
+               if (!$for_plaintext && DI::config()->get('system', 'big_emojis') && ($simple_html != self::DIASPORA)) {
+                       $conv = html_entity_decode(str_replace([' ', "\n", "\r"], '', $text));
+                       // Emojis are always 4 byte Unicode characters
+                       if (!empty($conv) && (strlen($conv) / mb_strlen($conv) == 4)) {
+                               $text = '<span style="font-size: xx-large; line-height: initial;">' . $text . '</span>';
+                       }
                }
 
                if (!$for_plaintext) {
-                       if (in_array($simple_html, [7, 9])) {
+                       if (in_array($simple_html, [self::OSTATUS, self::ACTIVITYPUB])) {
                                $text = preg_replace_callback("/\[url\](.*?)\[\/url\]/ism", 'self::convertUrlForActivityPubCallback', $text);
                                $text = preg_replace_callback("/\[url\=(.*?)\](.*?)\[\/url\]/ism", 'self::convertUrlForActivityPubCallback', $text);
                        }
@@ -1730,14 +1748,14 @@ class BBCode
                $text = str_replace(["\r","\n"], ['<br />', '<br />'], $text);
 
                // Remove all hashtag addresses
-               if ($simple_html && !in_array($simple_html, [3, 7, 9])) {
+               if ($simple_html && !in_array($simple_html, [self::DIASPORA, self::OSTATUS, self::ACTIVITYPUB])) {
                        $text = preg_replace("/([#@!])\[url\=(.*?)\](.*?)\[\/url\]/ism", '$1$3', $text);
-               } elseif ($simple_html == 3) {
+               } elseif ($simple_html == self::DIASPORA) {
                        // The ! is converted to @ since Diaspora only understands the @
                        $text = preg_replace("/([@!])\[url\=(.*?)\](.*?)\[\/url\]/ism",
                                '@<a href="$2">$3</a>',
                                $text);
-               } elseif (in_array($simple_html, [7, 9])) {
+               } elseif (in_array($simple_html, [self::OSTATUS, self::ACTIVITYPUB])) {
                        $text = preg_replace("/([@!])\[url\=(.*?)\](.*?)\[\/url\]/ism",
                                '$1<span class="vcard"><a href="$2" class="url u-url mention" title="$3"><span class="fn nickname mention">$3</span></a></span>',
                                $text);
@@ -1753,26 +1771,18 @@ class BBCode
                $text = preg_replace("/#\[url\=.*?\]\^\[\/url\]\[url\=(.*?)\](.*?)\[\/url\]/i",
                                        "[bookmark=$1]$2[/bookmark]", $text);
 
-               if (in_array($simple_html, [2, 6, 7, 8])) {
+               if (in_array($simple_html, [self::API, self::OSTATUS, self::TWITTER])) {
                        $text = preg_replace_callback("/([^#@!])\[url\=([^\]]*)\](.*?)\[\/url\]/ism", "self::expandLinksCallback", $text);
                        //$Text = preg_replace("/[^#@!]\[url\=([^\]]*)\](.*?)\[\/url\]/ism", ' $2 [url]$1[/url]', $Text);
                        $text = preg_replace("/\[bookmark\=([^\]]*)\](.*?)\[\/bookmark\]/ism", ' $2 [url]$1[/url]',$text);
                }
 
-               if ($simple_html == 5) {
-                       $text = preg_replace("/[^#@!]\[url\=(.*?)\](.*?)\[\/url\]/ism", '[url]$1[/url]', $text);
-               }
-
                // Perform URL Search
                if ($try_oembed) {
                        $text = preg_replace_callback("/\[bookmark\=([^\]]*)\](.*?)\[\/bookmark\]/ism", $try_oembed_callback, $text);
                }
 
-               if ($simple_html == 5) {
-                       $text = preg_replace("/\[bookmark\=([^\]]*)\](.*?)\[\/bookmark\]/ism", '[url]$1[/url]', $text);
-               } else {
-                       $text = preg_replace("/\[bookmark\=([^\]]*)\](.*?)\[\/bookmark\]/ism", '[url=$1]$2[/url]', $text);
-               }
+               $text = preg_replace("/\[bookmark\=([^\]]*)\](.*?)\[\/bookmark\]/ism", '[url=$1]$2[/url]', $text);
 
                // Handle Diaspora posts
                $text = preg_replace_callback(
@@ -1799,12 +1809,16 @@ class BBCode
                 * - #[url=<anything>]<term>[/url]
                 * - [url=<anything>]#<term>[/url]
                 */
-               $text = preg_replace_callback("/(?:#\[url\=[^\[\]]*\]|\[url\=[^\[\]]*\]#)(.*?)\[\/url\]/ism", function($matches) {
-                       return '#<a href="'
-                               . DI::baseUrl() . '/search?tag=' . rawurlencode($matches[1])
-                               . '" class="tag" rel="tag" title="' . XML::escape($matches[1]) . '">'
-                               . XML::escape($matches[1])
-                               . '</a>';
+               $text = preg_replace_callback("/(?:#\[url\=[^\[\]]*\]|\[url\=[^\[\]]*\]#)(.*?)\[\/url\]/ism", function($matches) use ($simple_html) {
+                       if ($simple_html == BBCode::ACTIVITYPUB) {
+                               return '<a href="' . DI::baseUrl() . '/search?tag=' . rawurlencode($matches[1])
+                                       . '" data-tag="' . XML::escape($matches[1]) . '" rel="tag ugc">#'
+                                       . XML::escape($matches[1]) . '</a>';
+                       } else {
+                               return '#<a href="' . DI::baseUrl() . '/search?tag=' . rawurlencode($matches[1])
+                                       . '" class="tag" rel="tag" title="' . XML::escape($matches[1]) . '">'
+                                       . XML::escape($matches[1]) . '</a>';
+                       }
                }, $text);
 
                // We need no target="_blank" rel="noopener noreferrer" for local links
@@ -2033,7 +2047,7 @@ class BBCode
 
                // Convert it to HTML - don't try oembed
                if ($for_diaspora) {
-                       $text = self::convert($text, false, 3);
+                       $text = self::convert($text, false, self::DIASPORA);
 
                        // Add all tags that maybe were removed
                        if (preg_match_all("/#\[url\=([$url_search_string]*)\](.*?)\[\/url\]/ism", $original_text, $tags)) {
@@ -2047,7 +2061,7 @@ class BBCode
                                $text = $text . " " . $tagline;
                        }
                } else {
-                       $text = self::convert($text, false, 4);
+                       $text = self::convert($text, false, self::CONNECTORS);
                }
 
                // If a link is followed by a quote then there should be a newline before it