From c1ecef377229da3b6af65834109c8fc76508479c Mon Sep 17 00:00:00 2001 From: Ian Bradley Date: Mon, 15 Sep 2014 16:33:37 -0700 Subject: [PATCH 1/3] Added support for BSD md5 incase md5sum isn't available. --- inc/config.php | 15 +++++++++++++++ post.php | 5 +++-- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/inc/config.php b/inc/config.php index 1525b8bb..3dd8eb6c 100644 --- a/inc/config.php +++ b/inc/config.php @@ -751,6 +751,13 @@ // Display the file's original filename. $config['show_filename'] = true; + // WebM Settings + $config['webm']['use_ffmpeg'] = false; + $config['webm']['allow_audio'] = false; + $config['webm']['max_length'] = 120; + $config['webm']['ffmpeg_path'] = 'ffmpeg'; + $config['webm']['ffprobe_path'] = 'ffprobe'; + // Display image identification links for ImgOps, regex.info/exif, Google Images and iqdb. $config['image_identification'] = false; // Which of the identification links to display. Only works if $config['image_identification'] is true. @@ -760,6 +767,9 @@ // Anime/manga search engine. $config['image_identification_iqdb'] = false; + // Set this to true if you're using a BSD + $config['bsd_md5'] = false; + // Number of posts in a "View Last X Posts" page $config['noko50_count'] = 50; // Number of posts a thread needs before it gets a "View Last X Posts" page. @@ -1032,6 +1042,10 @@ $config['error']['unknownext'] = _('Unknown file extension.'); $config['error']['filesize'] = _('Maximum file size: %maxsz% bytes
Your file\'s size: %filesz% bytes'); $config['error']['maxsize'] = _('The file was too big.'); + $config['error']['webmerror'] = _('There was a problem processing your webm.'); + $config['error']['invalidwebm'] = _('Invalid webm uploaded.'); + $config['error']['webmhasaudio'] = _('The uploaded webm contains an audio or another type of additional stream.'); + $config['error']['webmtoolong'] = _('The uploaded webm is longer than ' . $config['webm']['max_length'] . ' seconds.'); $config['error']['fileexists'] = _('That file already exists!'); $config['error']['fileexistsinthread'] = _('That file already exists in this thread!'); $config['error']['delete_too_soon'] = _('You\'ll have to wait another %s before deleting that.'); @@ -1039,6 +1053,7 @@ $config['error']['invalid_embed'] = _('Couldn\'t make sense of the URL of the video you tried to embed.'); $config['error']['captcha'] = _('You seem to have mistyped the verification.'); + // Moderator errors $config['error']['toomanyunban'] = _('You are only allowed to unban %s users at a time. You tried to unban %u users.'); $config['error']['invalid'] = _('Invalid username and/or password.'); diff --git a/post.php b/post.php index d6dfdaa1..033e5ab5 100644 --- a/post.php +++ b/post.php @@ -566,7 +566,9 @@ if (isset($_POST['delete'])) { error($config['error']['nomove']); } - if ($output = shell_exec_error("cat $filenames | md5sum")) { + $md5cmd = $config['bsd_md5'] ? 'md5 -r' : 'md5sum'; + + if ($output = shell_exec_error("cat $filenames | $md5cmd")) { $explodedvar = explode(' ', $output); $hash = $explodedvar[0]; $post['filehash'] = $hash; @@ -925,4 +927,3 @@ if (isset($_POST['delete'])) { error($config['error']['nopost']); } } - From 0a9de3deb544e2e5f29e9db539298a8681087847 Mon Sep 17 00:00:00 2001 From: Ian Bradley Date: Mon, 15 Sep 2014 16:34:36 -0700 Subject: [PATCH 2/3] FFmpeg support for WebMs. Fixes threads with large amounts of WebM's causing crashes for some users. --- inc/lib/webm/README.md | 10 ++++++ inc/lib/webm/ffmpeg.php | 58 +++++++++++++++++++++++++++++++++++ inc/lib/webm/posthandler.php | 72 ++++++++++++++++++++++++++++++++++++-------- 3 files changed, 128 insertions(+), 12 deletions(-) create mode 100644 inc/lib/webm/ffmpeg.php diff --git a/inc/lib/webm/README.md b/inc/lib/webm/README.md index baa7a641..dc3394c9 100644 --- a/inc/lib/webm/README.md +++ b/inc/lib/webm/README.md @@ -20,6 +20,16 @@ Add these lines to inc/instance-config.php: $config['additional_javascript'][] = 'js/webm-settings.js'; $config['additional_javascript'][] = 'js/expand-video.js'; +If you have an [FFmpeg](https://www.ffmpeg.org/) binary on your server and you wish to generate real thumbnails (the webm thumbnails created with the original implementation reportedly cause users' browsers to crash), add the following to inc/instance-config.php as well: + + $config['webm']['use_ffmpeg'] = true; + + // If your ffmpeg binary isn't in your path you need to set these options + // as well. + + $config['webm']['ffmpeg_path'] = '/path/to/ffmeg'; + $config['webm']['ffprobe_path'] = '/path/to/ffprobe'; + License ------- diff --git a/inc/lib/webm/ffmpeg.php b/inc/lib/webm/ffmpeg.php new file mode 100644 index 00000000..7b635b5c --- /dev/null +++ b/inc/lib/webm/ffmpeg.php @@ -0,0 +1,58 @@ + 1, 'msg' => $config['error']['genwebmerror']); + + if ($ffprobe_out['format']['format_name'] != 'matroska,webm') + return array('code' => 2, 'msg' => $config['error']['invalidwebm']); + + if ((count($ffprobe_out['streams']) > 1) && (!$config['webm']['allow_audio'])) + return array('code' => 3, 'msg' => $config['error']['webmhasaudio']); + + if ($ffprobe_out['streams'][0]['codec_name'] != 'vp8') + return array('code' => 2, 'msg' => $config['error']['invalidwebm']); + + if (empty($ffprobe_out['streams'][0]['width']) || (empty($ffprobe_out['streams'][0]['height']))) + return array('code' => 2, 'msg' => $config['error']['invalidwebm']); + + if ($ffprobe_out['format']['duration'] > $config['webm']['max_length']) + return array('code' => 4, 'msg' => $config['error']['webmtoolong']); +} + +function make_webm_thumbnail($filename, $thumbnail, $width, $height) { + global $board, $config; + + $ffmpeg = $config['webm']['ffmpeg_path']; + $ffmpeg_out = array(); + + exec("$ffmpeg -i $filename -v quiet -ss 00:00:00 -an -vframes 1 -f mjpeg -vf scale=$width:$height $thumbnail 2>&1"); + + return count($ffmpeg_out); +} diff --git a/inc/lib/webm/posthandler.php b/inc/lib/webm/posthandler.php index 1f831f5a..308c7507 100644 --- a/inc/lib/webm/posthandler.php +++ b/inc/lib/webm/posthandler.php @@ -6,6 +6,34 @@ function postHandler($post) { global $board, $config; if ($post->has_file) foreach ($post->files as &$file) if ($file->extension == 'webm') { + if ($config['webm']['use_ffmpeg']) { + require_once dirname(__FILE__) . '/ffmpeg.php'; + $webminfo = get_webm_info($file->file_path); + + if (empty($webminfo['error'])) { + $file->width = $webminfo['width']; + $file->height = $webminfo['height']; + + if ($config['spoiler_images'] && isset($_POST['spoiler'])) { + $file = webm_set_spoiler($file); + } + else { + $file = set_thumbnail_dimensions($post, $file); + $tn_path = $board['dir'] . $config['dir']['thumb'] . $file->file_id . '.jpg'; + + if(empty(make_webm_thumbnail($file->file_path, $tn_path, $file->thumbwidth, $file->thumbheight))) { + $file->thumb = $file->file_id . '.jpg'; + } + else { + $file->thumb = 'file'; + } + } + } + else { + return $webminfo['error']['msg']; + } + } + else { require_once dirname(__FILE__) . '/videodata.php'; $videoDetails = videoData($file->file_path); if (!isset($videoDetails['container']) || $videoDetails['container'] != 'webm') return "not a WebM file"; @@ -14,10 +42,7 @@ function postHandler($post) { $thumbName = $board['dir'] . $config['dir']['thumb'] . $file->file_id . '.webm'; if ($config['spoiler_images'] && isset($_POST['spoiler'])) { // Use spoiler thumbnail - $file->thumb = 'spoiler'; - $size = @getimagesize($config['spoiler_image']); - $file->thumbwidth = $size[0]; - $file->thumbheight = $size[1]; + $file = webm_set_spoiler($file); } elseif (isset($videoDetails['frame']) && $thumbFile = fopen($thumbName, 'wb')) { // Use single frame from video as pseudo-thumbnail fwrite($thumbFile, $videoDetails['frame']); @@ -33,17 +58,40 @@ function postHandler($post) { if (isset($videoDetails['width']) && isset($videoDetails['height'])) { $file->width = $videoDetails['width']; $file->height = $videoDetails['height']; + if ($file->thumb != 'file' && $file->thumb != 'spoiler') { - $thumbMaxWidth = $post->op ? $config['thumb_op_width'] : $config['thumb_width']; - $thumbMaxHeight = $post->op ? $config['thumb_op_height'] : $config['thumb_height']; - if ($videoDetails['width'] > $thumbMaxWidth || $videoDetails['height'] > $thumbMaxHeight) { - $file->thumbwidth = min($thumbMaxWidth, intval(round($videoDetails['width'] * $thumbMaxHeight / $videoDetails['height']))); - $file->thumbheight = min($thumbMaxHeight, intval(round($videoDetails['height'] * $thumbMaxWidth / $videoDetails['width']))); - } else { - $file->thumbwidth = $videoDetails['width']; - $file->thumbheight = $videoDetails['height']; + $file = set_thumbnail_dimensions($post, $file); } } } } } + +function set_thumbnail_dimensions($post,$file) { + global $board, $config; + + $tn_dimensions = array(); + $tn_maxw = $post->op ? $config['thumb_op_width'] : $config['thumb_width']; + $tn_maxh = $post->op ? $config['thumb_op_height'] : $config['thumb_height']; + + if ($file->width > $tn_maxw || $file->height > $tn_maxh) { + $file->thumbwidth = min($tn_maxw, intval(round($file->width * $tn_maxh / $file->height))); + $file->thumbheight = min($tn_maxh, intval(round($file->height * $tn_maxw / $file->width))); + } else { + $file->thumbwidth = $file->width; + $file->thumbheight = $file->height; + } + + return $file; +} + +function webm_set_spoiler($file) { + global $board, $config; + + $file->thumb = 'spoiler'; + $size = @getimagesize($config['spoiler_image']); + $file->thumbwidth = $size[0]; + $file->thumbheight = $size[1]; + + return $file; +} From 306f4ef46bcbede59b427268fe6d8b5e18c811b2 Mon Sep 17 00:00:00 2001 From: Ian Bradley Date: Mon, 15 Sep 2014 16:57:06 -0700 Subject: [PATCH 3/3] Added escapeshellarg() for WebM thumbnail generation. --- inc/lib/webm/ffmpeg.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/inc/lib/webm/ffmpeg.php b/inc/lib/webm/ffmpeg.php index 7b635b5c..edd2c73a 100644 --- a/inc/lib/webm/ffmpeg.php +++ b/inc/lib/webm/ffmpeg.php @@ -49,6 +49,10 @@ function is_valid_webm($ffprobe_out) { function make_webm_thumbnail($filename, $thumbnail, $width, $height) { global $board, $config; + $filename = escapeshellarg($filename); + $thumbnail = escapeshellarg($thumbnail); // Should be safe by default but you + // can never be too safe. + $ffmpeg = $config['webm']['ffmpeg_path']; $ffmpeg_out = array();