diff --git a/public_html/dispatch.php b/public_html/dispatch.php
index 4971299d..ee6e2045 100644
--- a/public_html/dispatch.php
+++ b/public_html/dispatch.php
@@ -89,6 +89,8 @@ $postValidation =
\Chibi\Router::register(['PostController', 'upvotedView'], 'GET', '/upvoted/{page}', $postValidation);
\Chibi\Router::register(['PostController', 'genericView'], 'GET', '/post/{id}', $postValidation);
+\Chibi\Router::register(['PostController', 'fileView'], 'GET', '/post/{name}/retrieve', $postValidation);
+\Chibi\Router::register(['PostController', 'thumbView'], 'GET', '/post/{name}/thumb', $postValidation);
\Chibi\Router::register(['PostController', 'toggleTagAction'], 'POST', '/post/{id}/toggle-tag/{tag}/{enable}', $postValidation);
\Chibi\Router::register(['PostController', 'flagAction'], 'POST', '/post/{id}/flag', $postValidation);
@@ -114,9 +116,6 @@ $commentValidation =
foreach (['GET', 'POST'] as $method)
{
- \Chibi\Router::register(['PostController', 'retrieveAction'], $method, '/post/{name}/retrieve', $postValidation);
- \Chibi\Router::register(['PostController', 'thumbAction'], $method, '/post/{name}/thumb', $postValidation);
-
$tagValidation =
[
'page' => '\d*',
diff --git a/src/Api.php b/src/Api.php
index caa1baf2..26555d8a 100644
--- a/src/Api.php
+++ b/src/Api.php
@@ -40,12 +40,4 @@ class Api
});
return $statuses;
}
-
- public static function serializeFile($filePath, $fileName)
- {
- $x = new StdClass;
- $x->filePath = $filePath;
- $x->fileName = $fileName;
- return $x;
- }
}
diff --git a/src/ApiFileInput.php b/src/ApiFileInput.php
new file mode 100644
index 00000000..e2fe7fd0
--- /dev/null
+++ b/src/ApiFileInput.php
@@ -0,0 +1,17 @@
+filePath = $filePath;
+ $this->fileName = $fileName;
+ }
+}
diff --git a/src/ApiFileOutput.php b/src/ApiFileOutput.php
new file mode 100644
index 00000000..9b2547db
--- /dev/null
+++ b/src/ApiFileOutput.php
@@ -0,0 +1,17 @@
+fileContent = file_get_contents($filePath);
+ $this->fileName = $fileName;
+ $this->lastModified = filemtime($filePath);
+ $this->mimeType = mime_content_type($filePath);
+ }
+}
diff --git a/src/Controllers/PostController.php b/src/Controllers/PostController.php
index ef4631bd..cdea2a36 100644
--- a/src/Controllers/PostController.php
+++ b/src/Controllers/PostController.php
@@ -107,7 +107,7 @@ class PostController
$file = $_FILES['file'];
TransferHelper::handleUploadErrors($file);
- $jobArgs[EditPostContentJob::POST_CONTENT] = Api::serializeFile(
+ $jobArgs[EditPostContentJob::POST_CONTENT] = new ApiFileInput(
$file['tmp_name'],
$file['name']);
}
@@ -147,7 +147,7 @@ class PostController
$file = $_FILES['file'];
TransferHelper::handleUploadErrors($file);
- $jobArgs[EditPostContentJob::POST_CONTENT] = Api::serializeFile(
+ $jobArgs[EditPostContentJob::POST_CONTENT] = new ApiFileInput(
$file['tmp_name'],
$file['name']);
}
@@ -157,7 +157,7 @@ class PostController
$file = $_FILES['thumb'];
TransferHelper::handleUploadErrors($file);
- $jobArgs[EditPostThumbJob::THUMB_CONTENT] = Api::serializeFile(
+ $jobArgs[EditPostThumbJob::THUMB_CONTENT] = new ApiFileInput(
$file['tmp_name'],
$file['name']);
}
@@ -256,67 +256,34 @@ class PostController
$context->transport->nextPostId = $nextPostId ? $nextPostId : null;
}
- public function thumbAction($name, $width = null, $height = null)
+ public function fileView($name)
{
+ $ret = Api::run(new GetPostContentJob(), [GetPostContentJob::POST_NAME => $name]);
+
$context = getContext();
- $path = PostModel::getThumbCustomPath($name, $width, $height);
- if (!file_exists($path))
- {
- $path = PostModel::getThumbDefaultPath($name, $width, $height);
- if (!file_exists($path))
- {
- $post = PostModel::findByIdOrName($name);
- Access::assert(Privilege::ListPosts);
- Access::assert(Privilege::ListPosts, PostSafety::toString($post->safety));
- $post->generateThumb($width, $height);
- if (!file_exists($path))
- {
- $path = getConfig()->main->mediaPath . DS . 'img' . DS . 'thumb.jpg';
- $path = TextHelper::absolutePath($path);
- }
- }
- }
-
- if (!is_readable($path))
- throw new SimpleException('Thumbnail file is not readable');
-
+ $context->transport->cacheDaysToLive = 14;
+ $context->transport->customFileName = $ret->fileName;
+ $context->transport->mimeType = $ret->mimeType;
+ $context->transport->fileHash = 'post' . md5(substr($ret->fileContent, 0, 4096));
+ $context->transport->fileContent = $ret->fileContent;
+ $context->transport->lastModified = $ret->lastModified;
$context->layoutName = 'layout-file';
- $context->transport->cacheDaysToLive = 365;
- $context->transport->mimeType = 'image/jpeg';
- $context->transport->fileHash = 'thumb' . md5($name . filemtime($path));
- $context->transport->filePath = $path;
}
- public function retrieveAction($name)
+ public function thumbView($name, $width = null, $height = null)
{
- $post = PostModel::findByName($name, true);
- $config = getConfig();
+ $ret = Api::run(new GetPostThumbJob(), [
+ GetPostThumbJob::POST_NAME => $name,
+ GetPostThumbJob::WIDTH => $width,
+ GetPostThumbJob::HEIGHT => $height]);
+
$context = getContext();
-
- Access::assert(Privilege::RetrievePost);
- Access::assert(Privilege::RetrievePost, PostSafety::toString($post->safety));
-
- $path = $config->main->filesPath . DS . $post->name;
- $path = TextHelper::absolutePath($path);
- if (!file_exists($path))
- throw new SimpleNotFoundException('Post file does not exist');
- if (!is_readable($path))
- throw new SimpleException('Post file is not readable');
-
- $fn = sprintf('%s_%s_%s.%s',
- $config->main->title,
- $post->id,
- join(',', array_map(function($tag) { return $tag->name; }, $post->getTags())),
- TextHelper::resolveMimeType($post->mimeType) ?: 'dat');
- $fn = preg_replace('/[[:^print:]]/', '', $fn);
-
- $ttl = 60 * 60 * 24 * 14;
-
+ $context->transport->cacheDaysToLive = 365;
+ $context->transport->customFileName = $ret->fileName;
+ $context->transport->mimeType = 'image/jpeg';
+ $context->transport->fileHash = 'thumb' . md5(substr($ret->fileContent, 0, 4096));
+ $context->transport->fileContent = $ret->fileContent;
+ $context->transport->lastModified = $ret->lastModified;
$context->layoutName = 'layout-file';
- $context->transport->cacheDaysToLive = 14;
- $context->transport->customFileName = $fn;
- $context->transport->mimeType = $post->mimeType;
- $context->transport->fileHash = 'post' . $post->fileHash;
- $context->transport->filePath = $path;
}
}
diff --git a/src/Jobs/Abstraction/AbstractJob.php b/src/Jobs/Abstraction/AbstractJob.php
index a17a7768..32139658 100644
--- a/src/Jobs/Abstraction/AbstractJob.php
+++ b/src/Jobs/Abstraction/AbstractJob.php
@@ -3,6 +3,7 @@ abstract class AbstractJob
{
const COMMENT_ID = 'comment-id';
const POST_ID = 'post-id';
+ const POST_NAME = 'post-name';
const TAG_NAME = 'tag-name';
const TAG_NAMES = 'tags';
const TEXT = 'text';
diff --git a/src/Jobs/GetPostContentJob.php b/src/Jobs/GetPostContentJob.php
new file mode 100644
index 00000000..2c556da7
--- /dev/null
+++ b/src/Jobs/GetPostContentJob.php
@@ -0,0 +1,48 @@
+getArgument(self::POST_NAME));
+
+ //todo: refactor this so that requiresPrivilege can accept multiple privileges
+ if ($post->hidden)
+ Access::assert(Privilege::RetrievePost, 'hidden');
+ Access::assert(Privilege::RetrievePost);
+ Access::assert(Privilege::RetrievePost, PostSafety::toString($post->safety));
+
+ $config = getConfig();
+
+ $path = $config->main->filesPath . DS . $post->name;
+ $path = TextHelper::absolutePath($path);
+ if (!file_exists($path))
+ throw new SimpleNotFoundException('Post file does not exist');
+ if (!is_readable($path))
+ throw new SimpleException('Post file is not readable');
+
+ $fileName = sprintf('%s_%s_%s.%s',
+ $config->main->title,
+ $post->id,
+ join(',', array_map(function($tag) { return $tag->name; }, $post->getTags())),
+ TextHelper::resolveMimeType($post->mimeType) ?: 'dat');
+ $fileName = preg_replace('/[[:^print:]]/', '', $fileName);
+
+ return new ApiFileOutput($path, $fileName);
+ }
+
+ public function requiresPrivilege()
+ {
+ //temporarily enforced in execute
+ return false;
+ }
+
+ public function requiresAuthentication()
+ {
+ return false;
+ }
+
+ public function requiresConfirmedEmail()
+ {
+ return false;
+ }
+}
diff --git a/src/Jobs/GetPostJob.php b/src/Jobs/GetPostJob.php
index 410f2088..cd0c945e 100644
--- a/src/Jobs/GetPostJob.php
+++ b/src/Jobs/GetPostJob.php
@@ -6,10 +6,10 @@ class GetPostJob extends AbstractPostEditJob
$post = $this->post;
//todo: refactor this so that requiresPrivilege can accept multiple privileges
- if ($this->post->hidden)
+ if ($post->hidden)
Access::assert(Privilege::ViewPost, 'hidden');
Access::assert(Privilege::ViewPost);
- Access::assert(Privilege::ViewPost, PostSafety::toString($this->post->safety));
+ Access::assert(Privilege::ViewPost, PostSafety::toString($post->safety));
CommentModel::preloadCommenters($post->getComments());
diff --git a/src/Jobs/GetPostThumbJob.php b/src/Jobs/GetPostThumbJob.php
new file mode 100644
index 00000000..e44810d9
--- /dev/null
+++ b/src/Jobs/GetPostThumbJob.php
@@ -0,0 +1,57 @@
+getArgument(self::POST_NAME);
+ $width = $this->hasArgument(self::WIDTH) ? $this->getArgument(self::WIDTH) : null;
+ $height = $this->hasArgument(self::HEIGHT) ? $this->getArgument(self::HEIGHT) : null;
+
+ $path = PostModel::getThumbCustomPath($name, $width, $height);
+ if (!file_exists($path))
+ {
+ $path = PostModel::getThumbDefaultPath($name, $width, $height);
+ if (!file_exists($path))
+ {
+ $post = PostModel::findByIdOrName($name);
+
+ if ($post->hidden)
+ Access::assert(Privilege::ListPosts, 'hidden');
+ Access::assert(Privilege::ListPosts);
+ Access::assert(Privilege::ListPosts, PostSafety::toString($post->safety));
+
+ $post->generateThumb($width, $height);
+
+ if (!file_exists($path))
+ {
+ $path = getConfig()->main->mediaPath . DS . 'img' . DS . 'thumb.jpg';
+ $path = TextHelper::absolutePath($path);
+ }
+ }
+ }
+
+ if (!is_readable($path))
+ throw new SimpleException('Thumbnail file is not readable');
+
+ return new ApiFileOutput($path, 'thumbnail.jpg');
+ }
+
+ public function requiresPrivilege()
+ {
+ //manually enforced in execute when post is retrieved
+ return false;
+ }
+
+ public function requiresAuthentication()
+ {
+ return false;
+ }
+
+ public function requiresConfirmedEmail()
+ {
+ return false;
+ }
+}
diff --git a/src/Views/layout-file.phtml b/src/Views/layout-file.phtml
index 05363f3c..70d8400f 100644
--- a/src/Views/layout-file.phtml
+++ b/src/Views/layout-file.phtml
@@ -1,47 +1,38 @@
context->transport->errorMessage))
+$lastModified = $this->context->transport->lastModified;
+$eTag = $this->context->transport->fileHash;
+$ttl = $this->context->transport->cacheDaysToLive * 24 * 3600;
+
+$ifModifiedSince = isset($_SERVER['HTTP_IF_MODIFIED_SINCE'])
+ ? $_SERVER['HTTP_IF_MODIFIED_SINCE']
+ : false;
+
+$eTagHeader = isset($_SERVER['HTTP_IF_NONE_MATCH'])
+ ? trim(trim($_SERVER['HTTP_IF_NONE_MATCH']), '"')
+ : false;
+
+\Chibi\Util\Headers::set('ETag', '"' . $eTag . '"');
+\Chibi\Util\Headers::set('Last-Modified', gmdate('D, d M Y H:i:s \G\M\T', $lastModified));
+\Chibi\Util\Headers::set('Pragma', 'public');
+\Chibi\Util\Headers::set('Cache-Control', 'public, max-age=' . $ttl);
+\Chibi\Util\Headers::set('Expires', gmdate('D, d M Y H:i:s \G\M\T', time() + $ttl));
+
+if (isset($this->context->transport->customFileName))
{
- \Chibi\Util\Headers::set('Content-Type', 'text/plain; charset=utf-8');
- echo $this->context->transport->errorMessage;
-}
-else
-{
- $lastModified = filemtime($this->context->transport->filePath);
- $eTag = $this->context->transport->fileHash;
- $ttl = $this->context->transport->cacheDaysToLive * 24 * 3600;
-
- $ifModifiedSince = isset($_SERVER['HTTP_IF_MODIFIED_SINCE'])
- ? $_SERVER['HTTP_IF_MODIFIED_SINCE']
- : false;
-
- $eTagHeader = isset($_SERVER['HTTP_IF_NONE_MATCH'])
- ? trim(trim($_SERVER['HTTP_IF_NONE_MATCH']), '"')
- : false;
-
- \Chibi\Util\Headers::set('ETag', '"' . $eTag . '"');
- \Chibi\Util\Headers::set('Last-Modified', gmdate('D, d M Y H:i:s \G\M\T', $lastModified));
- \Chibi\Util\Headers::set('Pragma', 'public');
- \Chibi\Util\Headers::set('Cache-Control', 'public, max-age=' . $ttl);
- \Chibi\Util\Headers::set('Expires', gmdate('D, d M Y H:i:s \G\M\T', time() + $ttl));
-
- if (isset($this->context->transport->customFileName))
- {
- \Chibi\Util\Headers::set(
- 'Content-Disposition',
- 'inline; filename="' . $this->context->transport->customFileName . '"');
- }
-
\Chibi\Util\Headers::set(
- 'Content-Type',
- $this->context->transport->mimeType);
-
-
- if (strtotime($ifModifiedSince) == $lastModified or $eTagHeader == $eTag)
- {
- header('HTTP/1.1 304 Not Modified');
- exit;
- }
-
- readfile($this->context->transport->filePath);
- flush();
+ 'Content-Disposition',
+ 'inline; filename="' . $this->context->transport->customFileName . '"');
}
+
+\Chibi\Util\Headers::set(
+ 'Content-Type',
+ $this->context->transport->mimeType);
+
+if (strtotime($ifModifiedSince) == $lastModified or $eTagHeader == $eTag)
+{
+ \Chibi\Util\Headers::setCode('304');
+ exit;
+}
+
+echo $this->context->transport->fileContent;
+flush();
diff --git a/src/Views/post-file-render.phtml b/src/Views/post-file-render.phtml
index 4a743f68..17aa4a3c 100644
--- a/src/Views/post-file-render.phtml
+++ b/src/Views/post-file-render.phtml
@@ -1,6 +1,6 @@
$this->context->transport->post->name]));
$post = $this->context->transport->post;
?>
@@ -13,7 +13,7 @@ $post = $this->context->transport->post;
context->imageLink)): ?>
@@ -27,12 +27,12 @@ $post = $this->context->transport->post;
width="= $post->imageWidth ?>"
height="= $post->imageHeight ?>"
data="= \Chibi\Router::linkTo(
- ['PostController', 'retrieveAction'],
+ ['PostController', 'fileView'],
['name' => $post->name]) ?>">
@@ -52,7 +52,7 @@ $post = $this->context->transport->post;
Your browser doesn't support HTML5 <video> tag.
diff --git a/src/Views/post-small.phtml b/src/Views/post-small.phtml
index 5ac83ce2..013915cd 100644
--- a/src/Views/post-small.phtml
+++ b/src/Views/post-small.phtml
@@ -48,7 +48,7 @@ if ($masstag)
0;
context->transport->post->type != PostType::Youtube): ?>