Initial commit — Rosary Presenter App
Full source for loveandrosary.com: slide-based Rosary/novena/Divine Mercy Chaplet presentation tool with multi-user roles, SVG bead ring, audio uploads, donate strip, and public session profiles. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,78 @@
|
||||
<?php
|
||||
/**
|
||||
* api/upload_photo.php
|
||||
* POST: handle photo upload.
|
||||
* Returns JSON: {"path": "uploads/filename.jpg"} on success, {"error": "..."} on failure.
|
||||
*/
|
||||
require_once __DIR__ . '/../config/db.php';
|
||||
require_once __DIR__ . '/../includes/auth.php';
|
||||
|
||||
header('Content-Type: application/json');
|
||||
|
||||
require_auth();
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
|
||||
http_response_code(405);
|
||||
echo json_encode(['error' => 'Method not allowed']);
|
||||
exit;
|
||||
}
|
||||
|
||||
if (!isset($_FILES['photo']) || $_FILES['photo']['error'] !== UPLOAD_ERR_OK) {
|
||||
$upload_errors = [
|
||||
UPLOAD_ERR_INI_SIZE => 'File exceeds server upload limit',
|
||||
UPLOAD_ERR_FORM_SIZE => 'File exceeds form size limit',
|
||||
UPLOAD_ERR_PARTIAL => 'File was only partially uploaded',
|
||||
UPLOAD_ERR_NO_FILE => 'No file was uploaded',
|
||||
UPLOAD_ERR_NO_TMP_DIR => 'Missing temporary folder',
|
||||
UPLOAD_ERR_CANT_WRITE => 'Failed to write file to disk',
|
||||
UPLOAD_ERR_EXTENSION => 'A PHP extension stopped the upload',
|
||||
];
|
||||
$err_code = $_FILES['photo']['error'] ?? UPLOAD_ERR_NO_FILE;
|
||||
$err_msg = $upload_errors[$err_code] ?? 'Unknown upload error';
|
||||
http_response_code(400);
|
||||
echo json_encode(['error' => $err_msg]);
|
||||
exit;
|
||||
}
|
||||
|
||||
$file = $_FILES['photo'];
|
||||
$max_size = 5 * 1024 * 1024; // 5 MB
|
||||
|
||||
// Validate file size
|
||||
if ($file['size'] > $max_size) {
|
||||
http_response_code(400);
|
||||
echo json_encode(['error' => 'File is too large (max 5 MB)']);
|
||||
exit;
|
||||
}
|
||||
|
||||
// Validate MIME type using finfo (not just extension)
|
||||
$finfo = new finfo(FILEINFO_MIME_TYPE);
|
||||
$mime = $finfo->file($file['tmp_name']);
|
||||
$allowed = ['image/jpeg', 'image/png', 'image/gif', 'image/webp'];
|
||||
|
||||
if (!in_array($mime, $allowed, true)) {
|
||||
http_response_code(400);
|
||||
echo json_encode(['error' => 'Invalid file type. Allowed: JPEG, PNG, GIF, WebP']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$ext_map = [
|
||||
'image/jpeg' => 'jpg',
|
||||
'image/png' => 'png',
|
||||
'image/gif' => 'gif',
|
||||
'image/webp' => 'webp',
|
||||
];
|
||||
$ext = $ext_map[$mime];
|
||||
$filename = bin2hex(random_bytes(16)) . '.' . $ext;
|
||||
$dest = UPLOADS_DIR . $filename;
|
||||
|
||||
if (!is_dir(UPLOADS_DIR)) {
|
||||
mkdir(UPLOADS_DIR, 0755, true);
|
||||
}
|
||||
|
||||
if (!move_uploaded_file($file['tmp_name'], $dest)) {
|
||||
http_response_code(500);
|
||||
echo json_encode(['error' => 'Failed to save file']);
|
||||
exit;
|
||||
}
|
||||
|
||||
echo json_encode(['path' => UPLOADS_URL . $filename]);
|
||||
Reference in New Issue
Block a user