mirror of
https://github.com/myronblair/epictravelexpeditions
synced 2026-07-28 08:52:26 -05:00
0dfcfa2f7e
- mailer.php: re-enable TLS certificate verification for CyberMail API calls (was CURLOPT_SSL_VERIFYPEER => false, exposing outbound mail traffic to MITM). - .htaccess / api/.htaccess: block direct HTTP access to .git/, db/, and api/config.php via mod_rewrite [F] rules. Confirmed live that /.git/config, /.git/logs/HEAD, and /db/schema.sql were all directly downloadable (200 OK with real content) - .git exposure leaks the repo's embedded GitHub token and full history; schema.sql leaks the DB layout. Also drops the dead "/setup -> setup_password.php" rewrite, since that file was already deleted from production. - index.php: remove the 'download' route, which required a api/download.php that has never existed in this repo - confirmed live that GET /api/download returns a fatal 500. - functions.php / upload.php / testimonials.php: extract the duplicated image-upload validation/move logic (MIME check, size check, UUID rename, move_uploaded_file) into one handleImageUpload() helper used by both upload endpoints. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
125 lines
3.3 KiB
PHP
125 lines
3.3 KiB
PHP
<?php
|
|
/**
|
|
* Helper Functions
|
|
*/
|
|
|
|
/**
|
|
* Set CORS headers
|
|
*/
|
|
function setCorsHeaders() {
|
|
$origin = isset($_SERVER['HTTP_ORIGIN']) ? $_SERVER['HTTP_ORIGIN'] : '';
|
|
|
|
if ($origin && (ALLOWED_ORIGINS === '*' || strpos(ALLOWED_ORIGINS, $origin) !== false)) {
|
|
header("Access-Control-Allow-Origin: $origin");
|
|
} else {
|
|
header("Access-Control-Allow-Origin: " . ALLOWED_ORIGINS);
|
|
}
|
|
|
|
header("Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS");
|
|
header("Access-Control-Allow-Headers: Content-Type, Authorization");
|
|
header("Access-Control-Allow-Credentials: true");
|
|
|
|
// Handle preflight requests
|
|
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
|
|
http_response_code(200);
|
|
exit;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Send JSON response
|
|
*/
|
|
function jsonResponse($data, $statusCode = 200) {
|
|
http_response_code($statusCode);
|
|
header('Content-Type: application/json');
|
|
echo json_encode($data);
|
|
exit;
|
|
}
|
|
|
|
/**
|
|
* Get JSON input
|
|
*/
|
|
function getJsonInput() {
|
|
$input = file_get_contents('php://input');
|
|
return json_decode($input, true);
|
|
}
|
|
|
|
/**
|
|
* Validate email
|
|
*/
|
|
function isValidEmail($email) {
|
|
return filter_var($email, FILTER_VALIDATE_EMAIL) !== false;
|
|
}
|
|
|
|
/**
|
|
* Generate UUID v4
|
|
*/
|
|
function generateUuid() {
|
|
return sprintf('%04x%04x-%04x-%04x-%04x-%04x%04x%04x',
|
|
mt_rand(0, 0xffff), mt_rand(0, 0xffff),
|
|
mt_rand(0, 0xffff),
|
|
mt_rand(0, 0x0fff) | 0x4000,
|
|
mt_rand(0, 0x3fff) | 0x8000,
|
|
mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0xffff)
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Sanitize string
|
|
*/
|
|
function sanitizeString($string) {
|
|
return htmlspecialchars(strip_tags(trim($string)), ENT_QUOTES, 'UTF-8');
|
|
}
|
|
|
|
/**
|
|
* Validate required fields
|
|
*/
|
|
function validateRequired($data, $requiredFields) {
|
|
$errors = [];
|
|
|
|
foreach ($requiredFields as $field) {
|
|
if (!isset($data[$field]) || empty(trim($data[$field]))) {
|
|
$errors[] = "$field is required";
|
|
}
|
|
}
|
|
|
|
return $errors;
|
|
}
|
|
|
|
/**
|
|
* Validate an uploaded image file ($_FILES['file']) and move it into
|
|
* UPLOAD_DIR under a fresh UUID filename. Shared by all endpoints that
|
|
* accept image uploads (was previously duplicated per-endpoint).
|
|
*
|
|
* Returns ['url' => ..., 'filename' => ...] on success, or
|
|
* ['error' => ..., 'status' => ...] on failure.
|
|
*/
|
|
function handleImageUpload($file) {
|
|
if (!$file || $file['error'] !== UPLOAD_ERR_OK) {
|
|
return ['error' => 'File upload failed', 'status' => 400];
|
|
}
|
|
|
|
if ($file['size'] > MAX_UPLOAD_SIZE) {
|
|
return ['error' => 'File too large. Maximum size is 5MB', 'status' => 400];
|
|
}
|
|
|
|
$allowedTypes = ['image/jpeg', 'image/jpg', 'image/png', 'image/webp'];
|
|
$finfo = finfo_open(FILEINFO_MIME_TYPE);
|
|
$mimeType = finfo_file($finfo, $file['tmp_name']);
|
|
finfo_close($finfo);
|
|
|
|
if (!in_array($mimeType, $allowedTypes)) {
|
|
return ['error' => 'Invalid file type. Only JPG, PNG, and WebP allowed', 'status' => 400];
|
|
}
|
|
|
|
$extension = strtolower(pathinfo($file['name'], PATHINFO_EXTENSION));
|
|
$filename = generateUuid() . '.' . $extension;
|
|
$filepath = UPLOAD_DIR . $filename;
|
|
|
|
if (!move_uploaded_file($file['tmp_name'], $filepath)) {
|
|
return ['error' => 'Failed to save file', 'status' => 500];
|
|
}
|
|
|
|
return ['url' => '/api/uploads/' . $filename, 'filename' => $filename];
|
|
}
|