Skip to content

Commit

Permalink
Image Proxy
Browse files Browse the repository at this point in the history
Pipe out image files stored in folder `.\lot\image` with a proxy. This
allows other developers to create a feature to limit the image access
with certain criteria.
  • Loading branch information
taufik-nurrohman committed Feb 15, 2023
1 parent 46b814e commit 863e356
Show file tree
Hide file tree
Showing 6 changed files with 46 additions and 13 deletions.
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.

Preamble
Preamble

The GNU General Public License is a free, copyleft license for
software and other kinds of works.
Expand Down
1 change: 1 addition & 0 deletions about.page
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
title: Image
description: Image manipulation using GD library.
icon: 'M19,19H5V5H19M19,3H5A2,2 0 0,0 3,5V19A2,2 0 0,0 5,21H19A2,2 0 0,0 21,19V5A2,2 0 0,0 19,3M13.96,12.29L11.21,15.83L9.25,13.47L6.5,17H17.5L13.96,12.29Z'
color: '#153522'
author: Taufik Nurrohman
type: Markdown
version: 2.4.0
Expand Down
21 changes: 10 additions & 11 deletions engine/r/hook.php → engine/r/page.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?php

namespace x\page\images {
namespace x\image\page\images {
function crop(array $images, array $lot = []) {
foreach ($images as &$image) {
$image = \x\page\image\crop($image, $lot);
Expand All @@ -10,7 +10,7 @@ function crop(array $images, array $lot = []) {
\Hook::set('page.images', __NAMESPACE__ . "\\crop", 2.2);
}

namespace x\page\image {
namespace x\image\page\image {
function crop($image, array $lot = []) {
if (!$lot || !$image || !\is_string($image)) {
return $image;
Expand All @@ -22,27 +22,26 @@ function crop($image, array $lot = []) {
$path = \To::path(\long($image));
$store = \LOT . \D . 'image' . \D . 't' . \D . $width . ($height !== $width ? \D . $height : "") . \D . \dechex(\crc32($image . $quality)) . '.' . $x;
if (\is_file($store)) {
$image = \To::URL($store); // Return the image cache
$image = \To::URL($store); // Return the image cache URL
} else if (null !== \State::get('x.image')) {
$blob = new \Image(\is_file($path) ? $path : $image);
// `$page->image($width, $height, $quality)`
$blob->crop($width, $height)->blob($store, $quality); // Generate image cache
$image = \To::URL($store); // Return the image cache
$image = \To::URL($store); // Return the image cache URL
} else if (\is_file($path)) {
$image = \To::URL($path);
}
// Convert direct image URL from folder `.\lot\image` to its proxy image URL
\extract($GLOBALS, \EXTR_SKIP);
if ($image && 0 === \strpos($image, $url . '/lot/image/')) {
$image = \substr_replace($image, $url . '/' . \trim($state->x->image->route ?? 'image', '/') . '/', 0, \strlen($url . '/lot/image/'));
}
return $image;
}
\Hook::set('page.image', __NAMESPACE__ . "\\crop", 2.2);
}

namespace x\page {
if (!\is_dir($folder = \LOT . \D . 'image')) {
\mkdir($folder, 0775, true);
}
if (!\is_file($file = $folder . \D . '.htaccess')) {
\file_put_contents($file, 'Allow from all');
}
namespace x\image\page {
function image($image) {
// Skip if `image` data has been set!
if ($image) {
Expand Down
25 changes: 25 additions & 0 deletions engine/r/route.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php namespace x\image;

function route($content, $path) {
$age = 60 * 60 * 24 * 30; // Cache output for 30 day(s)
\status(200, [
'cache-control' => 'max-age=' . $age . ', private',
'expires' => \gmdate('D, d M Y H:i:s', $age + $_SERVER['REQUEST_TIME']) . ' GMT',
'pragma' => 'private'
]);
\type(\mime_content_type($file = \LOT . \D . 'image' . \D . \trim($path ?? "", '/')));
echo \file_get_contents($file);
exit;
}

$path = \trim($url->path ?? "", '/');
$route = \trim($state->x->image->route ?? 'image', '/');
if (0 === \strpos($path, $route . '/') && \is_file($file = \LOT . \D . 'image' . \D . \substr($path, \strlen($route) + 1))) {
\Hook::set('route.image', __NAMESPACE__ . "\\route", 100);
\Hook::set('route', function ($content, $path, $query, $hash) use ($file, $route) {
if (false !== \strpos(',apng,avif,bmp,gif,jpeg,jpg,png,webp,xbm,xpm,', ',' . \pathinfo($file, \PATHINFO_EXTENSION) . ',')) {
return \Hook::fire('route.image', [$content, \substr($path, \strlen($route) + 1), $query, $hash]);
}
return $content;
}, 0);
}
7 changes: 6 additions & 1 deletion index.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,13 @@
abort(i('Missing %s extension.', ['PHP <a href="https://www.php.net/manual/en/book.image.php" rel="nofollow" target="_blank">gd</a>']));
}

if (!is_dir($folder = LOT . D . 'image')) {
mkdir($folder, 0775, true);
}

if (defined('TEST') && 'x.image' === TEST && is_file($test = __DIR__ . D . 'test.php')) {
require $test;
}

require __DIR__ . D . 'engine' . D . 'r' . D . 'hook.php';
require __DIR__ . D . 'engine' . D . 'r' . D . 'page.php';
require __DIR__ . D . 'engine' . D . 'r' . D . 'route.php';
3 changes: 3 additions & 0 deletions state.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<?php

return ['route' => '/image'];

0 comments on commit 863e356

Please sign in to comment.