Security: fix auth bypass, open redirects, cookie security, OAuth CSRF, and Sf() misuse

- Fix critical inverted authentication logic in tools.auth.php (password_verify was inverted)
- Fix broken Sf() misuse for username lookups (was always returning empty string)
- Add safe_username_to_filename() to tools.security.php for proper username handling
- Fix open redirect vulnerability in _login.php for all redirect targets
- Add HttpOnly, Secure, SameSite cookie flags to all setcookie() calls
- Add CSRF nonce to OAuth state parameter and verify it on callback
- Add session_regenerate_id(true) after successful login
- Remove redundant session_regenerate_id() from tools.session.php (was called on every request)
- Add authentication check to entreaulas/_filefetch.php
- Fix broken Sf() usage in entreaulas pages (aulario.php, comedor.php, diario.php, paneldiario.php, proyectos.php, api/comedor.php)
- Fix broken Sf() usage in sysadmin/users.php and sysadmin/reset_password.php

Co-authored-by: naielv <109038805+naielv@users.noreply.github.com>
This commit is contained in:
copilot-swe-agent[bot]
2026-02-21 18:55:06 +00:00
parent 35fa27b199
commit ffb6b6ce45
13 changed files with 171 additions and 89 deletions

View File

@@ -8,12 +8,17 @@ $ua = $_SERVER['HTTP_USER_AGENT'];
if (str_starts_with($ua, "Axia4Auth/")) {
$username = explode("/", $ua)[1];
$userpass = explode("/", $ua)[2];
$userdata = json_decode(file_get_contents("/DATA/Usuarios/" . Sf($username) . ".json"), true);
$user_filename = safe_username_to_filename($username);
if ($user_filename === "") {
header("HTTP/1.1 403 Forbidden");
die();
}
$userdata = json_decode(file_get_contents("/DATA/Usuarios/" . $user_filename . ".json"), true);
if (!$userdata) {
header("HTTP/1.1 403 Forbidden");
die();
}
if (password_verify($userpass, $userdata["password"])) {
if (!password_verify($userpass, $userdata["password_hash"])) {
header("HTTP/1.1 403 Forbidden");
die();
}
@@ -30,11 +35,14 @@ if ($_SESSION["auth_ok"] != true && isset($_COOKIE["auth_user"]) && isset($_COOK
$username = $_COOKIE["auth_user"];
$userpass_b64 = $_COOKIE["auth_pass_b64"];
$userpass = base64_decode($userpass_b64);
$userdata = json_decode(file_get_contents("/DATA/Usuarios/" . Sf($username) . ".json"), true);
if ($userdata && password_verify($userpass, $userdata["password_hash"])) {
$_SESSION["auth_user"] = $username;
$_SESSION["auth_data"] = $userdata;
$_SESSION["auth_ok"] = true;
$user_filename = safe_username_to_filename($username);
if ($user_filename !== "") {
$userdata = json_decode(file_get_contents("/DATA/Usuarios/" . $user_filename . ".json"), true);
if ($userdata && password_verify($userpass, $userdata["password_hash"])) {
$_SESSION["auth_user"] = $username;
$_SESSION["auth_data"] = $userdata;
$_SESSION["auth_ok"] = true;
}
}
}
@@ -42,8 +50,11 @@ if ($_SESSION["auth_ok"] != true && isset($_COOKIE["auth_user"]) && isset($_COOK
if (isset($_SESSION["auth_ok"]) && $_SESSION["auth_ok"] && isset($_SESSION["auth_user"])) {
if (isset($AuthConfig["session_load_mode"]) && $AuthConfig["session_load_mode"] === "force") {
$username = $_SESSION["auth_user"];
$userdata = json_decode(file_get_contents("/DATA/Usuarios/" . Sf($username) . ".json"), true);
$_SESSION["auth_data"] = $userdata;
$user_filename = safe_username_to_filename($username);
if ($user_filename !== "") {
$userdata = json_decode(file_get_contents("/DATA/Usuarios/" . $user_filename . ".json"), true);
$_SESSION["auth_data"] = $userdata;
}
$_SESSION["last_reload_time"] = time();
} elseif (isset($AuthConfig["session_load_mode"]) && $AuthConfig["session_load_mode"] === "never") {
// Do nothing, never reload session data
@@ -52,8 +63,11 @@ if (isset($_SESSION["auth_ok"]) && $_SESSION["auth_ok"] && isset($_SESSION["auth
$last_reload = $_SESSION["last_reload_time"];
if (time() - $last_reload > 300) {
$username = $_SESSION["auth_user"];
$userdata = json_decode(file_get_contents("/DATA/Usuarios/" . Sf($username) . ".json"), true);
$_SESSION["auth_data"] = $userdata;
$user_filename = safe_username_to_filename($username);
if ($user_filename !== "") {
$userdata = json_decode(file_get_contents("/DATA/Usuarios/" . $user_filename . ".json"), true);
$_SESSION["auth_data"] = $userdata;
}
$_SESSION["last_reload_time"] = time();
}
} else {

View File

@@ -58,6 +58,32 @@ function Si($input) {
return $input;
}
function safe_username_to_filename($username) {
/**
* Convert a username (plain username or email) to a safe filename for use in file operations.
*
* Email addresses have @ replaced with __ to match how Google OAuth users are stored.
* The result contains only alphanumeric characters, dots, underscores, and hyphens.
*
* @param string $username The username or email to convert.
* @return string The safe filename (without path or extension), or "" if invalid.
*/
$filename = strtolower((string)$username);
// Remove null bytes
$filename = str_replace("\0", "", $filename);
// Replace @ with __ (to match Google OAuth file naming)
$filename = str_replace("@", "__", $filename);
// Remove any path components to prevent directory traversal
$filename = basename($filename);
// Remove .. sequences
$filename = str_replace("..", "", $filename);
// Keep only alphanumeric, dot, underscore, hyphen
$filename = preg_replace("/[^a-zA-Z0-9._-]/", "_", $filename);
// Trim dots and underscores from ends
$filename = trim($filename, "._");
return $filename;
}
function Sb($input) {
/**
* Sanitize a boolean input by converting it to a boolean value.

View File

@@ -1,5 +1,4 @@
<?php
session_start([ 'cookie_lifetime' => 604800 ]);
session_regenerate_id();
ini_set("session.use_only_cookies", "true");
ini_set("session.use_trans_sid", "false");

View File

@@ -5,11 +5,30 @@ if (!isset($AuthConfig)) {
$AuthConfig = json_decode(file_get_contents("/DATA/AuthConfig.json"), true);
}
$DOMAIN = $_SERVER["HTTP_X_FORWARDED_HOST"] ?? $_SERVER["HTTP_HOST"];
/**
* Return a safe redirect URL: only allow relative paths starting with a single slash.
* Falls back to "/" for any external, protocol-relative, or otherwise unsafe URLs.
*/
function safe_redir($url) {
$url = (string)$url;
// Must start with a single "/" but not "//" (protocol-relative)
if (preg_match('#^/[^/]#', $url) || $url === '/') {
// Strip newlines to prevent header injection
return preg_replace('/[\r\n]/', '', $url);
}
return '/';
}
if ($_GET["reload_user"] == "1") {
$user = str_replace("@", "__", $_SESSION["auth_user"]);
$userdata = json_decode(file_get_contents("/DATA/Usuarios/" . Sf($user) . ".json"), true);
$user_filename = safe_username_to_filename($_SESSION["auth_user"] ?? "");
if ($user_filename === "") {
header("Location: /");
die();
}
$userdata = json_decode(file_get_contents("/DATA/Usuarios/" . $user_filename . ".json"), true);
$_SESSION['auth_data'] = $userdata;
$redir = $_GET["redir"] ?? "/";
$redir = safe_redir($_GET["redir"] ?? "/");
header("Location: $redir");
die();
}
@@ -21,6 +40,15 @@ if ($_GET["google_callback"] == "1") {
die("Error: No se recibió el código de autorización de Google.");
}
// Validate CSRF nonce from state parameter
$state_raw = $_GET["state"] ?? "";
$state = json_decode(base64_decode($state_raw), true);
$state_nonce = $state["nonce"] ?? "";
if (!$state_nonce || !isset($_SESSION["oauth_nonce"]) || !hash_equals($_SESSION["oauth_nonce"], $state_nonce)) {
die("Error: Estado OAuth inválido. Por favor, inténtalo de nuevo.");
}
unset($_SESSION["oauth_nonce"]);
$code = $_GET["code"];
// Intercambiar el código de autorización por un token de acceso
@@ -56,7 +84,11 @@ if ($_GET["google_callback"] == "1") {
$email = $user_info["email"];
$name = $user_info["name"] ?? explode("@", $email)[0];
$userfile = "/DATA/Usuarios/" . Sf(strtolower(str_replace("@", "__", $email))) . ".json";
$user_filename = safe_username_to_filename($email);
if ($user_filename === "") {
die("Error: Dirección de correo inválida.");
}
$userfile = "/DATA/Usuarios/" . $user_filename . ".json";
$password = bin2hex(random_bytes(16)); // Generar una contraseña aleatoria para el usuario, aunque no se usará para iniciar sesión
if (file_exists($userfile)) {
$userdata = json_decode(file_get_contents($userfile), true);
@@ -72,13 +104,15 @@ if ($_GET["google_callback"] == "1") {
file_put_contents($userfile, json_encode($userdata));
}
session_regenerate_id(true);
$_SESSION['auth_user'] = $email;
$_SESSION['auth_data'] = $userdata;
$_SESSION['auth_ok'] = true;
setcookie("auth_user", $email, time() + (86400 * 30), "/");
setcookie("auth_pass_b64", base64_encode($password), time() + (86400 * 30), "/");
$cookie_options = ["expires" => time() + (86400 * 30), "path" => "/", "httponly" => true, "secure" => true, "samesite" => "Lax"];
setcookie("auth_user", $email, $cookie_options);
setcookie("auth_pass_b64", base64_encode($password), $cookie_options);
$redir = json_decode(base64_decode($_GET["state"]), true)["redir"] ?? "/";
$redir = safe_redir($state["redir"] ?? "/");
header("Location: $redir");
die();
@@ -89,6 +123,10 @@ if ($_GET["google"] == "1") {
}
$url = "https://accounts.google.com/o/oauth2/auth";
// Generate a CSRF nonce and store it in the session
$oauth_nonce = bin2hex(random_bytes(16));
$_SESSION["oauth_nonce"] = $oauth_nonce;
// build the HTTP GET query
$params = array(
"response_type" => "code",
@@ -96,7 +134,8 @@ if ($_GET["google"] == "1") {
"redirect_uri" => "https://$DOMAIN/_login.php?google_callback=1",
"scope" => "email openid profile",
"state" => base64_encode(json_encode([
"redir" => $_GET["redir"] ?? "/"
"redir" => safe_redir($_GET["redir"] ?? "/"),
"nonce" => $oauth_nonce
]))
);
@@ -107,16 +146,17 @@ if ($_GET["google"] == "1") {
die();
}
if ($_GET["logout"] == "1") {
$redir = $_GET["redir"] ?? "/";
setcookie("auth_user", "", time() - 3600, "/");
setcookie("auth_pass_b64", "", time() - 3600, "/");
$redir = safe_redir($_GET["redir"] ?? "/");
$cookie_options_expired = ["expires" => time() - 3600, "path" => "/", "httponly" => true, "secure" => true, "samesite" => "Lax"];
setcookie("auth_user", "", $cookie_options_expired);
setcookie("auth_pass_b64", "", $cookie_options_expired);
session_destroy();
header("Location: $redir");
die();
}
if ($_GET["clear_session"] == "1") {
session_destroy();
$redir = $_GET["redir"] ?? "/";
$redir = safe_redir($_GET["redir"] ?? "/");
header("Location: $redir");
die();
}
@@ -124,19 +164,22 @@ if (isset($_POST["user"])) {
$valid = "";
$user = trim(strtolower($_POST["user"]));
$password = $_POST["password"];
$userdata = json_decode(file_get_contents("/DATA/Usuarios/" . Sf($user) . ".json"), true);
$user_filename = safe_username_to_filename($user);
$userdata = ($user_filename !== "") ? json_decode(@file_get_contents("/DATA/Usuarios/" . $user_filename . ".json"), true) : null;
if (!isset($userdata["password_hash"])) {
$_GET["_result"] = "El usuario no existe.";
}
$hash = $userdata["password_hash"];
if (password_verify($password, $hash)) {
$hash = $userdata["password_hash"] ?? null;
if ($hash && password_verify($password, $hash)) {
session_regenerate_id(true);
$_SESSION['auth_user'] = $user;
$_SESSION['auth_data'] = $userdata;
$_SESSION['auth_ok'] = true;
setcookie("auth_user", $user, time() + (86400 * 30), "/");
setcookie("auth_pass_b64", base64_encode($password), time() + (86400 * 30), "/");
$redir = $_GET["redir"] ?? "/";
$cookie_options = ["expires" => time() + (86400 * 30), "path" => "/", "httponly" => true, "secure" => true, "samesite" => "Lax"];
setcookie("auth_user", $user, $cookie_options);
setcookie("auth_pass_b64", base64_encode($password), $cookie_options);
$redir = safe_redir($_GET["redir"] ?? "/");
header("Location: $redir");
die();
} else {

View File

@@ -1,8 +1,11 @@
<?php
ini_set("display_errors", 0);
ini_set('memory_limit', '1G');
require_once __DIR__ . "/_incl/auth_redir.php";
ob_implicit_flush(true);
ob_end_flush();
ini_set('memory_limit', '1G');
header("Access-Control-Allow-Origin: *");
function safe_id_segment($value)

View File

@@ -52,7 +52,7 @@ if ($centro_id === "") {
}
$action = $_GET["action"] ?? ($_POST["action"] ?? "");
$aulario_id = safe_id_segment(Sf($_GET["aulario"] ?? $_POST["aulario"] ?? ""));
$aulario_id = safe_id_segment($_GET["aulario"] ?? $_POST["aulario"] ?? "");
// Validate aulario_id
if ($aulario_id === "") {

View File

@@ -24,7 +24,7 @@ function safe_aulario_config_path($centro_id, $aulario_id)
return "/DATA/entreaulas/Centros/$centro/Aularios/$aulario.json";
}
$aulario_id = safe_id_segment(Sf($_GET["id"] ?? ""));
$aulario_id = safe_id_segment($_GET["id"] ?? "");
$centro_id = safe_centro_id($_SESSION["auth_data"]["entreaulas"]["centro"] ?? "");
$aulario_path = safe_aulario_config_path($centro_id, $aulario_id);
$aulario = ($aulario_path && file_exists($aulario_path)) ? json_decode(file_get_contents($aulario_path), true) : null;

View File

@@ -26,7 +26,7 @@ function safe_aulario_config_path($centro_id, $aulario_id)
return "/DATA/entreaulas/Centros/$centro/Aularios/$aulario.json";
}
$aulario_id = safe_id_segment(Sf($_GET["aulario"] ?? ""));
$aulario_id = safe_id_segment($_GET["aulario"] ?? "");
$centro_id = safe_centro_id($_SESSION["auth_data"]["entreaulas"]["centro"] ?? "");
if ($aulario_id === "" || $centro_id === "") {

View File

@@ -28,9 +28,9 @@ function path_is_within($real_base, $real_path)
return strpos($real_path, $base_prefix) === 0 || $real_path === rtrim($real_base, DIRECTORY_SEPARATOR);
}
$aulario_id = safe_id_segment(Sf($_GET["aulario"] ?? ""));
$centro_id = safe_centro_id(Sf($_SESSION["auth_data"]["entreaulas"]["centro"] ?? ""));
$alumno = safe_id_segment(Sf($_GET["alumno"] ?? ""));
$aulario_id = safe_id_segment($_GET["aulario"] ?? "");
$centro_id = safe_centro_id($_SESSION["auth_data"]["entreaulas"]["centro"] ?? "");
$alumno = safe_id_segment($_GET["alumno"] ?? "");
if (empty($aulario_id) || empty($centro_id)) {
require_once "_incl/pre-body.php";
@@ -250,11 +250,10 @@ require_once "_incl/pre-body.php";
<?php
// Show specific diary entry if requested
$type = safe_id_segment(Sf($_GET["type"] ?? ""));
$date = Sf($_GET["date"] ?? date("Y-m-d"));
$type = safe_id_segment($_GET["type"] ?? "");
$date = preg_replace('/[^0-9-]/', '', $_GET["date"] ?? date("Y-m-d"));
if (!empty($type) && !empty($date)) {
$date = preg_replace('/[^0-9-]/', '', $date);
$is_valid_date = false;
if (preg_match('/^\d{4}-\d{2}-\d{2}$/', $date)) {
$date_obj = DateTime::createFromFormat('Y-m-d', $date);

View File

@@ -796,7 +796,7 @@ switch ($view_action) {
break;
case "menu":
// Menú del comedor (nuevo sistema, vista simplificada)
$aulario_id = safe_id_segment(Sf($_GET["aulario"] ?? ''));
$aulario_id = safe_id_segment($_GET["aulario"] ?? '');
$centro_id = safe_centro_id($_SESSION["auth_data"]["entreaulas"]["centro"] ?? "");
$source_aulario_id = $aulario_id;
@@ -805,7 +805,7 @@ switch ($view_action) {
$aulario_path = safe_aulario_config_path($centro_id, $aulario_id);
$aulario = ($aulario_path && file_exists($aulario_path)) ? json_decode(file_get_contents($aulario_path), true) : null;
if ($aulario && !empty($aulario["shared_comedor_from"])) {
$shared_from = safe_id_segment(Sf($aulario["shared_comedor_from"]));
$shared_from = safe_id_segment($aulario["shared_comedor_from"]);
$shared_aulario_path = safe_aulario_config_path($centro_id, $shared_from);
if ($shared_aulario_path && file_exists($shared_aulario_path)) {
$source_aulario_id = $shared_from;

View File

@@ -7,13 +7,11 @@ if (in_array("entreaulas:docente", $_SESSION["auth_data"]["permissions"] ?? [])
die("Access denied");
}
$aulario_id = Sf($_GET["aulario"] ?? "");
$centro_id = $_SESSION["auth_data"]["entreaulas"]["centro"] ?? "";
$aulario_id = safe_path_segment($_GET["aulario"] ?? "");
$centro_id = safe_path_segment($_SESSION["auth_data"]["entreaulas"]["centro"] ?? "");
// Sanitize and validate centro_id and aulario_id to prevent directory traversal
$centro_id = safe_filename($centro_id);
$aulario_id = safe_filename($aulario_id);
if ($aulario_id === "" || $centro_id === "" || strpos($centro_id, '..') !== false || strpos($aulario_id, '..') !== false) {
// Validate centro_id and aulario_id to prevent directory traversal
if ($aulario_id === "" || $centro_id === "") {
require_once "_incl/pre-body.php";
?>
<div class="card pad">
@@ -461,8 +459,8 @@ if ($_SERVER["REQUEST_METHOD"] === "POST") {
}
if ($action === "share_project") {
$project_id = Sf($_POST["project_id"] ?? "");
$target_aulario = safe_path_segment(Sf($_POST["target_aulario"] ?? ""));
$project_id = safe_path_segment($_POST["project_id"] ?? "");
$target_aulario = safe_path_segment($_POST["target_aulario"] ?? "");
if ($project_id !== "" && $target_aulario !== "" && $target_aulario !== $aulario_id) {
// Only allow sharing local projects
@@ -512,7 +510,7 @@ if ($_SERVER["REQUEST_METHOD"] === "POST") {
if (in_array("entreaulas:proyectos:delete", $_SESSION["auth_data"]["permissions"] ?? []) === false) {
$error = "No tienes permisos para borrar proyectos.";
} else {
$project_id = Sf($_POST["project_id"] ?? "");
$project_id = safe_path_segment($_POST["project_id"] ?? "");
if ($project_id !== "") {
$project = load_project($proyectos_dir, $project_id);
$project_dir = find_project_path($proyectos_dir, $project_id);
@@ -538,7 +536,7 @@ if ($_SERVER["REQUEST_METHOD"] === "POST") {
}
if ($action === "edit_project") {
$project_id = Sf($_POST["project_id"] ?? "");
$project_id = safe_path_segment($_POST["project_id"] ?? "");
$name = trim($_POST["name"] ?? "");
$description = sanitize_html($_POST["description"] ?? "");
@@ -559,15 +557,15 @@ if ($_SERVER["REQUEST_METHOD"] === "POST") {
}
if ($action === "add_item") {
$project_id = Sf($_POST["project_id"] ?? "");
$item_type = Sf($_POST["item_type"] ?? "link");
$item_name = trim(Sf($_POST["item_name"] ?? ""));
$item_url = trim(Sf($_POST["item_url"] ?? ""));
$item_content = sanitize_html(Sf($_POST["item_content"] ?? ""));
$videocall_platform = Sf($_POST["videocall_platform"] ?? "jitsi");
$videocall_room = trim(Sf($_POST["videocall_room"] ?? ""));
$videocall_url = trim(Sf($_POST["videocall_url"] ?? ""));
$source_aulario_param = Sf($_POST["source_aulario"] ?? "");
$project_id = safe_path_segment($_POST["project_id"] ?? "");
$item_type = safe_path_segment($_POST["item_type"] ?? "link");
$item_name = trim($_POST["item_name"] ?? "");
$item_url = trim($_POST["item_url"] ?? "");
$item_content = sanitize_html($_POST["item_content"] ?? "");
$videocall_platform = safe_path_segment($_POST["videocall_platform"] ?? "jitsi");
$videocall_room = trim($_POST["videocall_room"] ?? "");
$videocall_url = trim($_POST["videocall_url"] ?? "");
$source_aulario_param = safe_path_segment($_POST["source_aulario"] ?? "");
// Determine which directory to use and permission level
$working_dir = $proyectos_dir;
@@ -579,10 +577,10 @@ if ($_SERVER["REQUEST_METHOD"] === "POST") {
// Validate the link
$linked_projects = $aulario["linked_projects"] ?? [];
foreach ($linked_projects as $link) {
if ((Sf($link["source_aulario"] ?? "") === $source_aulario_param) &&
(Sf($link["project_id"] ?? "") === $project_id)
if ((($link["source_aulario"] ?? "") === $source_aulario_param) &&
(($link["project_id"] ?? "") === $project_id)
) {
$permission = Sf($link["permission"] ?? "read_only");
$permission = safe_path_segment($link["permission"] ?? "read_only");
if ($permission === "full_edit") {
$working_dir = $proyectos_dir;
} elseif ($permission === "request_edit") {
@@ -777,8 +775,8 @@ if ($_SERVER["REQUEST_METHOD"] === "POST") {
}
if ($action === "approve_change" || $action === "reject_change") {
$change_id = safe_filename(Sf($_POST["change_id"] ?? ""));
$project_id = Sf($_POST["project_id"] ?? "");
$change_id = safe_filename($_POST["change_id"] ?? "");
$project_id = safe_path_segment($_POST["project_id"] ?? "");
if (!empty($change_id) && !empty($project_id)) {
$project_dir = find_project_path($proyectos_dir, $project_id);
@@ -841,7 +839,7 @@ if ($_SERVER["REQUEST_METHOD"] === "POST") {
}
if (in_array(($item["type"] ?? ""), ["file", "pdf_secure"], true) && !empty($change_data["pending_filename"])) {
$pending_filename = safe_filename(Sf($change_data["pending_filename"]));
$pending_filename = safe_filename($change_data["pending_filename"]);
$pending_file = safe_join_file($pending_dir, $pending_filename);
$target_file = safe_join_file($project_dir, $pending_filename);
if ($pending_file && $target_file && file_exists($pending_file)) {
@@ -850,7 +848,7 @@ if ($_SERVER["REQUEST_METHOD"] === "POST") {
}
rename($pending_file, $target_file);
if (!empty($item["filename"])) {
$old_path = safe_join_file($project_dir, Sf($item["filename"]));
$old_path = safe_join_file($project_dir, $item["filename"]);
if ($old_path && file_exists($old_path)) {
unlink($old_path);
if (file_exists($old_path . ".eadat")) {
@@ -859,7 +857,7 @@ if ($_SERVER["REQUEST_METHOD"] === "POST") {
}
}
$item["filename"] = $pending_filename;
$item["original_name"] = Sf($change_data["original_filename"] ?? $pending_filename);
$item["original_name"] = safe_filename($change_data["original_filename"] ?? $pending_filename);
$file_meta = [
"id" => $item_id,
@@ -907,7 +905,7 @@ if ($_SERVER["REQUEST_METHOD"] === "POST") {
$item["room"] = $change_data["item_room"] ?? "";
} elseif (in_array($change_data["item_type"], ["file", "pdf_secure"], true) && !empty($change_data["pending_filename"])) {
// Move file from pending to project directory
$pending_filename = safe_filename(Sf($change_data["pending_filename"]));
$pending_filename = safe_filename($change_data["pending_filename"]);
$pending_file = safe_join_file($pending_dir, $pending_filename);
$target_file = safe_join_file($project_dir, $pending_filename);
@@ -917,12 +915,12 @@ if ($_SERVER["REQUEST_METHOD"] === "POST") {
}
rename($pending_file, $target_file);
$item["filename"] = $pending_filename;
$item["original_name"] = Sf($change_data["original_filename"] ?? $pending_filename);
$item["original_name"] = safe_filename($change_data["original_filename"] ?? $pending_filename);
$file_meta = [
"id" => $item_id,
"name" => Sf($change_data["item_name"]),
"type" => Sf($change_data["item_type"]),
"name" => $change_data["item_name"],
"type" => $change_data["item_type"],
"original_name" => $item["original_name"],
"created_at" => $item["created_at"]
];
@@ -943,7 +941,7 @@ if ($_SERVER["REQUEST_METHOD"] === "POST") {
} else {
// Reject - just delete pending file if exists
if (!empty($change_data["pending_filename"])) {
$pending_file = safe_join_file($pending_dir, Sf($change_data["pending_filename"]));
$pending_file = safe_join_file($pending_dir, safe_filename($change_data["pending_filename"]));
if ($pending_file && file_exists($pending_file)) {
unlink($pending_file);
}
@@ -960,9 +958,9 @@ if ($_SERVER["REQUEST_METHOD"] === "POST") {
}
if ($action === "delete_item") {
$project_id = Sf($_POST["project_id"] ?? "");
$item_id = Sf($_POST["item_id"] ?? "");
$source_aulario_param = Sf($_POST["source_aulario"] ?? "");
$project_id = safe_path_segment($_POST["project_id"] ?? "");
$item_id = safe_path_segment($_POST["item_id"] ?? "");
$source_aulario_param = safe_path_segment($_POST["source_aulario"] ?? "");
// Determine which directory to use based on whether this is a linked project
$working_dir = $proyectos_dir;
@@ -1069,15 +1067,15 @@ if ($_SERVER["REQUEST_METHOD"] === "POST") {
}
if ($action === "edit_item") {
$project_id = Sf($_POST["project_id"] ?? "");
$item_id = Sf($_POST["item_id"] ?? "");
$item_name = Sf(trim($_POST["item_name"] ?? ""));
$item_url = Sf(trim($_POST["item_url"] ?? ""));
$item_content = Sf(sanitize_html($_POST["item_content"] ?? ""));
$videocall_platform = Sf($_POST["edit_videocall_platform"] ?? "jitsi");
$videocall_room = Sf(trim($_POST["edit_videocall_room"] ?? ""));
$videocall_url = Sf(trim($_POST["edit_videocall_url"] ?? ""));
$source_aulario_param = Sf($_POST["source_aulario"] ?? "");
$project_id = safe_path_segment($_POST["project_id"] ?? "");
$item_id = safe_path_segment($_POST["item_id"] ?? "");
$item_name = trim($_POST["item_name"] ?? "");
$item_url = trim($_POST["item_url"] ?? "");
$item_content = sanitize_html($_POST["item_content"] ?? "");
$videocall_platform = safe_path_segment($_POST["edit_videocall_platform"] ?? "jitsi");
$videocall_room = trim($_POST["edit_videocall_room"] ?? "");
$videocall_url = trim($_POST["edit_videocall_url"] ?? "");
$source_aulario_param = safe_path_segment($_POST["source_aulario"] ?? "");
$working_dir = $proyectos_dir;
$permission = "full_edit";

View File

@@ -14,7 +14,7 @@ function safe_username($value)
switch ($_GET['form'] ?? '') {
case 'save_password':
$username = safe_username(Sf($_POST['username'] ?? ''));
$username = safe_username($_POST['username'] ?? '');
$new_password = $_POST['new_password'] ?? '';
$confirm_password = $_POST['confirm_password'] ?? '';

View File

@@ -32,7 +32,7 @@ function safe_aulario_id($value)
switch ($_GET['form'] ?? '') {
case 'save_edit':
$username = safe_username(Sf($_POST['username'] ?? ''));
$username = safe_username($_POST['username'] ?? '');
if (empty($username)) {
die("Nombre de usuario no proporcionado.");
}
@@ -175,7 +175,7 @@ switch ($_GET['action'] ?? '') {
break;
case 'edit':
require_once "_incl/pre-body.php";
$username = safe_username(Sf($_GET['user'] ?? ''));
$username = safe_username($_GET['user'] ?? '');
if (empty($username)) {
die("Nombre de usuario inválido.");
}