Cofem/lib/upload.php

282 lines
8.4 KiB
PHP
Raw Normal View History

2024-03-01 22:14:20 +01:00
<?php
2024-04-27 11:48:58 +02:00
declare(strict_types=1);
2024-03-01 22:14:20 +01:00
function makePathSafe($userInput): string
{
// Keep only alphanumeric characters, underscores, and hyphens
$safeString = preg_replace('/[^\w\-]/', '', $userInput);
// Ensure no path traversal
$safeString = str_replace('..', '_', $safeString);
// Trim leading/trailing underscores
$safeString = trim($safeString, '_');
// Replace directory separator characters with underscores
$safeString = str_replace(['/', '\\'], '_', $safeString);
// Limit length for safety
return substr($safeString, 0, 255);
}
2024-04-26 14:37:54 +02:00
function autoRotateImage(Imagick $imagick): void {
// Get the current orientation of the image
try {
$orientation = $imagick->getImageOrientation();
switch ($orientation) {
case Imagick::ORIENTATION_BOTTOMRIGHT: // upside down
$imagick->rotateimage("#000", 180); // rotate 180 degrees
break;
case Imagick::ORIENTATION_RIGHTTOP: // 90 degrees CW
$imagick->rotateimage("#000", 90); // rotate 90 degrees CW
break;
case Imagick::ORIENTATION_LEFTBOTTOM: // 90 degrees CCW
$imagick->rotateimage("#000", -90); // rotate 90 degrees CCW
break;
}
// Reset orientation to normal after the correction
$imagick->setImageOrientation(Imagick::ORIENTATION_TOPLEFT);
} catch (ImagickException) {
}
}
2024-03-01 22:14:20 +01:00
function getIncomingFiles(): array
{
$files = $_FILES;
$files2 = [];
foreach ($files as $infoArr) {
$filesByInput = [];
foreach ($infoArr as $key => $valueArr) {
if (is_array($valueArr)) { // file input "multiple"
foreach ($valueArr as $i => $value) {
$filesByInput[$i][$key] = $value;
}
} else { // -> string, normal file input
$filesByInput[] = $infoArr;
break;
}
}
$files2 = array_merge($files2, $filesByInput);
}
$files3 = [];
foreach ($files2 as $file) { // let's filter empty & errors
if (!$file['error']) $files3[] = $file;
}
return $files3;
}
2024-04-27 11:48:58 +02:00
function saveUploadedFileInDatabase(string $filePath, string $fileType, int $width, int $height): bool
2024-03-01 22:14:20 +01:00
{
global $mysqli;
2024-04-27 11:48:58 +02:00
$stmt = $mysqli->prepare("INSERT INTO Files (Path, Type, UploadedBy, UploadedAt, Width, Height) VALUES (?, ?, ?, NOW(), ?, ?)");
$stmt->bind_param("ssiii", $filePath, $fileType, $_SESSION["ID"], $width, $height);
2024-03-01 22:14:20 +01:00
$stmt->execute();
$stat = $stmt->affected_rows > 0;
$stmt->close();
return $stat;
}
function doImageUpload($inFile, $outFile): bool
{
// Create Imagick object
2024-04-27 11:48:58 +02:00
$width = 0;
$height = 0;
2024-03-10 22:55:29 +01:00
try {
$imagick = new Imagick($inFile);
$imagick->setImageFormat('webp');
2024-04-26 14:37:54 +02:00
autoRotateImage($imagick);
2024-03-10 22:55:29 +01:00
$imagick->stripImage();
$imagick->writeImage($outFile);
2024-04-27 11:48:58 +02:00
$width = $imagick->getImageWidth();
$height = $imagick->getImageHeight();
2024-04-25 10:19:24 +02:00
$imagick->destroy();
2024-04-26 14:37:54 +02:00
} catch (ImagickException) {
2024-03-10 22:55:29 +01:00
}
2024-03-01 22:14:20 +01:00
// Check if the reencoding was successful
if (file_exists($outFile)) {
2024-04-27 11:48:58 +02:00
return saveUploadedFileInDatabase($outFile, 'image/webp', $width, $height);
2024-03-01 22:14:20 +01:00
} else {
return false;
}
}
2024-04-11 10:36:40 +02:00
function listFiles($onlyMine = true): array
2024-03-01 22:14:20 +01:00
{
$output = ["Status" => "Fail"];
require_once "lib/account.php";
2024-04-26 09:46:10 +02:00
if (isLoggedIn()) {
2024-03-01 22:14:20 +01:00
global $mysqli;
2024-04-26 09:46:10 +02:00
if (!$onlyMine && !isModerator()) {
$onlyMine = true;
}
2024-04-26 15:09:45 +02:00
$query = "SELECT Files.ID, Files.Path, Files.Type, Files.UploadedAt, Files.UploadedBy, Users.Nickname FROM Files INNER JOIN Users ON Files.UploadedBy = Users.ID ORDER BY UploadedAt DESC";
2024-03-01 22:14:20 +01:00
2024-04-11 10:36:40 +02:00
if ($onlyMine) {
2024-03-01 22:14:20 +01:00
$query .= " WHERE UploadedBy = ?";
}
$stmt = $mysqli->prepare($query);
2024-04-11 10:36:40 +02:00
if ($onlyMine) {
2024-03-01 22:14:20 +01:00
$stmt->bind_param("i", $_SESSION["ID"]);
}
$id = 0;
$path = "";
$type = "";
$uploadedAt = "";
2024-04-26 15:09:45 +02:00
$uploadedByID = 0;
$uploadedBy = "";
2024-03-01 22:14:20 +01:00
2024-04-26 15:09:45 +02:00
$stmt->bind_result($id, $path, $type, $uploadedAt, $uploadedByID, $uploadedBy);
2024-03-01 22:14:20 +01:00
$stmt->execute();
// Fetch the results into the bound variables
while ($stmt->fetch()) {
$files[] = [
'ID' => $id,
'Path' => $path,
'Type' => $type,
'UploadedAt' => $uploadedAt,
2024-04-26 15:09:45 +02:00
'UploadedByID' => $uploadedByID,
2024-03-01 22:14:20 +01:00
'UploadedBy' => $uploadedBy,
];
}
// Check if any results were fetched
if (!empty($files)) {
$output["Status"] = "Success";
$output["Files"] = $files;
}
$stmt->close();
}
return $output;
}
function parseIncomingFiles(): array
{
$incomingFiles = getIncomingFiles();
$success = true;
foreach ($incomingFiles as $incomingFile) {
if ($incomingFile["error"] == 0 && is_file($incomingFile["tmp_name"])) {
$type = explode("/", $incomingFile["type"]);
2024-04-25 10:49:45 +02:00
if ($type[0] == "image") {
2024-03-10 22:55:29 +01:00
$imgFname = pathinfo($incomingFile["name"], PATHINFO_FILENAME);
$uploadPath = getUploadPath("image", $imgFname);
if (!empty($uploadPath)) {
if (!doImageUpload($incomingFile["tmp_name"], $uploadPath)) {
2024-03-01 22:14:20 +01:00
$success = false;
}
2024-03-10 22:55:29 +01:00
} else {
$success = false;
}
2024-03-01 22:14:20 +01:00
}
}
}
$output = ["Status" => "Fail"];
2024-04-11 10:36:40 +02:00
if ($success) {
2024-03-01 22:14:20 +01:00
$output["Status"] = "Success";
}
return $output;
}
function getUploadPath($type = "unknown", $filename = "hehe"): string
{
$type = makePathSafe($type);
$id = makePathSafe($_SESSION["ID"]);
2024-04-26 01:33:20 +02:00
$date = makePathSafe(date("YmdHis"));
2024-03-01 22:14:20 +01:00
$filename = makePathSafe($filename);
$extension = match ($type) {
'image' => 'webp',
default => 'dummy',
};
2024-04-11 10:36:40 +02:00
if ($extension != "dummy") {
2024-04-25 10:30:22 +02:00
$basepath = "uploads/$type/$id/$date";
mkdir($basepath, 755, true);
return $basepath . "/$filename.$extension";
2024-04-11 10:36:40 +02:00
} else {
2024-03-01 22:14:20 +01:00
return "";
}
2024-04-11 10:36:40 +02:00
}
2024-04-25 15:01:17 +02:00
function fileExists(int $fileId, bool $onlyMine = true): bool|string
2024-04-11 10:36:40 +02:00
{
2024-04-26 09:46:10 +02:00
if (!$fileId) {
2024-04-11 10:36:40 +02:00
return false;
}
global $mysqli;
2024-04-26 09:51:40 +02:00
if (!$onlyMine && !isModerator()) {
2024-04-11 10:36:40 +02:00
$onlyMine = true;
}
2024-04-26 10:47:42 +02:00
$query = 'SELECT ID, Path FROM Files WHERE ID = ?' . ($onlyMine ? ' AND UploadedBy = ?' : '');
$stmtfileexists = $mysqli->prepare($query);
2024-04-11 10:36:40 +02:00
if ($onlyMine) {
2024-04-26 10:47:42 +02:00
$stmtfileexists->bind_param('ii', $fileId, $_SESSION['ID']);
2024-04-11 10:36:40 +02:00
} else {
$stmtfileexists->bind_param('i', $fileId);
}
2024-04-25 15:01:17 +02:00
$filePath = "";
2024-04-26 10:39:00 +02:00
$id = null;
2024-04-26 10:46:34 +02:00
$stmtfileexists->bind_result($id, $filePath);
2024-04-26 10:47:42 +02:00
$stmtfileexists->execute();
2024-04-25 23:37:52 +02:00
$stmtfileexists->fetch();
2024-04-26 10:47:42 +02:00
if ($id != null) {
2024-04-25 15:01:17 +02:00
return $filePath;
2024-04-26 09:46:10 +02:00
} else {
2024-04-25 15:01:17 +02:00
return false;
}
2024-04-11 10:36:40 +02:00
}
2024-04-25 10:19:24 +02:00
function addToGroup(int $groupId, int $fileId): array
2024-04-11 10:36:40 +02:00
{
$output = ["Status" => "Fail"];
if (!$groupId || !$fileId) {
return $output;
}
global $mysqli;
$stmtcheck = $mysqli->prepare('SELECT ID FROM FileGroups WHERE CreatorID != ? AND ID = ?');
2024-04-26 10:52:11 +02:00
$stmtcheck->bind_param('ii', $_SESSION['ID'], $groupId);
2024-04-11 10:36:40 +02:00
$stmtcheck->execute();
if ($stmtcheck->affected_rows == 0) {
if (fileExists($fileId, false)) {
$stmtadd = $mysqli->prepare('INSERT INTO FileGroups (FileID, CreatorID, ID) VALUES (?, ?, ?)');
2024-04-26 10:52:11 +02:00
$stmtadd->bind_param('iii', $fileId, $_SESSION['ID'], $groupId);
2024-04-11 10:36:40 +02:00
$stmtadd->execute();
if ($stmtadd->affected_rows > 0) {
$output["Status"] = "Success";
}
}
}
return $output;
2024-04-25 09:04:10 +02:00
}
2024-04-26 14:37:54 +02:00
function deleteFile(int $fileID): array
2024-04-25 15:01:17 +02:00
{
2024-04-26 01:17:49 +02:00
global $mysqli;
2024-04-25 15:01:17 +02:00
$out = ["Status" => "Fail"];
2024-04-26 09:46:10 +02:00
if (isLoggedIn()) {
2024-04-26 01:17:49 +02:00
$file_location = fileExists($fileID, !isAdmin());
$query = !isAdmin() ? 'DELETE FROM Files WHERE ID = ? AND UploadedBy = ?' : 'DELETE FROM Files WHERE ID = ?';
$stmtDelete = $mysqli->prepare($query);
if (!isAdmin()) {
2024-04-26 10:52:11 +02:00
$stmtDelete->bind_param('ii', $fileID, $_SESSION['ID']);
2024-04-26 01:17:49 +02:00
} else {
$stmtDelete->bind_param('i', $fileID);
}
$stmtDelete->execute();
if ($file_location) {
if (unlink($file_location) && $stmtDelete->affected_rows > 0) {
$out['Status'] = 'Success';
}
2024-04-25 15:01:17 +02:00
}
}
return $out;
2024-03-01 22:14:20 +01:00
}