diff --git a/public/proxy.php b/public/proxy.php index 94b087ad..97fd6047 100644 --- a/public/proxy.php +++ b/public/proxy.php @@ -3,22 +3,26 @@ require_once '../misuzu.php'; $acceptedProtocols = ['http', 'https']; $acceptedMimeTypes = [ - 'image/png', 'image/jpeg', 'image/bmp', 'image/gif', 'image/svg', 'image/svg+xml', 'image/tiff', 'image/webp', - 'video/mp4', 'video/webm', 'video/x-msvideo', 'video/mpeg', 'video/ogg', - 'audio/aac', 'audio/ogg', 'audio/mp3', 'audio/mpeg', 'audio/wav', 'audio/webm', + 'image/png', 'image/jpeg', 'image/bmp', 'image/x-bmp', 'image/gif', 'image/svg', 'image/svg+xml', 'image/tiff', 'image/tiff-fx', 'image/webp', + 'video/mp4', 'video/webm', 'video/x-msvideo', 'video/vnd.avi', 'video/msvideo', 'video/avi', 'video/mpeg', 'video/ogg', + 'audio/aac', 'audio/aacp', 'audio/3gpp', 'audio/3gpp2', 'audio/mp4', 'audio/mp4a-latm', 'audio/mpeg4-generic', + 'audio/ogg', 'audio/mp3', 'audio/mpeg', 'audio/mpa', 'audio/mpa-robust', + 'audio/wav', 'audio/vnd.wave', 'audio/wave', 'audio/x-wav', 'audio/webm', 'audio/x-flac', 'audio/flac', ]; header('Cache-Control: max-age=600'); -$proxyUrl = rawurldecode($_GET['u'] ?? ''); -$proxyHash = $_GET['h'] ?? ''; +$splitPath = explode('/', $_SERVER['PATH_INFO'] ?? '', 3); +$proxyHash = $splitPath[1] ?? ''; +$proxyUrl = $splitPath[2] ?? ''; if (empty($proxyHash) || empty($proxyUrl)) { echo render_error(400); return; } -$parsedUrl = parse_url($proxyUrl); +$proxyUrlDecoded = base64url_decode($proxyUrl); +$parsedUrl = parse_url($proxyUrlDecoded); if (empty($parsedUrl['scheme']) || empty($parsedUrl['host']) @@ -28,7 +32,7 @@ if (empty($parsedUrl['scheme']) } if (!config_get_default(false, 'Proxy', 'enabled')) { - header('Location: ' . $proxyUrl); + header('Location: ' . $proxyUrlDecoded); return; } @@ -40,7 +44,7 @@ if (!hash_equals($expectedHash, $proxyHash)) { return; } -$curl = curl_init($proxyUrl); +$curl = curl_init($proxyUrlDecoded); curl_setopt_array($curl, [ CURLOPT_CERTINFO => false, CURLOPT_FAILONERROR => false, @@ -64,7 +68,7 @@ if (!empty($_SERVER['HTTP_IF_NONE_MATCH']) && strtolower($_SERVER['HTTP_IF_NONE_ } $finfo = finfo_open(FILEINFO_MIME_TYPE); -$fileMime = finfo_buffer($finfo, $curlBody); +$fileMime = strtolower(finfo_buffer($finfo, $curlBody)); finfo_close($finfo); if (!in_array($fileMime, $acceptedMimeTypes, true)) { diff --git a/utility.php b/utility.php index 8e0255e6..96f66d0e 100644 --- a/utility.php +++ b/utility.php @@ -342,6 +342,17 @@ function is_user_int($value): bool return ctype_digit(strval($value)); } +// https://secure.php.net/manual/en/function.base64-encode.php#103849 +function base64url_encode(string $data): string +{ + return rtrim(strtr(base64_encode($data), '+/', '-_'), '='); +} + +function base64url_decode(string $data): string +{ + return base64_decode(str_pad(strtr($data, '-_', '+/'), strlen($data) % 4, '=', STR_PAD_RIGHT)); +} + function proxy_media_url(?string $url): ?string { if (empty($url) || !config_get_default(false, 'Proxy', 'enabled') || is_local_url($url)) { @@ -349,8 +360,8 @@ function proxy_media_url(?string $url): ?string } $secret = config_get_default('insecure', 'Proxy', 'secret_key'); - $hash = hash_hmac('sha256', rawurldecode($url), $secret); - $encodedUrl = rawurlencode($url); + $encodedUrl = base64url_encode($url); + $hash = hash_hmac('sha256', $encodedUrl, $secret); - return "/proxy.php?h={$hash}&u={$encodedUrl}"; + return "/proxy.php/{$hash}/{$encodedUrl}"; }