From 3cd8110928ba32303ab1c7fe4c5200f086fdbba5 Mon Sep 17 00:00:00 2001 From: Bradie Tilley Date: Thu, 4 Jun 2020 09:56:19 +0800 Subject: [PATCH 1/3] Update Local URL detection facility to cater for more scenarios, to prevent erroring out on localhost URLs that don't have matching hosts (virtual hosts and even 127.0.0.1 vs localhost) --- classes/Resizer.php | 99 ++++++++++++++++++++++++++++++++++++++------ updates/version.yaml | 4 +- 2 files changed, 89 insertions(+), 14 deletions(-) diff --git a/classes/Resizer.php b/classes/Resizer.php index d4d06da..6fc44ee 100644 --- a/classes/Resizer.php +++ b/classes/Resizer.php @@ -8,6 +8,7 @@ use Exception; use Event; use File; +use Illuminate\Support\Facades\Storage; use Intervention\Image\ImageManagerStatic as Image; use Validator; @@ -15,6 +16,8 @@ class Resizer { public const CACHE_PREFIX = 'image_resize_'; + public const EVENT_PREFIX = 'abweb.imageresize.'; + /** * A list of computed values to override $options * @@ -100,6 +103,72 @@ public function setFormatCache(array $cache) return $this; } + /** + * Get the absolute path of an image by passing it a local URL (https://mysite.com/themes/demo/assets/logo.png) + * + * @param string $url + * @return string|null Null if remote URL or file not exists + */ + protected function getAbsolutePathOfLocalUrl(string $url): ?string + { + if (empty($url)) { + return false; + } + + // Local path (allow events to override logic) + $localPath = null; + + /* Root paths to check files against, first we'll try relative to the base_path (document root) followed by a local disk check */ + $roots = [ + base_path(), + Storage::disk('local')->getDriver()->getAdapter()->getPathPrefix(), + ]; + + Event::fire(static::EVENT_PREFIX . 'getAbsolutePathOfLocalUrl', [ + &$url, + &$roots, + &$localPath, + ]); + + // If the event sets localPath to false, then assume it's not local (is remote URL) + if ($localPath === false) { + return null; + } + + // If the event sets localPath to a string, then assume it's a local path + if (is_string($localPath)) { + // Convert to absolute, if needed. + return (strpos($localPath, '/') === 0) ? $localPath : base_path($localPath); + } + + // No event handler + + // Check if hosts match (without www. prefix) + $host = preg_replace('/^www\./', '', parse_url((string) url('/'), PHP_URL_HOST), 1); + $found = preg_replace('/^www\./', '', parse_url((string) $url, PHP_URL_HOST), 1); + + // It's local if the hosts match, or if no host was found in the URL, or both are localhost/127.0.0.1 + $isLocal = ($host === $found) || + empty($found) || + (($host === '127.0.0.1' || $host === 'localhost') && ($found === '127.0.0.1' || $found === 'localhost')); + + if ($isLocal) { + $path = parse_url($url, PHP_URL_PATH); + + // iterate each possible root directory to try find the file + foreach ($roots as $root) { + $maybe = $root . DIRECTORY_SEPARATOR . ltrim($path, '/'); + + if (file_exists($maybe)) { + // if the file exists, assume this is the path to the file we're expecting + return $maybe; + } + } + } + + return null; + } + /** * Specify the image to use * @@ -115,8 +184,6 @@ public function setImage(string $image = null, bool $doNotModifyPath = false) } if ($image !== null) { - $absolutePath = false; - // Support JSON objects containing path property, e.g: {"path":"USETHISPATH",...} if (substr($image, 0, 2) === '{"') { $attempt = json_decode($image); @@ -126,17 +193,19 @@ public function setImage(string $image = null, bool $doNotModifyPath = false) } } - // Check if the image is an absolute url to the same server, if so get the storage path of the image - $regex = '/^(?:https?:\/\/)?' . $_SERVER['SERVER_NAME'] . '(?::\d+)?\/(.+)$/'; - if (preg_match($regex, $image, $m)) { - // Convert spaces, not going to urldecode as it will mess with pluses - $image = base_path(str_replace('%20', ' ', $m[1])); - $absolutePath = true; - } + if (preg_match('/^(https?:\/\/)/i', $image)) { + $path = $this->getAbsolutePathOfLocalUrl($image); + + // If path is string (local path, if local url) + if ($path !== null) { + $image = $path; + } + } elseif (strpos($image, '/') !== 0) { + $path = base_path($image); - // If not an absolute path, set it to an absolute path - if (!$absolutePath) { - $image = base_path(trim($image, '/')); + if (file_exists($path)) { + $image = $path; + } } } @@ -850,7 +919,9 @@ public function modify() break; case 'colorize': list($r, $g, $b) = explode(',', $value); + $this->im->colorize($r, $g, $b); + break; case 'insert': $exp = explode(',', $value); @@ -858,7 +929,9 @@ public function modify() $position = (isset($exp[1])) ? $exp[1] : null; $x = (isset($exp[2])) ? $exp[2] : null; $y = (isset($exp[3])) ? $exp[3] : null; + $this->im->insert($path, $position, $x, $y); + break; default: // Pass argument if configured to do so: @@ -926,7 +999,7 @@ public static function clearFiles(Carbon $minAge = null, string $directory = nul }); // Fire event to hook into and modify $files before deleting - Event::fire('abweb.imageresize.clearFiles', [&$files, $minAge]); + Event::fire(static::EVENT_PREFIX . 'clearFiles', [&$files, $minAge]); // Delete the files File::delete($files); diff --git a/updates/version.yaml b/updates/version.yaml index e20be29..96e4d85 100644 --- a/updates/version.yaml +++ b/updates/version.yaml @@ -38,4 +38,6 @@ 2.1.6: - Fix migration (2.1.2 migration) that causes installations to fail (due to plugin settings not existing for new projects at time of execution) 2.1.7: - - Fix - Update plugin's boot method to not directly reference Settings until DB connection is established \ No newline at end of file + - Fix - Update plugin's boot method to not directly reference Settings until DB connection is established +2.2.0: + - Fix - Update Local URL detection facility to cater for more scenarios \ No newline at end of file From d0f9b52d682d7e2115619b99ad71b205a96a5b3c Mon Sep 17 00:00:00 2001 From: Bradie Tilley Date: Thu, 4 Jun 2020 09:59:15 +0800 Subject: [PATCH 2/3] Only use local disk path prefix as a root path if it exists --- classes/Resizer.php | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/classes/Resizer.php b/classes/Resizer.php index 6fc44ee..ed45b8d 100644 --- a/classes/Resizer.php +++ b/classes/Resizer.php @@ -121,9 +121,14 @@ protected function getAbsolutePathOfLocalUrl(string $url): ?string /* Root paths to check files against, first we'll try relative to the base_path (document root) followed by a local disk check */ $roots = [ base_path(), - Storage::disk('local')->getDriver()->getAdapter()->getPathPrefix(), ]; + // Add local storage path too, if it exists + $localDisk = Storage::disk('local'); + if ($localDisk) { + $roots[] = $localDisk->getDriver()->getAdapter()->getPathPrefix(); + } + Event::fire(static::EVENT_PREFIX . 'getAbsolutePathOfLocalUrl', [ &$url, &$roots, From 4bc12951441834af636023e8c72a8fd75fdff7c9 Mon Sep 17 00:00:00 2001 From: Bradie Tilley Date: Thu, 4 Jun 2020 09:59:52 +0800 Subject: [PATCH 3/3] Comments --- classes/Resizer.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/classes/Resizer.php b/classes/Resizer.php index ed45b8d..9b2d991 100644 --- a/classes/Resizer.php +++ b/classes/Resizer.php @@ -201,7 +201,7 @@ public function setImage(string $image = null, bool $doNotModifyPath = false) if (preg_match('/^(https?:\/\/)/i', $image)) { $path = $this->getAbsolutePathOfLocalUrl($image); - // If path is string (local path, if local url) + // If path is string (If URL was local, it will be the local path) if ($path !== null) { $image = $path; }