diff --git a/public_html/_incl/tools.security.php b/public_html/_incl/tools.security.php
index bb6ffcc..b7cfa5e 100644
--- a/public_html/_incl/tools.security.php
+++ b/public_html/_incl/tools.security.php
@@ -140,9 +140,62 @@ function safe_aulario_id($value)
function safe_filename($name)
{
+ // Normalize to base name to avoid directory traversal
$name = basename((string)$name);
+
+ // Best-effort normalize encoding to avoid odd Unicode tricks
+ if (function_exists('mb_convert_encoding')) {
+ $name = mb_convert_encoding($name, 'UTF-8', 'UTF-8');
+ }
+
+ // Replace disallowed characters with underscore
$name = preg_replace('/[^A-Za-z0-9._-]/', '_', $name);
+ // Collapse multiple underscores introduced by replacement
+ $name = preg_replace('/_+/', '_', $name);
+
+ // Remove leading dots to avoid hidden/special files like ".htaccess"
$name = ltrim($name, '.');
+
+ // Ensure there is at most one dot in the filename to prevent extension confusion
+ if (substr_count($name, '.') > 1) {
+ $parts = explode('.', $name);
+ $ext = array_pop($parts);
+ $base = implode('_', $parts);
+ // Ensure extension is not empty
+ if ($ext === '') {
+ $name = $base === '' ? 'file' : $base;
+ } else {
+ $name = ($base === '' ? 'file' : $base) . '.' . $ext;
+ }
+ }
+
+ // Trim stray dots/underscores from the start and end
+ $name = trim($name, "._");
+
+ // Enforce a maximum length (common filesystem limit is 255 bytes)
+ $maxLen = 255;
+ if (strlen($name) > $maxLen) {
+ $dotPos = strrpos($name, '.');
+ if ($dotPos !== false) {
+ $ext = substr($name, $dotPos);
+ $base = substr($name, 0, $dotPos);
+ $baseMaxLen = $maxLen - strlen($ext);
+ if ($baseMaxLen < 1) {
+ // Fallback if extension is unusually long
+ $name = substr($name, 0, $maxLen);
+ } else {
+ $name = substr($base, 0, $baseMaxLen) . $ext;
+ }
+ } else {
+ $name = substr($name, 0, $maxLen);
+ }
+ }
+
+ // Ensure we never return an empty or invalid filename
+ if ($name === '' || $name === '.' || $name === '..') {
+ $name = 'file';
+ }
+
return $name;
}
function safe_id_segment($value)
diff --git a/public_html/aulatek/api/comedor.php b/public_html/aulatek/api/comedor.php
index 7a50caa..f95a87d 100644
--- a/public_html/aulatek/api/comedor.php
+++ b/public_html/aulatek/api/comedor.php
@@ -1,7 +1,7 @@
1) {
- $parts = explode('.', $name);
- $ext = array_pop($parts);
- $base = implode('_', $parts);
- // Ensure extension is not empty
- if ($ext === '') {
- $name = $base === '' ? 'file' : $base;
- } else {
- $name = ($base === '' ? 'file' : $base) . '.' . $ext;
- }
- }
-
- // Trim stray dots/underscores from the start and end
- $name = trim($name, "._");
-
- // Enforce a maximum length (common filesystem limit is 255 bytes)
- $maxLen = 255;
- if (strlen($name) > $maxLen) {
- $dotPos = strrpos($name, '.');
- if ($dotPos !== false) {
- $ext = substr($name, $dotPos);
- $base = substr($name, 0, $dotPos);
- $baseMaxLen = $maxLen - strlen($ext);
- if ($baseMaxLen < 1) {
- // Fallback if extension is unusually long
- $name = substr($name, 0, $maxLen);
- } else {
- $name = substr($base, 0, $baseMaxLen) . $ext;
- }
- } else {
- $name = substr($name, 0, $maxLen);
- }
- }
-
- // Ensure we never return an empty or invalid filename
- if ($name === '' || $name === '.' || $name === '..') {
- $name = 'file';
- }
-
- return $name;
-}
-
function handle_image_upload($fieldName, $targetBaseName, $baseDir, &$uploadErrors)
{
if (!isset($_FILES[$fieldName]) || $_FILES[$fieldName]["error"] !== UPLOAD_ERR_OK) {
diff --git a/public_html/aulatek/proyectos.php b/public_html/aulatek/proyectos.php
index c4599e9..b0721f7 100644
--- a/public_html/aulatek/proyectos.php
+++ b/public_html/aulatek/proyectos.php
@@ -34,29 +34,6 @@ if (!is_dir($proyectos_dir)) {
}
// Helper functions
-function safe_filename($name)
-{
- // Normalize to base name to avoid directory traversal
- $name = basename($name);
- // Replace disallowed characters with underscore
- $name = preg_replace("/[^a-zA-Z0-9._-]/", "_", $name);
- // Remove leading dots to avoid hidden/special files like ".htaccess"
- $name = ltrim($name, '.');
- // Ensure there is at most one dot in the filename to prevent extension confusion
- if (substr_count($name, '.') > 1) {
- $parts = explode('.', $name);
- $ext = array_pop($parts);
- $base = implode('_', $parts);
- // Ensure extension is not empty
- if ($ext === '') {
- $name = $base === '' ? 'file' : $base;
- } else {
- $name = ($base === '' ? 'file' : $base) . '.' . $ext;
- }
- }
- return $name;
-}
-
function safe_path_segment($value)
{
$value = basename((string)$value);