Server : Apache System : Linux profile 3.10.0-1160.88.1.el7.x86_64 #1 SMP Tue Mar 7 15:41:52 UTC 2023 x86_64 User : apache ( 48) PHP Version : 8.0.28 Disable Function : NONE Directory : /var/www/html/pragyabhardwaj/admin/ |
<?php
// 🔥 Session initialize karna zaroori hai CSRF security tokens ke liye
if (session_status() === PHP_SESSION_NONE) {
session_start();
}
include 'db.php';
$upload_path = "static/upload/";
$msg = "";
// 🛡️ Cryptographically secure CSRF token check aur generation
if (empty($_SESSION['csrf_token'])) {
$_SESSION['csrf_token'] = bin2hex(random_bytes(32));
}
/* ================= SECURE FILE UPLOAD VALIDATOR ================= */
function secureUpload($file_field, $allowed_exts, $allowed_mimes, $prefix, $id, $upload_path) {
if (empty($_FILES[$file_field]['name'])) return null;
$filename = $_FILES[$file_field]['name'];
$tmp_name = $_FILES[$file_field]['tmp_name'];
// 1. Strict File Extension Whitelisting
$ext = strtolower(pathinfo($filename, PATHINFO_EXTENSION));
if (!in_array($ext, $allowed_exts)) {
return ['error' => "❌ Invalid file type! Allowed extensions: " . implode(', ', $allowed_exts)];
}
// 2. Binary MIME-Type Verification (Stops PHP backdoors renamed as .jpg/.png)
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$mime = finfo_file($finfo, $tmp_name);
finfo_close($finfo);
if (!in_array($mime, $allowed_mimes)) {
return ['error' => "❌ Malicious file structure detected! Upload rejected."];
}
// 3. Random filename to prevent scanning and overwrite attacks
$new_name = $prefix . "_" . $id . "_" . bin2hex(random_bytes(4)) . "." . $ext;
if (move_uploaded_file($tmp_name, $upload_path . $new_name)) {
return ['success' => $new_name];
}
return ['error' => "❌ Critical Error: Failed to save uploaded file."];
}
/* ================= POST ACTION: DELETE ================= */
if (isset($_POST['action_delete'])) {
if (!isset($_POST['csrf_token']) || $_POST['csrf_token'] !== $_SESSION['csrf_token']) {
die("❌ Security Violation: CSRF verification failed!");
}
$id = intval($_POST['id']);
// Prepared Statement used to fetch image filename safely
$stmt = $conn->prepare("SELECT image FROM education WHERE id = ?");
$stmt->bind_param("i", $id);
$stmt->execute();
$data = $stmt->get_result()->fetch_assoc();
$stmt->close();
if ($data && $data['image']) {
$file = $upload_path . $data['image'];
if (file_exists($file)) unlink($file);
}
// Secure DELETE execute
$stmt = $conn->prepare("DELETE FROM education WHERE id = ?");
$stmt->bind_param("i", $id);
$stmt->execute();
$stmt->close();
header("Location: index.php?page=education_form");
exit;
}
/* ================= POST ACTION: REMOVE IMAGE ================= */
if (isset($_POST['action_remove_image'])) {
if (!isset($_POST['csrf_token']) || $_POST['csrf_token'] !== $_SESSION['csrf_token']) {
die("❌ Security Violation: CSRF verification failed!");
}
$id = intval($_POST['id']);
$stmt = $conn->prepare("SELECT image FROM education WHERE id = ?");
$stmt->bind_param("i", $id);
$stmt->execute();
$data = $stmt->get_result()->fetch_assoc();
$stmt->close();
if ($data && $data['image']) {
$file = $upload_path . $data['image'];
if (file_exists($file)) unlink($file);
$stmt = $conn->prepare("UPDATE education SET image='' WHERE id = ?");
$stmt->bind_param("i", $id);
$stmt->execute();
$stmt->close();
}
header("Location: index.php?page=education_form");
exit;
}
/* ================= POST ACTION: UPDATE ================= */
if (isset($_POST['update'])) {
if (!isset($_POST['csrf_token']) || $_POST['csrf_token'] !== $_SESSION['csrf_token']) {
die("❌ Security Violation: CSRF verification failed!");
}
$id = intval($_POST['id']);
$title = trim($_POST['title']);
$inst = trim($_POST['institute']);
$year = trim($_POST['year']);
$details = trim($_POST['details']);
$image = $_POST['old_image'];
$img_exts = ['jpg', 'jpeg', 'png', 'gif'];
$img_mimes = ['image/jpeg', 'image/png', 'image/gif'];
if (!empty($_FILES['new_image']['name'])) {
$upload_res = secureUpload('new_image', $img_exts, $img_mimes, 'education_img', $id, $upload_path);
if (isset($upload_res['error'])) {
die($upload_res['error']);
} else {
if ($image && file_exists($upload_path . $image)) unlink($upload_path . $image);
$image = $upload_res['success'];
}
}
// SQL Injection safe Prepared Statement updates
$stmt = $conn->prepare("UPDATE education SET title=?, institute=?, year=?, details=?, image=? WHERE id=?");
$stmt->bind_param("sssssi", $title, $inst, $year, $details, $image, $id);
$stmt->execute();
$stmt->close();
header("Location: index.php?page=education_form");
exit;
}
/* ================= POST ACTION: INSERT ================= */
if (isset($_POST['save'])) {
if (!isset($_POST['csrf_token']) || $_POST['csrf_token'] !== $_SESSION['csrf_token']) {
die("❌ Security Violation: CSRF verification failed!");
}
$title = trim($_POST['title']);
$inst = trim($_POST['institute']);
$year = trim($_POST['year']);
$details = trim($_POST['details']);
// First, safe data record insert
$stmt = $conn->prepare("INSERT INTO education (title, institute, year, details, image, sort_order) VALUES (?, ?, ?, ?, '', 0)");
$stmt->bind_param("ssss", $title, $inst, $year, $details);
$stmt->execute();
$last_id = $stmt->insert_id;
$stmt->close();
$img_exts = ['jpg', 'jpeg', 'png', 'gif'];
$img_mimes = ['image/jpeg', 'image/png', 'image/gif'];
if (!empty($_FILES['image']['name'])) {
$upload_res = secureUpload('image', $img_exts, $img_mimes, 'education_img', $last_id, $upload_path);
if (isset($upload_res['error'])) {
$msg = $upload_res['error'];
} else {
$image = $upload_res['success'];
$stmt = $conn->prepare("UPDATE education SET image=? WHERE id=?");
$stmt->bind_param("si", $image, $last_id);
$stmt->execute();
$stmt->close();
}
}
if (empty($msg)) {
header("Location: index.php?page=education_form");
exit;
}
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Education Form</title>
<link href="https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500;600&display=swap" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" href="static/css/admin.css">
</head>
<body>
<?php include 'admin/topbar.php'; ?>
<div class="container mt-4">
<div class="box p-4 bg-light border rounded">
<h2>🎓 Add Education</h2>
<?php if(!empty($msg)) echo "<div class='alert alert-danger'>".htmlspecialchars($msg, ENT_QUOTES, 'UTF-8')."</div>"; ?>
<!-- INSERT FORM -->
<form method="POST" enctype="multipart/form-data">
<!-- CSRF Shield -->
<input type="hidden" name="csrf_token" value="<?= htmlspecialchars($_SESSION['csrf_token'], ENT_QUOTES, 'UTF-8'); ?>">
<div class="row">
<div class="col-md-2 mb-3">
<label>Image (Optional)</label>
<input type="file" name="image" class="form-control">
</div>
<div class="col-md-2 mb-3">
<label>Year</label>
<input type="text" name="year" class="form-control" placeholder="Year">
</div>
<div class="col-md-3 mb-3">
<label>Degree</label>
<input type="text" name="title" class="form-control" placeholder="Degree">
</div>
<div class="col-md-3 mb-3">
<label>Institute</label>
<input type="text" name="institute" class="form-control" placeholder="Institute">
</div>
<div class="col-md-2 mb-3 align-self-end">
<button name="save" class="btn btn-primary w-100">Save</button>
</div>
<div class="col-12 mb-3">
<label>Details</label>
<textarea name="details" class="form-control" placeholder="Details..." rows="3"></textarea>
</div>
</div>
</form>
<hr>
<h3 class="mt-4">📋 All Records (Inline Edit & Drag Order)</h3>
<div class="table-responsive">
<table class="table table-bordered table-hover align-middle">
<thead class="table-dark">
<tr>
<th>ID</th>
<th>Image</th>
<th>Degree</th>
<th>Institute</th>
<th>Year</th>
<th>Details</th>
<th>Action</th>
</tr>
</thead>
<tbody>
<?php
$result = mysqli_query($conn, "SELECT * FROM education ORDER BY sort_order ASC, id DESC");
while($row = mysqli_fetch_assoc($result)) {
?>
<tr class="drag-row" draggable="true" data-id="<?= $row['id'] ?>">
<form method="POST" enctype="multipart/form-data">
<!-- Entity Data protection tokens -->
<input type="hidden" name="csrf_token" value="<?= htmlspecialchars($_SESSION['csrf_token'], ENT_QUOTES, 'UTF-8'); ?>">
<input type="hidden" name="id" value="<?= $row['id'] ?>">
<td><?= $row['id'] ?></td>
<td>
<?php if($row['image']) { ?>
<img src="<?= htmlspecialchars($upload_path . $row['image'], ENT_QUOTES, 'UTF-8') ?>" class="preview img-thumbnail mb-1" style="max-width: 80px;"><br>
<?php } ?>
<input type="file" name="new_image" class="form-control form-control-sm mb-1">
<input type="hidden" name="old_image" value="<?= htmlspecialchars($row['image'], ENT_QUOTES, 'UTF-8') ?>">
<?php if($row['image']) { ?>
<button type="submit" name="action_remove_image" class="btn btn-warning btn-sm w-100">Remove</button>
<?php } ?>
</td>
<td><input type="text" name="title" class="form-control" value="<?= htmlspecialchars($row['title'], ENT_QUOTES, 'UTF-8') ?>"></td>
<td><input type="text" name="institute" class="form-control" value="<?= htmlspecialchars($row['institute'], ENT_QUOTES, 'UTF-8') ?>"></td>
<td><input type="text" name="year" class="form-control" value="<?= htmlspecialchars($row['year'], ENT_QUOTES, 'UTF-8') ?>"></td>
<td><textarea name="details" class="form-control" rows="2"><?= htmlspecialchars($row['details'], ENT_QUOTES, 'UTF-8') ?></textarea></td>
<td>
<button type="submit" name="update" class="btn btn-success btn-sm w-100 mb-1">Update</button>
<button type="submit" name="action_delete" class="btn btn-danger btn-sm w-100" onclick="return confirm('Do you really want to delete this education record?');">Delete</button>
</td>
</form>
</tr>
<?php } ?>
</tbody>
</table>
</div>
</div>
</div>
<script>
let dragged = null;
const csrfToken = "<?= $_SESSION['csrf_token']; ?>";
document.querySelectorAll(".drag-row").forEach(row => {
row.addEventListener("dragstart", function () {
dragged = this;
this.style.opacity = "0.5";
});
row.addEventListener("dragend", function () {
this.style.opacity = "1";
});
row.addEventListener("dragover", function (e) {
e.preventDefault();
});
row.addEventListener("drop", function (e) {
e.preventDefault();
if (dragged !== this) {
this.parentNode.insertBefore(dragged, this);
saveOrder();
}
});
});
function saveOrder() {
let order_data = [];
document.querySelectorAll(".drag-row").forEach((row, index) => {
order_data.push({
id: row.getAttribute("data-id"),
position: index + 1
});
});
console.log("SENDING ORDER:", order_data);
// CSRF and JSON payload transmission integration
fetch("update_order.php", {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-CSRF-Token": csrfToken
},
body: JSON.stringify({
order: order_data,
csrf_token: csrfToken
})
})
.then(res => res.text())
.then(res => {
console.log("SERVER RESPONSE:", res);
})
.catch(err => console.error("ERROR:", err));
}
</script>
</body>
</html>