From 4fe3c6644d8d78596fb33330b9e3b72ac6e2e1b9 Mon Sep 17 00:00:00 2001 From: flashwave Date: Thu, 3 Jan 2019 02:43:12 +0100 Subject: [PATCH] Add media proxying. --- config/config.example.ini | 7 +++ public/proxy.php | 81 ++++++++++++++++++++++++++++ src/Parsers/BBCode/Tags/ImageTag.php | 16 +++--- src/Parsers/BBCode/Tags/VideoTag.php | 3 +- src/Parsers/MarkdownParser.php | 7 +++ utility.php | 13 +++++ 6 files changed, 117 insertions(+), 10 deletions(-) create mode 100644 public/proxy.php diff --git a/config/config.example.ini b/config/config.example.ini index aea3f3ec..3046f7cd 100644 --- a/config/config.example.ini +++ b/config/config.example.ini @@ -43,3 +43,10 @@ method = null [Exceptions] report_url = http://misuzu-crash.localhost/report.php hash_key = secret_key_used_to_make_a_hmac_sha256_hash + +[CSRF] +secret_key = secret_key_for_generating_csrf_tokens + +[Proxy] +enabled = true +secret_key = change_this_or_i_will_beat_you_up diff --git a/public/proxy.php b/public/proxy.php new file mode 100644 index 00000000..f6f11ba3 --- /dev/null +++ b/public/proxy.php @@ -0,0 +1,81 @@ + false, + CURLOPT_FAILONERROR => false, + CURLOPT_FOLLOWLOCATION => true, + CURLOPT_RETURNTRANSFER => true, + CURLOPT_TCP_FASTOPEN => true, + CURLOPT_CONNECTTIMEOUT => 2, + CURLOPT_MAXREDIRS => 4, + CURLOPT_PROTOCOLS => CURLPROTO_HTTP | CURLPROTO_HTTPS, + CURLOPT_TIMEOUT => 10, + CURLOPT_USERAGENT => 'Mozilla/5.0 (compatible) Misuzu/' . git_tag(), +]); +$curlBody = curl_exec($curl); +curl_close($curl); + +$finfo = finfo_open(FILEINFO_MIME_TYPE); +$fileMime = finfo_buffer($finfo, $curlBody); +finfo_close($finfo); + +if (!in_array($fileMime, $acceptedMimeTypes, true)) { + echo render_error(404); + return; +} + +$fileSize = strlen($curlBody); +$fileName = basename($parsedUrl['path'] ?? "proxied-image-{$expectedHash}"); + +header("Content-Type: {$fileMime}"); +header("Content-Length: {$fileSize}"); +header("Content-Disposition: inline; filename=\"{$fileName}\""); + +echo $curlBody; diff --git a/src/Parsers/BBCode/Tags/ImageTag.php b/src/Parsers/BBCode/Tags/ImageTag.php index 1089610d..f639d3a8 100644 --- a/src/Parsers/BBCode/Tags/ImageTag.php +++ b/src/Parsers/BBCode/Tags/ImageTag.php @@ -1,17 +1,15 @@ '; + return preg_replace_callback("/\[img\]((?:https?:\/\/).*)\[\/img\]/", function ($matches) { + $mediaUrl = proxy_media_url($matches[1]); + return sprintf('%s', $mediaUrl, $matches[1]); + }, $text); } } diff --git a/src/Parsers/BBCode/Tags/VideoTag.php b/src/Parsers/BBCode/Tags/VideoTag.php index 6ebf4e1c..38561061 100644 --- a/src/Parsers/BBCode/Tags/VideoTag.php +++ b/src/Parsers/BBCode/Tags/VideoTag.php @@ -18,7 +18,8 @@ final class VideoTag extends BBCodeTag . '?rel=0" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen>'; } - return ""; + $mediaUrl = proxy_media_url($matches[1]); + return ""; }, $text ); diff --git a/src/Parsers/MarkdownParser.php b/src/Parsers/MarkdownParser.php index 3418f430..90e76a47 100644 --- a/src/Parsers/MarkdownParser.php +++ b/src/Parsers/MarkdownParser.php @@ -14,4 +14,11 @@ class MarkdownParser extends Parsedown implements ParserInterface { return $this->line($line); } + + protected function inlineImage($excerpt) + { + $object = parent::inlineImage($excerpt); + $object['element']['attributes']['src'] = proxy_media_url($object['element']['attributes']['src']); + return $object; + } } diff --git a/utility.php b/utility.php index 041fd78c..2d48ae75 100644 --- a/utility.php +++ b/utility.php @@ -346,3 +346,16 @@ function is_user_int($value): bool { return ctype_digit(strval($value)); } + +function proxy_media_url(string $url): string +{ + if (!config_get_default(false, 'Proxy', 'enabled') || is_local_url($url)) { + return $url; + } + + $secret = config_get_default('insecure', 'Proxy', 'secret_key'); + $hash = hash_hmac('sha256', $url, $secret); + $encodedUrl = rawurlencode($url); + + return "/proxy.php?h={$hash}&u={$encodedUrl}"; +}