Task 10: Harden file upload validation
Enhanced validateFileUpload() function in functions.php with comprehensive security: - Hardcoded MIME type whitelist per file type (profile_picture, proof_of_payment, document) - Strict file size limits per type (5MB images, 10MB documents) - Extension validation against whitelist - Double extension prevention (e.g., shell.php.jpg) - MIME type verification using finfo - Image validation with getimagesize() - is_uploaded_file() verification - Random filename generation to prevent path traversal Updated file upload handlers: - upload_profile_picture.php - Profile picture uploads (JPEG, PNG, GIF, WEBP, 5MB max) - submit_pop.php - Proof of payment uploads (PDF only, 10MB max) + CSRF validation + audit logging - add_campsite.php - Campsite thumbnail uploads + input validation + CSRF validation + audit logging Security improvements: - All uploads use random filenames to prevent directory traversal - All uploads use secure file permissions (0644) - File validation occurs before move_uploaded_file() - Comprehensive error logging for failed uploads - Audit logging for successful file operations
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
include_once('functions.php');
|
||||
require_once("env.php");
|
||||
session_start();
|
||||
$user_id = $_SESSION['user_id']; // assuming you're storing it like this
|
||||
$user_id = $_SESSION['user_id'] ?? null;
|
||||
|
||||
// CSRF Token Validation
|
||||
if (!isset($_POST['csrf_token']) || !validateCSRFToken($_POST['csrf_token'])) {
|
||||
@@ -14,26 +14,48 @@ if (!isset($_POST['csrf_token']) || !validateCSRFToken($_POST['csrf_token'])) {
|
||||
$conn = openDatabaseConnection();
|
||||
|
||||
// Get text inputs
|
||||
$name = $_POST['name'];
|
||||
$desc = $_POST['description'];
|
||||
$lat = $_POST['latitude'];
|
||||
$lng = $_POST['longitude'];
|
||||
$website = $_POST['website'];
|
||||
$telephone = $_POST['telephone'];
|
||||
$name = validateName($_POST['name'] ?? '') ?: '';
|
||||
$desc = isset($_POST['description']) ? htmlspecialchars($_POST['description'], ENT_QUOTES, 'UTF-8') : '';
|
||||
$lat = isset($_POST['latitude']) ? floatval($_POST['latitude']) : 0.0;
|
||||
$lng = isset($_POST['longitude']) ? floatval($_POST['longitude']) : 0.0;
|
||||
$website = isset($_POST['website']) ? filter_var($_POST['website'], FILTER_VALIDATE_URL) : '';
|
||||
$telephone = validatePhoneNumber($_POST['telephone'] ?? '') ?: '';
|
||||
|
||||
if (empty($name)) {
|
||||
http_response_code(400);
|
||||
die('Campsite name is required.');
|
||||
}
|
||||
|
||||
// Handle file upload
|
||||
$thumbnailPath = null;
|
||||
if (isset($_FILES['thumbnail']) && $_FILES['thumbnail']['error'] == 0) {
|
||||
$uploadDir = "assets/uploads/campsites/";
|
||||
if (!is_dir($uploadDir)) {
|
||||
mkdir($uploadDir, 0777, true);
|
||||
if (isset($_FILES['thumbnail']) && $_FILES['thumbnail']['error'] !== UPLOAD_ERR_NO_FILE) {
|
||||
// Validate file using hardened validation function
|
||||
$validationResult = validateFileUpload($_FILES['thumbnail'], 'profile_picture');
|
||||
|
||||
if ($validationResult === false) {
|
||||
http_response_code(400);
|
||||
die('Invalid thumbnail image. Only JPG, JPEG, PNG, GIF, and WEBP images under 5MB are allowed.');
|
||||
}
|
||||
|
||||
$filename = time() . "_" . basename($_FILES["thumbnail"]["name"]);
|
||||
$targetFile = $uploadDir . $filename;
|
||||
$uploadDir = "assets/uploads/campsites/";
|
||||
if (!is_dir($uploadDir)) {
|
||||
mkdir($uploadDir, 0755, true);
|
||||
}
|
||||
|
||||
if (!is_writable($uploadDir)) {
|
||||
http_response_code(500);
|
||||
die('Upload directory is not writable.');
|
||||
}
|
||||
|
||||
$randomFilename = $validationResult['filename'];
|
||||
$targetFile = $uploadDir . $randomFilename;
|
||||
|
||||
if (move_uploaded_file($_FILES["thumbnail"]["tmp_name"], $targetFile)) {
|
||||
chmod($targetFile, 0644);
|
||||
$thumbnailPath = $targetFile;
|
||||
} else {
|
||||
http_response_code(500);
|
||||
die('Failed to move uploaded file.');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,14 +70,25 @@ if ($id > 0) {
|
||||
$stmt = $conn->prepare("UPDATE campsites SET name=?, description=?, latitude=?, longitude=?, website=?, telephone=? WHERE id=?");
|
||||
$stmt->bind_param("ssddssi", $name, $desc, $lat, $lng, $website, $telephone, $id);
|
||||
}
|
||||
|
||||
// Log the action
|
||||
auditLog($user_id, 'CAMPSITE_UPDATE', 'campsites', $id, ['name' => $name]);
|
||||
} else {
|
||||
// INSERT
|
||||
$stmt = $conn->prepare("INSERT INTO campsites (name, description, latitude, longitude, website, telephone, thumbnail, user_id)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?)");
|
||||
$stmt->bind_param("ssddsssi", $name, $desc, $lat, $lng, $website, $telephone, $thumbnailPath, $user_id);
|
||||
$stmt->bind_param("ssddsssi", $name, $desc, $lat, $lng, $website, $telephone, $thumbnailPath, $user_id);
|
||||
|
||||
// Log the action
|
||||
auditLog($user_id, 'CAMPSITE_CREATE', 'campsites', 0, ['name' => $name]);
|
||||
}
|
||||
$stmt->execute();
|
||||
|
||||
if (!$stmt->execute()) {
|
||||
http_response_code(500);
|
||||
die('Database error: ' . $stmt->error);
|
||||
}
|
||||
|
||||
$stmt->close();
|
||||
|
||||
header("Location: campsites.php");
|
||||
?>
|
||||
|
||||
124
functions.php
124
functions.php
@@ -2280,40 +2280,134 @@ function sanitizeTextInput($text, $maxLength = 1000) {
|
||||
* @param int $maxSize Maximum file size in bytes
|
||||
* @return string|false Sanitized filename or false if invalid
|
||||
*/
|
||||
function validateFileUpload($file, $allowedTypes = [], $maxSize = 5242880) { // 5MB default
|
||||
// Check for upload errors
|
||||
if (!isset($file['error']) || $file['error'] !== UPLOAD_ERR_OK) {
|
||||
/**
|
||||
* HARDENED FILE UPLOAD VALIDATION
|
||||
*
|
||||
* Validates file uploads with strict security checks:
|
||||
* - Verifies upload completion
|
||||
* - Enforces strict MIME type validation using finfo
|
||||
* - Enforces strict file size limits per type
|
||||
* - Validates extensions against whitelist
|
||||
* - Prevents double extensions (e.g., .php.jpg)
|
||||
* - Generates random filenames to prevent path traversal
|
||||
* - Validates actual file content matches extension
|
||||
*
|
||||
* @param array $file The $_FILES['fieldname'] array
|
||||
* @param string $fileType The type of file being uploaded (profile_picture, proof_of_payment, document)
|
||||
* @return array|false Returns ['filename' => randomName, 'extension' => ext] on success, false on failure
|
||||
*/
|
||||
function validateFileUpload($file, $fileType = 'document') {
|
||||
// ===== CONFIGURATION: HARDCODED TYPE WHITELIST =====
|
||||
$fileTypeConfig = [
|
||||
'profile_picture' => [
|
||||
'extensions' => ['jpg', 'jpeg', 'png', 'gif', 'webp'],
|
||||
'mimeTypes' => ['image/jpeg', 'image/png', 'image/gif', 'image/webp'],
|
||||
'maxSize' => 5242880, // 5MB
|
||||
'description' => 'Profile Picture'
|
||||
],
|
||||
'proof_of_payment' => [
|
||||
'extensions' => ['pdf'],
|
||||
'mimeTypes' => ['application/pdf'],
|
||||
'maxSize' => 10485760, // 10MB
|
||||
'description' => 'Proof of Payment'
|
||||
],
|
||||
'document' => [
|
||||
'extensions' => ['pdf', 'doc', 'docx'],
|
||||
'mimeTypes' => ['application/pdf', 'application/msword', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'],
|
||||
'maxSize' => 10485760, // 10MB
|
||||
'description' => 'Document'
|
||||
]
|
||||
];
|
||||
|
||||
// Validate fileType exists in config
|
||||
if (!isset($fileTypeConfig[$fileType])) {
|
||||
error_log("Invalid file type requested: $fileType");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check file size
|
||||
if (!isset($file['size']) || $file['size'] > $maxSize) {
|
||||
$config = $fileTypeConfig[$fileType];
|
||||
|
||||
// ===== CHECK 1: Upload Error =====
|
||||
if (!isset($file['error']) || !isset($file['tmp_name']) || !isset($file['size']) || !isset($file['name'])) {
|
||||
error_log("File upload validation: Missing required file array keys");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check MIME type
|
||||
if ($file['error'] !== UPLOAD_ERR_OK) {
|
||||
error_log("File upload error code: {$file['error']} for type: $fileType");
|
||||
return false;
|
||||
}
|
||||
|
||||
// ===== CHECK 2: File Size Limit =====
|
||||
if ($file['size'] > $config['maxSize']) {
|
||||
error_log("File size {$file['size']} exceeds limit {$config['maxSize']} for type: $fileType");
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($file['size'] <= 0) {
|
||||
error_log("File size is zero or negative for type: $fileType");
|
||||
return false;
|
||||
}
|
||||
|
||||
// ===== CHECK 3: Extension Validation (Case-Insensitive) =====
|
||||
$pathinfo = pathinfo($file['name']);
|
||||
$extension = strtolower($pathinfo['extension'] ?? '');
|
||||
|
||||
if (empty($extension) || !in_array($extension, $config['extensions'], true)) {
|
||||
error_log("Invalid extension '$extension' for type: $fileType. Allowed: " . implode(', ', $config['extensions']));
|
||||
return false;
|
||||
}
|
||||
|
||||
// ===== CHECK 4: Prevent Double Extensions (e.g., shell.php.jpg) =====
|
||||
if (isset($pathinfo['filename'])) {
|
||||
// Check if filename contains suspicious extensions
|
||||
$suspiciousPatterns = ['/\.php/', '/\.phtml/', '/\.phar/', '/\.sh/', '/\.bat/', '/\.exe/', '/\.com/'];
|
||||
foreach ($suspiciousPatterns as $pattern) {
|
||||
if (preg_match($pattern, $pathinfo['filename'], $matches)) {
|
||||
error_log("Suspicious pattern detected in filename: {$pathinfo['filename']} for type: $fileType");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ===== CHECK 5: MIME Type Validation =====
|
||||
$finfo = finfo_open(FILEINFO_MIME_TYPE);
|
||||
if ($finfo === false) {
|
||||
error_log("Failed to open fileinfo resource");
|
||||
return false;
|
||||
}
|
||||
|
||||
$mimeType = finfo_file($finfo, $file['tmp_name']);
|
||||
finfo_close($finfo);
|
||||
|
||||
if (!in_array($mimeType, $allowedTypes, true)) {
|
||||
if (!in_array($mimeType, $config['mimeTypes'], true)) {
|
||||
error_log("Invalid MIME type '$mimeType' for type: $fileType. Expected: " . implode(', ', $config['mimeTypes']));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Generate random filename with original extension
|
||||
$pathinfo = pathinfo($file['name']);
|
||||
$extension = strtolower($pathinfo['extension']);
|
||||
// ===== CHECK 6: Additional Image Validation (for images) =====
|
||||
if (in_array($fileType, ['profile_picture'])) {
|
||||
$imageInfo = @getimagesize($file['tmp_name']);
|
||||
if ($imageInfo === false) {
|
||||
error_log("File is not a valid image for type: $fileType");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Whitelist allowed extensions
|
||||
$allowedExtensions = ['jpg', 'jpeg', 'png', 'pdf', 'gif', 'webp'];
|
||||
if (!in_array($extension, $allowedExtensions)) {
|
||||
// ===== CHECK 7: Verify File is Actually Uploaded (Not Executed) =====
|
||||
if (!is_uploaded_file($file['tmp_name'])) {
|
||||
error_log("File is not a valid uploaded file for type: $fileType");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Generate random filename
|
||||
// ===== GENERATE RANDOM FILENAME =====
|
||||
$randomName = bin2hex(random_bytes(16)) . '.' . $extension;
|
||||
|
||||
return $randomName;
|
||||
return [
|
||||
'filename' => $randomName,
|
||||
'extension' => $extension,
|
||||
'mimeType' => $mimeType
|
||||
];
|
||||
}
|
||||
|
||||
// ==================== RATE LIMITING & ACCOUNT LOCKOUT FUNCTIONS ====================
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
<?php include_once('header02.php');
|
||||
require_once("functions.php");
|
||||
checkUserSession();
|
||||
umask(002); // At the top of the PHP script, before move_uploaded_file()
|
||||
|
||||
|
||||
$user_id = $_SESSION['user_id'] ?? null;
|
||||
|
||||
@@ -11,48 +10,44 @@ if (!$user_id) {
|
||||
|
||||
// Handle POST submission
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
$eft_id = $_POST['eft_id'] ?? null;
|
||||
$file_name = str_replace(' ', '_', $eft_id);
|
||||
// CSRF Token Validation
|
||||
if (!isset($_POST['csrf_token']) || !validateCSRFToken($_POST['csrf_token'])) {
|
||||
http_response_code(403);
|
||||
die('Security token validation failed. Please try again.');
|
||||
}
|
||||
|
||||
$eft_id = $_POST['eft_id'] ?? null;
|
||||
|
||||
if (!$eft_id || !isset($_FILES['pop_file'])) {
|
||||
echo "<div class='alert alert-danger'>Invalid submission: missing eft_id or file.</div>";
|
||||
echo "<pre>";
|
||||
echo "POST data: " . print_r($_POST, true);
|
||||
echo "FILES data: " . print_r($_FILES, true);
|
||||
echo "</pre>";
|
||||
} else {
|
||||
$file = $_FILES['pop_file'];
|
||||
exit;
|
||||
}
|
||||
|
||||
// Validate file using hardened validation function
|
||||
$validationResult = validateFileUpload($_FILES['pop_file'], 'proof_of_payment');
|
||||
|
||||
if ($validationResult === false) {
|
||||
echo "<div class='alert alert-danger'>Invalid file. Only PDF files under 10MB are allowed.</div>";
|
||||
exit;
|
||||
}
|
||||
|
||||
$target_dir = "uploads/pop/";
|
||||
$target_file = $target_dir . $file_name . ".pdf";
|
||||
|
||||
// Check for upload errors first
|
||||
if ($file['error'] !== UPLOAD_ERR_OK) {
|
||||
echo "<div class='alert alert-danger'>Upload error code: " . $file['error'] . "</div>";
|
||||
// You can decode error code if needed:
|
||||
// https://www.php.net/manual/en/features.file-upload.errors.php
|
||||
exit;
|
||||
}
|
||||
|
||||
// Check for PDF extension
|
||||
$file_type = strtolower(pathinfo($file['name'], PATHINFO_EXTENSION));
|
||||
if ($file_type !== "pdf") {
|
||||
echo "<div class='alert alert-danger'>Only PDF files allowed. You tried uploading: .$file_type</div>";
|
||||
exit;
|
||||
}
|
||||
$randomFilename = $validationResult['filename'];
|
||||
$target_file = $target_dir . $randomFilename;
|
||||
|
||||
// Make sure target directory exists and writable
|
||||
if (!is_dir($target_dir)) {
|
||||
echo "<div class='alert alert-danger'>Upload directory does not exist: $target_dir</div>";
|
||||
exit;
|
||||
mkdir($target_dir, 0755, true);
|
||||
}
|
||||
|
||||
if (!is_writable($target_dir)) {
|
||||
echo "<div class='alert alert-danger'>Upload directory is not writable: $target_dir</div>";
|
||||
exit;
|
||||
}
|
||||
|
||||
if (move_uploaded_file($file['tmp_name'], $target_file)) {
|
||||
chmod($target_file, 0664);
|
||||
if (move_uploaded_file($_FILES['pop_file']['tmp_name'], $target_file)) {
|
||||
chmod($target_file, 0644);
|
||||
|
||||
// Update EFT and booking status
|
||||
$payment_type = $_POST['payment_type'] ?? 'booking';
|
||||
|
||||
@@ -61,42 +56,47 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
$stmt1 = $conn->prepare("UPDATE efts SET status = 'PROCESSING' WHERE eft_id = ?");
|
||||
$stmt1->bind_param("s", $eft_id);
|
||||
$stmt1->execute();
|
||||
$stmt1->close();
|
||||
|
||||
// Update membership fee status
|
||||
$stmt = $conn->prepare("UPDATE membership_fees SET payment_status = 'PROCESSING' WHERE payment_id = ?");
|
||||
$stmt->bind_param("s", $eft_id);
|
||||
$stmt->execute();
|
||||
$stmt->close();
|
||||
} else {
|
||||
// Update EFT and booking status
|
||||
$stmt1 = $conn->prepare("UPDATE efts SET status = 'PROCESSING' WHERE eft_id = ?");
|
||||
$stmt1->bind_param("s", $eft_id);
|
||||
$stmt1->execute();
|
||||
$stmt1->close();
|
||||
|
||||
$stmt2 = $conn->prepare("UPDATE bookings SET status = 'PROCESSING' WHERE eft_id = ?");
|
||||
$stmt2->bind_param("s", $eft_id);
|
||||
$stmt2->execute();
|
||||
$stmt2->close();
|
||||
}
|
||||
|
||||
// Send notification email using sendPOP()
|
||||
$fullname = getFullName($user_id); // Assuming this returns "First Last"
|
||||
|
||||
$fullname = getFullName($user_id);
|
||||
$eftDetails = getEFTDetails($eft_id);
|
||||
$modified = str_replace(' ', '_', $eft_id);
|
||||
|
||||
if ($eftDetails) {
|
||||
$amount = "R" . number_format($eftDetails['amount'], 2);
|
||||
$description = $eftDetails['description'];
|
||||
} else {
|
||||
$amount = "R0.00";
|
||||
$description = "Payment"; // fallback
|
||||
$description = "Payment";
|
||||
}
|
||||
|
||||
|
||||
if (sendPOP($fullname, $modified, $amount, $description)) {
|
||||
if (sendPOP($fullname, $randomFilename, $amount, $description)) {
|
||||
$_SESSION['message'] = "Thank you! Your payment proof has been uploaded and notification sent.";
|
||||
} else {
|
||||
$_SESSION['message'] = "Payment uploaded, but notification email could not be sent.";
|
||||
}
|
||||
|
||||
// Log the action
|
||||
auditLog($user_id, 'POP_UPLOAD', 'efts', $eft_id, ['filename' => $randomFilename, 'payment_type' => $payment_type]);
|
||||
|
||||
header("Location: bookings.php");
|
||||
exit;
|
||||
|
||||
@@ -158,7 +158,7 @@ if (!empty($bannerImages)) {
|
||||
<?php if (count($items) > 0) {?>
|
||||
|
||||
<form enctype="multipart/form-data" method="POST">
|
||||
|
||||
<input type="hidden" name="csrf_token" value="<?php echo generateCSRFToken(); ?>">
|
||||
<div class="row mt-35">
|
||||
<ul class="tickets clearfix">
|
||||
<li>
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
<?php
|
||||
session_start();
|
||||
include_once('connection.php'); // DB connection file
|
||||
include_once('connection.php');
|
||||
require_once("functions.php");
|
||||
require_once("env.php");
|
||||
|
||||
$response = array('status' => 'error', 'message' => 'Something went wrong');
|
||||
|
||||
// Check if the user is logged in
|
||||
@@ -14,50 +16,60 @@ if (!isset($_SESSION['user_id'])) {
|
||||
$user_id = $_SESSION['user_id'];
|
||||
|
||||
// Handle profile picture upload
|
||||
if (isset($_FILES['profile_picture']['name']) && $_FILES['profile_picture']['error'] == 0) {
|
||||
if (isset($_FILES['profile_picture']) && $_FILES['profile_picture']['error'] != UPLOAD_ERR_NO_FILE) {
|
||||
// Validate file using hardened validation function
|
||||
$validationResult = validateFileUpload($_FILES['profile_picture'], 'profile_picture');
|
||||
|
||||
if ($validationResult === false) {
|
||||
$response['message'] = 'Invalid file. Only JPG, JPEG, PNG, GIF, and WEBP images under 5MB are allowed.';
|
||||
echo json_encode($response);
|
||||
exit();
|
||||
}
|
||||
|
||||
// Extract validated filename
|
||||
$randomFilename = $validationResult['filename'];
|
||||
$target_dir = "assets/images/pp/";
|
||||
$imageFileType = strtolower(pathinfo($_FILES["profile_picture"]["name"], PATHINFO_EXTENSION));
|
||||
$target_file = $target_dir . $randomFilename;
|
||||
|
||||
// Set the target file as $user_id.EXT (where EXT is the image's extension)
|
||||
$target_file = $target_dir . $user_id . '.' . $imageFileType;
|
||||
$filename = $user_id . '.' . $imageFileType;
|
||||
// Ensure upload directory exists and is writable
|
||||
if (!is_dir($target_dir)) {
|
||||
mkdir($target_dir, 0755, true);
|
||||
}
|
||||
|
||||
// Check if the uploaded file is an image
|
||||
$check = getimagesize($_FILES["profile_picture"]["tmp_name"]);
|
||||
if ($check !== false) {
|
||||
// Limit the file size to 5MB
|
||||
if ($_FILES["profile_picture"]["size"] > 5000000) {
|
||||
$response['message'] = 'Sorry, your file is too large.';
|
||||
if (!is_writable($target_dir)) {
|
||||
$response['message'] = 'Upload directory is not writable.';
|
||||
echo json_encode($response);
|
||||
exit();
|
||||
}
|
||||
|
||||
// Allow certain file formats
|
||||
$allowed_types = array("jpg", "jpeg", "png", "gif");
|
||||
if (!in_array($imageFileType, $allowed_types)) {
|
||||
$response['message'] = 'Sorry, only JPG, JPEG, PNG & GIF files are allowed.';
|
||||
echo json_encode($response);
|
||||
exit();
|
||||
}
|
||||
// Move the uploaded file
|
||||
if (move_uploaded_file($_FILES['profile_picture']['tmp_name'], $target_file)) {
|
||||
// Set secure file permissions (readable but not executable)
|
||||
chmod($target_file, 0644);
|
||||
|
||||
// Move the uploaded file to the server and name it as $user_id.EXT
|
||||
if (move_uploaded_file($_FILES["profile_picture"]["tmp_name"], $target_file)) {
|
||||
// Update the profile picture path in the database
|
||||
$sql = "UPDATE users SET profile_pic = ? WHERE user_id = ?";
|
||||
$stmt = $conn->prepare($sql);
|
||||
if (!$stmt) {
|
||||
$response['message'] = 'Database error.';
|
||||
echo json_encode($response);
|
||||
exit();
|
||||
}
|
||||
|
||||
$stmt->bind_param("si", $target_file, $user_id);
|
||||
if ($stmt->execute()) {
|
||||
$_SESSION['profile_pic'] = $target_file;
|
||||
$response['status'] = 'success';
|
||||
$response['message'] = 'Profile picture updated successfully';
|
||||
|
||||
// Log the action
|
||||
auditLog($user_id, 'PROFILE_PIC_UPLOAD', 'users', $user_id, ['filename' => $randomFilename]);
|
||||
} else {
|
||||
$response['message'] = 'Failed to update profile picture in the database';
|
||||
}
|
||||
$stmt->close();
|
||||
} else {
|
||||
$response['message'] = 'Sorry, there was an error uploading your file.';
|
||||
}
|
||||
} else {
|
||||
$response['message'] = 'File is not an image.';
|
||||
$response['message'] = 'Failed to move uploaded file.';
|
||||
}
|
||||
} else {
|
||||
$response['message'] = 'No file uploaded or file error.';
|
||||
|
||||
Reference in New Issue
Block a user