Skip to content
Browse files

#130 #131 #132 133

  • Loading branch information...
1 parent db97214 commit 3e7dd61f4b7bda98816bab86bd88a8731adf89d2 @jaw-sh jaw-sh committed Oct 7, 2015
View
1 .gitignore
@@ -2,3 +2,4 @@
/packages
/vendor
.env
+composer.lock
View
3 app/FileAttachment.php
@@ -58,7 +58,8 @@ public static function boot()
*/
public static function getRecentImages($number = 16, $sfwOnly = true)
{
- return static::orderBy('attachment_id', 'desc')
+ return static::distinct('file_id')
+ ->orderBy('attachment_id', 'desc')
->whereHas('storage', function($query) {
$query->where('has_thumbnail', '=', true);
})
View
160 app/FileStorage.php
@@ -6,6 +6,7 @@
use File;
use Input;
+use Sleuth;
use Storage;
class FileStorage extends Model {
@@ -194,30 +195,45 @@ public function guessExtension()
return "png";
##
- # TEXT DOCUMENTS
+ # DOCUMENTS
##
case "text/plain" :
return "txt";
+ case "application/epub+zip" :
+ return "epub";
+
+ case "application/pdf" :
+ return "pdf";
+
##
# AUDIO
##
+ case "audio/mpeg" :
case "audio/mp3" :
return "mp3";
+ case "audio/aac" :
+ return "aac";
+
+ case "audio/mp4" :
+ return "mp3";
+
case "audio/ogg" :
return "ogg";
- case "audio/wav" :
+ case "audio/wave" :
return "wav";
- case "audio/mpeg" :
- return "mpga";
+ case "audio/webm" :
+ return "wav";
##
- # MULTIMEDIA
+ # VIDEO
##
- case "video/vp8" :
+ case "video/3gp" :
+ return "3gp";
+
case "video/webm" :
return "webm";
@@ -227,11 +243,8 @@ public function guessExtension()
case "video/ogg" :
return "ogg";
- case "application/epub+zip" :
- return "epub";
-
- case "application/pdf" :
- return "pdf";
+ case "video/x-flv" :
+ return "flv";
}
return $mimes[1];
@@ -367,13 +380,33 @@ public function getThumbnailURL(Board $board)
*/
public function isImage()
{
- switch ($this->guessExtension())
+ switch ($this->mime)
{
- case "bmp" :
- case "jpeg" :
- case "jpg" :
- case "gif" :
- case "png" :
+ case "image/jpg" :
+ case "image/gif" :
+ case "image/png" :
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Is this attachment audio?
+ *
+ * @return boolean
+ */
+ public function isAudio()
+ {
+ switch ($this->mime)
+ {
+ case "audio/mpeg" :
+ case "audio/mp3" :
+ case "audio/aac" :
+ case "audio/mp4" :
+ case "audio/ogg" :
+ case "audio/wave" :
+ case "audio/webm" :
return true;
}
@@ -390,8 +423,11 @@ public function isVideo()
{
switch ($this->guessExtension())
{
- case "mp4" :
- case "webm" :
+ case "video/3gp" :
+ case "video/webm" :
+ case "video/mp4" :
+ case "video/ogg" :
+ case "video/x-flv" :
return true;
}
@@ -464,39 +500,6 @@ public function createAttachmentWithThis(Post $post, $filename, $spoiler = false
}
/**
- * Collects data from an UploadFile type and stores it.
- *
- * @return int
- */
- public static function probe(UploadedFile &$file)
- {
- $video = $file->getPathname();
- $cmd = env('LIB_VIDEO_PROBE', "ffprobe") . " -v error -show_format -show_streams {$video} 2>&1";
-
- exec($cmd, $output, $returnvalue);
-
- if (count($output) <= 3)
- {
- foreach ($output as $line)
- {
- $line = (string) $line;
-
- if (strlen($line) > 0 && (stripos($line, 'invalid') !== false || stripos($line, 'error') !== false))
- {
- dd($output);
- return false;
- }
- }
- }
-
- // Hack.
- // Appends this output so we don't need to run twice.
- $file->ffmpegData = $output;
-
- return $returnvalue !== 1;
- }
-
- /**
* Work to be done upon creating an attachment using this storage.
*
* @param FileAttachment $attachment Defaults to null.
@@ -653,53 +656,18 @@ public static function storeUpload(UploadedFile $upload)
$storage->first_uploaded_at = $fileTime;
$storage->upload_count = 0;
- if (isset($upload->ffmpegData))
+ if (!isset($upload->case))
{
- $meta = [];
- $codecType = null;
- $codecName = null;
-
- foreach ($upload->ffmpegData as $datum)
- {
- $datumItems = explode("=", $datum, 2);
-
- if (count($datumItems) == 2)
- {
- $datumValue = $datumItems[1];
-
- switch ($datumItems[0])
- {
- case "codec_name" :
- $codecName = $datumItems[1];
- break;
-
- case "codec_type" :
- $codecType = $datumItems[1];
- break;
-
- default :
- $datumKeys = explode(":", $datumItems[0], 2);
-
- if (count($datumKeys) == 2)
- {
- if($datumKeys[0] === "TAG")
- {
- $meta[$datumKeys[1]] = $datumItems[1];
- }
- }
- break;
- }
- }
- }
-
- if (!is_null($codecType) && !is_null($codecName))
- {
- $storage->mime = "{$codecType}/{$codecName}";
- }
+ $upload->case = Sleuth::check($upload->getRealPath());
+ }
+
+ if (is_object($upload->case))
+ {
+ $storage->mime = $upload->case->getMimeType();
- if (count($meta))
+ if ($upload->case->getMetaData())
{
- $storage->meta = json_encode($meta);
+ $storage->meta = json_encode($upload->case->getMetaData());
}
}
}
View
2 app/Post.php
@@ -774,7 +774,7 @@ public function getCapcodeName()
{
if ($this->capcode_id)
{
- return trans($this->capcode_name);
+ return trans_choice((string) $this->capcode_name, 0);
}
return "";
View
14 app/Role.php
@@ -145,6 +145,20 @@ public function canSetPermissions(PermissionUser $user)
}
/**
+ * Returns a human-readable capcode string.
+ *
+ * @return string
+ */
+ public function getCapcodeName()
+ {
+ if ($this->capcode_id)
+ {
+ return trans_choice((string) $this->capcode_name, 0);
+ }
+
+ return "";
+ }
+ /**
* Returns a human-readable name for this role.
*
* @return string
View
60 app/Validators/FileValidator.php
@@ -4,6 +4,7 @@
use Illuminate\Validation\Validator;
use DB;
+use Sleuth;
class FileValidator extends Validator
{
@@ -21,61 +22,12 @@ public function validateFileIntegrity($attribute, $file, $parameters)
{
if ($file instanceof \Symfony\Component\HttpFoundation\File\UploadedFile)
{
- switch ($file->getClientMimeType())
+ $detective = Sleuth::check($file->getRealPath());
+
+ if ($detective !== false)
{
- // For some reason, MP3 files routinely get scanned as octet-streams.
- // Attempt to evaluate it as music or a video.
- case "application/octet-stream" :
- case "audio/mpeg" :
- case "audio/mp3" :
- case "video/mp4" :
- case "video/flv" :
- case "video/webm" :
- return FileStorage::probe($file);
-
- case "application/x-shockwave-flash" :
- // This is much slower than exif_imagetype but much more reliable with flash files.
- return getimagesize($file->getPathname())['mime'] == "application/x-shockwave-flash";
-
- case "image/x-ms-bmp" :
- return exif_imagetype($file->getPathname()) == IMAGETYPE_BMP;
-
- case "image/gif" :
- return exif_imagetype($file->getPathname()) == IMAGETYPE_GIF;
-
- case "image/jpeg" :
- case "image/jpg" :
- return exif_imagetype($file->getPathname()) == IMAGETYPE_JPEG;
-
- case "image/png" :
- return exif_imagetype($file->getPathname()) == IMAGETYPE_PNG;
-
- case "image/svg" :
- case "image/svg+xml" :
- try
- {
- $dom = new \DOMDocument;
- $dom->Load($file->getPathname());
-
- if ($dom->getElementsByTagName('script')->length > 0)
- {
- return false;
- }
-
- return $dom->saveXML() !== false;
- }
- catch (\Exception $error)
- {
- return false;
- }
-
- // Things we allow but can't validate.
- case "application/epub+zip" :
- case "application/pdf" :
- return true;
-
- default :
- return false;
+ $file->sleuth = $detective;
+ return true;
}
}
View
3 composer.json
@@ -40,7 +40,8 @@
"infinity-next/braintree": "*@dev",
"infinity-next/brennan-captcha": "1.*",
- "infinity-next/eightdown": "*@dev"
+ "infinity-next/eightdown": "*@dev",
+ "infinity-next/sleuth": "*@dev"
},
"require-dev": {
View
136 composer.lock
@@ -4,8 +4,8 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
"This file is @generated automatically"
],
- "hash": "3045433a8abe3afcde1881e15f6d455d",
- "content-hash": "ad6e1bcaca2d0b8c2cfe24c8bbd666cb",
+ "hash": "8c8ca445e371a0e3f9bc6ef00a50a10c",
+ "content-hash": "5add65114f749bb0d69400e94d217666",
"packages": [
{
"name": "braintree/braintree_php",
@@ -107,20 +107,20 @@
},
{
"name": "cviebrock/image-validator",
- "version": "2.0.0-beta",
+ "version": "2.0.0",
"source": {
"type": "git",
"url": "https://github.com/cviebrock/image-validator.git",
- "reference": "cd78e0fa6aeced2f4a0a61d8305d3cd160e5a3ee"
+ "reference": "83a7e7fc687f84a31ef72e9eee8cdc25a79b2f8e"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/cviebrock/image-validator/zipball/cd78e0fa6aeced2f4a0a61d8305d3cd160e5a3ee",
- "reference": "cd78e0fa6aeced2f4a0a61d8305d3cd160e5a3ee",
+ "url": "https://api.github.com/repos/cviebrock/image-validator/zipball/83a7e7fc687f84a31ef72e9eee8cdc25a79b2f8e",
+ "reference": "83a7e7fc687f84a31ef72e9eee8cdc25a79b2f8e",
"shasum": ""
},
"require": {
- "ext-gd": "*",
+ "ext-bcmath": "*",
"illuminate/support": "5.*",
"illuminate/translation": "5.*",
"illuminate/validation": "5.*",
@@ -154,7 +154,7 @@
"laravel",
"validator"
],
- "time": "2015-05-04 02:01:43"
+ "time": "2015-10-07 17:10:16"
},
{
"name": "danielstjules/stringy",
@@ -763,6 +763,43 @@
"time": "2014-09-09 13:34:57"
},
{
+ "name": "enshrined/svg-sanitize",
+ "version": "0.2.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/darylldoyle/svg-sanitizer.git",
+ "reference": "ed123c268311b2f64adb5f417ffe30ed84335f5f"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/darylldoyle/svg-sanitizer/zipball/ed123c268311b2f64adb5f417ffe30ed84335f5f",
+ "reference": "ed123c268311b2f64adb5f417ffe30ed84335f5f",
+ "shasum": ""
+ },
+ "require-dev": {
+ "codeclimate/php-test-reporter": "^0.1.2",
+ "phpunit/phpunit": "^4.7"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "enshrined\\svgSanitize\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "GPL-2.0+"
+ ],
+ "authors": [
+ {
+ "name": "Daryll Doyle",
+ "email": "daryll@enshrined.co.uk"
+ }
+ ],
+ "description": "An SVG sanitizer for PHP",
+ "time": "2015-07-06 23:33:41"
+ },
+ {
"name": "erusev/parsedown",
"version": "1.5.4",
"source": {
@@ -905,16 +942,16 @@
},
{
"name": "infinity-next/brennan-captcha",
- "version": "dev-master",
+ "version": "1.2.1",
"source": {
"type": "git",
"url": "https://github.com/infinity-next/brennan-captcha.git",
- "reference": "7449e37c2ff7c5201a5ef03d53a24ba471803d43"
+ "reference": "0de933e37cd3a2c4132df28de479baeef66983f7"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/infinity-next/brennan-captcha/zipball/7449e37c2ff7c5201a5ef03d53a24ba471803d43",
- "reference": "7449e37c2ff7c5201a5ef03d53a24ba471803d43",
+ "url": "https://api.github.com/repos/infinity-next/brennan-captcha/zipball/0de933e37cd3a2c4132df28de479baeef66983f7",
+ "reference": "0de933e37cd3a2c4132df28de479baeef66983f7",
"shasum": ""
},
"require": {
@@ -942,7 +979,7 @@
}
],
"description": "An anti-bot image captcha system written by Frederick Brennan and ported to Laravel for Infinity Next by Joshua Moon.",
- "time": "2015-10-03 02:02:13"
+ "time": "2015-10-03 13:06:09"
},
{
"name": "infinity-next/eightdown",
@@ -982,6 +1019,55 @@
"time": "2015-08-04 20:07:42"
},
{
+ "name": "infinity-next/sleuth",
+ "version": "dev-master",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/infinity-next/sleuth.git",
+ "reference": "303a20b282a24c6cb5a3544d2cd944671e639c2f"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/infinity-next/sleuth/zipball/303a20b282a24c6cb5a3544d2cd944671e639c2f",
+ "reference": "303a20b282a24c6cb5a3544d2cd944671e639c2f",
+ "shasum": ""
+ },
+ "require": {
+ "enshrined/svg-sanitize": "0.2.*",
+ "illuminate/support": "5.1.*",
+ "php": ">=5.4.0"
+ },
+ "require-dev": {
+ "mockery/mockery": "~0.9",
+ "phpunit/phpunit": "~4.0"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "InfinityNext\\Sleuth\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Joshua Moon",
+ "email": "josh@jaw.sh",
+ "homepage": "https://jaw.sh"
+ }
+ ],
+ "keywords": [
+ "detection",
+ "file",
+ "laravel",
+ "mime",
+ "type"
+ ],
+ "time": "2015-10-07 21:53:34"
+ },
+ {
"name": "intervention/image",
"version": "2.3.2",
"source": {
@@ -3515,16 +3601,16 @@
},
{
"name": "phpunit/php-code-coverage",
- "version": "2.2.3",
+ "version": "2.2.4",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-code-coverage.git",
- "reference": "ef1ca6835468857944d5c3b48fa503d5554cff2f"
+ "reference": "eabf68b476ac7d0f73793aada060f1c1a9bf8979"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/ef1ca6835468857944d5c3b48fa503d5554cff2f",
- "reference": "ef1ca6835468857944d5c3b48fa503d5554cff2f",
+ "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/eabf68b476ac7d0f73793aada060f1c1a9bf8979",
+ "reference": "eabf68b476ac7d0f73793aada060f1c1a9bf8979",
"shasum": ""
},
"require": {
@@ -3573,7 +3659,7 @@
"testing",
"xunit"
],
- "time": "2015-09-14 06:51:16"
+ "time": "2015-10-06 15:47:00"
},
{
"name": "phpunit/php-file-iterator",
@@ -3755,16 +3841,16 @@
},
{
"name": "phpunit/phpunit",
- "version": "4.8.10",
+ "version": "4.8.11",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/phpunit.git",
- "reference": "463163747474815c5ccd4ae12b5b355ec12158e8"
+ "reference": "bdd199472410fd7e32751f9c814c7e06f2c21bd5"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/463163747474815c5ccd4ae12b5b355ec12158e8",
- "reference": "463163747474815c5ccd4ae12b5b355ec12158e8",
+ "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/bdd199472410fd7e32751f9c814c7e06f2c21bd5",
+ "reference": "bdd199472410fd7e32751f9c814c7e06f2c21bd5",
"shasum": ""
},
"require": {
@@ -3823,7 +3909,7 @@
"testing",
"xunit"
],
- "time": "2015-10-01 09:14:30"
+ "time": "2015-10-07 10:39:46"
},
{
"name": "phpunit/phpunit-mock-objects",
@@ -4307,8 +4393,8 @@
"stability-flags": {
"cviebrock/image-validator": 10,
"infinity-next/braintree": 20,
- "infinity-next/brennan-captcha": 20,
- "infinity-next/eightdown": 20
+ "infinity-next/eightdown": 20,
+ "infinity-next/sleuth": 20
},
"prefer-stable": false,
"prefer-lowest": false,
View
10 config/app.php
@@ -166,6 +166,11 @@
'InfinityNext\Eightdown\EightdownServiceProvider',
/*
+ * File Validation
+ */
+ 'InfinityNext\Sleuth\Providers\SleuthServiceProvider',
+
+ /*
* Money
*/
//'Laravel\Cashier\CashierServiceProvider',
@@ -242,6 +247,11 @@
'Captcha' => 'InfinityNext\BrennanCaptcha\Facades\Captcha',
/*
+ * File Validation
+ */
+ 'Sleuth' => 'InfinityNext\Sleuth\Facades\Sleuth',
+
+ /*
* CSS+JS Minify
*/
'Minify' => 'Devfactory\Minify\Facades\MinifyFacade',
View
0 database/migrations/2015_10_04_140444_add_insecure_tripcodes_to_posts_table.php 100644 → 100755
File mode changed.
View
5 public/css/app/main.css
@@ -1370,11 +1370,12 @@ section.index-form {
}
form.form-post button.field-submit {
- width: 118px;
+ width: 125px;
margin: 0 5px 0 0;
}
form.form-post select.field-capcode {
- width: 140 px;
+ width: 145px;
+ float: right;
}
/* Dropzone */
View
8 resources/views/content/board.blade.php
@@ -5,7 +5,7 @@
<section class="index-form">
@include('content.board.post.form', [
- 'board' => &$board,
+ 'board' => $board,
'actions' => [ $reply_to ? "reply" : "thread" ],
])
</section>
@@ -24,9 +24,9 @@
<li class="thread-item">
<article class="thread">
@include('content.board.thread', [
- 'board' => &$board,
- 'thread' => &$thread,
- 'op' => &$thread,
+ 'board' => $board,
+ 'thread' => $thread,
+ 'op' => $thread,
])
</article>
</li>
View
4 resources/views/content/board/post/form.blade.php
@@ -136,7 +136,7 @@
</div>
@endif
- <div class="field row-submit row-inline">
+ <div class="field row-submit">
{!! Form::button(
trans("board.submit." . implode($actions, "+")),
[
@@ -151,7 +151,7 @@
<option value="" selected>Capcode</option>
@foreach ($user->getCapcodes($board) as $role)
- <option value="{!! $role->role_id !!}">{{{ $role->capcode }}}</option>
+ <option value="{!! $role->role_id !!}">{{{ $role->getCapcodeName() }}}</option>
@endforeach
</select>
@endif
View
16 resources/views/content/board/thread.blade.php
@@ -1,8 +1,8 @@
<div class="post-container @if ($op === $thread) op-container @else reply-container @endif post-{{$thread->post_id}} post-{{$thread->board_uri}}-{{$thread->board_id}}" data-widget="post" data-updated-at="{{ $thread->updated_at->timestamp }}">
@if ($thread->reports)
@include('content.board.post.single', [
- 'board' => &$board,
- 'post' => &$thread,
+ 'board' => $board,
+ 'post' => $thread,
'catalog' => false,
])
@@ -21,7 +21,7 @@
@if ($thread->updated_by)
<li class="post-meta meta-updated_by">
- <i class="fa fa-pencil"></i> @lang('board.meta.updated_by', [ 'name' => $thread->updated_by_username, 'time' => $thread->updated_at ])
+ <i class="fa fa-pencil"></i> @lang('board.meta.updated_by', [ 'name' => $thread->updated_by_username, 'time' => $thread->updated_at->timestamp ])
</li>
@endif
</ul>
@@ -36,18 +36,18 @@
--}}
@if ($op === $thread)
<ul class="thread-replies">
- @if ($thread->reply_count > count($thread->replies))
+ @if ($thread->reply_count > count($thread->replies) && !$reply_to)
<div class="thread-replies-omitted">{{ Lang::get('board.omitted_text_only', ['text_posts' => $thread->reply_count - count($thread->replies)]) }}</div>
@endif
@foreach ($thread->getReplies() as $reply)
<li class="thread-reply">
<article class="reply">
@include('content.board.thread', [
- 'board' => &$board,
- 'thread' => &$reply,
- 'op' => &$op,
- 'reply_to' => &$reply_to,
+ 'board' => $board,
+ 'thread' => $reply,
+ 'op' => $op,
+ 'reply_to' => $reply_to,
])
</article>
</li>

0 comments on commit 3e7dd61

Please sign in to comment.
Something went wrong with that request. Please try again.