From 65fc76562038473fa93a7bf64a85e8a2d090917c Mon Sep 17 00:00:00 2001 From: rica-carv Date: Sat, 27 Apr 2024 12:57:32 +0100 Subject: [PATCH 01/10] Aditional check for external missing avatars Aditional check for external linked avatars. Without the code, external linked avatars not available are shown without the default avatar --- e107_handlers/e_parse_class.php | 65 +++++++++++++-------------------- 1 file changed, 25 insertions(+), 40 deletions(-) diff --git a/e107_handlers/e_parse_class.php b/e107_handlers/e_parse_class.php index 2c7c223b50..38a9aefde8 100644 --- a/e107_handlers/e_parse_class.php +++ b/e107_handlers/e_parse_class.php @@ -63,10 +63,8 @@ class e_parse protected $staticUrl; - protected $staticUrlMap = []; - /** @var array Stored relative paths - used by replaceConstants() */ - private $relativePaths = []; + private $relativePaths = array(); // BBcode that contain preformatted code. @@ -256,8 +254,6 @@ class e_parse private $bootstrap; private $fontawesome; - private $modRewriteMedia; - private $removedList = array(); private $nodesToDelete = array(); private $nodesToConvert = array(); @@ -2424,36 +2420,26 @@ public function staticUrl($path = null, $opts = array()) } $staticArray = $this->staticUrl; // e_HTTP_STATIC; - $path = $this->replaceConstants($path, 'abs'); // replace any {THEME} etc. - $key = ltrim(eHelper::dasherize($path), '/'); if (is_array($staticArray)) { - if(!empty($this->staticUrlMap[$key])) + $cnt = count($staticArray); + $staticCount = $this->staticCount(); + if ($staticCount > ($cnt - 1)) { - $http = $this->staticUrlMap[$key]; + $staticCount = 0; + $this->staticCount(0); } - else - { - $cnt = count($staticArray); - $staticCount = $this->staticCount(); - if ($staticCount > ($cnt - 1)) - { - $staticCount = 0; - $this->staticCount(0); - } - $http = !empty($staticArray[$staticCount]) ? $staticArray[$staticCount] : e_HTTP; - $this->staticCount(1); - } + $http = !empty($staticArray[$staticCount]) ? $staticArray[$staticCount] : e_HTTP; + } else { $http = $this->staticUrl; } - $this->staticUrlMap[$key] = $http; - + $this->staticCount(1); if (empty($path)) { @@ -2462,7 +2448,7 @@ public function staticUrl($path = null, $opts = array()) $base = ''; - + $path = $this->replaceConstants($path, 'abs'); // replace any {THEME} etc. $srch = array( e_PLUGIN_ABS, @@ -2490,8 +2476,6 @@ public function staticUrl($path = null, $opts = array()) $ret = str_replace(e_MEDIA_ABS, $http . $base . e107::getFolder('media'), $ret); } - - return $ret; } @@ -2503,12 +2487,8 @@ public function staticUrl($path = null, $opts = array()) */ public function setStaticUrl($url) { - $this->staticUrl = $url; - } - public function getStaticUrlMap() - { - return $this->staticUrlMap; + $this->staticUrl = $url; } /** @@ -2656,10 +2636,10 @@ public function thumbUrl($url = null, $options = array(), $raw = false, $full = } - if ($this->modRewriteMedia && empty($options['nosef']))// SEF URL support. + if (e_MOD_REWRITE_MEDIA == true && empty($options['nosef']))// Experimental SEF URL support. { $options['full'] = $full; - $options['ext'] = pathinfo($url, PATHINFO_EXTENSION); + $options['ext'] = substr($url, -3); $options['thurl'] = $thurl; // $options['x'] = $this->thumbEncode(); @@ -3626,9 +3606,8 @@ public function init() if (defined('BOOTSTRAP')) { $this->bootstrap = (int) BOOTSTRAP; - } - $this->modRewriteMedia = deftrue('e_MOD_REWRITE_MEDIA'); + } if (defined('e_HTTP_STATIC')) { @@ -3802,6 +3781,7 @@ public function setScriptTags($array = array()) */ public function setFontAwesome($version) { + $this->fontawesome = (int) $version; } @@ -3810,13 +3790,10 @@ public function setFontAwesome($version) */ public function setBootstrap($version) { + $this->bootstrap = (int) $version; } - public function setmodRewriteMedia($bool) - { - $this->modRewriteMedia = (bool) $bool; - } /** * Add leading zeros to a number. eg. 3 might become 000003 @@ -4315,7 +4292,15 @@ public function toAvatar($userData = null, $options = array()) if (strpos($image, '://') !== false) // Remote Image { - $url = $image; + if (file_exists($image)) + { + $url = $image; + } + else + { + $file = $genericFile; + $url = $genericImg; + } } elseif (strpos($image, '-upload-') === 0) { From cc41528c3b09ccdad06079cb426b76254206612d Mon Sep 17 00:00:00 2001 From: rica-carv Date: Sat, 27 Apr 2024 13:09:03 +0100 Subject: [PATCH 02/10] Add files via upload --- e107_handlers/e_parse_class.php | 55 +++++++++++++++++++++++---------- 1 file changed, 39 insertions(+), 16 deletions(-) diff --git a/e107_handlers/e_parse_class.php b/e107_handlers/e_parse_class.php index 38a9aefde8..7b3cd85f2c 100644 --- a/e107_handlers/e_parse_class.php +++ b/e107_handlers/e_parse_class.php @@ -63,8 +63,10 @@ class e_parse protected $staticUrl; + protected $staticUrlMap = []; + /** @var array Stored relative paths - used by replaceConstants() */ - private $relativePaths = array(); + private $relativePaths = []; // BBcode that contain preformatted code. @@ -254,6 +256,8 @@ class e_parse private $bootstrap; private $fontawesome; + private $modRewriteMedia; + private $removedList = array(); private $nodesToDelete = array(); private $nodesToConvert = array(); @@ -2420,26 +2424,36 @@ public function staticUrl($path = null, $opts = array()) } $staticArray = $this->staticUrl; // e_HTTP_STATIC; + $path = $this->replaceConstants($path, 'abs'); // replace any {THEME} etc. + $key = ltrim(eHelper::dasherize($path), '/'); if (is_array($staticArray)) { - $cnt = count($staticArray); - $staticCount = $this->staticCount(); - if ($staticCount > ($cnt - 1)) + if(!empty($this->staticUrlMap[$key])) { - $staticCount = 0; - $this->staticCount(0); + $http = $this->staticUrlMap[$key]; } + else + { + $cnt = count($staticArray); + $staticCount = $this->staticCount(); + if ($staticCount > ($cnt - 1)) + { + $staticCount = 0; + $this->staticCount(0); + } - $http = !empty($staticArray[$staticCount]) ? $staticArray[$staticCount] : e_HTTP; - + $http = !empty($staticArray[$staticCount]) ? $staticArray[$staticCount] : e_HTTP; + $this->staticCount(1); + } } else { $http = $this->staticUrl; } - $this->staticCount(1); + $this->staticUrlMap[$key] = $http; + if (empty($path)) { @@ -2448,7 +2462,7 @@ public function staticUrl($path = null, $opts = array()) $base = ''; - $path = $this->replaceConstants($path, 'abs'); // replace any {THEME} etc. + $srch = array( e_PLUGIN_ABS, @@ -2476,6 +2490,8 @@ public function staticUrl($path = null, $opts = array()) $ret = str_replace(e_MEDIA_ABS, $http . $base . e107::getFolder('media'), $ret); } + + return $ret; } @@ -2487,10 +2503,14 @@ public function staticUrl($path = null, $opts = array()) */ public function setStaticUrl($url) { - $this->staticUrl = $url; } + public function getStaticUrlMap() + { + return $this->staticUrlMap; + } + /** * Generate an auto-sized Image URL. * @@ -2636,10 +2656,10 @@ public function thumbUrl($url = null, $options = array(), $raw = false, $full = } - if (e_MOD_REWRITE_MEDIA == true && empty($options['nosef']))// Experimental SEF URL support. + if ($this->modRewriteMedia && empty($options['nosef']))// SEF URL support. { $options['full'] = $full; - $options['ext'] = substr($url, -3); + $options['ext'] = pathinfo($url, PATHINFO_EXTENSION); $options['thurl'] = $thurl; // $options['x'] = $this->thumbEncode(); @@ -3606,9 +3626,10 @@ public function init() if (defined('BOOTSTRAP')) { $this->bootstrap = (int) BOOTSTRAP; - } + $this->modRewriteMedia = deftrue('e_MOD_REWRITE_MEDIA'); + if (defined('e_HTTP_STATIC')) { $this->staticUrl = e_HTTP_STATIC; @@ -3781,7 +3802,6 @@ public function setScriptTags($array = array()) */ public function setFontAwesome($version) { - $this->fontawesome = (int) $version; } @@ -3790,10 +3810,13 @@ public function setFontAwesome($version) */ public function setBootstrap($version) { - $this->bootstrap = (int) $version; } + public function setmodRewriteMedia($bool) + { + $this->modRewriteMedia = (bool) $bool; + } /** * Add leading zeros to a number. eg. 3 might become 000003 From bcaad61fdb829f10c816efe6429a74d4789572db Mon Sep 17 00:00:00 2001 From: rica-carv Date: Sat, 11 May 2024 11:32:57 +0100 Subject: [PATCH 03/10] Update e_parse_class.php Changed file_exists to fopen, to check if remote file exists --- e107_handlers/e_parse_class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/e107_handlers/e_parse_class.php b/e107_handlers/e_parse_class.php index 7b3cd85f2c..1354b19882 100644 --- a/e107_handlers/e_parse_class.php +++ b/e107_handlers/e_parse_class.php @@ -4315,7 +4315,7 @@ public function toAvatar($userData = null, $options = array()) if (strpos($image, '://') !== false) // Remote Image { - if (file_exists($image)) + if (@fopen($image, 'r')) { $url = $image; } From 912825660c97c5a0a581e04e841fbe7ee4732d74 Mon Sep 17 00:00:00 2001 From: rica-carv Date: Fri, 5 Jul 2024 21:24:55 +0100 Subject: [PATCH 04/10] Aditional change to make default avatar image render Aditional change to make default avatar image render --- e107_handlers/e_parse_class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/e107_handlers/e_parse_class.php b/e107_handlers/e_parse_class.php index 1354b19882..c60550660c 100644 --- a/e107_handlers/e_parse_class.php +++ b/e107_handlers/e_parse_class.php @@ -4308,7 +4308,7 @@ public function toAvatar($userData = null, $options = array()) $image = (!empty($userData['user_image'])) ? varset($userData['user_image']) : null; $genericFile = e_IMAGE . 'generic/blank_avatar.jpg'; - $genericImg = $tp->thumbUrl($genericFile, 'w=' . $width . '&h=' . $height, true, $full); + $genericImg = $tp->thumbUrl($genericFile, 'w=' . $width . '&h=' . $height, false, $full); if (!empty($image)) { From 9c156d417af94944bdef30d1dd9d5a7f6b4b1a70 Mon Sep 17 00:00:00 2001 From: rica-carv Date: Sat, 3 Aug 2024 15:51:12 +0100 Subject: [PATCH 05/10] Add files via upload --- e107_handlers/e_parse_class.php | 27 +++++++++++---------------- 1 file changed, 11 insertions(+), 16 deletions(-) diff --git a/e107_handlers/e_parse_class.php b/e107_handlers/e_parse_class.php index c60550660c..ffb7db99ff 100644 --- a/e107_handlers/e_parse_class.php +++ b/e107_handlers/e_parse_class.php @@ -1275,7 +1275,7 @@ public function html_truncate($text, $length = 100, $ending = '...', $exact = tr /** * @param string $text string to process - * @param integer $len length of characters to be truncated + * @param integer $len length of characters to be truncated, if it has 'w' at the end, it truncates on word instead of chars (example: limit=50w) * @param string $more string which will be added if truncation * @return string Always returns text. * @deprecated for public use. Will be made private. Use $tp->truncate() instead. @@ -1283,8 +1283,10 @@ public function html_truncate($text, $length = 100, $ending = '...', $exact = tr * Uses current CHARSET for utf-8, returns $len characters rather than $len bytes * */ - public function text_truncate($text, $len = 200, $more = ' ... ') + public function text_truncate($text, $lenght = 200, $more = ' ... ') { + + $len = intval($lenght); if ($this->ustrlen($text) <= $len) { @@ -1296,15 +1298,16 @@ public function text_truncate($text, $len = 200, $more = ' ... ') $text = $this->toText($text); } - $text = html_entity_decode($text, ENT_QUOTES, 'utf-8'); - if (function_exists('mb_strimwidth')) + if (stristr($lenght, "w") && false !== ($p = strpos(wordwrap($text, $len, $more), $more))) + {$ret = sprintf('%.'. $p . 's', $text);} + elseif (function_exists('mb_strimwidth')) { return mb_strimwidth($text, 0, $len, $more); } - - $ret = $this->usubstr($text, 0, $len); + else + {$ret = $this->usubstr($text, 0, $len);} // search for possible broken html entities // - if an & is in the last 8 chars, removing it and whatever follows shouldn't hurt @@ -4308,22 +4311,14 @@ public function toAvatar($userData = null, $options = array()) $image = (!empty($userData['user_image'])) ? varset($userData['user_image']) : null; $genericFile = e_IMAGE . 'generic/blank_avatar.jpg'; - $genericImg = $tp->thumbUrl($genericFile, 'w=' . $width . '&h=' . $height, false, $full); + $genericImg = $tp->thumbUrl($genericFile, 'w=' . $width . '&h=' . $height, true, $full); if (!empty($image)) { if (strpos($image, '://') !== false) // Remote Image { - if (@fopen($image, 'r')) - { - $url = $image; - } - else - { - $file = $genericFile; - $url = $genericImg; - } + $url = $image; } elseif (strpos($image, '-upload-') === 0) { From 3de1ea4911fcc39887901e3d6e03c01101666e53 Mon Sep 17 00:00:00 2001 From: rica-carv Date: Sat, 3 Aug 2024 15:52:05 +0100 Subject: [PATCH 06/10] Revert "Add files via upload" --- e107_handlers/e_parse_class.php | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/e107_handlers/e_parse_class.php b/e107_handlers/e_parse_class.php index ffb7db99ff..c60550660c 100644 --- a/e107_handlers/e_parse_class.php +++ b/e107_handlers/e_parse_class.php @@ -1275,7 +1275,7 @@ public function html_truncate($text, $length = 100, $ending = '...', $exact = tr /** * @param string $text string to process - * @param integer $len length of characters to be truncated, if it has 'w' at the end, it truncates on word instead of chars (example: limit=50w) + * @param integer $len length of characters to be truncated * @param string $more string which will be added if truncation * @return string Always returns text. * @deprecated for public use. Will be made private. Use $tp->truncate() instead. @@ -1283,10 +1283,8 @@ public function html_truncate($text, $length = 100, $ending = '...', $exact = tr * Uses current CHARSET for utf-8, returns $len characters rather than $len bytes * */ - public function text_truncate($text, $lenght = 200, $more = ' ... ') + public function text_truncate($text, $len = 200, $more = ' ... ') { - - $len = intval($lenght); if ($this->ustrlen($text) <= $len) { @@ -1298,16 +1296,15 @@ public function text_truncate($text, $lenght = 200, $more = ' ... ') $text = $this->toText($text); } + $text = html_entity_decode($text, ENT_QUOTES, 'utf-8'); - if (stristr($lenght, "w") && false !== ($p = strpos(wordwrap($text, $len, $more), $more))) - {$ret = sprintf('%.'. $p . 's', $text);} - elseif (function_exists('mb_strimwidth')) + if (function_exists('mb_strimwidth')) { return mb_strimwidth($text, 0, $len, $more); } - else - {$ret = $this->usubstr($text, 0, $len);} + + $ret = $this->usubstr($text, 0, $len); // search for possible broken html entities // - if an & is in the last 8 chars, removing it and whatever follows shouldn't hurt @@ -4311,14 +4308,22 @@ public function toAvatar($userData = null, $options = array()) $image = (!empty($userData['user_image'])) ? varset($userData['user_image']) : null; $genericFile = e_IMAGE . 'generic/blank_avatar.jpg'; - $genericImg = $tp->thumbUrl($genericFile, 'w=' . $width . '&h=' . $height, true, $full); + $genericImg = $tp->thumbUrl($genericFile, 'w=' . $width . '&h=' . $height, false, $full); if (!empty($image)) { if (strpos($image, '://') !== false) // Remote Image { - $url = $image; + if (@fopen($image, 'r')) + { + $url = $image; + } + else + { + $file = $genericFile; + $url = $genericImg; + } } elseif (strpos($image, '-upload-') === 0) { From 88e726119d5ce0015db41070f446d32aee456fa4 Mon Sep 17 00:00:00 2001 From: rica-carv Date: Sun, 4 Aug 2024 08:41:24 +0100 Subject: [PATCH 07/10] Delete e107_handlers/e_parse_class.php --- e107_handlers/e_parse_class.php | 5845 ------------------------------- 1 file changed, 5845 deletions(-) delete mode 100644 e107_handlers/e_parse_class.php diff --git a/e107_handlers/e_parse_class.php b/e107_handlers/e_parse_class.php deleted file mode 100644 index c60550660c..0000000000 --- a/e107_handlers/e_parse_class.php +++ /dev/null @@ -1,5845 +0,0 @@ -rror', '>', '"', ' & '); - - // Set to TRUE or FALSE once it has been calculated - protected $e_highlighting; - - // Highlight query - protected $e_query; - - private $thumbWidth = 100; - - private $thumbHeight = 0; - - private $thumbCrop = 0; - - private $thumbEncode = 0; - - private $staticCount = 0; - - protected $staticUrl; - - protected $staticUrlMap = []; - - /** @var array Stored relative paths - used by replaceConstants() */ - private $relativePaths = []; - - - // BBcode that contain preformatted code. - private $preformatted = array('html', 'markdown'); - - - // Set up the defaults - private $e_optDefault = array( - // default context: reflects legacy settings (many items enabled) - 'context' => 'OLDDEFAULT', - // - 'fromadmin' => false, - - // Enable emote display - 'emotes' => true, - - // Convert defines(constants) within text. - 'defs' => false, - - // replace all {e_XXX} constants with their e107 value - 'rel' or 'abs' - 'constants' => false, - - // Enable hooked parsers - 'hook' => true, - - // Allow scripts through (new for 0.8) - 'scripts' => true, - - // Make links clickable - 'link_click' => true, - - // Substitute on clickable links (only if link_click == TRUE) - 'link_replace' => true, - - // Parse shortcodes - TRUE enables parsing - 'parse_sc' => false, - - // remove HTML tags. - 'no_tags' => false, - - // Restore entity form of quotes and such to single characters - TRUE disables - 'value' => false, - - // Line break compression - TRUE removes newline characters - 'nobreak' => false, - - // Retain newlines - wraps to \n instead of
if TRUE (for non-HTML email text etc) - 'retain_nl' => false - ); - - // Super modifiers override default option values - private $e_SuperMods = array( - //text is part of a title (e.g. news title) - 'TITLE' => - array( - 'nobreak' => true, 'retain_nl' => true, 'link_click' => false, 'emotes' => false, 'defs' => true, 'parse_sc' => true - ), - 'TITLE_PLAIN' => - array( - 'nobreak' => true, 'retain_nl' => true, 'link_click' => false, 'emotes' => false, 'defs' => true, 'parse_sc' => true, 'no_tags' => true - ), - //text is user-entered (i.e. untrusted) and part of a title (e.g. forum title) - 'USER_TITLE' => - array( - 'nobreak' => true, 'retain_nl' => true, 'link_click' => false, 'scripts' => false, 'emotes' => false, 'hook' => false - ), - // text is 'body' of email or similar - being sent 'off-site' so don't rely on server availability - 'E_TITLE' => - array( - 'nobreak' => true, 'retain_nl' => true, 'defs' => true, 'parse_sc' => true, 'emotes' => false, 'scripts' => false, 'link_click' => false - ), - // text is part of the summary of a longer item (e.g. content summary) - 'SUMMARY' => - array( - 'defs' => true, 'constants' => 'full', 'parse_sc' => true - ), - // text is the description of an item (e.g. download, link) - 'DESCRIPTION' => - array( - 'defs' => true, 'constants' => 'full', 'parse_sc' => true - ), - // text is 'body' or 'bulk' text (e.g. custom page body, content body) - 'BODY' => - array( - 'defs' => true, 'constants' => 'full', 'parse_sc' => true - ), - // text is parsed by the Wysiwyg editor. eg. TinyMce - 'WYSIWYG' => - array( - 'hook' => false, 'link_click' => false, 'link_replace' => false, 'retain_nl' => true - ), - // text is user-entered (i.e. untrusted)'body' or 'bulk' text (e.g. custom page body, content body) - 'USER_BODY' => - array( - 'constants' => 'full', 'scripts' => false, 'nostrip' => false - ), - // text is 'body' of email or similar - being sent 'off-site' so don't rely on server availability - 'E_BODY' => - array( - 'defs' => true, 'constants' => 'full', 'parse_sc' => true, 'emotes' => false, 'scripts' => false, 'link_click' => false - ), - // text is text-only 'body' of email or similar - being sent 'off-site' so don't rely on server availability - 'E_BODY_PLAIN' => - array( - 'defs' => true, 'constants' => 'full', 'parse_sc' => true, 'emotes' => false, 'scripts' => false, 'link_click' => false, 'retain_nl' => true, 'no_tags' => true - ), - // text is the 'content' of a link (A tag, etc) - 'LINKTEXT' => - array( - 'nobreak' => true, 'retain_nl' => true, 'link_click' => false, 'emotes' => false, 'hook' => false, 'defs' => true, 'parse_sc' => true - ), - // text is used (for admin edit) without fancy conversions or html. - 'RAWTEXT' => - array( - 'nobreak' => true, 'retain_nl' => true, 'link_click' => false, 'emotes' => false, 'hook' => false, 'no_tags' => true - ), - 'NODEFAULT' => - array('context' => false, 'fromadmin' => false, 'emotes' => false, 'defs' => false, 'constants' => false, 'hook' => false, - 'scripts' => false, 'link_click' => false, 'link_replace' => false, 'parse_sc' => false, 'no_tags' => false, 'value' => false, - 'nobreak' => false, 'retain_nl' => false - ) - ); - - // Individual modifiers change the current context - private $e_Modifiers = array( - 'emotes_off' => array('emotes' => false), - 'emotes_on' => array('emotes' => true), - 'no_hook' => array('hook' => false), - 'do_hook' => array('hook' => true), - // New for 0.8 - 'scripts_off' => array('scripts' => false), - // New for 0.8 - 'scripts_on' => array('scripts' => true), - 'no_make_clickable' => array('link_click' => false), - 'make_clickable' => array('link_click' => true), - 'no_replace' => array('link_replace' => false), - // Replace text of clickable links (only if make_clickable option set) - 'replace' => array('link_replace' => true), - // No path replacement - 'consts_off' => array('constants' => false), - // Relative path replacement - 'consts_rel' => array('constants' => 'rel'), - // Absolute path replacement - 'consts_abs' => array('constants' => 'abs'), - // Full path replacement - 'consts_full' => array('constants' => 'full'), - // No shortcode parsing - 'scparse_off' => array('parse_sc' => false), - - 'scparse_on' => array('parse_sc' => true), - // Strip tags - 'no_tags' => array('no_tags' => true), - // Leave tags - 'do_tags' => array('no_tags' => false), - - 'fromadmin' => array('fromadmin' => true), - 'notadmin' => array('fromadmin' => false), - // entity replacement - 'er_off' => array('value' => false), - 'er_on' => array('value' => true), - // Decode constant if exists - 'defs_off' => array('defs' => false), - 'defs_on' => array('defs' => true), - - 'dobreak' => array('nobreak' => false), - 'nobreak' => array('nobreak' => true), - // Line break using \n - 'lb_nl' => array('retain_nl' => true), - // Line break using
- 'lb_br' => array('retain_nl' => false), - - // Legacy option names below here - discontinue later - 'retain_nl' => array('retain_nl' => true), - 'defs' => array('defs' => true), - 'parse_sc' => array('parse_sc' => true), - 'constants' => array('constants' => 'rel'), - 'value' => array('value' => true), - 'wysiwyg' => array('wysiwyg' => true) - ); - - /** - * @var DOMDocument - */ - private $domObj; - private $isHtml = false; - - private $bootstrap; - private $fontawesome; - - private $modRewriteMedia; - - private $removedList = array(); - private $nodesToDelete = array(); - private $nodesToConvert = array(); - private $nodesToDisableSC = array(); - private $pathList = array(); - - private $allowedAttributes = array(); - - - private $badAttrValues = array(); - - private $replaceAttrValues = array(); - - private $allowedTags = array(); - private $scriptTags = array(); - - private $scriptAttributes = array(); - - private $blockTags = array(); - - private $scriptAccess = false; // nobody. - private $replaceVars; - private $replaceUnset; - - /** - * Constructor - keep it public for backward compatibility - * still some new e_parse() in the core - * - */ - public function __construct() - { - - // initialise the type of UTF-8 processing methods depending on PHP version and mb string extension - $this->domObj = new DOMDocument('1.0', 'utf-8'); - $this->init(); - $this->compileAttributeDefaults(); - - } - - /** - * @param string $type - * @return array - */ - public function getModifierList($type = '') - { - if ($type === 'super') - { - return $this->e_SuperMods; - } - - return $this->e_Modifiers; - } - - - /** - * Initialise the type of UTF-8 processing methods depending on PHP version and mb string extension. - * Note: mb string is required during installation of e107. - * NOTE: can't be called until CHARSET is known - * but we all know that it is UTF-8 now - * - * @return void - */ - public function setMultibyte($bool) - { - - if ($bool === false) - { - $this->multibyte = false; - - return null; - } - - if (extension_loaded('mbstring')) - { - $this->multibyte = true; - mb_internal_encoding('UTF-8'); - } - } - - - /** - * Returns the length of the given string. - * Unicode (UTF-8) analogue of standard @link http://php.net/strlen strlen PHP function. - * - * @param string $str The UTF-8 encoded string being measured for length. - * @return integer The length (amount of UTF-8 characters) of the string on success, and 0 if the string is empty. - */ - public function ustrlen($str) - { - if ($this->multibyte) - { - return mb_strlen($str); - } - - return strlen($str); - - // return strlen(utf8_decode($str)); - } - - - /** - * Make a string lowercase. - * Unicode (UTF-8) analogue of standard @link http://php.net/strtolower strtolower PHP function. - * - * @param string $str The UTF-8 encoded string to be lowercased. - * @return string Specified string with all alphabetic characters converted to lowercase. - */ - public function ustrtolower($str) - { - if ($this->multibyte) - { - return mb_strtolower($str); - } - - return strtolower($str); - } - - - /** - * Make a string uppercase. - * Unicode (UTF-8) analogue of standard @link http://php.net/strtoupper strtoupper PHP function. - * - * @param string $str The UTF-8 encoded string to be uppercased. - * @return string Specified string with all alphabetic characters converted to uppercase. - */ - public function ustrtoupper($str) - { - - if ($this->multibyte) - { - return mb_strtoupper($str); - } - - return strtoupper($str); - - } - - - /** - * Find the position of the first occurrence of a case-sensitive UTF-8 encoded string. - * Unicode (UTF-8) analogue of standard @link http://php.net/strpos strpos PHP function. - * - * Returns the numeric position (offset in amount of UTF-8 characters) - * of the first occurrence of needle in the haystack string. - * - * @param string $haystack The UTF-8 encoded string being searched in. - * @param integer $needle The UTF-8 encoded string being searched for. - * @param integer $offset [optional] The optional offset parameter allows you to specify which character in haystack to start searching. - * The position returned is still relative to the beginning of haystack. - * @return integer|boolean Returns the position as an integer. If needle is not found, the function will return boolean FALSE. - */ - public function ustrpos($haystack, $needle, $offset = 0) - { - - if ($this->multibyte) - { - return mb_strpos($haystack, $needle, $offset); - } - - return strpos($haystack, $needle, $offset); - } - - - /** - * Find the position of the last occurrence of a case-sensitive UTF-8 encoded string. - * Unicode (UTF-8) analogue of standard @link http://php.net/strrpos strrpos PHP function. - * Returns the numeric position (offset in amount of UTF-8 characters) - * of the last occurrence of needle in the haystack string. - * - * @param string $haystack The UTF-8 encoded string being searched in. - * @param integer $needle The UTF-8 encoded string being searched for. - * @param integer $offset [optional] - The optional offset parameter allows you to specify which character in haystack to start searching. - * The position returned is still relative to the beginning of haystack. - * @return integer|boolean Returns the position as an integer. If needle is not found, the function will return boolean FALSE. - */ - public function ustrrpos($haystack, $needle, $offset = 0) - { - if ($this->multibyte) - { - return mb_strrpos($haystack, $needle, $offset); - } - - return strrpos($haystack, $needle, $offset); - } - - - /** - * Returns all of haystack starting from and including the first occurrence of needle to the end. - * Unicode (UTF-8) analogue of standard @link http://php.net/stristr stristr PHP function. - * - * @param string $haystack The UTF-8 encoded string to search in. - * @param mixed $needle If needle is not a string, it is converted to an integer and applied as the ordinal value of a character. - * @param bool $before_needle [optional] (PHP 5.3+) If TRUE, returns the part of the haystack before the first occurrence of the needle (excluding needle). - * @return string Returns the matched substring. If needle is not found, returns FALSE. - */ - public function ustristr($haystack, $needle, $before_needle = false) - { - - if ($this->multibyte) - { - return mb_stristr($haystack, $needle, $before_needle); - } - - return stristr($haystack, $needle, $before_needle); - - } - - /** - * Returns the portion of string specified by the start and length parameters. - * Unicode (UTF-8) analogue of standard @link http://php.net/substr substr PHP function. - * - * NOTE: May be subtle differences in return values dependent on which routine is used. - * Native substr() routine can return FALSE. mb_substr() and utf8_substr() just return an empty string. - * - * @param string $str The UTF-8 encoded string. - * @param integer $start Start of portion to be returned. Position is counted in amount of UTF-8 characters from the beginning of str. - * First character's position is 0. Second character position is 1, and so on. - * @param integer $length [optional] If length is given, the string returned will contain at most length characters beginning from start - * (depending on the length of string). If length is omitted, the rest of string from start will be returned. - * @return string The extracted UTF-8 encoded part of input string. - */ - public function usubstr($str, $start, $length = null) - { - - if ($this->multibyte) - { - return ($length === null) ? mb_substr($str, $start) : mb_substr($str, $start, $length); - } - - return substr($str, $start, $length); - - } - - /** - * Converts the supplied text (presumed to be from user input) to a format suitable for storing in a database table. - * - * @param mixed $data - * @param boolean $nostrip [optional] Assumes all data is GPC ($_GET, $_POST, $_COOKIE) unless indicate otherwise by setting this var to TRUE. - * If magic quotes is enabled on the server and you do not tell toDB() that the data is non GPC then slashes will be stripped when they should not be. - * @param boolean $no_encode [optional] This parameter should nearly always be FALSE. It is used by the save_prefs() function to preserve HTML content within prefs even when - * the save_prefs() function has been called by a non admin user / user without html posting permissions. - * @param boolean|string $mod [optional] model = admin-ui usage. The 'no_html' and 'no_php' modifiers blanket prevent HTML and PHP posting regardless of posting permissions. (used in logging) - * The 'pReFs' value is for internal use only, when saving prefs, to prevent sanitisation of HTML. - * @param mixed $parm [optional] - * @return mixed - * @todo complete the documentation of this essential method - */ - public function toDB($data = null, $nostrip = false, $no_encode = false, $mod = false, $parm = null) - { - - $variableType = gettype($data); - - if (($variableType !== 'string' && $variableType !== 'array') || $data === '0') - { - return $data; - } - - if ($variableType === 'array') - { - $ret = array(); - - foreach ($data as $key => $var) - { - //Fix - sanitize keys as well - $key = str_replace(['"', "'"], ['"', '''], $key); - $ret[$key] = $this->toDB($var, $nostrip, $no_encode, $mod, $parm); - } - - return $ret; - } - - - if (MAGIC_QUOTES_GPC === true && $nostrip === false) - { - $data = stripslashes($data); - } - - $core_pref = e107::getConfig(); - - if ($mod !== 'pReFs') //XXX We're not saving prefs. - { - - $data = $this->preFilter($data); // used by bb_xxx.php toDB() functions. bb_code.php toDB() allows us to properly bypass HTML cleaning below. - $data = $this->cleanHtml($data); // clean it regardless of if it is text or html. (html could have missing closing tags) - - if (($this->isHtml($data)) && strpos($mod, 'no_html') === false) - { - $this->isHtml = true; - // $data = $this->cleanHtml($data); // sanitize all html. (moved above to include everything) - - $data = str_replace(array('%7B', '%7D'), array('{', '}'), $data); // fix for {e_XXX} paths. - } - // else // caused double-encoding of '&' - { - // $data = str_replace('&','&',$data); - // $data = str_replace('<','<',$data); - // $data = str_replace('>','>',$data); - // $data = str_replace('&','&',$data); - - } - - - if (!check_class($core_pref->get('post_html', e_UC_MAINADMIN))) - { - $data = strip_tags($data); // remove tags from cleaned html. - $data = str_replace(array('[html]', '[/html]'), '', $data); - } - - // $data = html_entity_decode($data, ENT_QUOTES, 'utf-8'); // Prevent double-entities. Fix for [code] - see bb_code.php toDB(); - } - - - if (check_class($core_pref->get('post_html'))) /*$core_pref->is('post_html') && XXX preformecd by cleanHtml() */ - { - $no_encode = true; - } - - if ($parm !== null && is_numeric($parm) && !check_class($core_pref->get('post_html'), '', $parm)) - { - $no_encode = false; - } - - if ($no_encode === true && strpos($mod, 'no_html') === false) - { - $search = array('$', '"', "'", '\\', '', '<'); - $data = str_replace($search, $replace, $data); // prevent &gt; etc. - - $data = htmlspecialchars($data, ENT_QUOTES, 'UTF-8'); - $data = str_replace('\\', '\', $data); - - $ret = preg_replace("/&#(\d*?);/", "&#\\1;", $data); - } - - // XXX - php_bbcode has been deprecated. - if ((strpos($mod, 'no_php') !== false) || !check_class($core_pref->get('php_bbcode'))) - { - $ret = preg_replace("#\[(php)#i", "[\\1", $ret); - } - - // Don't allow hooks to mess with prefs. - if ($mod !== 'model') - { - return $ret; - } - - - /** - * e_parse hook - */ - $eParseList = $core_pref->get('e_parse_list'); - if (!empty($eParseList)) - { - - $opts = array( - 'nostrip' => $nostrip, - 'noencode' => $no_encode, - 'type' => $parm['type'], - 'field' => $parm['field'] - ); - - foreach ($eParseList as $plugin) - { - $hookObj = e107::getAddon($plugin, 'e_parse'); - if ($tmp = e107::callMethod($hookObj, 'toDB', $ret, $opts)) - { - $ret = $tmp; - } - - } - - } - - - return $ret; - } - - - /** - * Check for umatched 'dangerous' HTML tags - * (these can destroy page layout where users are able to post HTML) - * - * @param string $data - * @param string $tagList - if empty, uses default list of input tags. Otherwise a CSV list of tags to check (any type) - * - * @return string TRUE if an unopened closing tag found - * FALSE if nothing found - * @deprecated - */ - public function htmlAbuseFilter($data, $tagList = '') - { - - trigger_error('' . __METHOD__ . ' is deprecated. Use $tp->cleanHtml() instead.', E_USER_WARNING); // NO LAN - - return $data; - } - - - /** - * @deprecated - * Checks a string for potentially dangerous HTML tags, including malformed tags - * - */ - public function dataFilter($data, $mode = 'bbcode') - { - - trigger_error('$tp->dateFilter() is deprecated. Use $tp->filter() instead.', E_USER_WARNING); - - return $data; - } - - - /** - * Processes data as needed before its written to the DB. - * Currently gives bbcodes the opportunity to do something - * - * @param $data string - data about to be written to DB - * @return string - modified data - */ - public function preFilter($data) - { - - if (!$this->isBBcode($data)) - { - return $data; - } - - return e107::getBB()->parseBBCodes($data, defset('USERID'), 'default', 'PRE'); // $postID = logged in user here - } - - - /** - * Takes a multi-dimensional array and converts the keys to a list of routing paths. - * paths are the key and value are the top most key. - * - * @param array $array - * @return array - */ - public function toRoute($array) - { - $res = $this->_processRoute($array); - $tmp = explode("_#_", $res); - $ret = []; - foreach ($tmp as $v) - { - list($k) = explode('/', $v); - $ret[$v] = $k; - } - - return $ret; - } - - /** - * @param array $array - * @param string $prefix - * @return string - */ - private function _processRoute($array, $prefix = '') - { - $text = []; - - if (is_array($array)) - { - foreach ($array as $key => $val) - { - if ($tag = $this->_processRoute($val, $key . '/')) - { - $add = $tag; - } - else - { - $add = $key; - } - - $text[] = $prefix . $add; - } - } - - return implode('_#_', $text); - - } - - - /** - * @param string $text - * @return array|string|string[] - */ - public function toForm($text) - { - - if (empty($text)) // fix - handle proper 0, Space etc values. - { - return $text; - } - - - if (is_string($text) && strpos($text, '[html]') === 0) - { - // $text = $this->toHTML($text,true); - $search = array('"', ''', '\', '&',); // '&' must be last. - $replace = array('"', "'", "\\", '&'); - - // return htmlspecialchars_decode($text); - $text = str_replace($search, $replace, $text); - // return $text; - //$text = htmlentities($text,ENT_NOQUOTES, "UTF-8"); - - // return $text; - - } - // return htmlentities($text); - - $search = array('$', '"', '<', '>', '+'); - $replace = array('$', '"', '<', '>', '%2B'); - $text = str_replace($search, $replace, $text); - - if (is_string($text) && e107::wysiwyg() !== true) - { - // fix for utf-8 issue with html_entity_decode(); ??? - $text = urldecode($text); - // $text = str_replace(" ", " ", $text); - } - - return $text; - } - - /** - * @param $text - * @return array|string - */ - public function post_toForm($text) - { - - if (is_array($text)) - { - $arr = array(); - foreach ($text as $key => $value) - { - $key = $this->post_toForm($key); - $arr[$key] = $this->post_toForm($value); - } - - return $arr; - } - - $text = (string) $text; - - if (MAGIC_QUOTES_GPC == true) - { - $text = stripslashes($text); - } - - return str_replace(array("'", '"', '<', '>'), array(''', '"', '<', '>'), $text); - } - - - /** - * @param string $text - * @param $original_author - * @param string $extra - * @param bool $mod - * @return string - */ - public function post_toHTML($text, $original_author = false, $extra = '', $mod = false) - { - - $text = $this->toDB($text, false, false, $mod, $original_author); - - return $this->toHTML($text, true, $extra); - } - - /** - * @param $text - template to parse. - * @param boolean $parseSCFiles - parse core 'single' shortcodes - * @param object|array $extraCodes - shortcode class containing sc_xxxxx methods or an array of key/value pairs or legacy shortcode content (eg. content within .sc) - * @param object $eVars - XXX more info needed. - * @return string - */ - public function parseTemplate($text, $parseSCFiles = true, $extraCodes = null, $eVars = null) - { - - if (!is_bool($parseSCFiles)) - { - trigger_error('$parseSCFiles in parseTemplate() was given incorrect data'); - } - - return e107::getScParser()->parseCodes($text, $parseSCFiles, $extraCodes, $eVars); - } - - /** - * @experimental - * @param string $text - * @param bool $parseSCFiles - * @param object|array $extraCodes - * @param object $eVars - * @return string - */ - public function parseSchemaTemplate($text, $parseSCFiles = true, $extraCodes = null, $eVars = null) - { - $parse = e107::getScParser(); - $parse->setMode('schema'); - $text = e107::getScParser()->parseCodes($text, $parseSCFiles, $extraCodes, $eVars); - $text = str_replace(''; // markers for html-to-bbcode replacement. - $html_end = ''; - $full_text = str_replace(array('[html]', '[/html]'), '', $code_text); // quick fix.. security issue? - - $full_text = $this->parseBBCodes($full_text, $postID); // parse any embedded bbcodes eg. [img] - $full_text = $this->replaceConstants($full_text, 'abs'); // parse any other paths using {e_.... - $full_text = $html_start . $full_text . $html_end; - $full_text = $this->parseBBTags($full_text); // strip tags. - $opts['nobreak'] = true; - $parseBB = false; // prevent further bbcode processing. - - - break; - - case 'table' : // strip
from inside of - $convertNL = false; - // break; - - case 'hide' : - $proc_funcs = true; - - case 'scode': - case 'code' : - $full_text = $this->parseBBCodes($matches[0], $postID); - break; - } - - } - } - - - // Do the 'normal' processing - in principle, as previously - but think about the order. - if ($proc_funcs && !empty($full_text)) // some more speed - { - // Split out and ignore any scripts and style blocks. With just two choices we can match the closing tag in the regex - $subcon = preg_split('#((?:]+>.*?|tyle[^>]+>.*?))#mis', $full_text, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE); - foreach ($subcon as $sub_blk) - { - - if (strpos($sub_blk, '\s*[\r]*\n[\r]*#", ">", $sub_blk); - } - */ - - // Link substitution - // Convert URL's to clickable links, unless modifiers or prefs override - $sub_blk = $this->processModifiers($opts, $sub_blk, $convertNL, $parseBB, $modifiers, $postID); - - $ret_parser .= $sub_blk; - } // End of 'normal' processing for a block of text - - } // End of 'foreach() on each block of non-script text - - } // End of 'normal' parsing (non-script text) - else - { - // Text block that needed no processing at all - $ret_parser .= $full_text; - } - } - - // Quick Fix - Remove trailing
on block-level elements (eg. div, pre, table, etc. ) - $srch = array(); - $repl = array(); - - foreach ($this->blockTags as $val) - { - $srch[] = '
'; - $repl[] = ''; - } - - $ret_parser = str_replace($srch, $repl, $ret_parser); - - return trim($ret_parser); - } - - - /** - * Check if a string begins with a preformatter flag. - * - * @param $str - * @return bool - */ - private function preformatted($str) - { - - foreach ($this->preformatted as $type) - { - $code = '[' . $type . ']'; - if (strpos($str, $code) === 0) - { - return true; - } - - } - - return false; - } - - - /** - * @param $mixed - * @return array|false|string - */ - public function toUTF8($mixed) - { - - if (is_array($mixed)) - { - foreach ($mixed as $k => $v) - { - unset($mixed[$k]); - $mixed[$this->toUTF8($k)] = $this->toUTF8($v); - } - } - elseif (is_object($mixed)) - { - $objVars = get_object_vars($mixed); - foreach ($objVars as $key => $value) - { - $mixed->$key = $this->toUTF8($value); - } - } - elseif (is_string($mixed)) - { - return iconv('UTF-8', 'UTF-8//IGNORE', utf8_encode($mixed)); - } - - return $mixed; - } - - - /** - * @param string $text - * @return string - */ - public function toASCII($text) - { - - $char_map = array( - // Latin - 'À' => 'A', 'Á' => 'A', 'Â' => 'A', 'Ã' => 'A', 'Ä' => 'A', 'Å' => 'A', 'Æ' => 'AE', 'Ç' => 'C', - 'È' => 'E', 'É' => 'E', 'Ê' => 'E', 'Ë' => 'E', 'Ì' => 'I', 'Í' => 'I', 'Î' => 'I', 'Ï' => 'I', - 'Ð' => 'D', 'Ñ' => 'N', 'Ò' => 'O', 'Ó' => 'O', 'Ô' => 'O', 'Õ' => 'O', 'Ö' => 'O', 'Ő' => 'O', - 'Ø' => 'O', 'Ù' => 'U', 'Ú' => 'U', 'Û' => 'U', 'Ü' => 'U', 'Ű' => 'U', 'Ý' => 'Y', 'Þ' => 'TH', - 'ß' => 'ss', - 'à' => 'a', 'á' => 'a', 'â' => 'a', 'ã' => 'a', 'ä' => 'a', 'å' => 'a', 'æ' => 'ae', 'ç' => 'c', - 'è' => 'e', 'é' => 'e', 'ê' => 'e', 'ë' => 'e', 'ì' => 'i', 'í' => 'i', 'î' => 'i', 'ï' => 'i', - 'ð' => 'd', 'ñ' => 'n', 'ò' => 'o', 'ó' => 'o', 'ô' => 'o', 'õ' => 'o', 'ö' => 'o', 'ő' => 'o', - 'ø' => 'o', 'ù' => 'u', 'ú' => 'u', 'û' => 'u', 'ü' => 'u', 'ű' => 'u', 'ý' => 'y', 'þ' => 'th', - 'ÿ' => 'y', - // Latin symbols - '©' => '(c)', - // Greek - 'Α' => 'A', 'Β' => 'B', 'Γ' => 'G', 'Δ' => 'D', 'Ε' => 'E', 'Ζ' => 'Z', 'Η' => 'H', 'Θ' => '8', - 'Ι' => 'I', 'Κ' => 'K', 'Λ' => 'L', 'Μ' => 'M', 'Ν' => 'N', 'Ξ' => '3', 'Ο' => 'O', 'Π' => 'P', - 'Ρ' => 'R', 'Σ' => 'S', 'Τ' => 'T', 'Υ' => 'Y', 'Φ' => 'F', 'Χ' => 'X', 'Ψ' => 'PS', 'Ω' => 'W', - 'Ά' => 'A', 'Έ' => 'E', 'Ί' => 'I', 'Ό' => 'O', 'Ύ' => 'Y', 'Ή' => 'H', 'Ώ' => 'W', 'Ϊ' => 'I', - 'Ϋ' => 'Y', - 'α' => 'a', 'β' => 'b', 'γ' => 'g', 'δ' => 'd', 'ε' => 'e', 'ζ' => 'z', 'η' => 'h', 'θ' => '8', - 'ι' => 'i', 'κ' => 'k', 'λ' => 'l', 'μ' => 'm', 'ν' => 'n', 'ξ' => '3', 'ο' => 'o', 'π' => 'p', - 'ρ' => 'r', 'σ' => 's', 'τ' => 't', 'υ' => 'y', 'φ' => 'f', 'χ' => 'x', 'ψ' => 'ps', 'ω' => 'w', - 'ά' => 'a', 'έ' => 'e', 'ί' => 'i', 'ό' => 'o', 'ύ' => 'y', 'ή' => 'h', 'ώ' => 'w', 'ς' => 's', - 'ϊ' => 'i', 'ΰ' => 'y', 'ϋ' => 'y', 'ΐ' => 'i', - // Turkish - 'Ş' => 'S', 'İ' => 'I', /*'Ç' => 'C', 'Ü' => 'U', 'Ö' => 'O',*/ - 'Ğ' => 'G', - 'ş' => 's', 'ı' => 'i', /*'ç' => 'c', 'ü' => 'u', 'ö' => 'o',*/ - 'ğ' => 'g', - // Russian - 'А' => 'A', 'Б' => 'B', 'В' => 'V', 'Г' => 'G', 'Д' => 'D', 'Е' => 'E', 'Ё' => 'Yo', 'Ж' => 'Zh', - 'З' => 'Z', 'И' => 'I', 'Й' => 'J', 'К' => 'K', 'Л' => 'L', 'М' => 'M', 'Н' => 'N', 'О' => 'O', - 'П' => 'P', 'Р' => 'R', 'С' => 'S', 'Т' => 'T', 'У' => 'U', 'Ф' => 'F', 'Х' => 'H', 'Ц' => 'C', - 'Ч' => 'Ch', 'Ш' => 'Sh', 'Щ' => 'Sh', 'Ъ' => '', 'Ы' => 'Y', 'Ь' => '', 'Э' => 'E', 'Ю' => 'Yu', - 'Я' => 'Ya', - 'а' => 'a', 'б' => 'b', 'в' => 'v', 'г' => 'g', 'д' => 'd', 'е' => 'e', 'ё' => 'yo', 'ж' => 'zh', - 'з' => 'z', 'и' => 'i', 'й' => 'j', 'к' => 'k', 'л' => 'l', 'м' => 'm', 'н' => 'n', 'о' => 'o', - 'п' => 'p', 'р' => 'r', 'с' => 's', 'т' => 't', 'у' => 'u', 'ф' => 'f', 'х' => 'h', 'ц' => 'c', - 'ч' => 'ch', 'ш' => 'sh', 'щ' => 'sh', 'ъ' => '', 'ы' => 'y', 'ь' => '', 'э' => 'e', 'ю' => 'yu', - 'я' => 'ya', - // Ukrainian - 'Є' => 'Ye', 'І' => 'I', 'Ї' => 'Yi', 'Ґ' => 'G', - 'є' => 'ye', 'і' => 'i', 'ї' => 'yi', 'ґ' => 'g', - // Czech - 'Č' => 'C', 'Ď' => 'D', 'Ě' => 'E', 'Ň' => 'N', 'Ř' => 'R', 'Š' => 'S', 'Ť' => 'T', 'Ů' => 'U', - 'Ž' => 'Z', - 'č' => 'c', 'ď' => 'd', 'ě' => 'e', 'ň' => 'n', 'ř' => 'r', 'š' => 's', 'ť' => 't', 'ů' => 'u', - 'ž' => 'z', - // Polish - 'Ą' => 'A', 'Ć' => 'C', 'Ę' => 'e', 'Ł' => 'L', 'Ń' => 'N', /*'Ó' => 'o',*/ - 'Ś' => 'S', 'Ź' => 'Z', - 'Ż' => 'Z', - 'ą' => 'a', 'ć' => 'c', 'ę' => 'e', 'ł' => 'l', 'ń' => 'n',/* 'ó' => 'o',*/ - 'ś' => 's', 'ź' => 'z', - 'ż' => 'z', - // Latvian - 'Ā' => 'A',/* 'Č' => 'C',*/ - 'Ē' => 'E', 'Ģ' => 'G', 'Ī' => 'i', 'Ķ' => 'k', 'Ļ' => 'L', 'Ņ' => 'N', - /*'Š' => 'S',*/ - 'Ū' => 'u', - 'ā' => 'a', 'ē' => 'e', 'ģ' => 'g', 'ī' => 'i', 'ķ' => 'k', 'ļ' => 'l', 'ņ' => 'n', - 'ū' => 'u', - - 'ľ' => 'l', 'ŕ' => 'r', 'Ľ' => 'l', - ); - - return str_replace(array_keys($char_map), $char_map, $text); - - } - - - /** - * Use it on html attributes to avoid breaking markup . - * - * @param string $text - * @param bool $pure True to skip the text mutation by {@see e_parse::replaceConstants()} - * @example echo "Hello"; - */ - public function toAttribute($text, $pure = false) - { - - // URLs posted without HTML access may have an & in them. - - // Xhtml compliance. - $text = htmlspecialchars((string) $text, ENT_QUOTES, 'UTF-8'); - - if (!$pure && !preg_match('/&#|\'|"|<|>/s', $text)) - { - $text = $this->replaceConstants($text); - } - - return $text; - } - - /** - * Build a series of HTML attributes from the provided array - * - * Because of legacy loose typing client code usages, values that are {@see empty()} will not be added to the - * concatenated HTML attribute string except when the key is `value`, the key begins with `data-`, or the value is - * a number. - * - * @param array $attributes Key-value pairs of HTML attributes. The value must not be HTML-encoded. If the value is - * boolean true, the value will be set to the key (e.g. `['required' => true]` becomes - * "required='required'"). - * @param bool $pure True to skip the text mutation by {@see e_parse::replaceConstants()} - * @return string The HTML attributes to concatenate inside an HTML tag - * @see e_parseTest::testToAttributesMixedPureAndReplaceConstants() for an example of how to use this method - */ - public function toAttributes($attributes, $pure = false) - { - $stringifiedAttributes = []; - - foreach ($attributes as $key => $value) - { - if ($value === true && (strpos($key, 'data-') !== 0)) - { - $value = $key; - } - if (!empty($value) || is_numeric($value) || $key === "value" || strpos($key, 'data-') === 0) - { - $stringifiedAttributes[] = $key . "='" . $this->toAttribute($value, $pure) . "'"; - } - } - - return count($stringifiedAttributes) > 0 ? " " . implode(" ", $stringifiedAttributes) : ""; - } - - /** - * Flatten a multi-dimensional associative array with slashes. - * - * Based on Illuminate\Support\Arr::dot() - * - * @param $array - * @param string $prepend - * @return array - * @license https://github.com/illuminate/support/blob/master/LICENSE.md MIT License - * @copyright Copyright (c) Taylor Otwell - */ - public static function toFlatArray($array, $prepend = '') - { - $results = []; - - foreach ($array as $key => $value) - { - if (is_array($value) && !empty($value)) - { - $results = array_merge($results, static::toFlatArray($value, $prepend . $key . '/')); - } - else - { - $results[$prepend . $key] = $value; - } - } - - return $results; - } - - - /** - * Convert a flattened slash-delimited multi-dimensional array back into an actual multi-dimensional array - * - * Inverse of {@link e_parse::toFlatArray()} - * - * @param $array - * @param string $unprepend - * @return array - */ - public static function fromFlatArray($array, $unprepend = '') - { - $output = []; - foreach ($array as $key => $value) - { - if (!empty($unprepend) && substr($key, 0, strlen($unprepend)) == $unprepend) - { - $key = substr($key, strlen($unprepend)); - } - $parts = explode('/', $key); - $nested = &$output; - while (count($parts) > 1) - { - $nested = &$nested[array_shift($parts)]; - if (!is_array($nested)) $nested = []; - } - $nested[array_shift($parts)] = $value; - } - - return $output; - } - - - /** - * Convert text blocks which are to be embedded within JS - * - * @param string|array $stringarray - * @return string - * @deprecated v2.3.1 This method will not escape a string properly for use as a JavaScript or JSON string. Use - * {@see e_parse::toJSON()} instead. When using {@see e_parse::toJSON()}, do not surround its output - * with quotation marks, and do not attempt to escape sequences like "\n" as "\\n". If HTML tags need to - * be removed, consider {@see e_parse::toText()} separately. If the text needs to be used in an HTML - * tag attribute (e.g. <a onclick="ATTRIBUTE"></a>), surround the string with - * {@see e_parse::toAttribute()} and either single-quote or double-quote the attribute value. - */ - public function toJS($stringarray) - { - trigger_error('' . __METHOD__ . ' is deprecated. See method DocBlock for alternatives.', E_USER_WARNING); // NO LAN - - $search = array("\r\n", "\r", '
', "'"); - $replace = array("\\n", '', "\\n", "\'"); - $stringarray = str_replace($search, $replace, $stringarray); - $stringarray = strip_tags($stringarray); - - $trans_tbl = get_html_translation_table(HTML_ENTITIES); - $trans_tbl = array_flip($trans_tbl); - - return strtr($stringarray, $trans_tbl); - } - - - /** - * Converts a PHP variable into its JavaScript equivalent. - * We use HTML-safe strings, with several characters escaped. - * - * @param mixed $var - * PHP variable. - * @param bool $force_object - * True: Outputs an object rather than an array when a non-associative - * array is used. Especially useful when the recipient of the output - * is expecting an object and the array is empty. - * - * @return string - */ - public function toJSON($var, $force_object = false) - { - if ($force_object === true) - { - // Encode <, >, ', &, and " using the json_encode() options parameter. - return json_encode($var, JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_AMP | JSON_HEX_QUOT | JSON_FORCE_OBJECT); - } - - // Encode <, >, ', &, and " using the json_encode() options parameter. - return json_encode($var, JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_AMP | JSON_HEX_QUOT); - - } - - - /** - * Convert Text for RSS/XML use. - * - * @param string $text - * @param boolean $tags [optional] - * @return string - */ - public function toRss($text, $tags = false) - { - - if ($tags != true) - { - $text = $this->toHTML($text, true); - $text = strip_tags($text); - - } - - $text = $this->toEmail($text); - - $search = array('&#039;', '&#036;', ''', '$', e_BASE, "href='request.php", '', ''); - $replace = array("'", '$', "'", '$', SITEURL, "href='" . SITEURL . 'request.php', '', ''); - $text = str_replace($search, $replace, $text); - - $text = $this->ampEncode($text); - - // if CDATA happens to be quoted in the text. - $text = str_replace([''], ['<![CDATA', ']]>'], $text); - - if ($tags === true) - { - $text = !empty($text) ? '' : ''; - } - else - { - $text = str_replace(['<', '>'], ['<', '>'], $text); - } - - return $text; - } - - - /** - * Convert a string to a number (int/float) - * - * @param string $value - * @return int|float - */ - public function toNumber($value) - { - - // adapted from: https://secure.php.net/manual/en/function.floatval.php#114486 - $dotPos = strrpos($value, '.'); - $commaPos = strrpos($value, ','); - $sep = (($dotPos > $commaPos) && $dotPos) ? $dotPos : - ((($commaPos > $dotPos) && $commaPos) ? $commaPos : false); - - if (!$sep) - { - return (int) preg_replace('/[^-0-9]/', '', $value); - } - - return (float) ( - preg_replace('/[^-0-9]/', '', substr($value, 0, $sep)) . '.' . - preg_replace('/[^0-9]/', '', substr($value, $sep + 1, strlen($value))) - ); - } - - - /** - * Clean and Encode Ampersands '&' for output to browser. - * - * @param string $text - * @return array|string|string[] - */ - public function ampEncode($text = '') - { - - // Fix any left-over '&' - //first revert any previously converted. - $text = str_replace(array('&', '&'), array('&', '&'), $text); - - return $text; - } - - - /** - * Convert any string back to plain text. - * - * @param $text - * @return array|string|string[] - */ - public function toText($text) - { - $text = (string) $text; - - if ($this->isBBcode($text) === true) // convert any bbcodes to html - { - $text = $this->toHTML($text, true); - } - - if ($this->isHtml($text) === true) // strip any html. - { - $text = $this->toHTML($text, true); - $text = str_replace("\n", '', $text); // clean-out line-breaks. - $text = str_ireplace(array('
', '
', '
'), "\n", $text); - $text = strip_tags($text); - } - - $search = array('&#039;', '&#036;', ''', '$', '\', '&#092;'); - $replace = array("'", '$', "'", '$', "\\", "\\"); - $text = str_replace($search, $replace, $text); - - return $text; - } - - - /** - * Set the dimensions of a thumbNail (generated by thumbUrl) - */ - public function setThumbSize($w = null, $h = null, $crop = null) - { - - if ($w !== null) - { - $this->thumbWidth = (int) $w; - } - - if ($h !== null) - { - $this->thumbHeight = (int) $h; - } - - if ($crop !== null) - { - $this->thumbCrop = (int) $crop; - } - - } - - /** - * @param $val - * @return int|null - */ - public function thumbEncode($val = null) - { - - if ($val !== null) - { - $this->thumbEncode = (int) $val; - - return null; - } - - return $this->thumbEncode; - } - - - /** - * Retrieve img tag width and height attributes for current thumbnail. - * - * @return string - */ - public function thumbDimensions($type = 'single') - { - - if (!empty($this->thumbCrop) && !empty($this->thumbWidth) && !empty($this->thumbHeight)) // dimensions are known. - { - return ($type === 'double') ? 'width="' . $this->thumbWidth . '" height="' . $this->thumbHeight . '"' : "width='" . $this->thumbWidth . "' height='" . $this->thumbHeight . "'"; - } - - return null; - } - - - /** - * Set or Get the value of the thumbNail Width. - * - * @param $width (optional) - */ - public function thumbWidth($width = null) - { - - if ($width !== null) - { - $this->thumbWidth = (int) $width; - } - - return $this->thumbWidth; - } - - /** - * Set or Get the value of the thumbNailbCrop. - * - * @param bool $status = true/false - */ - public function thumbCrop($status = false) - { - - if ($status !== false) - { - $this->thumbCrop = (int) $status; - } - - return $this->thumbCrop; - } - - - /** - * Set or Get the value of the thumbNail height. - * - * @param $height (optional) - */ - public function thumbHeight($height = null) - { - - if ($height !== null) - { - $this->thumbHeight = (int) $height; - } - - return $this->thumbHeight; - - } - - /** - * Generated a Thumb Cache File Name from path and options. - * - * @param string $path - * @param array $options - * @param string $log (optional) - log file name - * @return null|string - */ - public function thumbCacheFile($path, $options = null, $log = null) - { - - if (empty($path)) - { - return null; - } - - if (is_string($options)) - { - parse_str($options, $options); - } - - $path = str_replace($this->getUrlConstants('raw'), $this->getUrlConstants('sc'), $path); - $path = $this->replaceConstants(str_replace('..', '', $path)); - - $filename = basename($path); - $tmp = explode('.', $filename); - $ext = end($tmp); - $len = strlen($ext) + 1; - $start = substr($filename, 0, -$len); - - // cleanup. - $newOpts = array( - 'w' => isset($options['w']) ? (string) intval($options['w']) : '', - 'h' => isset($options['h']) ? (string) intval($options['h']) : '', - 'aw' => isset($options['aw']) ? (string) intval($options['aw']) : '', - 'ah' => isset($options['ah']) ? (string) intval($options['ah']) : '', - 'c' => strtoupper(vartrue($options['c'], '0')), - ); - - if (!empty($options['type'])) - { - $newOpts['type'] = $options['type']; - $ext = $newOpts['type']; - } - - - if (!empty($options['aw'])) - { - $options['w'] = $options['aw']; - } - - if (!empty($options['ah'])) - { - $options['h'] = $options['ah']; - } - - - $size = varset($options['w'], 0) . 'x' . varset($options['h'], 0); - - $thumbQuality = e107::getPref('thumbnail_quality', 65); - - $cache_str = md5(serialize($newOpts) . $path . $thumbQuality); - - $pre = 'thumb_'; - $post = '.cache.bin'; - - // $cache_str = http_build_query($newOpts,null,'_'); // testing files. - - if (defined('e_MEDIA_STATIC')) // experimental - subject to change. - { - $pre = ''; - $post = ''; - } - - $fname = $pre . strtolower($start . '_' . $cache_str . '_' . $size . '.' . $ext) . $post; - - - if ($log !== null) - { - file_put_contents(e_LOG . $log, "\n++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n\n", FILE_APPEND); - $message = 'Name: ' . $fname . "\n"; - $message .= $path . "\n" . var_export($newOpts, true) . "\n\n\n"; - file_put_contents(e_LOG . $log, $message, FILE_APPEND); - - // file_put_contents(e_LOG.$log, "\t\tFOUND!!\n\n\n", FILE_APPEND); - } - - - return $fname; - } - - - /** - * @param bool|int $val - * @return int - */ - private function staticCount($val = false) - { - - $count = $this->staticCount; - - if ($val === 0) - { - $this->staticCount = 0; - } - elseif ($val !== false) - { - $this->staticCount += (int) $val; - } - - return $count; - - } - - - /** - * @param string $path - absolute path or e107 path {e_PLUGIN} etc. - * @param array $opts - when $opts['full'] is true, a full siteurl will be used instead of an absolute path. (unless static url is found) - * @return string - full path or static path. - * @todo Move to e107_class ? - */ - public function staticUrl($path = null, $opts = array()) - { - - if (empty($this->staticUrl) || deftrue('e_ADMIN_AREA')) - { - // e107::getDebug()->log("e_HTTP_STATIC not defined"); - if ($path === null) - { - return !empty($opts['full']) ? SITEURL : e_HTTP; - } - - return !empty($opts['full']) ? $this->replaceConstants($path, 'full') : $this->replaceConstants($path, 'abs'); // self::replaceConstants($path, 'full'); - } - - $staticArray = $this->staticUrl; // e_HTTP_STATIC; - $path = $this->replaceConstants($path, 'abs'); // replace any {THEME} etc. - $key = ltrim(eHelper::dasherize($path), '/'); - - if (is_array($staticArray)) - { - if(!empty($this->staticUrlMap[$key])) - { - $http = $this->staticUrlMap[$key]; - } - else - { - $cnt = count($staticArray); - $staticCount = $this->staticCount(); - if ($staticCount > ($cnt - 1)) - { - $staticCount = 0; - $this->staticCount(0); - } - - $http = !empty($staticArray[$staticCount]) ? $staticArray[$staticCount] : e_HTTP; - $this->staticCount(1); - } - } - else - { - $http = $this->staticUrl; - } - - $this->staticUrlMap[$key] = $http; - - - if (empty($path)) - { - return $http; - } - - $base = ''; - - - - $srch = array( - e_PLUGIN_ABS, - e_THEME_ABS, - e_WEB_ABS, - e_CACHE_IMAGE_ABS, - ); - - - $repl = array( - $http . $base . e107::getFolder('plugins'), - $http . $base . e107::getFolder('themes'), - $http . $base . e107::getFolder('web'), - $http . $base . str_replace('../', '', e_CACHE_IMAGE), - ); - - // Quickfix for any '/./' that may occur. - $srch[] = '/./'; - $repl[] = '/'; - - $ret = str_replace($srch, $repl, $path); - - if (strpos($ret, 'http') !== 0) // if not converted, check media folder also. - { - $ret = str_replace(e_MEDIA_ABS, $http . $base . e107::getFolder('media'), $ret); - } - - - - return $ret; - - } - - /** - * Used internally to store e_HTTP_STATIC. - * - * @param string|null $url The static URL ie. e_HTTP_STATIC - */ - public function setStaticUrl($url) - { - $this->staticUrl = $url; - } - - public function getStaticUrlMap() - { - return $this->staticUrlMap; - } - - /** - * Generate an auto-sized Image URL. - * - * @param $url - path to image or leave blank for a placeholder. eg. {e_MEDIA}folder/my-image.jpg - * @param array $options = [ width and height, but leaving this empty and using $this->thumbWidth() and $this->thumbHeight() is preferred. ie. {SETWIDTH: w=x&y=x} - * 'w' => int width (optional) - * 'h' => int height (optional) - * 'crop' => bool|string true/false or A(auto) or T(op) or B(ottom) or C(enter) or L(eft) or R(right) - * 'scale' => string '2x' (optional) - * 'x' => bool encode/mask the url parms (optional) - * 'nosef' => bool when set to true disabled SEF Url being returned (optional) - * ] - * @param bool $raw set to true when the $url does not being with an e107 variable ie. "{e_XXXX}" eg. {e_MEDIA} (optional) - * @param bool $full when true returns full http:// url. (optional) - * ] - * @return string - */ - public function thumbUrl($url = null, $options = array(), $raw = false, $full = false) - { - $url = (string) $url; - - $this->staticCount++; // increment counter. - - $ext = pathinfo($url, PATHINFO_EXTENSION); - - if ($ext === 'svg') - { - return $this->replaceConstants($url, 'abs'); - } - - if (strpos($url, '{e_') === 0) // Fix for broken links that use {e_MEDIA} etc. - { - //$url = $this->replaceConstants($url,'abs'); - // always switch to 'nice' urls when SC is used - $url = str_replace($this->getUrlConstants('sc'), $this->getUrlConstants('raw'), $url); - } - - if (is_string($options)) - { - parse_str($options, $options); - } - - if (!empty($options['scale'])) // eg. scale the width height 2x 3x 4x. etc. - { - $options['return'] = 'src'; - $options['size'] = $options['scale']; - unset($options['scale']); - - return $this->thumbSrcSet($url, $options); - } - - - if (strpos($url, e_MEDIA) !== false || strpos($url, e_SYSTEM) !== false) // prevent disclosure of 'hashed' path. - { - $raw = true; - } - - if ($raw) - { - $url = $this->createConstants($url, 'mix'); - } - - $baseurl = ($full ? SITEURL : e_HTTP) . 'thumb.php?'; - - if (!empty($this->staticUrl)) - { - $baseurl = $this->staticUrl() . 'thumb.php?'; - } - - $thurl = 'src=' . urlencode($url) . '&'; - - // e107::getDebug()->log("Thumb: ".basename($url). print_a($options,true), E107_DBG_BASIC); - - if (!empty($options) && (isset($options['w']) || isset($options['aw']) || isset($options['h']))) - { - $options['w'] = varset($options['w']); - $options['h'] = varset($options['h']); - $options['crop'] = (isset($options['aw']) || isset($options['ah'])) ? 1 : varset($options['crop']); - $options['aw'] = varset($options['aw']); - $options['ah'] = varset($options['ah']); - $options['x'] = varset($options['x']); - } - else - { - $options['w'] = $this->thumbWidth; - $options['h'] = $this->thumbHeight; - $options['crop'] = $this->thumbCrop; - $options['aw'] = null; - $options['ah'] = null; - $options['x'] = $this->thumbEncode; - - } - - - if (!empty($options['crop'])) - { - if (!empty($options['aw']) || !empty($options['ah'])) - { - $options['w'] = $options['aw']; - $options['h'] = $options['ah']; - } - - $thurl .= 'aw=' . (int) $options['w'] . '&ah=' . (int) $options['h']; - - if (!is_numeric($options['crop'])) - { - $thurl .= '&c=' . $options['crop']; - $options['nosef'] = true; - } - - } - else - { - - $thurl .= 'w=' . (int) $options['w'] . '&h=' . (int) $options['h']; - - } - - if (!empty($options['type'])) - { - $thurl .= '&type=' . $options['type']; - } - - - if (defined('e_MEDIA_STATIC')) // experimental - subject to change. - { - $opts = str_replace('&', '&', $thurl); - - $staticFile = $this->thumbCacheFile($url, $opts); - - - if (!empty($staticFile) && is_readable(e_CACHE_IMAGE . $staticFile)) - { - return $this->staticUrl(e_CACHE_IMAGE_ABS . $staticFile); - - } - - // echo "
static-not-found: ".$staticFile; - - $options['nosef'] = true; - $options['x'] = null; - // file_put_contents(e_LOG."thumb.log", "\n++++++++++++++++++++++++++++++++++\n\n", FILE_APPEND); - } - - - if ($this->modRewriteMedia && empty($options['nosef']))// SEF URL support. - { - $options['full'] = $full; - $options['ext'] = pathinfo($url, PATHINFO_EXTENSION); - $options['thurl'] = $thurl; - // $options['x'] = $this->thumbEncode(); - - if ($sefUrl = $this->thumbUrlSEF($url, $options)) - { - return $sefUrl; - } - } - - if (!empty($options['x']))//base64 encode url - { - $thurl = 'id=' . base64_encode($thurl); - } - - return $baseurl . $thurl; - } - - - /** - * Split a thumb.php url into an array which can be parsed back into the thumbUrl method. . - * - * @param $src - * @return array - */ - public function thumbUrlDecode($src) - { - - list($url, $qry) = array_pad(explode('?', $src), 2, null); - - $ret = array(); - - if (!empty($qry) && strpos($url, 'thumb.php') !== false) // Regular - { - parse_str($qry, $val); - $ret = $val; - } - elseif (preg_match('/media\/img\/(a)?([\d]*)x(a)?([\d]*)\/(.*)/', $url, $match)) // SEF - { - $wKey = $match[1] . 'w'; - $hKey = $match[3] . 'h'; - - $ret = array( - 'src' => 'e_MEDIA_IMAGE/' . $match[5], - $wKey => $match[2], - $hKey => $match[4] - ); - } - elseif (preg_match('/theme\/img\/(a)?([\d]*)x(a)?([\d]*)\/(.*)/', $url, $match)) // Theme-image SEF Urls - { - $wKey = $match[1] . 'w'; - $hKey = $match[3] . 'h'; - - $ret = array( - 'src' => 'e_THEME/' . $match[5], - $wKey => $match[2], - $hKey => $match[4] - ); - - } - elseif (defined('TINYMCE_DEBUG')) - { - print_a('thumbUrlDecode: No Matches'); - - } - - - return $ret; - } - - - /** - * Experimental: Generate a Thumb URL for use in the img srcset attribute. - * - * @param string $src eg. {e_MEDIA_IMAGE}myimage.jpg - * @param int|string|array $width - desired size in px or '2x' or '3x' or null for all or array ( - * @return string - */ - public function thumbSrcSet($src = '', $width = null) - { - - $multiply = null; - $encode = false; - $parm = array(); - - if (is_array($width)) - { - $parm = $width; - $multiply = $width['size']; - $encode = (!empty($width['x'])) ? $width['x'] : false; - $width = $width['size']; - } - - - // $encode = $this->thumbEncode();; - if ($width == null || $width === 'all') - { - $links = array(); - $mag = ($width == null) ? array(1, 2) : array(160, 320, 460, 600, 780, 920, 1100); - foreach ($mag as $v) - { - $w = ($this->thumbWidth * $v); - $h = ($this->thumbHeight * $v); - - $att = (!empty($this->thumbCrop)) ? array('aw' => $w, 'ah' => $h) : compact('w', 'h'); - $att['x'] = $encode; - - $add = ($width == null) ? ' ' . $v . 'x' : ' ' . $v . 'w'; - $links[] = $this->thumbUrl($src, $att) . $add; // " w".$width; // - } - - return implode(', ', $links); - - } - elseif ($multiply === '2x' || $multiply === '3x' || $multiply === '4x') - { - $multiInt = (int) $multiply; - - if (empty($parm['w']) && isset($parm['h'])) - { - $parm['h'] = ($parm['h'] * $multiInt); - - return $this->thumbUrl($src, $parm) . ' ' . $multiply; - } - - if (isset($parm['w']) && !isset($parm['h'])) // if w set, assume h value of 0 is set. - { - $parm['h'] = 0; - } - - $width = !empty($parm['w']) ? (intval($parm['w']) * $multiInt) : ($this->thumbWidth * $multiInt); - $height = isset($parm['h']) ? (intval($parm['h']) * $multiInt) : ($this->thumbHeight * $multiInt); - - } - else - { - $height = (($this->thumbHeight * $width) / $this->thumbWidth); - - } - - - if (!isset($parm['aw'])) - { - $parm['aw'] = null; - } - - if (!isset($parm['ah'])) - { - $parm['ah'] = null; - } - - if (!isset($parm['x'])) - { - $parm['x'] = null; - } - - if (!isset($parm['crop'])) - { - $parm['crop'] = null; - } - - $parms = array('w' => $width, 'h' => $height, 'crop' => $parm['crop'], 'x' => $parm['x'], 'aw' => $parm['aw'], 'ah' => $parm['ah']); - - if (!empty($parm['type'])) - { - $parms['type'] = $parm['type']; - } - // $parms = !empty($this->thumbCrop) ? array('aw' => $width, 'ah' => $height, 'x'=>$encode) : array('w' => $width, 'h' => $height, 'x'=>$encode ); - - // $parms['x'] = $encode; - - if (!empty($parm['return']) && $parm['return'] === 'src') - { - return $this->thumbUrl($src, $parms); - } - - $ret = $this->thumbUrl($src, $parms); - - $ret .= ($multiply) ? ' ' . $multiply : ' ' . $width . 'w'; - - return $ret; - - } - - - - /** - * Used by thumbUrl when SEF Image URLS is active. @param $url - * - * @param array $options - * @return string - * @see e107.htaccess - */ - public function thumbUrlSEF($url = '', $options = array()) - { - - if (!empty($options['full'])) - { - $base = SITEURL; - } - else - { - $base = (!empty($options['ebase'])) ? '{e_BASE}' : e_HTTP; - } - - if (!empty($this->staticUrl)) - { - $base = $this->staticUrl(); - } - // $base = (!empty($options['full'])) ? SITEURL : e_HTTP; - - if (!empty($options['x']) && !empty($options['ext'])) // base64 encoded. Build URL for: RewriteRule ^media\/img\/([-A-Za-z0-9+/]*={0,3})\.(jpg|gif|png)?$ thumb.php?id=$1 - { - $ext = strtolower($options['ext']); - - return $base . 'media/img/' . base64_encode($options['thurl']) . '.' . str_replace('jpeg', 'jpg', $ext); - } - elseif (strpos($url, 'e_MEDIA_IMAGE') !== false) // media images. - { - $sefPath = 'media/img/'; - $clean = array('{e_MEDIA_IMAGE}', 'e_MEDIA_IMAGE/'); - } - elseif (strpos($url, 'e_AVATAR') !== false) // avatars - { - $sefPath = 'media/avatar/'; - $clean = array('{e_AVATAR}', 'e_AVATAR/'); - } - elseif (strpos($url, 'e_THEME') !== false) // theme folder images. - { - $sefPath = 'theme/img/'; - $clean = array('{e_THEME}', 'e_THEME/'); - } - else - { - // e107::getDebug()->log("SEF URL False: ".$url); - return false; - } - - // Build URL for ReWriteRule ^media\/img\/(a)?([\d]*)x(a)?([\d]*)\/(.*)?$ thumb.php?src=e_MEDIA_IMAGE/$5&$1w=$2&$3h=$4 - $sefUrl = $base . $sefPath; - - if (!empty($options['scale'])) - { - $multiInt = (int) $options['scale']; - $options['w'] = $options['w'] * $multiInt; - $options['h'] = $options['h'] * $multiInt; - } - - - if (!empty($options['aw']) || !empty($options['ah'])) - { - $sefUrl .= 'a' . intval($options['aw']) . 'xa' . intval($options['ah']); - } - elseif (!empty($options['crop'])) - { - - if (!is_numeric($options['crop'])) - { - $sefUrl .= strtolower($options['crop']) . intval($options['w']) . 'x' . strtolower($options['crop']) . intval($options['h']); - } - else - { - $sefUrl .= 'a' . intval($options['w']) . 'xa' . intval($options['h']); - } - - - } - else - { - $sefUrl .= intval($options['w']) . 'x' . intval($options['h']); - } - - $sefUrl .= '/'; - $sefUrl .= str_replace($clean, '', $url); - - return $sefUrl; - - } - - /** - * Help for converting to more safe URLs - * e.g. {e_MEDIA_FILE}path/to/video.flv => e_MEDIA_FILE/path/to/video.flv - * - * @param string $type sc|raw|rev|all - * @return array - * @todo support for ALL URL shortcodes (replacement methods) - */ - public function getUrlConstants($type = 'sc') - { - - // sub-folders first! - static $array = array( - 'e_MEDIA_FILE/' => '{e_MEDIA_FILE}', - 'e_MEDIA_VIDEO/' => '{e_MEDIA_VIDEO}', - 'e_MEDIA_IMAGE/' => '{e_MEDIA_IMAGE}', - 'e_MEDIA_ICON/' => '{e_MEDIA_ICON}', - 'e_AVATAR/' => '{e_AVATAR}', - 'e_AVATAR_DEFAULT/' => '{e_AVATAR_DEFAULT}', - 'e_AVATAR_UPLOAD/' => '{e_AVATAR_UPLOAD}', - 'e_WEB_JS/' => '{e_WEB_JS}', - 'e_WEB_CSS/' => '{e_WEB_CSS}', - 'e_WEB_IMAGE/' => '{e_WEB_IMAGE}', - 'e_IMPORT/' => '{e_IMPORT}', - // 'e_WEB_PACK/' => '{e_WEB_PACK}', - - 'e_BASE/' => '{e_BASE}', - 'e_ADMIN/' => '{e_ADMIN}', - 'e_IMAGE/' => '{e_IMAGE}', - 'e_THEME/' => '{e_THEME}', - 'e_PLUGIN/' => '{e_PLUGIN}', - 'e_HANDLER/' => '{e_HANDLER}', // BC - 'e_MEDIA/' => '{e_MEDIA}', - 'e_WEB/' => '{e_ADMIN}', - // 'THEME/' => '{THEME}', - ); - - - switch ($type) - { - case 'sc': - return array_values($array); - break; - - case 'raw': - return array_keys($array); - break; - - case 'rev': - return array_reverse($array, true); - break; - - case 'all': - return $array; - break; - } - - return array(); - } - - - /** - * @return array - */ - public function getEmotes() - { - - return e107::getEmote()->getList(); - } - - - /** - * Replace e107 path constants - * Note: only an ADMIN user can convert {e_ADMIN} - * TODO - runtime cache of search/replace arrays (object property) when $mode !== '' - * - * @param string $text - * @param string $mode [optional] abs|full "full" = produce absolute URL path, e.g. http://sitename.com/e107_plugins/etc - * 'abs' = produce truncated URL path, e.g. e107plugins/etc - * "" (default) = URL's get relative path e.g. ../e107_plugins/etc - * @param mixed $all [optional] if TRUE, then when $mode is "full" or TRUE, USERID is also replaced... - * when $mode is "" (default), ALL other e107 constants are replaced - * @return string|array - */ - public function replaceConstants($text, $mode = '', $all = false) - { - - if (is_array($text)) - { - $new = array(); - foreach ($text as $k => $v) - { - $new[$k] = $this->replaceConstants($v, $mode, $all); - } - - return $new; - } - - $replace_absolute = array(); - - if (!empty($mode)) - { - $e107 = e107::getInstance(); - - if (empty($this->relativePaths)) // prevent multiple lookups. - { - - $this->relativePaths = array( - $e107::getFolder('media_files'), - $e107::getFolder('media_video'), - $e107::getFolder('media_image'), - $e107::getFolder('media_icon'), - $e107::getFolder('avatars'), - $e107::getFolder('web_js'), - $e107::getFolder('web_css'), - $e107::getFolder('web_image'), - //$e107->getFolder('web_pack'), - e_IMAGE_ABS, - e_THEME_ABS, - $e107::getFolder('images'), - $e107::getFolder('plugins'), - $e107::getFolder('files'), - $e107::getFolder('themes'), - // $e107->getFolder('downloads'), - $e107::getFolder('handlers'), - $e107::getFolder('media'), - $e107::getFolder('web'), - $e107->site_theme ? $e107::getFolder('themes') . $e107->site_theme . '/' : '', - defset('THEME_ABS'), - (deftrue('ADMIN') ? $e107::getFolder('admin') : ''), - '', - $e107::getFolder('core'), - $e107::getFolder('system'), - ); - } - - $replace_relative = $this->relativePaths; - - switch ($mode) - { - case 'abs': - $replace_absolute = array( - e_MEDIA_FILE_ABS, - e_MEDIA_VIDEO_ABS, - e_MEDIA_IMAGE_ABS, - e_MEDIA_ICON_ABS, - e_AVATAR_ABS, - e_JS_ABS, - e_CSS_ABS, - e_WEB_IMAGE_ABS, - // e_PACK_ABS, - e_IMAGE_ABS, - e_THEME_ABS, - e_IMAGE_ABS, - e_PLUGIN_ABS, - e_FILE_ABS, - e_THEME_ABS, - // e_DOWNLOAD_ABS, //impossible when download is done via php. - '', // handlers - no ABS path available - e_MEDIA_ABS, - e_WEB_ABS, - defset('THEME_ABS'), - defset('THEME_ABS'), - (ADMIN ? e_ADMIN_ABS : ''), - $e107->server_path, - '', // no e_CORE absolute path - '', // no e_SYSTEM absolute path - ); - break; - - case 'full': - $replace_absolute = array( - SITEURLBASE . e_MEDIA_FILE_ABS, - SITEURLBASE . e_MEDIA_VIDEO_ABS, - SITEURLBASE . e_MEDIA_IMAGE_ABS, - SITEURLBASE . e_MEDIA_ICON_ABS, - SITEURLBASE . e_AVATAR_ABS, - SITEURLBASE . e_JS_ABS, - SITEURLBASE . e_CSS_ABS, - SITEURLBASE . e_WEB_IMAGE_ABS, - // SITEURLBASE.e_PACK_ABS, - SITEURLBASE . e_IMAGE_ABS, - SITEURLBASE . e_THEME_ABS, - SITEURLBASE . e_IMAGE_ABS, - SITEURLBASE . e_PLUGIN_ABS, - SITEURLBASE . e_FILE_ABS, // deprecated - SITEURLBASE . e_THEME_ABS, - //SITEURL.$e107->getFolder('downloads'), - '', // handlers - no ABS path available - SITEURLBASE . e_MEDIA_ABS, - SITEURLBASE . e_WEB_ABS, - defset('THEME_ABS') ? SITEURLBASE . THEME_ABS : '', - defset('THEME_ABS') ? SITEURLBASE . THEME_ABS : '', - (deftrue('ADMIN') ? SITEURLBASE . e_ADMIN_ABS : ''), - SITEURL, - '', // no e_CORE absolute path - '', // no e_SYSTEM absolute path - ); - break; - } - // sub-folders first! - $search = array( - '{e_MEDIA_FILE}', - '{e_MEDIA_VIDEO}', - '{e_MEDIA_IMAGE}', - '{e_MEDIA_ICON}', - '{e_AVATAR}', - '{e_WEB_JS}', - '{e_WEB_CSS}', - '{e_WEB_IMAGE}', - // '{e_WEB_PACK}', - '{e_IMAGE_ABS}', - '{e_THEME_ABS}', - '{e_IMAGE}', - '{e_PLUGIN}', - '{e_FILE}', - '{e_THEME}', - //,"{e_DOWNLOAD}" - '{e_HANDLER}', - '{e_MEDIA}', - '{e_WEB}', - '{THEME}', - '{THEME_ABS}', - '{e_ADMIN}', - '{e_BASE}', - '{e_CORE}', - '{e_SYSTEM}', - ); - - /*if (ADMIN) - { - $replace_relative[] = $e107->getFolder('admin'); - $replace_absolute[] = SITEURL.$e107->getFolder('admin'); - $search[] = "{e_ADMIN}"; - }*/ - - if ($all) - { - if (USER) - { // Can only replace with valid number for logged in users - $replace_relative[] = USERID; - $replace_absolute[] = USERID; - } - else - { - $replace_relative[] = ''; - $replace_absolute[] = ''; - } - $search[] = '{USERID}'; - } - - // current THEME - /*if(!defined('THEME')) - { - //if not already parsed by doReplace - $text = str_replace(array('{THEME}', '{THEME_ABS}'), '', $text); - } - else - { - $replace_relative[] = THEME; - $replace_absolute[] = THEME_ABS; - $search[] = "{THEME}"; - $replace_relative[] = THEME; - $replace_absolute[] = THEME_ABS; - $search[] = "{THEME_ABS}"; - }*/ - - $replace = ((string) $mode === 'full' || (string) $mode === 'abs') ? $replace_absolute : $replace_relative; - - return str_replace($search, $replace, $text); - } - -// $pattern = ($all ? "#\{([A-Za-z_0-9]*)\}#s" : "#\{(e_[A-Z]*)\}#s"); - $pattern = ($all ? '#\{([A-Za-z_0-9]*)\}#s' : '#\{(e_[A-Z]*(?:_IMAGE|_VIDEO|_FILE|_CONTENT|_ICON|_AVATAR|_JS|_CSS|_PACK|_DB|_ABS){0,1})\}#s'); - $text = preg_replace_callback($pattern, array($this, 'doReplace'), $text); - - if (!defined('THEME')) - { - //if not already parsed by doReplace - $text = str_replace(array('{THEME}', '{THEME_ABS}'), '', $text); - } - else - { - $srch = array('{THEME}', '{THEME_ABS}'); - $repl = array(THEME, THEME_ABS); - $text = str_replace($srch, $repl, $text); - } - - return $text; - } - - - /** - * @param array $matches - * @return mixed|string - */ - private function doReplace($matches) - { - - if (defined($matches[1]) && (deftrue('ADMIN') || strpos($matches[1], 'ADMIN') === false)) - { - return constant($matches[1]); - } - - return $matches[1]; - } - - /** - * Create and substitute e107 constants in passed URL - * - * @param string $url - * @param integer $mode 0-folders, 1-relative ('rel'), 2-absolute ('abs'), 3-full ('full') (with domain), 4-absolute & relative ('mix') (combination of 1,2,3) - * @return string - */ - public function createConstants($url, $mode = 0) - { - - //FIXME - create constants for absolute paths and site URL's - if (!is_numeric($mode)) - { - switch ($mode) - { - case 'rel' : - $mode = 1; - break; - case 'abs' : - $mode = 2; - break; - case 'full' : - $mode = 3; - break; - case 'mix' : - $mode = 4; - break; - case 'nice': - $mode = 5; - break; - } - } - $e107 = e107::getInstance(); - switch ($mode) - { - case 0: // folder name only. - $tmp = array( - '{e_MEDIA_FILE}' => $e107::getFolder('media_files'), - '{e_MEDIA_VIDEO}' => $e107::getFolder('media_videos'), - '{e_MEDIA_IMAGE}' => $e107::getFolder('media_images'), - '{e_MEDIA_ICON}' => $e107::getFolder('media_icons'), - '{e_AVATAR}' => $e107::getFolder('avatars'), - '{e_WEB_JS}' => $e107::getFolder('web_js'), - '{e_WEB_CSS}' => $e107::getFolder('web_css'), - '{e_WEB_IMAGE}' => $e107::getFolder('web_images'), - // '{e_WEB_PACK}' => $e107::getFolder('web_packs'), - - '{e_IMAGE}' => $e107::getFolder('images'), - '{e_PLUGIN}' => $e107::getFolder('plugins'), - '{e_FILE}' => $e107::getFolder('files'), - '{e_THEME}' => $e107::getFolder('themes'), - '{e_DOWNLOAD}' => $e107::getFolder('downloads'), - '{e_ADMIN}' => $e107::getFolder('admin'), - '{e_HANDLER}' => $e107::getFolder('handlers'), - '{e_MEDIA}' => $e107::getFolder('media'), - '{e_WEB}' => $e107::getFolder('web'), - '{e_UPLOAD}' => $e107::getFolder('uploads'), - ); - - break; - - - case 1: // relative path only - $tmp = array( - '{e_MEDIA_FILE}' => e_MEDIA_FILE, - '{e_MEDIA_VIDEO}' => e_MEDIA_VIDEO, - '{e_MEDIA_IMAGE}' => e_MEDIA_IMAGE, - '{e_MEDIA_ICON}' => e_MEDIA_ICON, - '{e_AVATAR}' => e_AVATAR, - '{e_IMPORT}' => e_IMPORT, - '{e_WEB_JS}' => e_WEB_JS, - '{e_WEB_CSS}' => e_WEB_CSS, - '{e_WEB_IMAGE}' => e_WEB_IMAGE, - // '{e_WEB_PACK}' => e_WEB_PACK, - - '{e_IMAGE}' => e_IMAGE, - '{e_PLUGIN}' => e_PLUGIN, - '{e_FILE}' => e_FILE, - '{e_THEME}' => e_THEME, - '{e_DOWNLOAD}' => e_DOWNLOAD, - '{e_ADMIN}' => e_ADMIN, - '{e_HANDLER}' => e_HANDLER, - '{e_MEDIA}' => e_MEDIA, - '{e_WEB}' => e_WEB, - '{e_UPLOAD}' => e_UPLOAD, - ); - break; - - case 2: // absolute path only - $tmp = array( - '{e_MEDIA_FILE}' => e_MEDIA_FILE_ABS, - '{e_MEDIA_VIDEO}' => e_MEDIA_VIDEO_ABS, - '{e_MEDIA_IMAGE}' => e_MEDIA_IMAGE_ABS, - '{e_MEDIA_ICON}' => e_MEDIA_ICON_ABS, - '{e_AVATAR}' => e_AVATAR_ABS, - '{e_WEB_JS}' => e_JS_ABS, - '{e_WEB_CSS}' => e_CSS_ABS, - '{e_WEB_IMAGE}' => e_WEB_IMAGE_ABS, - // '{e_WEB_PACK}' => e_PACK_ABS, - - '{e_IMAGE}' => e_IMAGE_ABS, - '{e_PLUGIN}' => e_PLUGIN_ABS, - '{e_FILE}' => e_FILE_ABS, // deprecated - '{e_THEME}' => e_THEME_ABS, - '{e_DOWNLOAD}' => e_HTTP . 'request.php?',// FIXME - we need solution! - '{e_ADMIN}' => e_ADMIN_ABS, - //'{e_HANDLER}' => e_HANDLER_ABS, - no ABS path available - '{e_MEDIA}' => e_MEDIA_ABS, - '{e_WEB}' => e_WEB_ABS, - '{e_BASE}' => e_HTTP, - ); - break; - - case 3: // full path (e.g http://domain.com/e107_images/) - $tmp = array( - '{e_MEDIA_FILE}' => SITEURLBASE . e_MEDIA_FILE_ABS, - '{e_MEDIA_VIDEO}' => SITEURLBASE . e_MEDIA_VIDEO_ABS, - '{e_MEDIA_IMAGE}' => SITEURLBASE . e_MEDIA_IMAGE_ABS, - '{e_MEDIA_ICON}' => SITEURLBASE . e_MEDIA_ICON_ABS, - '{e_AVATAR}' => SITEURLBASE . e_AVATAR_ABS, - '{e_WEB_JS}' => SITEURLBASE . e_JS_ABS, - '{e_WEB_CSS}' => SITEURLBASE . e_CSS_ABS, - '{e_WEB_IMAGE}' => SITEURLBASE . e_WEB_IMAGE_ABS, - // '{e_WEB_PACK}' => SITEURLBASE.e_PACK_ABS, - - '{e_IMAGE}' => SITEURLBASE . e_IMAGE_ABS, - '{e_PLUGIN}' => SITEURLBASE . e_PLUGIN_ABS, - '{e_FILE}' => SITEURLBASE . e_FILE_ABS, // deprecated - '{e_THEME}' => SITEURLBASE . e_THEME_ABS, - '{e_DOWNLOAD}' => SITEURLBASE . e_HTTP . 'request.php?',// FIXME - we need solution! - '{e_ADMIN}' => SITEURLBASE . e_ADMIN_ABS, - //'{e_HANDLER}' => e_HANDLER_ABS, - no ABS path available - '{e_MEDIA}' => SITEURLBASE . e_MEDIA_ABS, - '{e_WEB}' => SITEURLBASE . e_WEB_ABS, - '{e_BASE}' => SITEURL, - ); - break; - - case 4: // absolute & relative paths - $url = $this->createConstants($url, 3); - $url = $this->createConstants($url, 2); - $url = $this->createConstants($url, 1); - - return $url; - break; - - case 5: // nice urls - e.g. e_MEDIA_VIDEO/mystream.flv - $url = $this->createConstants($url, 4); - - return str_replace($this->getUrlConstants('sc'), $this->getUrlConstants('raw'), $url); - break; - - default: - $tmp = array(); - break; - } - - $hasCDN = strpos($url, '//') === 0; - - foreach ($tmp as $key => $val) - { - // Fix - don't break the CDN '//cdn.com' URLs - if ($hasCDN && $val === '/') - { - continue; - } - - $len = strlen($val); - if (substr($url, 0, $len) == $val) - { - // replace the first instance only - return substr_replace($url, $key, 0, $len); - } - } - - return $url; - } - - - //FIXME - $match not used? - - /** - * @param $text - * @param $match - * @return array|string|string[]|null - */ - public function e_highlight($text, $match) - { - - $tags = array(); - preg_match_all('#<[^>]+>#', $text, $tags); - $text = preg_replace('#<[^>]+>#', '<|>', $text); - $text = preg_replace('#(\b".$match."\b)#i', '\\1', $text); - foreach ($tags[0] as $tag) - { - $text = preg_replace('#<\|>#', $tag, $text, 1); - } - - return $text; - } - - - /** - * Convert Text to a suitable format for use in emails. eg. relative links will be replaced with full links etc. - * - * @param string $text - * @param boolean $posted - if the text has been posted. (uses stripslashes etc) - * @param string $mods - flags for text transformation. - */ - public function toEmail($text, $posted = '', $mods = 'parse_sc, no_make_clickable') - { - - if ($posted === true) - { - if (MAGIC_QUOTES_GPC) - { - $text = stripslashes($text); - } - $text = preg_replace('#\[(php)#i', '[\\1', $text); - } - - $text = (strtolower($mods) !== 'rawtext') ? $this->replaceConstants($text, 'full') : $text; - - if ($this->isHtml($text)) - { - $text = str_replace(array('[html]', '[/html]'), '', $text); - $text = html_entity_decode($text, ENT_COMPAT, 'UTF-8'); - } - else - { - - $text = $this->toHTML($text, true, $mods); - } - - return $text; - } - - - /** - * Given an email address, returns a link including with obfuscated text. - * e-email css in e107.css inserts the user/domain data for display. - * - * @param string $email - * @param string $words [optional] text to display - * @param null $subject [optional] default subject for email. - * @return string - */ - public function emailObfuscate($email, $words = null, $subject = null) - { - - if (strpos($email, '@') === false) - { - return ''; - } - - if ($subject) - { - $subject = '?subject=' . $subject; - } - - list($name, $address) = explode('@', $email, 2); - - if (empty($words)) - { - $words = '@'; - $user = "data-user='" . $this->obfuscate($name) . "'"; - $dom = "data-dom='" . $this->obfuscate($address) . "'"; - } - else - { - $user = ''; - $dom = ''; - } - - $url = 'mailto:' . $email . $subject; - - $safe = $this->obfuscate($url); - - return "" . $words . ''; - } - - - /** - * Obfuscate text from bots using Randomized encoding. - * - * @param $text - * @return string - */ - public function obfuscate($text) - { - - $ret = ''; - foreach (str_split($text) as $letter) - { - switch (mt_rand(1, 3)) - { - // HTML entity code - case 1: - $ret .= '&#' . ord($letter) . ';'; - break; - - // Hex character code - case 2: - $ret .= '&#x' . dechex(ord($letter)) . ';'; - break; - - // Raw (no) encoding - case 3: - $ret .= $letter; - } - } - - return $ret; - } - - - /** - * @param $name - * @return array|e_parse_shortcode|null - */ - public function __get($name) - { - - switch ($name) - { - case 'e_sc': - $ret = e107::getScParser(); - break; - - - default: - // trigger_error('$e107->$'.$name.' not defined', E_USER_WARNING); - return null; - break; - } - - - $this->$name = $ret; - - return $ret; - } - - // Formerly located in e_parser -------------------------- - - - /** - * Merge default 'global' attributes into assigned tags. - */ - private function compileAttributeDefaults() - { - - foreach ($this->allowedAttributes as $tag => $array) - { - if ($tag === 'default') - { - continue; - } - - foreach ($this->allowedAttributes['default'] as $def) - { - $this->allowedAttributes[$tag][] = $def; - } - - } - - } - - /** - * Used by e_parse to start - */ - public function init() - { - - if (defined('FONTAWESOME')) - { - $this->fontawesome = (int) FONTAWESOME; - } - - if (defined('BOOTSTRAP')) - { - $this->bootstrap = (int) BOOTSTRAP; - } - - $this->modRewriteMedia = deftrue('e_MOD_REWRITE_MEDIA'); - - if (defined('e_HTTP_STATIC')) - { - $this->staticUrl = e_HTTP_STATIC; - } - - // Preprocess the supermods to be useful default arrays with all values - foreach ($this->e_SuperMods as $key => $val) - { - // precalculate super defaults - $this->e_SuperMods[$key] = array_merge($this->e_optDefault, $this->e_SuperMods[$key]); - $this->e_SuperMods[$key]['context'] = $key; - } - - $this->allowedTags = array('html', 'body', 'div', 'a', 'img', 'table', 'tr', 'td', 'th', 'tbody', 'thead', 'colgroup', 'b', - 'i', 'pre', 'code', 'strong', 'u', 'em', 'ul', 'ol', 'li', 'img', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'p', - 'section', 'article', 'blockquote', 'hgroup', 'aside', 'figure', 'figcaption', 'abbr', 'span', 'audio', 'video', 'source', 'br', - 'small', 'caption', 'noscript', 'hr', 'section', 'iframe', 'sub', 'sup', 'cite', 'x-bbcode', 'label', 'dl', 'dt', 'dd', - ); - - $this->scriptTags = array('script', 'applet', 'form', 'input', 'button', 'embed', 'object', 'ins', 'select', 'textarea'); //allowed when $pref['post_script'] is enabled. - - $this->allowedAttributes = array( - 'default' => array('id', 'style', 'class', 'title', 'lang', 'accesskey'), - 'img' => array('src', 'alt', 'width', 'height'), - 'a' => array('href', 'target', 'rel'), - 'script' => array('type', 'src', 'language', 'async'), - 'iframe' => array('src', 'frameborder', 'width', 'height', 'allowfullscreen', 'allow'), - 'input' => array('type', 'name', 'value'), - 'form' => array('action', 'method', 'target'), - 'audio' => array('src', 'controls', 'autoplay', 'loop', 'muted', 'preload'), - 'video' => array('autoplay', 'controls', 'height', 'loop', 'muted', 'poster', 'preload', 'src', 'width'), - 'table' => array('border', 'cellpadding', 'cellspacing'), // BC Fix. - 'td' => array('colspan', 'rowspan', 'name', 'bgcolor'), - 'th' => array('colspan', 'rowspan'), - 'col' => array('span'), - 'embed' => array('src', 'wmode', 'type', 'width', 'height'), - 'x-bbcode' => array('alt'), - 'label' => array('for'), - 'source' => array('media', 'sizes', 'src', 'srcset', 'type'), - - ); - - $this->scriptAttributes = array('onclick', 'onchange', 'onblur', 'onload', 'onfocus', 'onkeydown', 'onkeypress', 'onkeyup', - 'ondblclick', 'onmousedown', 'onmousemove', 'onmouseout', 'onmouseover', 'onmouseup', 'onmousewheel', - 'onwheel', 'oncopy', 'oncut', 'onpaste' - ); - - $this->blockTags = array('p', 'pre', 'div', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'blockquote'); // element includes its own line-break. - - $this->badAttrValues = array('javascript[\s]*?:', 'alert\(', 'vbscript[\s]*?:', 'data:text\/html', 'mhtml[\s]*?:', 'data:[\s]*?image'); - - $this->replaceAttrValues = array( - 'default' => array() - ); - - } - - /** - * Add Allowed Tags. - * - * @param string - */ - public function addAllowedTag($tag) - { - - $this->allowedTags[] = $tag; - } - - - /** - * @param $tag - html tag. - * @param $attArray - array of attributes. eg. array('style', 'id', 'class') etc. - */ - public function addAllowedAttribute($tag, $attArray) - { - - $this->allowedAttributes[$tag] = (array) $attArray; - } - - - /** - * Set Allowed Tags. - * - * @param $array - */ - public function setAllowedTags($array = array()) - { - - $this->allowedTags = $array; - } - - /** - * Set Script Access - * - * @param $val int e_UC_MEMBER, e_UC_NOBODY, e_UC_MAINADMIN or userclass number. - */ - public function setScriptAccess($val) - { - - $this->scriptAccess = $val; - } - - /** - * @param array $arr - * @return void - */ - public function setScriptAttibutes($arr) - { - $this->scriptAttributes = (array) $arr; - } - - /** - * @return array - */ - public function getAllowedTags() - { - return $this->allowedTags; - } - - /** - * @return array - */ - public function getAllowedAttributes() - { - return $this->allowedAttributes; - } - - - /** - * @return bool - */ - public function getScriptAccess() - { - return $this->scriptAccess; - } - - /** - * @return array - */ - public function getRemoved() - { - return $this->removedList; - } - - /** - * Set Allowed Attributes. - * - * @param $array - */ - public function setAllowedAttributes($array = array()) - { - - $this->allowedAttributes = $array; - } - - /** - * Set Script Tags. - * - * @param $array - */ - public function setScriptTags($array = array()) - { - - $this->scriptTags = $array; - } - - - /** - * @param int $version - */ - public function setFontAwesome($version) - { - $this->fontawesome = (int) $version; - } - - /** - * @param int $version - */ - public function setBootstrap($version) - { - $this->bootstrap = (int) $version; - } - - public function setmodRewriteMedia($bool) - { - $this->modRewriteMedia = (bool) $bool; - } - - /** - * Add leading zeros to a number. eg. 3 might become 000003 - * - * @param $num integer - * @param $numDigits - total number of digits - * @return string number with leading zeros. - */ - public function leadingZeros($num, $numDigits) - { - return (string) sprintf('%0' . $numDigits . 'd', $num); - } - - /** - * Generic variable translator for LAN definitions. - * - * @param $lan - string LAN - * @param string | array $vals - either a single value, which will replace '[x]' or an array with key=>value pairs. - * @return string - * @example $tp->lanVars("My name is [x] and I own a [y]", array("John","Cat")); - * @example $tp->lanVars("My name is [x] and I own a [y]", array('x'=>"John", 'y'=>"Cat")); - */ - public function lanVars($lan, $vals, $bold = false) - { - - $array = (!is_array($vals)) ? array('x' => $vals) : $vals; - - $search = array(); - $replace = array(); - - $defaults = array('x', 'y', 'z'); - - foreach ($array as $k => $v) - { - if (is_numeric($k)) // convert array of numeric to x,y,z - { - $k = $defaults[$k]; - } - - $search[] = '[' . $k . ']'; - $replace[] = ($bold === true) ? '' . $v . '' : $v; - } - - return str_replace($search, $replace, $lan); - } - - /** - * Return an Array of all specific tags found in an HTML document and their attributes. - * - * @param $html - raw html code - * @param $taglist - comma separated list of tags to search or '*' for all. - * @param $header - if the $html includes the html head or body tags - it should be set to true. - */ - public function getTags($html, $taglist = '*', $header = false) - { - - if ($header == false) - { - $html = '' . $html . ''; - } - - $doc = $this->domObj; - - $doc->preserveWhiteSpace = true; - libxml_use_internal_errors(true); - $doc->loadHTML($html); - - $tg = explode(',', $taglist); - $ret = array(); - - foreach ($tg as $find) - { - $tmp = $doc->getElementsByTagName($find); - - /** - * @var $k - * @var DOMDocument $node - */ - foreach ($tmp as $k => $node) - { - $tag = $node->nodeName; - $inner = $node->C14N(); - $inner = str_replace(' ', '', $inner); - - foreach ($node->attributes as $attr) - { - $name = $attr->nodeName; - $value = $attr->nodeValue; - $ret[$tag][$k][$name] = $value; - } - - $ret[$tag][$k]['@value'] = $inner; - - - } - } - - if ($header == false) - { - unset($ret['html'], $ret['body']); - } - - - return $ret; - } - - /** - * Glyph Embed Method Direct from svg file. - * - * @param string $cat far|fab|fas - * @param string $id eg. fa-search - * @param array $parm eg. ['fw'=>true] - * @return string|false - */ - private function toGlyphEmbed($cat, $id, $parm = array()) - { - $dirs = ['far' => 'regular', 'fab' => 'brands', 'fas' => 'solid']; - $path = e_WEB . 'lib/font-awesome/5/svgs/'; - $path .= $dirs[$cat] . '/'; - $path .= str_replace('fa-', '', $id) . ".svg"; - - - if ($ret = file_get_contents($path)) - { - $class = 'svg-inline--fa '; - $class .= $id; - $class .= ' fa-w-16'; - $class .= !empty($parm['fw']) ? ' fa-fw' : ''; - - return str_replace('
+ $convertNL = false; + // break; + + case 'hide' : + $proc_funcs = true; + + case 'scode': + case 'code' : + $full_text = $this->parseBBCodes($matches[0], $postID); + break; + } + + } + } + + + // Do the 'normal' processing - in principle, as previously - but think about the order. + if ($proc_funcs && !empty($full_text)) // some more speed + { + // Split out and ignore any scripts and style blocks. With just two choices we can match the closing tag in the regex + $subcon = preg_split('#((?:]+>.*?|tyle[^>]+>.*?))#mis', $full_text, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE); + foreach ($subcon as $sub_blk) + { + + if (strpos($sub_blk, '\s*[\r]*\n[\r]*#", ">", $sub_blk); + } + */ + + // Link substitution + // Convert URL's to clickable links, unless modifiers or prefs override + $sub_blk = $this->processModifiers($opts, $sub_blk, $convertNL, $parseBB, $modifiers, $postID); + + $ret_parser .= $sub_blk; + } // End of 'normal' processing for a block of text + + } // End of 'foreach() on each block of non-script text + + } // End of 'normal' parsing (non-script text) + else + { + // Text block that needed no processing at all + $ret_parser .= $full_text; + } + } + + // Quick Fix - Remove trailing
on block-level elements (eg. div, pre, table, etc. ) + $srch = array(); + $repl = array(); + + foreach ($this->blockTags as $val) + { + $srch[] = '
'; + $repl[] = ''; + } + + $ret_parser = str_replace($srch, $repl, $ret_parser); + + return trim($ret_parser); + } + + + /** + * Check if a string begins with a preformatter flag. + * + * @param $str + * @return bool + */ + private function preformatted($str) + { + + foreach ($this->preformatted as $type) + { + $code = '[' . $type . ']'; + if (strpos($str, $code) === 0) + { + return true; + } + + } + + return false; + } + + + /** + * @param $mixed + * @return array|false|string + */ + public function toUTF8($mixed) + { + + if (is_array($mixed)) + { + foreach ($mixed as $k => $v) + { + unset($mixed[$k]); + $mixed[$this->toUTF8($k)] = $this->toUTF8($v); + } + } + elseif (is_object($mixed)) + { + $objVars = get_object_vars($mixed); + foreach ($objVars as $key => $value) + { + $mixed->$key = $this->toUTF8($value); + } + } + elseif (is_string($mixed)) + { + return iconv('UTF-8', 'UTF-8//IGNORE', utf8_encode($mixed)); + } + + return $mixed; + } + + + /** + * @param string $text + * @return string + */ + public function toASCII($text) + { + + $char_map = array( + // Latin + 'À' => 'A', 'Á' => 'A', 'Â' => 'A', 'Ã' => 'A', 'Ä' => 'A', 'Å' => 'A', 'Æ' => 'AE', 'Ç' => 'C', + 'È' => 'E', 'É' => 'E', 'Ê' => 'E', 'Ë' => 'E', 'Ì' => 'I', 'Í' => 'I', 'Î' => 'I', 'Ï' => 'I', + 'Ð' => 'D', 'Ñ' => 'N', 'Ò' => 'O', 'Ó' => 'O', 'Ô' => 'O', 'Õ' => 'O', 'Ö' => 'O', 'Ő' => 'O', + 'Ø' => 'O', 'Ù' => 'U', 'Ú' => 'U', 'Û' => 'U', 'Ü' => 'U', 'Ű' => 'U', 'Ý' => 'Y', 'Þ' => 'TH', + 'ß' => 'ss', + 'à' => 'a', 'á' => 'a', 'â' => 'a', 'ã' => 'a', 'ä' => 'a', 'å' => 'a', 'æ' => 'ae', 'ç' => 'c', + 'è' => 'e', 'é' => 'e', 'ê' => 'e', 'ë' => 'e', 'ì' => 'i', 'í' => 'i', 'î' => 'i', 'ï' => 'i', + 'ð' => 'd', 'ñ' => 'n', 'ò' => 'o', 'ó' => 'o', 'ô' => 'o', 'õ' => 'o', 'ö' => 'o', 'ő' => 'o', + 'ø' => 'o', 'ù' => 'u', 'ú' => 'u', 'û' => 'u', 'ü' => 'u', 'ű' => 'u', 'ý' => 'y', 'þ' => 'th', + 'ÿ' => 'y', + // Latin symbols + '©' => '(c)', + // Greek + 'Α' => 'A', 'Β' => 'B', 'Γ' => 'G', 'Δ' => 'D', 'Ε' => 'E', 'Ζ' => 'Z', 'Η' => 'H', 'Θ' => '8', + 'Ι' => 'I', 'Κ' => 'K', 'Λ' => 'L', 'Μ' => 'M', 'Ν' => 'N', 'Ξ' => '3', 'Ο' => 'O', 'Π' => 'P', + 'Ρ' => 'R', 'Σ' => 'S', 'Τ' => 'T', 'Υ' => 'Y', 'Φ' => 'F', 'Χ' => 'X', 'Ψ' => 'PS', 'Ω' => 'W', + 'Ά' => 'A', 'Έ' => 'E', 'Ί' => 'I', 'Ό' => 'O', 'Ύ' => 'Y', 'Ή' => 'H', 'Ώ' => 'W', 'Ϊ' => 'I', + 'Ϋ' => 'Y', + 'α' => 'a', 'β' => 'b', 'γ' => 'g', 'δ' => 'd', 'ε' => 'e', 'ζ' => 'z', 'η' => 'h', 'θ' => '8', + 'ι' => 'i', 'κ' => 'k', 'λ' => 'l', 'μ' => 'm', 'ν' => 'n', 'ξ' => '3', 'ο' => 'o', 'π' => 'p', + 'ρ' => 'r', 'σ' => 's', 'τ' => 't', 'υ' => 'y', 'φ' => 'f', 'χ' => 'x', 'ψ' => 'ps', 'ω' => 'w', + 'ά' => 'a', 'έ' => 'e', 'ί' => 'i', 'ό' => 'o', 'ύ' => 'y', 'ή' => 'h', 'ώ' => 'w', 'ς' => 's', + 'ϊ' => 'i', 'ΰ' => 'y', 'ϋ' => 'y', 'ΐ' => 'i', + // Turkish + 'Ş' => 'S', 'İ' => 'I', /*'Ç' => 'C', 'Ü' => 'U', 'Ö' => 'O',*/ + 'Ğ' => 'G', + 'ş' => 's', 'ı' => 'i', /*'ç' => 'c', 'ü' => 'u', 'ö' => 'o',*/ + 'ğ' => 'g', + // Russian + 'А' => 'A', 'Б' => 'B', 'В' => 'V', 'Г' => 'G', 'Д' => 'D', 'Е' => 'E', 'Ё' => 'Yo', 'Ж' => 'Zh', + 'З' => 'Z', 'И' => 'I', 'Й' => 'J', 'К' => 'K', 'Л' => 'L', 'М' => 'M', 'Н' => 'N', 'О' => 'O', + 'П' => 'P', 'Р' => 'R', 'С' => 'S', 'Т' => 'T', 'У' => 'U', 'Ф' => 'F', 'Х' => 'H', 'Ц' => 'C', + 'Ч' => 'Ch', 'Ш' => 'Sh', 'Щ' => 'Sh', 'Ъ' => '', 'Ы' => 'Y', 'Ь' => '', 'Э' => 'E', 'Ю' => 'Yu', + 'Я' => 'Ya', + 'а' => 'a', 'б' => 'b', 'в' => 'v', 'г' => 'g', 'д' => 'd', 'е' => 'e', 'ё' => 'yo', 'ж' => 'zh', + 'з' => 'z', 'и' => 'i', 'й' => 'j', 'к' => 'k', 'л' => 'l', 'м' => 'm', 'н' => 'n', 'о' => 'o', + 'п' => 'p', 'р' => 'r', 'с' => 's', 'т' => 't', 'у' => 'u', 'ф' => 'f', 'х' => 'h', 'ц' => 'c', + 'ч' => 'ch', 'ш' => 'sh', 'щ' => 'sh', 'ъ' => '', 'ы' => 'y', 'ь' => '', 'э' => 'e', 'ю' => 'yu', + 'я' => 'ya', + // Ukrainian + 'Є' => 'Ye', 'І' => 'I', 'Ї' => 'Yi', 'Ґ' => 'G', + 'є' => 'ye', 'і' => 'i', 'ї' => 'yi', 'ґ' => 'g', + // Czech + 'Č' => 'C', 'Ď' => 'D', 'Ě' => 'E', 'Ň' => 'N', 'Ř' => 'R', 'Š' => 'S', 'Ť' => 'T', 'Ů' => 'U', + 'Ž' => 'Z', + 'č' => 'c', 'ď' => 'd', 'ě' => 'e', 'ň' => 'n', 'ř' => 'r', 'š' => 's', 'ť' => 't', 'ů' => 'u', + 'ž' => 'z', + // Polish + 'Ą' => 'A', 'Ć' => 'C', 'Ę' => 'e', 'Ł' => 'L', 'Ń' => 'N', /*'Ó' => 'o',*/ + 'Ś' => 'S', 'Ź' => 'Z', + 'Ż' => 'Z', + 'ą' => 'a', 'ć' => 'c', 'ę' => 'e', 'ł' => 'l', 'ń' => 'n',/* 'ó' => 'o',*/ + 'ś' => 's', 'ź' => 'z', + 'ż' => 'z', + // Latvian + 'Ā' => 'A',/* 'Č' => 'C',*/ + 'Ē' => 'E', 'Ģ' => 'G', 'Ī' => 'i', 'Ķ' => 'k', 'Ļ' => 'L', 'Ņ' => 'N', + /*'Š' => 'S',*/ + 'Ū' => 'u', + 'ā' => 'a', 'ē' => 'e', 'ģ' => 'g', 'ī' => 'i', 'ķ' => 'k', 'ļ' => 'l', 'ņ' => 'n', + 'ū' => 'u', + + 'ľ' => 'l', 'ŕ' => 'r', 'Ľ' => 'l', + ); + + return str_replace(array_keys($char_map), $char_map, $text); + + } + + + /** + * Use it on html attributes to avoid breaking markup . + * + * @param string $text + * @param bool $pure True to skip the text mutation by {@see e_parse::replaceConstants()} + * @example echo "Hello"; + */ + public function toAttribute($text, $pure = false) + { + + // URLs posted without HTML access may have an & in them. + + // Xhtml compliance. + $text = htmlspecialchars((string) $text, ENT_QUOTES, 'UTF-8'); + + if (!$pure && !preg_match('/&#|\'|"|<|>/s', $text)) + { + $text = $this->replaceConstants($text); + } + + return $text; + } + + /** + * Build a series of HTML attributes from the provided array + * + * Because of legacy loose typing client code usages, values that are {@see empty()} will not be added to the + * concatenated HTML attribute string except when the key is `value`, the key begins with `data-`, or the value is + * a number. + * + * @param array $attributes Key-value pairs of HTML attributes. The value must not be HTML-encoded. If the value is + * boolean true, the value will be set to the key (e.g. `['required' => true]` becomes + * "required='required'"). + * @param bool $pure True to skip the text mutation by {@see e_parse::replaceConstants()} + * @return string The HTML attributes to concatenate inside an HTML tag + * @see e_parseTest::testToAttributesMixedPureAndReplaceConstants() for an example of how to use this method + */ + public function toAttributes($attributes, $pure = false) + { + $stringifiedAttributes = []; + + foreach ($attributes as $key => $value) + { + if ($value === true && (strpos($key, 'data-') !== 0)) + { + $value = $key; + } + if (!empty($value) || is_numeric($value) || $key === "value" || strpos($key, 'data-') === 0) + { + $stringifiedAttributes[] = $key . "='" . $this->toAttribute($value, $pure) . "'"; + } + } + + return count($stringifiedAttributes) > 0 ? " " . implode(" ", $stringifiedAttributes) : ""; + } + + /** + * Flatten a multi-dimensional associative array with slashes. + * + * Based on Illuminate\Support\Arr::dot() + * + * @param $array + * @param string $prepend + * @return array + * @license https://github.com/illuminate/support/blob/master/LICENSE.md MIT License + * @copyright Copyright (c) Taylor Otwell + */ + public static function toFlatArray($array, $prepend = '') + { + $results = []; + + foreach ($array as $key => $value) + { + if (is_array($value) && !empty($value)) + { + $results = array_merge($results, static::toFlatArray($value, $prepend . $key . '/')); + } + else + { + $results[$prepend . $key] = $value; + } + } + + return $results; + } + + + /** + * Convert a flattened slash-delimited multi-dimensional array back into an actual multi-dimensional array + * + * Inverse of {@link e_parse::toFlatArray()} + * + * @param $array + * @param string $unprepend + * @return array + */ + public static function fromFlatArray($array, $unprepend = '') + { + $output = []; + foreach ($array as $key => $value) + { + if (!empty($unprepend) && substr($key, 0, strlen($unprepend)) == $unprepend) + { + $key = substr($key, strlen($unprepend)); + } + $parts = explode('/', $key); + $nested = &$output; + while (count($parts) > 1) + { + $nested = &$nested[array_shift($parts)]; + if (!is_array($nested)) $nested = []; + } + $nested[array_shift($parts)] = $value; + } + + return $output; + } + + + /** + * Convert text blocks which are to be embedded within JS + * + * @param string|array $stringarray + * @return string + * @deprecated v2.3.1 This method will not escape a string properly for use as a JavaScript or JSON string. Use + * {@see e_parse::toJSON()} instead. When using {@see e_parse::toJSON()}, do not surround its output + * with quotation marks, and do not attempt to escape sequences like "\n" as "\\n". If HTML tags need to + * be removed, consider {@see e_parse::toText()} separately. If the text needs to be used in an HTML + * tag attribute (e.g. <a onclick="ATTRIBUTE"></a>), surround the string with + * {@see e_parse::toAttribute()} and either single-quote or double-quote the attribute value. + */ + public function toJS($stringarray) + { + trigger_error('' . __METHOD__ . ' is deprecated. See method DocBlock for alternatives.', E_USER_WARNING); // NO LAN + + $search = array("\r\n", "\r", '
', "'"); + $replace = array("\\n", '', "\\n", "\'"); + $stringarray = str_replace($search, $replace, $stringarray); + $stringarray = strip_tags($stringarray); + + $trans_tbl = get_html_translation_table(HTML_ENTITIES); + $trans_tbl = array_flip($trans_tbl); + + return strtr($stringarray, $trans_tbl); + } + + + /** + * Converts a PHP variable into its JavaScript equivalent. + * We use HTML-safe strings, with several characters escaped. + * + * @param mixed $var + * PHP variable. + * @param bool $force_object + * True: Outputs an object rather than an array when a non-associative + * array is used. Especially useful when the recipient of the output + * is expecting an object and the array is empty. + * + * @return string + */ + public function toJSON($var, $force_object = false) + { + if ($force_object === true) + { + // Encode <, >, ', &, and " using the json_encode() options parameter. + return json_encode($var, JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_AMP | JSON_HEX_QUOT | JSON_FORCE_OBJECT); + } + + // Encode <, >, ', &, and " using the json_encode() options parameter. + return json_encode($var, JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_AMP | JSON_HEX_QUOT); + + } + + + /** + * Convert Text for RSS/XML use. + * + * @param string $text + * @param boolean $tags [optional] + * @return string + */ + public function toRss($text, $tags = false) + { + + if ($tags != true) + { + $text = $this->toHTML($text, true); + $text = strip_tags($text); + + } + + $text = $this->toEmail($text); + + $search = array('&#039;', '&#036;', ''', '$', e_BASE, "href='request.php", '', ''); + $replace = array("'", '$', "'", '$', SITEURL, "href='" . SITEURL . 'request.php', '', ''); + $text = str_replace($search, $replace, $text); + + $text = $this->ampEncode($text); + + // if CDATA happens to be quoted in the text. + $text = str_replace([''], ['<![CDATA', ']]>'], $text); + + if ($tags === true) + { + $text = !empty($text) ? '' : ''; + } + else + { + $text = str_replace(['<', '>'], ['<', '>'], $text); + } + + return $text; + } + + + /** + * Convert a string to a number (int/float) + * + * @param string $value + * @return int|float + */ + public function toNumber($value) + { + + // adapted from: https://secure.php.net/manual/en/function.floatval.php#114486 + $dotPos = strrpos($value, '.'); + $commaPos = strrpos($value, ','); + $sep = (($dotPos > $commaPos) && $dotPos) ? $dotPos : + ((($commaPos > $dotPos) && $commaPos) ? $commaPos : false); + + if (!$sep) + { + return (int) preg_replace('/[^-0-9]/', '', $value); + } + + return (float) ( + preg_replace('/[^-0-9]/', '', substr($value, 0, $sep)) . '.' . + preg_replace('/[^0-9]/', '', substr($value, $sep + 1, strlen($value))) + ); + } + + + /** + * Clean and Encode Ampersands '&' for output to browser. + * + * @param string $text + * @return array|string|string[] + */ + public function ampEncode($text = '') + { + + // Fix any left-over '&' + //first revert any previously converted. + $text = str_replace(array('&', '&'), array('&', '&'), $text); + + return $text; + } + + + /** + * Convert any string back to plain text. + * + * @param $text + * @return array|string|string[] + */ + public function toText($text) + { + $text = (string) $text; + + if ($this->isBBcode($text) === true) // convert any bbcodes to html + { + $text = $this->toHTML($text, true); + } + + if ($this->isHtml($text) === true) // strip any html. + { + $text = $this->toHTML($text, true); + $text = str_replace("\n", '', $text); // clean-out line-breaks. + $text = str_ireplace(array('
', '
', '
'), "\n", $text); + $text = strip_tags($text); + } + + $search = array('&#039;', '&#036;', ''', '$', '\', '&#092;'); + $replace = array("'", '$', "'", '$', "\\", "\\"); + $text = str_replace($search, $replace, $text); + + return $text; + } + + + /** + * Set the dimensions of a thumbNail (generated by thumbUrl) + */ + public function setThumbSize($w = null, $h = null, $crop = null) + { + + if ($w !== null) + { + $this->thumbWidth = (int) $w; + } + + if ($h !== null) + { + $this->thumbHeight = (int) $h; + } + + if ($crop !== null) + { + $this->thumbCrop = (int) $crop; + } + + } + + /** + * @param $val + * @return int|null + */ + public function thumbEncode($val = null) + { + + if ($val !== null) + { + $this->thumbEncode = (int) $val; + + return null; + } + + return $this->thumbEncode; + } + + + /** + * Retrieve img tag width and height attributes for current thumbnail. + * + * @return string + */ + public function thumbDimensions($type = 'single') + { + + if (!empty($this->thumbCrop) && !empty($this->thumbWidth) && !empty($this->thumbHeight)) // dimensions are known. + { + return ($type === 'double') ? 'width="' . $this->thumbWidth . '" height="' . $this->thumbHeight . '"' : "width='" . $this->thumbWidth . "' height='" . $this->thumbHeight . "'"; + } + + return null; + } + + + /** + * Set or Get the value of the thumbNail Width. + * + * @param $width (optional) + */ + public function thumbWidth($width = null) + { + + if ($width !== null) + { + $this->thumbWidth = (int) $width; + } + + return $this->thumbWidth; + } + + /** + * Set or Get the value of the thumbNailbCrop. + * + * @param bool $status = true/false + */ + public function thumbCrop($status = false) + { + + if ($status !== false) + { + $this->thumbCrop = (int) $status; + } + + return $this->thumbCrop; + } + + + /** + * Set or Get the value of the thumbNail height. + * + * @param $height (optional) + */ + public function thumbHeight($height = null) + { + + if ($height !== null) + { + $this->thumbHeight = (int) $height; + } + + return $this->thumbHeight; + + } + + /** + * Generated a Thumb Cache File Name from path and options. + * + * @param string $path + * @param array $options + * @param string $log (optional) - log file name + * @return null|string + */ + public function thumbCacheFile($path, $options = null, $log = null) + { + + if (empty($path)) + { + return null; + } + + if (is_string($options)) + { + parse_str($options, $options); + } + + $path = str_replace($this->getUrlConstants('raw'), $this->getUrlConstants('sc'), $path); + $path = $this->replaceConstants(str_replace('..', '', $path)); + + $filename = basename($path); + $tmp = explode('.', $filename); + $ext = end($tmp); + $len = strlen($ext) + 1; + $start = substr($filename, 0, -$len); + + // cleanup. + $newOpts = array( + 'w' => isset($options['w']) ? (string) intval($options['w']) : '', + 'h' => isset($options['h']) ? (string) intval($options['h']) : '', + 'aw' => isset($options['aw']) ? (string) intval($options['aw']) : '', + 'ah' => isset($options['ah']) ? (string) intval($options['ah']) : '', + 'c' => strtoupper(vartrue($options['c'], '0')), + ); + + if (!empty($options['type'])) + { + $newOpts['type'] = $options['type']; + $ext = $newOpts['type']; + } + + + if (!empty($options['aw'])) + { + $options['w'] = $options['aw']; + } + + if (!empty($options['ah'])) + { + $options['h'] = $options['ah']; + } + + + $size = varset($options['w'], 0) . 'x' . varset($options['h'], 0); + + $thumbQuality = e107::getPref('thumbnail_quality', 65); + + $cache_str = md5(serialize($newOpts) . $path . $thumbQuality); + + $pre = 'thumb_'; + $post = '.cache.bin'; + + // $cache_str = http_build_query($newOpts,null,'_'); // testing files. + + if (defined('e_MEDIA_STATIC')) // experimental - subject to change. + { + $pre = ''; + $post = ''; + } + + $fname = $pre . strtolower($start . '_' . $cache_str . '_' . $size . '.' . $ext) . $post; + + + if ($log !== null) + { + file_put_contents(e_LOG . $log, "\n++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n\n", FILE_APPEND); + $message = 'Name: ' . $fname . "\n"; + $message .= $path . "\n" . var_export($newOpts, true) . "\n\n\n"; + file_put_contents(e_LOG . $log, $message, FILE_APPEND); + + // file_put_contents(e_LOG.$log, "\t\tFOUND!!\n\n\n", FILE_APPEND); + } + + + return $fname; + } + + + /** + * @param bool|int $val + * @return int + */ + private function staticCount($val = false) + { + + $count = $this->staticCount; + + if ($val === 0) + { + $this->staticCount = 0; + } + elseif ($val !== false) + { + $this->staticCount += (int) $val; + } + + return $count; + + } + + + /** + * @param string $path - absolute path or e107 path {e_PLUGIN} etc. + * @param array $opts - when $opts['full'] is true, a full siteurl will be used instead of an absolute path. (unless static url is found) + * @return string - full path or static path. + * @todo Move to e107_class ? + */ + public function staticUrl($path = null, $opts = array()) + { + + if (empty($this->staticUrl) || deftrue('e_ADMIN_AREA')) + { + // e107::getDebug()->log("e_HTTP_STATIC not defined"); + if ($path === null) + { + return !empty($opts['full']) ? SITEURL : e_HTTP; + } + + return !empty($opts['full']) ? $this->replaceConstants($path, 'full') : $this->replaceConstants($path, 'abs'); // self::replaceConstants($path, 'full'); + } + + $staticArray = $this->staticUrl; // e_HTTP_STATIC; + $path = $this->replaceConstants($path, 'abs'); // replace any {THEME} etc. + $key = ltrim(eHelper::dasherize($path), '/'); + + if (is_array($staticArray)) + { + if(!empty($this->staticUrlMap[$key])) + { + $http = $this->staticUrlMap[$key]; + } + else + { + $cnt = count($staticArray); + $staticCount = $this->staticCount(); + if ($staticCount > ($cnt - 1)) + { + $staticCount = 0; + $this->staticCount(0); + } + + $http = !empty($staticArray[$staticCount]) ? $staticArray[$staticCount] : e_HTTP; + $this->staticCount(1); + } + } + else + { + $http = $this->staticUrl; + } + + $this->staticUrlMap[$key] = $http; + + + if (empty($path)) + { + return $http; + } + + $base = ''; + + + + $srch = array( + e_PLUGIN_ABS, + e_THEME_ABS, + e_WEB_ABS, + e_CACHE_IMAGE_ABS, + ); + + + $repl = array( + $http . $base . e107::getFolder('plugins'), + $http . $base . e107::getFolder('themes'), + $http . $base . e107::getFolder('web'), + $http . $base . str_replace('../', '', e_CACHE_IMAGE), + ); + + // Quickfix for any '/./' that may occur. + $srch[] = '/./'; + $repl[] = '/'; + + $ret = str_replace($srch, $repl, $path); + + if (strpos($ret, 'http') !== 0) // if not converted, check media folder also. + { + $ret = str_replace(e_MEDIA_ABS, $http . $base . e107::getFolder('media'), $ret); + } + + + + return $ret; + + } + + /** + * Used internally to store e_HTTP_STATIC. + * + * @param string|null $url The static URL ie. e_HTTP_STATIC + */ + public function setStaticUrl($url) + { + $this->staticUrl = $url; + } + + public function getStaticUrlMap() + { + return $this->staticUrlMap; + } + + /** + * Generate an auto-sized Image URL. + * + * @param $url - path to image or leave blank for a placeholder. eg. {e_MEDIA}folder/my-image.jpg + * @param array $options = [ width and height, but leaving this empty and using $this->thumbWidth() and $this->thumbHeight() is preferred. ie. {SETWIDTH: w=x&y=x} + * 'w' => int width (optional) + * 'h' => int height (optional) + * 'crop' => bool|string true/false or A(auto) or T(op) or B(ottom) or C(enter) or L(eft) or R(right) + * 'scale' => string '2x' (optional) + * 'x' => bool encode/mask the url parms (optional) + * 'nosef' => bool when set to true disabled SEF Url being returned (optional) + * ] + * @param bool $raw set to true when the $url does not being with an e107 variable ie. "{e_XXXX}" eg. {e_MEDIA} (optional) + * @param bool $full when true returns full http:// url. (optional) + * ] + * @return string + */ + public function thumbUrl($url = null, $options = array(), $raw = false, $full = false) + { + $url = (string) $url; + + $this->staticCount++; // increment counter. + + $ext = pathinfo($url, PATHINFO_EXTENSION); + + if ($ext === 'svg') + { + return $this->replaceConstants($url, 'abs'); + } + + if (strpos($url, '{e_') === 0) // Fix for broken links that use {e_MEDIA} etc. + { + //$url = $this->replaceConstants($url,'abs'); + // always switch to 'nice' urls when SC is used + $url = str_replace($this->getUrlConstants('sc'), $this->getUrlConstants('raw'), $url); + } + + if (is_string($options)) + { + parse_str($options, $options); + } + + if (!empty($options['scale'])) // eg. scale the width height 2x 3x 4x. etc. + { + $options['return'] = 'src'; + $options['size'] = $options['scale']; + unset($options['scale']); + + return $this->thumbSrcSet($url, $options); + } + + + if (strpos($url, e_MEDIA) !== false || strpos($url, e_SYSTEM) !== false) // prevent disclosure of 'hashed' path. + { + $raw = true; + } + + if ($raw) + { + $url = $this->createConstants($url, 'mix'); + } + + $baseurl = ($full ? SITEURL : e_HTTP) . 'thumb.php?'; + + if (!empty($this->staticUrl)) + { + $baseurl = $this->staticUrl() . 'thumb.php?'; + } + + $thurl = 'src=' . urlencode($url) . '&'; + + // e107::getDebug()->log("Thumb: ".basename($url). print_a($options,true), E107_DBG_BASIC); + + if (!empty($options) && (isset($options['w']) || isset($options['aw']) || isset($options['h']))) + { + $options['w'] = varset($options['w']); + $options['h'] = varset($options['h']); + $options['crop'] = (isset($options['aw']) || isset($options['ah'])) ? 1 : varset($options['crop']); + $options['aw'] = varset($options['aw']); + $options['ah'] = varset($options['ah']); + $options['x'] = varset($options['x']); + } + else + { + $options['w'] = $this->thumbWidth; + $options['h'] = $this->thumbHeight; + $options['crop'] = $this->thumbCrop; + $options['aw'] = null; + $options['ah'] = null; + $options['x'] = $this->thumbEncode; + + } + + + if (!empty($options['crop'])) + { + if (!empty($options['aw']) || !empty($options['ah'])) + { + $options['w'] = $options['aw']; + $options['h'] = $options['ah']; + } + + $thurl .= 'aw=' . (int) $options['w'] . '&ah=' . (int) $options['h']; + + if (!is_numeric($options['crop'])) + { + $thurl .= '&c=' . $options['crop']; + $options['nosef'] = true; + } + + } + else + { + + $thurl .= 'w=' . (int) $options['w'] . '&h=' . (int) $options['h']; + + } + + if (!empty($options['type'])) + { + $thurl .= '&type=' . $options['type']; + } + + + if (defined('e_MEDIA_STATIC')) // experimental - subject to change. + { + $opts = str_replace('&', '&', $thurl); + + $staticFile = $this->thumbCacheFile($url, $opts); + + + if (!empty($staticFile) && is_readable(e_CACHE_IMAGE . $staticFile)) + { + return $this->staticUrl(e_CACHE_IMAGE_ABS . $staticFile); + + } + + // echo "
static-not-found: ".$staticFile; + + $options['nosef'] = true; + $options['x'] = null; + // file_put_contents(e_LOG."thumb.log", "\n++++++++++++++++++++++++++++++++++\n\n", FILE_APPEND); + } + + + if ($this->modRewriteMedia && empty($options['nosef']))// SEF URL support. + { + $options['full'] = $full; + $options['ext'] = pathinfo($url, PATHINFO_EXTENSION); + $options['thurl'] = $thurl; + // $options['x'] = $this->thumbEncode(); + + if ($sefUrl = $this->thumbUrlSEF($url, $options)) + { + return $sefUrl; + } + } + + if (!empty($options['x']))//base64 encode url + { + $thurl = 'id=' . base64_encode($thurl); + } + + return $baseurl . $thurl; + } + + + /** + * Split a thumb.php url into an array which can be parsed back into the thumbUrl method. . + * + * @param $src + * @return array + */ + public function thumbUrlDecode($src) + { + + list($url, $qry) = array_pad(explode('?', $src), 2, null); + + $ret = array(); + + if (!empty($qry) && strpos($url, 'thumb.php') !== false) // Regular + { + parse_str($qry, $val); + $ret = $val; + } + elseif (preg_match('/media\/img\/(a)?([\d]*)x(a)?([\d]*)\/(.*)/', $url, $match)) // SEF + { + $wKey = $match[1] . 'w'; + $hKey = $match[3] . 'h'; + + $ret = array( + 'src' => 'e_MEDIA_IMAGE/' . $match[5], + $wKey => $match[2], + $hKey => $match[4] + ); + } + elseif (preg_match('/theme\/img\/(a)?([\d]*)x(a)?([\d]*)\/(.*)/', $url, $match)) // Theme-image SEF Urls + { + $wKey = $match[1] . 'w'; + $hKey = $match[3] . 'h'; + + $ret = array( + 'src' => 'e_THEME/' . $match[5], + $wKey => $match[2], + $hKey => $match[4] + ); + + } + elseif (defined('TINYMCE_DEBUG')) + { + print_a('thumbUrlDecode: No Matches'); + + } + + + return $ret; + } + + + /** + * Experimental: Generate a Thumb URL for use in the img srcset attribute. + * + * @param string $src eg. {e_MEDIA_IMAGE}myimage.jpg + * @param int|string|array $width - desired size in px or '2x' or '3x' or null for all or array ( + * @return string + */ + public function thumbSrcSet($src = '', $width = null) + { + + $multiply = null; + $encode = false; + $parm = array(); + + if (is_array($width)) + { + $parm = $width; + $multiply = $width['size']; + $encode = (!empty($width['x'])) ? $width['x'] : false; + $width = $width['size']; + } + + + // $encode = $this->thumbEncode();; + if ($width == null || $width === 'all') + { + $links = array(); + $mag = ($width == null) ? array(1, 2) : array(160, 320, 460, 600, 780, 920, 1100); + foreach ($mag as $v) + { + $w = ($this->thumbWidth * $v); + $h = ($this->thumbHeight * $v); + + $att = (!empty($this->thumbCrop)) ? array('aw' => $w, 'ah' => $h) : compact('w', 'h'); + $att['x'] = $encode; + + $add = ($width == null) ? ' ' . $v . 'x' : ' ' . $v . 'w'; + $links[] = $this->thumbUrl($src, $att) . $add; // " w".$width; // + } + + return implode(', ', $links); + + } + elseif ($multiply === '2x' || $multiply === '3x' || $multiply === '4x') + { + $multiInt = (int) $multiply; + + if (empty($parm['w']) && isset($parm['h'])) + { + $parm['h'] = ($parm['h'] * $multiInt); + + return $this->thumbUrl($src, $parm) . ' ' . $multiply; + } + + if (isset($parm['w']) && !isset($parm['h'])) // if w set, assume h value of 0 is set. + { + $parm['h'] = 0; + } + + $width = !empty($parm['w']) ? (intval($parm['w']) * $multiInt) : ($this->thumbWidth * $multiInt); + $height = isset($parm['h']) ? (intval($parm['h']) * $multiInt) : ($this->thumbHeight * $multiInt); + + } + else + { + $height = (($this->thumbHeight * $width) / $this->thumbWidth); + + } + + + if (!isset($parm['aw'])) + { + $parm['aw'] = null; + } + + if (!isset($parm['ah'])) + { + $parm['ah'] = null; + } + + if (!isset($parm['x'])) + { + $parm['x'] = null; + } + + if (!isset($parm['crop'])) + { + $parm['crop'] = null; + } + + $parms = array('w' => $width, 'h' => $height, 'crop' => $parm['crop'], 'x' => $parm['x'], 'aw' => $parm['aw'], 'ah' => $parm['ah']); + + if (!empty($parm['type'])) + { + $parms['type'] = $parm['type']; + } + // $parms = !empty($this->thumbCrop) ? array('aw' => $width, 'ah' => $height, 'x'=>$encode) : array('w' => $width, 'h' => $height, 'x'=>$encode ); + + // $parms['x'] = $encode; + + if (!empty($parm['return']) && $parm['return'] === 'src') + { + return $this->thumbUrl($src, $parms); + } + + $ret = $this->thumbUrl($src, $parms); + + $ret .= ($multiply) ? ' ' . $multiply : ' ' . $width . 'w'; + + return $ret; + + } + + + + /** + * Used by thumbUrl when SEF Image URLS is active. @param $url + * + * @param array $options + * @return string + * @see e107.htaccess + */ + public function thumbUrlSEF($url = '', $options = array()) + { + + if (!empty($options['full'])) + { + $base = SITEURL; + } + else + { + $base = (!empty($options['ebase'])) ? '{e_BASE}' : e_HTTP; + } + + if (!empty($this->staticUrl)) + { + $base = $this->staticUrl(); + } + // $base = (!empty($options['full'])) ? SITEURL : e_HTTP; + + if (!empty($options['x']) && !empty($options['ext'])) // base64 encoded. Build URL for: RewriteRule ^media\/img\/([-A-Za-z0-9+/]*={0,3})\.(jpg|gif|png)?$ thumb.php?id=$1 + { + $ext = strtolower($options['ext']); + + return $base . 'media/img/' . base64_encode($options['thurl']) . '.' . str_replace('jpeg', 'jpg', $ext); + } + elseif (strpos($url, 'e_MEDIA_IMAGE') !== false) // media images. + { + $sefPath = 'media/img/'; + $clean = array('{e_MEDIA_IMAGE}', 'e_MEDIA_IMAGE/'); + } + elseif (strpos($url, 'e_AVATAR') !== false) // avatars + { + $sefPath = 'media/avatar/'; + $clean = array('{e_AVATAR}', 'e_AVATAR/'); + } + elseif (strpos($url, 'e_THEME') !== false) // theme folder images. + { + $sefPath = 'theme/img/'; + $clean = array('{e_THEME}', 'e_THEME/'); + } + else + { + // e107::getDebug()->log("SEF URL False: ".$url); + return false; + } + + // Build URL for ReWriteRule ^media\/img\/(a)?([\d]*)x(a)?([\d]*)\/(.*)?$ thumb.php?src=e_MEDIA_IMAGE/$5&$1w=$2&$3h=$4 + $sefUrl = $base . $sefPath; + + if (!empty($options['scale'])) + { + $multiInt = (int) $options['scale']; + $options['w'] = $options['w'] * $multiInt; + $options['h'] = $options['h'] * $multiInt; + } + + + if (!empty($options['aw']) || !empty($options['ah'])) + { + $sefUrl .= 'a' . intval($options['aw']) . 'xa' . intval($options['ah']); + } + elseif (!empty($options['crop'])) + { + + if (!is_numeric($options['crop'])) + { + $sefUrl .= strtolower($options['crop']) . intval($options['w']) . 'x' . strtolower($options['crop']) . intval($options['h']); + } + else + { + $sefUrl .= 'a' . intval($options['w']) . 'xa' . intval($options['h']); + } + + + } + else + { + $sefUrl .= intval($options['w']) . 'x' . intval($options['h']); + } + + $sefUrl .= '/'; + $sefUrl .= str_replace($clean, '', $url); + + return $sefUrl; + + } + + /** + * Help for converting to more safe URLs + * e.g. {e_MEDIA_FILE}path/to/video.flv => e_MEDIA_FILE/path/to/video.flv + * + * @param string $type sc|raw|rev|all + * @return array + * @todo support for ALL URL shortcodes (replacement methods) + */ + public function getUrlConstants($type = 'sc') + { + + // sub-folders first! + static $array = array( + 'e_MEDIA_FILE/' => '{e_MEDIA_FILE}', + 'e_MEDIA_VIDEO/' => '{e_MEDIA_VIDEO}', + 'e_MEDIA_IMAGE/' => '{e_MEDIA_IMAGE}', + 'e_MEDIA_ICON/' => '{e_MEDIA_ICON}', + 'e_AVATAR/' => '{e_AVATAR}', + 'e_AVATAR_DEFAULT/' => '{e_AVATAR_DEFAULT}', + 'e_AVATAR_UPLOAD/' => '{e_AVATAR_UPLOAD}', + 'e_WEB_JS/' => '{e_WEB_JS}', + 'e_WEB_CSS/' => '{e_WEB_CSS}', + 'e_WEB_IMAGE/' => '{e_WEB_IMAGE}', + 'e_IMPORT/' => '{e_IMPORT}', + // 'e_WEB_PACK/' => '{e_WEB_PACK}', + + 'e_BASE/' => '{e_BASE}', + 'e_ADMIN/' => '{e_ADMIN}', + 'e_IMAGE/' => '{e_IMAGE}', + 'e_THEME/' => '{e_THEME}', + 'e_PLUGIN/' => '{e_PLUGIN}', + 'e_HANDLER/' => '{e_HANDLER}', // BC + 'e_MEDIA/' => '{e_MEDIA}', + 'e_WEB/' => '{e_ADMIN}', + // 'THEME/' => '{THEME}', + ); + + + switch ($type) + { + case 'sc': + return array_values($array); + break; + + case 'raw': + return array_keys($array); + break; + + case 'rev': + return array_reverse($array, true); + break; + + case 'all': + return $array; + break; + } + + return array(); + } + + + /** + * @return array + */ + public function getEmotes() + { + + return e107::getEmote()->getList(); + } + + + /** + * Replace e107 path constants + * Note: only an ADMIN user can convert {e_ADMIN} + * TODO - runtime cache of search/replace arrays (object property) when $mode !== '' + * + * @param string $text + * @param string $mode [optional] abs|full "full" = produce absolute URL path, e.g. http://sitename.com/e107_plugins/etc + * 'abs' = produce truncated URL path, e.g. e107plugins/etc + * "" (default) = URL's get relative path e.g. ../e107_plugins/etc + * @param mixed $all [optional] if TRUE, then when $mode is "full" or TRUE, USERID is also replaced... + * when $mode is "" (default), ALL other e107 constants are replaced + * @return string|array + */ + public function replaceConstants($text, $mode = '', $all = false) + { + + if (is_array($text)) + { + $new = array(); + foreach ($text as $k => $v) + { + $new[$k] = $this->replaceConstants($v, $mode, $all); + } + + return $new; + } + + $replace_absolute = array(); + + if (!empty($mode)) + { + $e107 = e107::getInstance(); + + if (empty($this->relativePaths)) // prevent multiple lookups. + { + + $this->relativePaths = array( + $e107::getFolder('media_files'), + $e107::getFolder('media_video'), + $e107::getFolder('media_image'), + $e107::getFolder('media_icon'), + $e107::getFolder('avatars'), + $e107::getFolder('web_js'), + $e107::getFolder('web_css'), + $e107::getFolder('web_image'), + //$e107->getFolder('web_pack'), + e_IMAGE_ABS, + e_THEME_ABS, + $e107::getFolder('images'), + $e107::getFolder('plugins'), + $e107::getFolder('files'), + $e107::getFolder('themes'), + // $e107->getFolder('downloads'), + $e107::getFolder('handlers'), + $e107::getFolder('media'), + $e107::getFolder('web'), + $e107->site_theme ? $e107::getFolder('themes') . $e107->site_theme . '/' : '', + defset('THEME_ABS'), + (deftrue('ADMIN') ? $e107::getFolder('admin') : ''), + '', + $e107::getFolder('core'), + $e107::getFolder('system'), + ); + } + + $replace_relative = $this->relativePaths; + + switch ($mode) + { + case 'abs': + $replace_absolute = array( + e_MEDIA_FILE_ABS, + e_MEDIA_VIDEO_ABS, + e_MEDIA_IMAGE_ABS, + e_MEDIA_ICON_ABS, + e_AVATAR_ABS, + e_JS_ABS, + e_CSS_ABS, + e_WEB_IMAGE_ABS, + // e_PACK_ABS, + e_IMAGE_ABS, + e_THEME_ABS, + e_IMAGE_ABS, + e_PLUGIN_ABS, + e_FILE_ABS, + e_THEME_ABS, + // e_DOWNLOAD_ABS, //impossible when download is done via php. + '', // handlers - no ABS path available + e_MEDIA_ABS, + e_WEB_ABS, + defset('THEME_ABS'), + defset('THEME_ABS'), + (ADMIN ? e_ADMIN_ABS : ''), + $e107->server_path, + '', // no e_CORE absolute path + '', // no e_SYSTEM absolute path + ); + break; + + case 'full': + $replace_absolute = array( + SITEURLBASE . e_MEDIA_FILE_ABS, + SITEURLBASE . e_MEDIA_VIDEO_ABS, + SITEURLBASE . e_MEDIA_IMAGE_ABS, + SITEURLBASE . e_MEDIA_ICON_ABS, + SITEURLBASE . e_AVATAR_ABS, + SITEURLBASE . e_JS_ABS, + SITEURLBASE . e_CSS_ABS, + SITEURLBASE . e_WEB_IMAGE_ABS, + // SITEURLBASE.e_PACK_ABS, + SITEURLBASE . e_IMAGE_ABS, + SITEURLBASE . e_THEME_ABS, + SITEURLBASE . e_IMAGE_ABS, + SITEURLBASE . e_PLUGIN_ABS, + SITEURLBASE . e_FILE_ABS, // deprecated + SITEURLBASE . e_THEME_ABS, + //SITEURL.$e107->getFolder('downloads'), + '', // handlers - no ABS path available + SITEURLBASE . e_MEDIA_ABS, + SITEURLBASE . e_WEB_ABS, + defset('THEME_ABS') ? SITEURLBASE . THEME_ABS : '', + defset('THEME_ABS') ? SITEURLBASE . THEME_ABS : '', + (deftrue('ADMIN') ? SITEURLBASE . e_ADMIN_ABS : ''), + SITEURL, + '', // no e_CORE absolute path + '', // no e_SYSTEM absolute path + ); + break; + } + // sub-folders first! + $search = array( + '{e_MEDIA_FILE}', + '{e_MEDIA_VIDEO}', + '{e_MEDIA_IMAGE}', + '{e_MEDIA_ICON}', + '{e_AVATAR}', + '{e_WEB_JS}', + '{e_WEB_CSS}', + '{e_WEB_IMAGE}', + // '{e_WEB_PACK}', + '{e_IMAGE_ABS}', + '{e_THEME_ABS}', + '{e_IMAGE}', + '{e_PLUGIN}', + '{e_FILE}', + '{e_THEME}', + //,"{e_DOWNLOAD}" + '{e_HANDLER}', + '{e_MEDIA}', + '{e_WEB}', + '{THEME}', + '{THEME_ABS}', + '{e_ADMIN}', + '{e_BASE}', + '{e_CORE}', + '{e_SYSTEM}', + ); + + /*if (ADMIN) + { + $replace_relative[] = $e107->getFolder('admin'); + $replace_absolute[] = SITEURL.$e107->getFolder('admin'); + $search[] = "{e_ADMIN}"; + }*/ + + if ($all) + { + if (USER) + { // Can only replace with valid number for logged in users + $replace_relative[] = USERID; + $replace_absolute[] = USERID; + } + else + { + $replace_relative[] = ''; + $replace_absolute[] = ''; + } + $search[] = '{USERID}'; + } + + // current THEME + /*if(!defined('THEME')) + { + //if not already parsed by doReplace + $text = str_replace(array('{THEME}', '{THEME_ABS}'), '', $text); + } + else + { + $replace_relative[] = THEME; + $replace_absolute[] = THEME_ABS; + $search[] = "{THEME}"; + $replace_relative[] = THEME; + $replace_absolute[] = THEME_ABS; + $search[] = "{THEME_ABS}"; + }*/ + + $replace = ((string) $mode === 'full' || (string) $mode === 'abs') ? $replace_absolute : $replace_relative; + + return str_replace($search, $replace, $text); + } + +// $pattern = ($all ? "#\{([A-Za-z_0-9]*)\}#s" : "#\{(e_[A-Z]*)\}#s"); + $pattern = ($all ? '#\{([A-Za-z_0-9]*)\}#s' : '#\{(e_[A-Z]*(?:_IMAGE|_VIDEO|_FILE|_CONTENT|_ICON|_AVATAR|_JS|_CSS|_PACK|_DB|_ABS){0,1})\}#s'); + $text = preg_replace_callback($pattern, array($this, 'doReplace'), $text); + + if (!defined('THEME')) + { + //if not already parsed by doReplace + $text = str_replace(array('{THEME}', '{THEME_ABS}'), '', $text); + } + else + { + $srch = array('{THEME}', '{THEME_ABS}'); + $repl = array(THEME, THEME_ABS); + $text = str_replace($srch, $repl, $text); + } + + return $text; + } + + + /** + * @param array $matches + * @return mixed|string + */ + private function doReplace($matches) + { + + if (defined($matches[1]) && (deftrue('ADMIN') || strpos($matches[1], 'ADMIN') === false)) + { + return constant($matches[1]); + } + + return $matches[1]; + } + + /** + * Create and substitute e107 constants in passed URL + * + * @param string $url + * @param integer $mode 0-folders, 1-relative ('rel'), 2-absolute ('abs'), 3-full ('full') (with domain), 4-absolute & relative ('mix') (combination of 1,2,3) + * @return string + */ + public function createConstants($url, $mode = 0) + { + + //FIXME - create constants for absolute paths and site URL's + if (!is_numeric($mode)) + { + switch ($mode) + { + case 'rel' : + $mode = 1; + break; + case 'abs' : + $mode = 2; + break; + case 'full' : + $mode = 3; + break; + case 'mix' : + $mode = 4; + break; + case 'nice': + $mode = 5; + break; + } + } + $e107 = e107::getInstance(); + switch ($mode) + { + case 0: // folder name only. + $tmp = array( + '{e_MEDIA_FILE}' => $e107::getFolder('media_files'), + '{e_MEDIA_VIDEO}' => $e107::getFolder('media_videos'), + '{e_MEDIA_IMAGE}' => $e107::getFolder('media_images'), + '{e_MEDIA_ICON}' => $e107::getFolder('media_icons'), + '{e_AVATAR}' => $e107::getFolder('avatars'), + '{e_WEB_JS}' => $e107::getFolder('web_js'), + '{e_WEB_CSS}' => $e107::getFolder('web_css'), + '{e_WEB_IMAGE}' => $e107::getFolder('web_images'), + // '{e_WEB_PACK}' => $e107::getFolder('web_packs'), + + '{e_IMAGE}' => $e107::getFolder('images'), + '{e_PLUGIN}' => $e107::getFolder('plugins'), + '{e_FILE}' => $e107::getFolder('files'), + '{e_THEME}' => $e107::getFolder('themes'), + '{e_DOWNLOAD}' => $e107::getFolder('downloads'), + '{e_ADMIN}' => $e107::getFolder('admin'), + '{e_HANDLER}' => $e107::getFolder('handlers'), + '{e_MEDIA}' => $e107::getFolder('media'), + '{e_WEB}' => $e107::getFolder('web'), + '{e_UPLOAD}' => $e107::getFolder('uploads'), + ); + + break; + + + case 1: // relative path only + $tmp = array( + '{e_MEDIA_FILE}' => e_MEDIA_FILE, + '{e_MEDIA_VIDEO}' => e_MEDIA_VIDEO, + '{e_MEDIA_IMAGE}' => e_MEDIA_IMAGE, + '{e_MEDIA_ICON}' => e_MEDIA_ICON, + '{e_AVATAR}' => e_AVATAR, + '{e_IMPORT}' => e_IMPORT, + '{e_WEB_JS}' => e_WEB_JS, + '{e_WEB_CSS}' => e_WEB_CSS, + '{e_WEB_IMAGE}' => e_WEB_IMAGE, + // '{e_WEB_PACK}' => e_WEB_PACK, + + '{e_IMAGE}' => e_IMAGE, + '{e_PLUGIN}' => e_PLUGIN, + '{e_FILE}' => e_FILE, + '{e_THEME}' => e_THEME, + '{e_DOWNLOAD}' => e_DOWNLOAD, + '{e_ADMIN}' => e_ADMIN, + '{e_HANDLER}' => e_HANDLER, + '{e_MEDIA}' => e_MEDIA, + '{e_WEB}' => e_WEB, + '{e_UPLOAD}' => e_UPLOAD, + ); + break; + + case 2: // absolute path only + $tmp = array( + '{e_MEDIA_FILE}' => e_MEDIA_FILE_ABS, + '{e_MEDIA_VIDEO}' => e_MEDIA_VIDEO_ABS, + '{e_MEDIA_IMAGE}' => e_MEDIA_IMAGE_ABS, + '{e_MEDIA_ICON}' => e_MEDIA_ICON_ABS, + '{e_AVATAR}' => e_AVATAR_ABS, + '{e_WEB_JS}' => e_JS_ABS, + '{e_WEB_CSS}' => e_CSS_ABS, + '{e_WEB_IMAGE}' => e_WEB_IMAGE_ABS, + // '{e_WEB_PACK}' => e_PACK_ABS, + + '{e_IMAGE}' => e_IMAGE_ABS, + '{e_PLUGIN}' => e_PLUGIN_ABS, + '{e_FILE}' => e_FILE_ABS, // deprecated + '{e_THEME}' => e_THEME_ABS, + '{e_DOWNLOAD}' => e_HTTP . 'request.php?',// FIXME - we need solution! + '{e_ADMIN}' => e_ADMIN_ABS, + //'{e_HANDLER}' => e_HANDLER_ABS, - no ABS path available + '{e_MEDIA}' => e_MEDIA_ABS, + '{e_WEB}' => e_WEB_ABS, + '{e_BASE}' => e_HTTP, + ); + break; + + case 3: // full path (e.g http://domain.com/e107_images/) + $tmp = array( + '{e_MEDIA_FILE}' => SITEURLBASE . e_MEDIA_FILE_ABS, + '{e_MEDIA_VIDEO}' => SITEURLBASE . e_MEDIA_VIDEO_ABS, + '{e_MEDIA_IMAGE}' => SITEURLBASE . e_MEDIA_IMAGE_ABS, + '{e_MEDIA_ICON}' => SITEURLBASE . e_MEDIA_ICON_ABS, + '{e_AVATAR}' => SITEURLBASE . e_AVATAR_ABS, + '{e_WEB_JS}' => SITEURLBASE . e_JS_ABS, + '{e_WEB_CSS}' => SITEURLBASE . e_CSS_ABS, + '{e_WEB_IMAGE}' => SITEURLBASE . e_WEB_IMAGE_ABS, + // '{e_WEB_PACK}' => SITEURLBASE.e_PACK_ABS, + + '{e_IMAGE}' => SITEURLBASE . e_IMAGE_ABS, + '{e_PLUGIN}' => SITEURLBASE . e_PLUGIN_ABS, + '{e_FILE}' => SITEURLBASE . e_FILE_ABS, // deprecated + '{e_THEME}' => SITEURLBASE . e_THEME_ABS, + '{e_DOWNLOAD}' => SITEURLBASE . e_HTTP . 'request.php?',// FIXME - we need solution! + '{e_ADMIN}' => SITEURLBASE . e_ADMIN_ABS, + //'{e_HANDLER}' => e_HANDLER_ABS, - no ABS path available + '{e_MEDIA}' => SITEURLBASE . e_MEDIA_ABS, + '{e_WEB}' => SITEURLBASE . e_WEB_ABS, + '{e_BASE}' => SITEURL, + ); + break; + + case 4: // absolute & relative paths + $url = $this->createConstants($url, 3); + $url = $this->createConstants($url, 2); + $url = $this->createConstants($url, 1); + + return $url; + break; + + case 5: // nice urls - e.g. e_MEDIA_VIDEO/mystream.flv + $url = $this->createConstants($url, 4); + + return str_replace($this->getUrlConstants('sc'), $this->getUrlConstants('raw'), $url); + break; + + default: + $tmp = array(); + break; + } + + $hasCDN = strpos($url, '//') === 0; + + foreach ($tmp as $key => $val) + { + // Fix - don't break the CDN '//cdn.com' URLs + if ($hasCDN && $val === '/') + { + continue; + } + + $len = strlen($val); + if (substr($url, 0, $len) == $val) + { + // replace the first instance only + return substr_replace($url, $key, 0, $len); + } + } + + return $url; + } + + + //FIXME - $match not used? + + /** + * @param $text + * @param $match + * @return array|string|string[]|null + */ + public function e_highlight($text, $match) + { + + $tags = array(); + preg_match_all('#<[^>]+>#', $text, $tags); + $text = preg_replace('#<[^>]+>#', '<|>', $text); + $text = preg_replace('#(\b".$match."\b)#i', '\\1', $text); + foreach ($tags[0] as $tag) + { + $text = preg_replace('#<\|>#', $tag, $text, 1); + } + + return $text; + } + + + /** + * Convert Text to a suitable format for use in emails. eg. relative links will be replaced with full links etc. + * + * @param string $text + * @param boolean $posted - if the text has been posted. (uses stripslashes etc) + * @param string $mods - flags for text transformation. + */ + public function toEmail($text, $posted = '', $mods = 'parse_sc, no_make_clickable') + { + + if ($posted === true) + { + if (MAGIC_QUOTES_GPC) + { + $text = stripslashes($text); + } + $text = preg_replace('#\[(php)#i', '[\\1', $text); + } + + $text = (strtolower($mods) !== 'rawtext') ? $this->replaceConstants($text, 'full') : $text; + + if ($this->isHtml($text)) + { + $text = str_replace(array('[html]', '[/html]'), '', $text); + $text = html_entity_decode($text, ENT_COMPAT, 'UTF-8'); + } + else + { + + $text = $this->toHTML($text, true, $mods); + } + + return $text; + } + + + /** + * Given an email address, returns a link including with obfuscated text. + * e-email css in e107.css inserts the user/domain data for display. + * + * @param string $email + * @param string $words [optional] text to display + * @param null $subject [optional] default subject for email. + * @return string + */ + public function emailObfuscate($email, $words = null, $subject = null) + { + + if (strpos($email, '@') === false) + { + return ''; + } + + if ($subject) + { + $subject = '?subject=' . $subject; + } + + list($name, $address) = explode('@', $email, 2); + + if (empty($words)) + { + $words = '@'; + $user = "data-user='" . $this->obfuscate($name) . "'"; + $dom = "data-dom='" . $this->obfuscate($address) . "'"; + } + else + { + $user = ''; + $dom = ''; + } + + $url = 'mailto:' . $email . $subject; + + $safe = $this->obfuscate($url); + + return "" . $words . ''; + } + + + /** + * Obfuscate text from bots using Randomized encoding. + * + * @param $text + * @return string + */ + public function obfuscate($text) + { + + $ret = ''; + foreach (str_split($text) as $letter) + { + switch (mt_rand(1, 3)) + { + // HTML entity code + case 1: + $ret .= '&#' . ord($letter) . ';'; + break; + + // Hex character code + case 2: + $ret .= '&#x' . dechex(ord($letter)) . ';'; + break; + + // Raw (no) encoding + case 3: + $ret .= $letter; + } + } + + return $ret; + } + + + /** + * @param $name + * @return array|e_parse_shortcode|null + */ + public function __get($name) + { + + switch ($name) + { + case 'e_sc': + $ret = e107::getScParser(); + break; + + + default: + // trigger_error('$e107->$'.$name.' not defined', E_USER_WARNING); + return null; + break; + } + + + $this->$name = $ret; + + return $ret; + } + + // Formerly located in e_parser -------------------------- + + + /** + * Merge default 'global' attributes into assigned tags. + */ + private function compileAttributeDefaults() + { + + foreach ($this->allowedAttributes as $tag => $array) + { + if ($tag === 'default') + { + continue; + } + + foreach ($this->allowedAttributes['default'] as $def) + { + $this->allowedAttributes[$tag][] = $def; + } + + } + + } + + /** + * Used by e_parse to start + */ + public function init() + { + + if (defined('FONTAWESOME')) + { + $this->fontawesome = (int) FONTAWESOME; + } + + if (defined('BOOTSTRAP')) + { + $this->bootstrap = (int) BOOTSTRAP; + } + + $this->modRewriteMedia = deftrue('e_MOD_REWRITE_MEDIA'); + + if (defined('e_HTTP_STATIC')) + { + $this->staticUrl = e_HTTP_STATIC; + } + + // Preprocess the supermods to be useful default arrays with all values + foreach ($this->e_SuperMods as $key => $val) + { + // precalculate super defaults + $this->e_SuperMods[$key] = array_merge($this->e_optDefault, $this->e_SuperMods[$key]); + $this->e_SuperMods[$key]['context'] = $key; + } + + $this->allowedTags = array('html', 'body', 'div', 'a', 'img', 'table', 'tr', 'td', 'th', 'tbody', 'thead', 'colgroup', 'b', + 'i', 'pre', 'code', 'strong', 'u', 'em', 'ul', 'ol', 'li', 'img', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'p', + 'section', 'article', 'blockquote', 'hgroup', 'aside', 'figure', 'figcaption', 'abbr', 'span', 'audio', 'video', 'source', 'br', + 'small', 'caption', 'noscript', 'hr', 'section', 'iframe', 'sub', 'sup', 'cite', 'x-bbcode', 'label', 'dl', 'dt', 'dd', + ); + + $this->scriptTags = array('script', 'applet', 'form', 'input', 'button', 'embed', 'object', 'ins', 'select', 'textarea'); //allowed when $pref['post_script'] is enabled. + + $this->allowedAttributes = array( + 'default' => array('id', 'style', 'class', 'title', 'lang', 'accesskey'), + 'img' => array('src', 'alt', 'width', 'height'), + 'a' => array('href', 'target', 'rel'), + 'script' => array('type', 'src', 'language', 'async'), + 'iframe' => array('src', 'frameborder', 'width', 'height', 'allowfullscreen', 'allow'), + 'input' => array('type', 'name', 'value'), + 'form' => array('action', 'method', 'target'), + 'audio' => array('src', 'controls', 'autoplay', 'loop', 'muted', 'preload'), + 'video' => array('autoplay', 'controls', 'height', 'loop', 'muted', 'poster', 'preload', 'src', 'width'), + 'table' => array('border', 'cellpadding', 'cellspacing'), // BC Fix. + 'td' => array('colspan', 'rowspan', 'name', 'bgcolor'), + 'th' => array('colspan', 'rowspan'), + 'col' => array('span'), + 'embed' => array('src', 'wmode', 'type', 'width', 'height'), + 'x-bbcode' => array('alt'), + 'label' => array('for'), + 'source' => array('media', 'sizes', 'src', 'srcset', 'type'), + + ); + + $this->scriptAttributes = array('onclick', 'onchange', 'onblur', 'onload', 'onfocus', 'onkeydown', 'onkeypress', 'onkeyup', + 'ondblclick', 'onmousedown', 'onmousemove', 'onmouseout', 'onmouseover', 'onmouseup', 'onmousewheel', + 'onwheel', 'oncopy', 'oncut', 'onpaste' + ); + + $this->blockTags = array('p', 'pre', 'div', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'blockquote'); // element includes its own line-break. + + $this->badAttrValues = array('javascript[\s]*?:', 'alert\(', 'vbscript[\s]*?:', 'data:text\/html', 'mhtml[\s]*?:', 'data:[\s]*?image'); + + $this->replaceAttrValues = array( + 'default' => array() + ); + + } + + /** + * Add Allowed Tags. + * + * @param string + */ + public function addAllowedTag($tag) + { + + $this->allowedTags[] = $tag; + } + + + /** + * @param $tag - html tag. + * @param $attArray - array of attributes. eg. array('style', 'id', 'class') etc. + */ + public function addAllowedAttribute($tag, $attArray) + { + + $this->allowedAttributes[$tag] = (array) $attArray; + } + + + /** + * Set Allowed Tags. + * + * @param $array + */ + public function setAllowedTags($array = array()) + { + + $this->allowedTags = $array; + } + + /** + * Set Script Access + * + * @param $val int e_UC_MEMBER, e_UC_NOBODY, e_UC_MAINADMIN or userclass number. + */ + public function setScriptAccess($val) + { + + $this->scriptAccess = $val; + } + + /** + * @param array $arr + * @return void + */ + public function setScriptAttibutes($arr) + { + $this->scriptAttributes = (array) $arr; + } + + /** + * @return array + */ + public function getAllowedTags() + { + return $this->allowedTags; + } + + /** + * @return array + */ + public function getAllowedAttributes() + { + return $this->allowedAttributes; + } + + + /** + * @return bool + */ + public function getScriptAccess() + { + return $this->scriptAccess; + } + + /** + * @return array + */ + public function getRemoved() + { + return $this->removedList; + } + + /** + * Set Allowed Attributes. + * + * @param $array + */ + public function setAllowedAttributes($array = array()) + { + + $this->allowedAttributes = $array; + } + + /** + * Set Script Tags. + * + * @param $array + */ + public function setScriptTags($array = array()) + { + + $this->scriptTags = $array; + } + + + /** + * @param int $version + */ + public function setFontAwesome($version) + { + $this->fontawesome = (int) $version; + } + + /** + * @param int $version + */ + public function setBootstrap($version) + { + $this->bootstrap = (int) $version; + } + + public function setmodRewriteMedia($bool) + { + $this->modRewriteMedia = (bool) $bool; + } + + /** + * Add leading zeros to a number. eg. 3 might become 000003 + * + * @param $num integer + * @param $numDigits - total number of digits + * @return string number with leading zeros. + */ + public function leadingZeros($num, $numDigits) + { + return (string) sprintf('%0' . $numDigits . 'd', $num); + } + + /** + * Generic variable translator for LAN definitions. + * + * @param $lan - string LAN + * @param string | array $vals - either a single value, which will replace '[x]' or an array with key=>value pairs. + * @return string + * @example $tp->lanVars("My name is [x] and I own a [y]", array("John","Cat")); + * @example $tp->lanVars("My name is [x] and I own a [y]", array('x'=>"John", 'y'=>"Cat")); + */ + public function lanVars($lan, $vals, $bold = false) + { + + $array = (!is_array($vals)) ? array('x' => $vals) : $vals; + + $search = array(); + $replace = array(); + + $defaults = array('x', 'y', 'z'); + + foreach ($array as $k => $v) + { + if (is_numeric($k)) // convert array of numeric to x,y,z + { + $k = $defaults[$k]; + } + + $search[] = '[' . $k . ']'; + $replace[] = ($bold === true) ? '' . $v . '' : $v; + } + + return str_replace($search, $replace, $lan); + } + + /** + * Return an Array of all specific tags found in an HTML document and their attributes. + * + * @param $html - raw html code + * @param $taglist - comma separated list of tags to search or '*' for all. + * @param $header - if the $html includes the html head or body tags - it should be set to true. + */ + public function getTags($html, $taglist = '*', $header = false) + { + + if ($header == false) + { + $html = '' . $html . ''; + } + + $doc = $this->domObj; + + $doc->preserveWhiteSpace = true; + libxml_use_internal_errors(true); + $doc->loadHTML($html); + + $tg = explode(',', $taglist); + $ret = array(); + + foreach ($tg as $find) + { + $tmp = $doc->getElementsByTagName($find); + + /** + * @var $k + * @var DOMDocument $node + */ + foreach ($tmp as $k => $node) + { + $tag = $node->nodeName; + $inner = $node->C14N(); + $inner = str_replace(' ', '', $inner); + + foreach ($node->attributes as $attr) + { + $name = $attr->nodeName; + $value = $attr->nodeValue; + $ret[$tag][$k][$name] = $value; + } + + $ret[$tag][$k]['@value'] = $inner; + + + } + } + + if ($header == false) + { + unset($ret['html'], $ret['body']); + } + + + return $ret; + } + + /** + * Glyph Embed Method Direct from svg file. + * + * @param string $cat far|fab|fas + * @param string $id eg. fa-search + * @param array $parm eg. ['fw'=>true] + * @return string|false + */ + private function toGlyphEmbed($cat, $id, $parm = array()) + { + $dirs = ['far' => 'regular', 'fab' => 'brands', 'fas' => 'solid']; + $path = e_WEB . 'lib/font-awesome/5/svgs/'; + $path .= $dirs[$cat] . '/'; + $path .= str_replace('fa-', '', $id) . ".svg"; + + + if ($ret = file_get_contents($path)) + { + $class = 'svg-inline--fa '; + $class .= $id; + $class .= ' fa-w-16'; + $class .= !empty($parm['fw']) ? ' fa-fw' : ''; + + return str_replace('