if (!function_exists('aib_thumb_data')) { /** * FIX 2026-09-10: build thumbnail bytes from the LOCAL source file. * * Replaces file_get_contents() on this site's own /timthumb.php URL. That old call * made the server issue an HTTP request to itself for every thumbnail it had to * build, tying up an extra Apache + php-fpm worker while the outer request waited, * and it kept an abandoned 2014 script (timthumb) on the critical path. * * Traversal is blocked on the incoming path rather than by comparing realpath() * against public_path(): Laravel's public/storage is a symlink that legitimately * resolves outside public/, so a realpath containment test rejects valid images. * * Returns the encoded image as a string, or false when the source is missing so * callers keep their existing "could not build the thumb" branch. */ function aib_thumb_data($path, $width = null, $height = null, $quality = null) { $rel = '/' . ltrim(str_replace('\\', '/', (string) $path), '/'); // No traversal, no null bytes, no remote schemes. if ($rel === '/' || strpos($rel, "\0") !== false || strpos($rel, '../') !== false || preg_match('#^/+[a-z][a-z0-9+.\-]*:#i', $rel)) { return false; } // Doc roots differ across these sites (public/, public_html/, ...). $bases = array(); if (function_exists('public_path')) { $bases[] = public_path(); } if (!empty($_SERVER['DOCUMENT_ROOT'])) { $bases[] = rtrim($_SERVER['DOCUMENT_ROOT'], '/'); } $src = false; foreach ($bases as $base) { if ($base !== '' && is_file($base . $rel)) { $src = $base . $rel; break; } } if ($src === false) { return false; } // Only ever re-encode real images. $info = @getimagesize($src); if ($info === false) { return false; } $quality = $quality ? (int) $quality : 95; if ($quality < 1 || $quality > 100) { $quality = 95; } // No resize requested -> hand back the original bytes, as before. if (!$width && !$height) { return file_get_contents($src); } try { $img = \Intervention\Image\Facades\Image::make($src); if ($width && $height) { $img->fit((int) $width, (int) $height); } elseif ($width) { $img->resize((int) $width, null, function ($c) { $c->aspectRatio(); $c->upsize(); }); } else { $img->resize(null, (int) $height, function ($c) { $c->aspectRatio(); $c->upsize(); }); } $data = (string) $img->encode(null, $quality); $img->destroy(); return strlen($data) > 0 ? $data : file_get_contents($src); } catch (\Exception $e) { // Resize failed (corrupt image, memory cap): cache the original rather than // letting an empty file get written and stick as a permanently broken thumb. return file_get_contents($src); } } }