diff --git a/public_html/css/post-list.css b/public_html/css/post-list.css
index f383d304..b501669d 100644
--- a/public_html/css/post-list.css
+++ b/public_html/css/post-list.css
@@ -158,6 +158,9 @@
.post-small.post-type-flash .link::after {
content: 'flash';
}
+.post-small.post-type-animation .link::after {
+ content: 'anim';
+}
.post-small .action {
display: none;
diff --git a/public_html/templates/post-content.tpl b/public_html/templates/post-content.tpl
index b71908c3..4e8caf33 100644
--- a/public_html/templates/post-content.tpl
+++ b/public_html/templates/post-content.tpl
@@ -2,7 +2,7 @@
var postContentUrl = '/data/posts/' + post.name + '?' + Math.round(Math.random() * 1000) /* reset gif animations */
var width;
var height;
- if (post.contentType === 'image' || post.contentType === 'flash') {
+ if (post.contentType === 'image' || post.contentType === 'animation' || post.contentType === 'flash') {
width = post.imageWidth;
height = post.imageHeight;
} else {
@@ -21,7 +21,7 @@
data-height="<%= height %>"
style="max-width: <%= width %>px">
- <% if (post.contentType === 'image') { %>
+ <% if (post.contentType === 'image' || post.contentType === 'animation') { %>
diff --git a/src/Entities/Post.php b/src/Entities/Post.php
index bc6d548b..b54d2bd1 100644
--- a/src/Entities/Post.php
+++ b/src/Entities/Post.php
@@ -12,6 +12,7 @@ final class Post extends Entity
const POST_TYPE_FLASH = 2;
const POST_TYPE_VIDEO = 3;
const POST_TYPE_YOUTUBE = 4;
+ const POST_TYPE_ANIMATED_IMAGE = 5;
const FLAG_LOOP = 1;
diff --git a/src/Helpers/EnumHelper.php b/src/Helpers/EnumHelper.php
index 2fb4bd69..89a5c715 100644
--- a/src/Helpers/EnumHelper.php
+++ b/src/Helpers/EnumHelper.php
@@ -37,6 +37,7 @@ class EnumHelper
'video' => Post::POST_TYPE_VIDEO,
'flash' => Post::POST_TYPE_FLASH,
'youtube' => Post::POST_TYPE_YOUTUBE,
+ 'animation' => Post::POST_TYPE_ANIMATED_IMAGE,
];
private static $snapshotTypeMap =
diff --git a/src/Helpers/MimeHelper.php b/src/Helpers/MimeHelper.php
index 8d9166a2..a771aa15 100644
--- a/src/Helpers/MimeHelper.php
+++ b/src/Helpers/MimeHelper.php
@@ -18,6 +18,12 @@ class MimeHelper
return self::getMimeTypeFrom16Bytes(substr($buffer, 0, 16));
}
+ public static function isBufferAnimatedGif($buffer)
+ {
+ return strtolower(self::getMimeTypeFromBuffer($buffer)) === 'image/gif'
+ and preg_match_all('#\x21\xf9\x04.{4}\x00[\x2c\x21]#s', $buffer) > 1;
+ }
+
public static function isFlash($mime)
{
return strtolower($mime) === 'application/x-shockwave-flash';
diff --git a/src/Services/PostService.php b/src/Services/PostService.php
index 4edbf48b..7837bdc5 100644
--- a/src/Services/PostService.php
+++ b/src/Services/PostService.php
@@ -206,13 +206,24 @@ class PostService
$post->setContentMimeType($mime);
if (MimeHelper::isFlash($mime))
+ {
$post->setContentType(Post::POST_TYPE_FLASH);
+ }
elseif (MimeHelper::isImage($mime))
- $post->setContentType(Post::POST_TYPE_IMAGE);
+ {
+ $post->setContentType(
+ MimeHelper::isBufferAnimatedGif($content)
+ ? Post::POST_TYPE_ANIMATED_IMAGE
+ : Post::POST_TYPE_IMAGE);
+ }
elseif (MimeHelper::isVideo($mime))
+ {
$post->setContentType(Post::POST_TYPE_VIDEO);
+ }
else
+ {
throw new \DomainException('Unhandled file type: "' . $mime . '"');
+ }
$post->setContentChecksum(sha1($content));
$this->assertNoPostWithThisContentChecksum($post);
diff --git a/src/Services/UpgradeService.php b/src/Services/UpgradeService.php
index 27662d45..0f340c3c 100644
--- a/src/Services/UpgradeService.php
+++ b/src/Services/UpgradeService.php
@@ -41,13 +41,10 @@ final class UpgradeService
if ($this->isUpgradeNeeded($upgrade))
{
if ($verbose)
- {
- echo 'Running ' . get_class($upgrade) . PHP_EOL;
- if (ob_get_level())
- ob_flush();
- flush();
- }
+ $this->log('Running ' . get_class($upgrade));
$this->runUpgrade($upgrade);
+ if ($verbose)
+ $this->log(PHP_EOL);
}
}
}
@@ -87,4 +84,12 @@ final class UpgradeService
preg_match('/(\d+)/', $className, $matches);
return intval($matches[1]);
}
+
+ private function log($message)
+ {
+ echo $message;
+ if (ob_get_level())
+ ob_flush();
+ flush();
+ }
}
diff --git a/src/Upgrades/Upgrade38.php b/src/Upgrades/Upgrade38.php
new file mode 100644
index 00000000..da648493
--- /dev/null
+++ b/src/Upgrades/Upgrade38.php
@@ -0,0 +1,52 @@
+postDao = $postDao;
+ $this->fileDao = $fileDao;
+ }
+
+ public function run(DatabaseConnection $databaseConnection)
+ {
+ $posts = $this->postDao->findAll();
+ $progress = 0;
+ foreach ($posts as $post)
+ {
+ if ($post->getContentType() === Post::POST_TYPE_IMAGE)
+ {
+ $fullPath = $this->fileDao->getFullPath($post->getContentPath());
+ try
+ {
+ $contents = file_get_contents($fullPath);
+ }
+ catch (\Exception $e)
+ {
+ continue;
+ }
+ if (MimeHelper::isBufferAnimatedGif($contents))
+ {
+ $post->setContentType(Post::POST_TYPE_ANIMATED_IMAGE);
+ $this->postDao->save($post);
+ }
+ if (++ $progress == 100)
+ {
+ echo '.';
+ $progress = 0;
+ }
+ }
+ }
+ }
+}
diff --git a/src/di.php b/src/di.php
index 3d3aebc2..35cb09e8 100644
--- a/src/di.php
+++ b/src/di.php
@@ -54,6 +54,7 @@ return [
$container->get(\Szurubooru\Upgrades\Upgrade35::class),
$container->get(\Szurubooru\Upgrades\Upgrade36::class),
$container->get(\Szurubooru\Upgrades\Upgrade37::class),
+ $container->get(\Szurubooru\Upgrades\Upgrade38::class),
];
}),
diff --git a/tests/Helpers/MimeHelperTest.php b/tests/Helpers/MimeHelperTest.php
index 8362dc06..7e1cddef 100644
--- a/tests/Helpers/MimeHelperTest.php
+++ b/tests/Helpers/MimeHelperTest.php
@@ -5,6 +5,19 @@ use Szurubooru\Tests\AbstractTestCase;
final class MimeHelperTest extends AbstractTestCase
{
+ public static function animatedGifProvider()
+ {
+ return
+ [
+ ['test_files/video.mp4', false],
+ ['test_files/static.gif', false],
+ ['test_files/animated.gif', true],
+ ['test_files/animated2.gif', true],
+ ['test_files/animated3.gif', true],
+ ['test_files/animated4.gif', true],
+ ];
+ }
+
public function testGettingMime()
{
$expected = 'image/jpeg';
@@ -38,4 +51,16 @@ final class MimeHelperTest extends AbstractTestCase
$this->assertTrue(MimeHelper::isVideo('application/ogg'));
$this->assertFalse(MimeHelper::isVideo('something else'));
}
+
+ /**
+ * @dataProvider animatedGifProvider
+ */
+ public function testIsAnimatedGif($path, $expected)
+ {
+ $fullPath = __DIR__
+ . DIRECTORY_SEPARATOR . '..'
+ . DIRECTORY_SEPARATOR . $path;
+ $actual = MimeHelper::isBufferAnimatedGif(file_get_contents($fullPath));
+ $this->assertEquals($expected, $actual);
+ }
}
diff --git a/tests/test_files/animated.gif b/tests/test_files/animated.gif
new file mode 100644
index 00000000..ac99b82a
Binary files /dev/null and b/tests/test_files/animated.gif differ
diff --git a/tests/test_files/animated2.gif b/tests/test_files/animated2.gif
new file mode 100644
index 00000000..cda5d338
Binary files /dev/null and b/tests/test_files/animated2.gif differ
diff --git a/tests/test_files/animated3.gif b/tests/test_files/animated3.gif
new file mode 100644
index 00000000..6015ff1b
Binary files /dev/null and b/tests/test_files/animated3.gif differ
diff --git a/tests/test_files/animated4.gif b/tests/test_files/animated4.gif
new file mode 100644
index 00000000..a133d26f
Binary files /dev/null and b/tests/test_files/animated4.gif differ
diff --git a/tests/test_files/static.gif b/tests/test_files/static.gif
new file mode 100644
index 00000000..547037c9
Binary files /dev/null and b/tests/test_files/static.gif differ