(int)date('Y') + 1) { throw new Exception("Année invalide. Veuillez entrer une année valide."); } $mail = filter_var($_POST["mail"] ?? '', FILTER_VALIDATE_EMAIL); if ($mail === false && !empty($_POST["mail"])) { throw new Exception("Adresse email invalide."); } $titre = validate_required(sanitize_string($_POST["titre"] ?? ''), "Titre du mémoire"); $tag = sanitize_string($_POST["tag"] ?? ''); $promoteurice = sanitize_string($_POST["promoteurice"] ?? ''); $problematique = sanitize_string($_POST["problématique"] ?? ''); $description = sanitize_string($_POST["description"] ?? ''); $orientation = validate_required(sanitize_string($_POST["orientation"] ?? ''), "Orientation"); $ap = validate_required(sanitize_string($_POST["ap"] ?? ''), "Atelier Pratique"); // Validate URL if provided $lien = $_POST["lien"] ?? ''; if (!empty($lien)) { $lien = filter_var($lien, FILTER_VALIDATE_URL); if ($lien === false) { throw new Exception("Lien URL invalide."); } } $couverture = $_FILES["couverture"] ?? null; $files = $_FILES["files"] ?? null; // Transformation du string de mot-clé en un array. $tagArray = !empty($tag) ? array_map('trim', explode(',', $tag)) : []; // Generate unique identifiers FIRST (before using them) $uniqueId = time() . "_" . rand(1000, 9999); $sanitizedAuteurice = Transliterator::transliterate($auteurice); $uniqueFileName = $sanitizedAuteurice . "_" . $date . "_" . $uniqueId; // Create necessary directories $memoireFolder = __DIR__ . "/data/content/{$annee}/{$auteurice}/"; $coverFolder = __DIR__ . "/data/cover/"; if (!file_exists($yamlFolder)) { mkdir($yamlFolder, 0755, true); } if (!file_exists($memoireFolder)) { mkdir($memoireFolder, 0755, true); } if (!file_exists($coverFolder)) { mkdir($coverFolder, 0755, true); } $targetDir = $memoireFolder; $uploadedFiles = []; $couverturePath = ""; // Define security constraints $allowedMimeTypes = ['image/jpeg', 'image/png', 'application/pdf', 'video/mp4', 'application/zip']; $allowedExtensions = ['jpg', 'jpeg', 'png', 'pdf', 'mp4', 'zip']; $maxFileSize = 50 * 1024 * 1024; // 50 MB // Process cover image first if ($couverture && isset($couverture["error"]) && $couverture["error"] === UPLOAD_ERR_OK) { // Security: validate MIME type $finfo = new finfo(FILEINFO_MIME_TYPE); $mimeType = $finfo->file($couverture["tmp_name"]); $fileExtension = strtolower(pathinfo($couverture["name"], PATHINFO_EXTENSION)); // Only allow image files for cover if (in_array($mimeType, ['image/jpeg', 'image/png']) && in_array($fileExtension, ['jpg', 'jpeg', 'png'])) { // Security: Generate random filename to prevent overwrites and path traversal $randomName = bin2hex(random_bytes(16)); $newCouvertureName = $randomName . "." . $fileExtension; $targetFile = $coverFolder . $newCouvertureName; if (move_uploaded_file($couverture["tmp_name"], $targetFile)) { chmod($targetFile, 0644); $couverturePath = "data/cover/" . $newCouvertureName; error_log("Cover image uploaded: " . $newCouvertureName); } else { error_log("Failed to move uploaded couverture file: " . $couverture["name"]); } } else { error_log("Invalid cover image type: " . $mimeType); } } // Process uploaded files if ($files && is_array($files["name"])) { for ($i = 0; $i < count($files["name"]); $i++) { // Skip if no file was uploaded for this slot if ($files["error"][$i] === UPLOAD_ERR_NO_FILE) { continue; } // Log the file being processed error_log("Processing file: " . $files["name"][$i]); // Check for file upload errors if ($files["error"][$i] !== UPLOAD_ERR_OK) { error_log("File upload error code " . $files["error"][$i] . ": " . $files["name"][$i]); continue; } // Check MIME type and file extension $finfo = new finfo(FILEINFO_MIME_TYPE); $mimeType = $finfo->file($files["tmp_name"][$i]); $fileExtension = strtolower(pathinfo($files["name"][$i], PATHINFO_EXTENSION)); if (!in_array($mimeType, $allowedMimeTypes) || !in_array($fileExtension, $allowedExtensions)) { error_log("Invalid file type or extension: " . $files["name"][$i] . " (MIME: $mimeType, Ext: $fileExtension)"); continue; } // Check file size if ($files["size"][$i] > $maxFileSize) { error_log("File is too large: " . $files["name"][$i] . " (" . $files["size"][$i] . " bytes)"); continue; } // Security: Generate random filename to prevent overwrites and path traversal $randomName = bin2hex(random_bytes(16)); $safeFileName = $randomName . "." . $fileExtension; $targetFile = $targetDir . $safeFileName; if (move_uploaded_file($files["tmp_name"][$i], $targetFile)) { // Log successful file move error_log("File successfully moved: " . $safeFileName); chmod($targetFile, 0644); $uploadedFiles[] = [ 'path' => "data/content/{$annee}/{$auteurice}/" . $safeFileName, 'original_name' => basename($files["name"][$i]), 'size' => $files["size"][$i] ]; } else { error_log("Failed to move uploaded file: " . $files["name"][$i]); } } } // Prepare form data for YAML $formData = [ 'auteurice' => $auteurice, 'année' => $annee, 'email' => $mail ?: '', 'titre' => $titre, 'tag' => $tagArray, 'promoteurice' => $promoteurice, 'problématique' => $problematique, 'description' => $description, // Fixed: was $resume 'orientation' => $orientation, 'ap' => $ap, 'lien' => $lien, 'couverture' => $couverturePath, 'files' => $uploadedFiles ]; // Convert form data to YAML $yamlData = Yaml::dump($formData); // Save YAML file $yamlFilePath = $yamlFolder . $uniqueFileName . ".yaml"; if (file_put_contents($yamlFilePath, $yamlData) === false) { throw new Exception("Erreur lors de l'écriture du fichier YAML."); } error_log("Form submission saved: " . $yamlFilePath); // Clear CSRF token after successful submission unset($_SESSION['csrf_token']); // Redirect to the thank you page header('Location: thanks.php?file=' . urlencode($yamlFilePath)); exit(); } catch (Exception $e) { error_log("Form processing error: " . $e->getMessage()); die("Erreur lors du traitement du formulaire : " . htmlspecialchars($e->getMessage()) . "

Retour au formulaire"); } ?>