diff options
Diffstat (limited to 'app/class')
-rw-r--r-- | app/class/globals.php | 81 | ||||
-rw-r--r-- | app/class/image.php | 70 | ||||
-rw-r--r-- | app/class/object.class.php | 88 |
3 files changed, 239 insertions, 0 deletions
diff --git a/app/class/globals.php b/app/class/globals.php index 8bfa029..615efa6 100644 --- a/app/class/globals.php +++ b/app/class/globals.php @@ -20,6 +20,19 @@ define("__VERSION__", "v0.0"); /* + * These global variables are arrays of strings logged by Scrott business + * logic to report errors, warnings, or informational responses to the + * user in cases where an exception doesn't need to be thrown. + */ +define("ERROR", "errorlist"); +define("WARNING", "warninglist"); +define("NOTICE", "noticelist"); + +$_SCROTT[ERROR] = array(); +$_SCROTT[WARNING] = array(); +$_SCROTT[NOTICE] = array(); + +/* * Get the application root path. This is an absolute path on the server. */ function ar() : string @@ -63,4 +76,72 @@ function require_https() : void redirect("https://" . $_SERVER['SERVER_NAME'] . ap()); } +/* + * Check for errors, warnings, or notices + */ +function isError(string $level) : bool +{ + global $_SCROTT; + return count($_SCROTT[$level]) > 0; +} + +/* + * Log an error, warning, or notice + */ +function logError(string $level, string $error) : void +{ + global $_SCROTT; + $_SCROTT[$level][] = $error; +} + +/* + * Get an array of all errors, warnings, or notices + */ +function getErrors(string $level) : array +{ + global $_SCROTT; + return $_SCROTT[$level]; +} + +/* + * Save an uploaded file and impose some constraints on supplied + * data. Caller can optionally pass some strings by reference to + * be given the supplied file's original name and mime-type. + * Maxsize is in bytes. If this function returns false, the + * appropriate error will be logged. + */ +function saveFile(array $file, string $path, int $maxsize, ?array $allowedMime = NULL, + ?string &$origName = NULL, ?string &$origMime = NULL) : bool +{ + if ($file['error'] > 0) + { + if ($file['error'] != UPLOAD_ERR_NO_FILE) + logError(ERROR, "An unknown error occurred"); + + return false; + } + + if ($file['size'] > $maxsize) + { + logError(ERROR, "File must be no larger than " . $maxsize . " bytes"); + return false; + } + + if (is_array($allowedMime) && array_search($file['type'], $allowedMime) === false) + { + logError(ERROR, "File type is not supported"); + return false; + } + + if (!move_uploaded_file($file['tmp_name'], $path)) + { + logError(ERROR, "Error saving uploaded file"); + return false; + } + + $origName = $file['name']; + $origMime = $file['type']; + return true; +} + ?> diff --git a/app/class/image.php b/app/class/image.php new file mode 100644 index 0000000..6b73cae --- /dev/null +++ b/app/class/image.php @@ -0,0 +1,70 @@ +<?php + +/* + * SCROTT IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * For more information, please refer to UNLICENSE + */ + +/* + * This file defines custom image manipulation routines for Scrott. All + * are available in the global namespace. + */ + +/* + * Mappings from image MIME types to PHP open/write functions + */ +$_IMG_OPEN_FUNCS['image/jpeg'] = "imagecreatefromjpeg"; +$_IMG_OPEN_FUNCS['image/jpg'] = "imagecreatefromjpeg"; +$_IMG_OPEN_FUNCS['image/png'] = "imagecreatefrompng"; + +$_IMG_WRITE_FUNCS['image/jpeg'] = "imagejpeg"; +$_IMG_WRITE_FUNCS['image/jpg'] = "imagejpeg"; +$_IMG_WRITE_FUNCS['image/png'] = "imagepng"; + +/* + * Open the given image and crop it, such that the result is a square + * image whose side length is equal to the smaller of the original + * dimensions and whose area is centered on the area of the original + * image. The resulting image is written to the same path as provided, + * overwriting the image. + */ +function imageSquareCrop(string $uri) : bool +{ + global $_IMG_OPEN_FUNCS; + global $_IMG_WRITE_FUNCS; + + $mime = mime_content_type($uri); + $img = $_IMG_OPEN_FUNCS[$mime]($uri); + + if ($img === false) + return false; + + $wid = imagesx($img); + $hei = imagesy($img); + + $rec = array(); + $rec['width'] = min($wid, $hei); + $rec['height'] = $rec['width']; + $rec['y'] = ($hei / 2) - ($rec['height'] / 2); + $rec['x'] = ($wid / 2) - ($rec['width'] / 2); + + $cropped = imagecrop($img, $rec); + imagedestroy($img); + + if ($cropped === false) + return false; + + $ret = $_IMG_WRITE_FUNCS[$mime]($cropped, $uri); + imagedestroy($cropped); + + return $ret; +} + +?> diff --git a/app/class/object.class.php b/app/class/object.class.php index 14ab891..7c80b5b 100644 --- a/app/class/object.class.php +++ b/app/class/object.class.php @@ -13,6 +13,7 @@ */ require_once "class/table.class.php"; +require_once "class/image.php"; /* * This is a generic database object. This is a supertype of all Scrott @@ -21,6 +22,17 @@ require_once "class/table.class.php"; class object extends table { /* + * Constants used for uploading images + */ + public const HEAD_MAXSIZE = 1048576; // 1Mb + public const BG_MAXSIZE = 1048576; // 1Mb + public const IMAGE_MIME = array( + "image/jpeg", + "image/jpg", + "image/png", + ); + + /* * Constructor */ public function __construct(?string $guid = NULL) @@ -149,6 +161,82 @@ class object extends table database::query($query); return true; } + + /* + * Get the URL to the head image resource for this object + */ + public function getHeadImg() : string + { + return ar() . "/df.php?d=heads&f=" . $this->guid; + } + + /* + * Set the head image for this object, overwriting any existing + * image. $image should be an uploaded file to PHP, still + * unhandled. + */ + public function setHeadImg(array $image) : bool + { + $path = "dynmic/heads/" . $this->guid; + + if (!saveFile($image, $path, self::HEAD_MAXSIZE, self::IMAGE_MIME)) + return false; + + if (!imageSquareCrop($path)) + { + $this->rmHeadImg(); + return false; + } + + return true; + } + + /* + * Remove the head image for this object. This deletes the image + * on disk. + */ + public function rmHeadImg() : bool + { + if (!is_file("dynmic/heads/" . $this->guid)) + return true; + + return unlink("dynmic/heads/" . $this->guid); + } + + /* + * Get the URL to the background image resource for this + * object. If no image is set, NULL is returned. + */ + public function getBgImg() : ?string + { + if (!is_file("dynmic/bgs/" . $this->guid)) + return NULL; + + return ar() . "/df.php?d=bgs&f=" . $this->guid; + } + + /* + * Set the background image for this object, overwriting any + * existing image. $image should be an uploaded file to PHP, + * still unhandled. + */ + public function setBgImg(array $image) : bool + { + $path = "dynmic/bgs/" . $this->guid; + return saveFile($image, $path, self::BG_MAXSIZE, self::IMAGE_MIME); + } + + /* + * Remove the background image for this object. This deletes + * the image on disk. + */ + public function rmBgImg() : bool + { + if (!is_file("dynmic/bgs/" . $this->guid)) + return true; + + return unlink("dynmic/bgs/" . $this->guid); + } } ?> |