Skip to content

Commit e0ae607

Browse files
authored
Updates
1 parent fd988d5 commit e0ae607

11 files changed

Lines changed: 110 additions & 34 deletions

File tree

.github/ci-config/enginescript-variables-ci.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ SSE_PLUGIN_VER="1.9.1"
2424
SWPO_PLUGIN_VER="1.8.0"
2525

2626
# Frontend Dependencies
27-
CHARTJS_VER="4.5.1"
2827
FONTAWESOME_VER="7.0.1"
2928
TINYFILEMANAGER_VER="2.6"
3029

.github/workflows/software-version-check.yml

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -283,19 +283,6 @@ jobs:
283283
fi
284284
fi
285285
286-
# Chart.js
287-
echo "::debug::Fetching Chart.js version..."
288-
CHARTJS_API_RESPONSE=$(curl -s https://api.github.com/repos/chartjs/Chart.js/releases/latest)
289-
echo "::debug::Chart.js API Response: $CHARTJS_API_RESPONSE"
290-
291-
LATEST_CHARTJS=$(echo "$CHARTJS_API_RESPONSE" | jq -r '.tag_name // empty' | sed 's/v//')
292-
echo "::debug::Parsed Chart.js version: '$LATEST_CHARTJS'"
293-
294-
if [[ -n "$LATEST_CHARTJS" && "$LATEST_CHARTJS" != "null" ]]; then
295-
check_version "CHARTJS_VER" "$LATEST_CHARTJS"
296-
else
297-
echo "::warning::Failed to fetch Chart.js version, keeping current version"
298-
fi
299286
300287
# Font Awesome (restricted to 7.0.x releases)
301288
echo "::debug::Fetching Font Awesome 7.0.x version..."
@@ -362,7 +349,6 @@ jobs:
362349
-e "s#^(\\|MARIADB\\|)[^|]*#\1$(get_current_version MARIADB_VER)#" \
363350
-e "s#^(\\|PLUGIN: EngineScript: Simple Site Exporter\\|)[^|]*#\1$(get_current_version SSE_PLUGIN_VER)#" \
364351
-e "s#^(\\|PLUGIN: EngineScript: Simple WP Optimizer\\|)[^|]*#\1$(get_current_version SWPO_PLUGIN_VER)#" \
365-
-e "s#^(\\|Chart\\.js\\|)[^|]*#\1$(get_current_version CHARTJS_VER)#" \
366352
-e "s#^(\\|Font Awesome\\|)[^|]*#\1$(get_current_version FONTAWESOME_VER)#" \
367353
-e "s#^(\\|TinyFileManager\\|)[^|]*#\1$(get_current_version TINYFILEMANAGER_VER)#" \
368354
README.md

config/var/www/admin/control-panel/api.php

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -309,16 +309,15 @@ function sanitizeOutput($data) {
309309
}
310310

311311
function logSecurityEvent($event, $details = '') { // codacy:ignore - Direct $_SERVER access required for security logging in standalone API
312-
// Sanitize all log inputs to prevent log injection attacks
313-
$safe_event = preg_replace('/[\r\n\t]/', ' ', $event);
314-
$safe_event = substr(trim($safe_event), 0, 255); // Limit length
312+
// Enhanced log injection protection
313+
// Sanitize all log inputs to prevent log injection/forging attacks
314+
$safe_event = sanitizeLogInput($event);
315315

316316
$log_entry = date('Y-m-d H:i:s') . " [SECURITY] " . $safe_event;
317317

318318
if ($details) {
319-
// Sanitize details to prevent log injection
320-
$safe_details = preg_replace('/[\r\n\t]/', ' ', $details);
321-
$safe_details = substr(trim($safe_details), 0, 255); // Limit length
319+
// Sanitize details using same function
320+
$safe_details = sanitizeLogInput($details);
322321
$log_entry .= " - " . $safe_details;
323322
}
324323

@@ -337,6 +336,28 @@ function logSecurityEvent($event, $details = '') { // codacy:ignore - Direct $_S
337336
error_log($log_entry, 3, $log_file);
338337
}
339338

339+
/**
340+
* Sanitize input for safe log output
341+
* Prevents log injection attacks by escaping control characters
342+
* @param string $input Raw input to sanitize
343+
* @return string Sanitized string safe for logging
344+
*/
345+
function sanitizeLogInput($input) {
346+
// Remove all control characters (ASCII 0-31 and 127)
347+
// This includes \r, \n, \t, and other dangerous characters
348+
$sanitized = preg_replace('/[\x00-\x1F\x7F]/', ' ', $input);
349+
350+
// Collapse multiple spaces
351+
$sanitized = preg_replace('/\s+/', ' ', $sanitized);
352+
353+
// Limit length to prevent log flooding
354+
$sanitized = substr(trim($sanitized), 0, 255);
355+
356+
// Encode any remaining special characters for safe output
357+
// This prevents log format string attacks
358+
return addcslashes($sanitized, '\\');
359+
}
360+
340361
// Path was already extracted and validated above, validate again for security
341362
if (strlen($path) > 100 || !preg_match('/^\/[a-zA-Z0-9\/_-]*$/', $path)) {
342363
http_response_code(400);

config/var/www/admin/control-panel/dashboard.css

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
--accent-hover: #00c49a;
1515
--text-primary: #fff;
1616
--text-secondary: #b3b3b3;
17-
--text-muted: #808080;
17+
--text-muted: #9a9a9a;
1818
--border-color: #444;
1919
--success-color: #00d4aa;
2020
--warning-color: #ffb800;

config/var/www/admin/control-panel/dashboard.js

Lines changed: 66 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33

44
import { DashboardAPI } from './modules/api.js?v=2025.11.21.09';
55
import { DashboardState } from './modules/state.js?v=2025.11.21.09';
6-
import { DashboardCharts } from './modules/charts.js?v=2025.11.21.09';
76
import { DashboardUtils } from './modules/utils.js?v=2025.11.21.09';
87
// External services loaded dynamically when needed (lazy loading)
98

@@ -12,7 +11,6 @@ class EngineScriptDashboard {
1211
// Initialize modules
1312
this.api = new DashboardAPI();
1413
this.state = new DashboardState();
15-
this.charts = new DashboardCharts();
1614
this.utils = new DashboardUtils();
1715
this.externalServices = null; // Lazy loaded when needed
1816

@@ -212,15 +210,81 @@ class EngineScriptDashboard {
212210
toggleMobileMenu() {
213211
const sidebar = document.querySelector(".sidebar");
214212
if (sidebar) {
213+
const isOpening = !sidebar.classList.contains("mobile-open");
215214
sidebar.classList.toggle("mobile-open");
215+
216+
// Manage focus when menu opens/closes
217+
if (isOpening) {
218+
this.setupMobileFocusTrap(sidebar);
219+
} else {
220+
this.removeMobileFocusTrap();
221+
// Return focus to toggle button
222+
const mobileToggle = document.getElementById("mobile-menu-toggle");
223+
if (mobileToggle) mobileToggle.focus();
224+
}
216225
}
217226
}
218227

219228
closeMobileMenu() {
220229
const sidebar = document.querySelector(".sidebar");
221230
if (sidebar) {
222231
sidebar.classList.remove("mobile-open");
232+
this.removeMobileFocusTrap();
233+
// Return focus to toggle button
234+
const mobileToggle = document.getElementById("mobile-menu-toggle");
235+
if (mobileToggle) mobileToggle.focus();
236+
}
237+
}
238+
239+
/**
240+
* Set up focus trap for mobile menu accessibility
241+
* Prevents focus from escaping the menu overlay when open
242+
*/
243+
setupMobileFocusTrap(sidebar) {
244+
// Get all focusable elements in sidebar
245+
const focusableSelector = 'a[href], button, [tabindex]:not([tabindex="-1"])';
246+
const focusableElements = sidebar.querySelectorAll(focusableSelector);
247+
248+
if (focusableElements.length === 0) return;
249+
250+
this.firstFocusable = focusableElements[0];
251+
this.lastFocusable = focusableElements[focusableElements.length - 1];
252+
253+
// Focus first element when menu opens
254+
this.firstFocusable.focus();
255+
256+
// Store bound handler for removal
257+
this.focusTrapHandler = (e) => {
258+
if (e.key !== 'Tab') return;
259+
260+
if (e.shiftKey) {
261+
// Shift+Tab: if on first element, wrap to last
262+
if (document.activeElement === this.firstFocusable) {
263+
e.preventDefault();
264+
this.lastFocusable.focus();
265+
}
266+
} else {
267+
// Tab: if on last element, wrap to first
268+
if (document.activeElement === this.lastFocusable) {
269+
e.preventDefault();
270+
this.firstFocusable.focus();
271+
}
272+
}
273+
};
274+
275+
document.addEventListener('keydown', this.focusTrapHandler);
276+
}
277+
278+
/**
279+
* Remove focus trap when mobile menu closes
280+
*/
281+
removeMobileFocusTrap() {
282+
if (this.focusTrapHandler) {
283+
document.removeEventListener('keydown', this.focusTrapHandler);
284+
this.focusTrapHandler = null;
223285
}
286+
this.firstFocusable = null;
287+
this.lastFocusable = null;
224288
}
225289

226290
setupKeyboardShortcuts() {

config/var/www/admin/control-panel/external-services/external-services-api.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -672,10 +672,10 @@ function handleStatusFeed() {
672672

673673
// Sanitize filter parameter to prevent injection
674674
if ($filter !== null) {
675-
// Allow alphanumeric, spaces, hyphens, periods, parentheses for service names
676-
$filter = preg_replace('/[^a-zA-Z0-9 \-\.\(\)]/', '', $filter);
675+
// Restrict to alphanumeric, hyphens, underscores only (removed spaces/parentheses as injection vectors)
676+
$filter = preg_replace('/[^a-zA-Z0-9_-]/', '', $filter);
677677
// Limit length to reasonable service name size
678-
$filter = substr($filter, 0, 100);
678+
$filter = substr($filter, 0, 50);
679679
if (empty($filter)) {
680680
$filter = null;
681681
}

config/var/www/admin/control-panel/external-services/external-services.js

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -751,15 +751,18 @@ export class ExternalServicesManager {
751751
date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
752752
expires = "; expires=" + date.toUTCString();
753753
}
754-
// Set cookie with SameSite=Lax for security
755-
document.cookie = name + "=" + (value || "") + expires + "; path=/; SameSite=Lax";
754+
// Set cookie with Secure, HttpOnly cannot be set via JS, SameSite=Strict for maximum security
755+
// Secure flag ensures cookie only sent over HTTPS
756+
// SameSite=Strict prevents CSRF attacks (stricter than Lax)
757+
document.cookie = name + "=" + (value || "") + expires + "; path=/; SameSite=Strict; Secure";
756758
}
757759

758760
/**
759761
* Delete cookie
762+
* Include Secure flag in deletion for consistency
760763
*/
761764
deleteCookie(name) {
762-
document.cookie = name + '=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;';
765+
document.cookie = name + '=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/; SameSite=Strict; Secure';
763766
}
764767

765768
// ============ Service Preferences ============

config/var/www/admin/control-panel/index.html

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
<link rel="icon" type="image/png" href="favicon.png">
99

1010
<!-- External Dependencies -->
11-
<script src="https://cdn.jsdelivr.net/npm/chart.js@{CHARTJS_VER}/dist/chart.umd.js" data-cfasync="false"></script>
1211
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/{FONTAWESOME_VER}/css/all.min.css" rel="stylesheet" crossorigin="anonymous">
1312

1413
<!-- Custom Styles -->

config/var/www/admin/control-panel/modules/charts.js

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,14 @@
11
// EngineScript Admin Dashboard - Charts Module
2-
// Handles Chart.js initialization and management
2+
// DEPRECATED - Chart.js removed from project
3+
// This module is no longer imported or used
4+
// Kept for reference only - safe to delete
35

6+
/**
7+
* @deprecated No longer used - Chart.js dependency removed
8+
*/
49
export class DashboardCharts {
510
constructor() {
11+
console.warn('DashboardCharts is deprecated and no longer used');
612
this.charts = {};
713
}
814

enginescript-variables.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ SSE_PLUGIN_VER="1.9.1"
2424
SWPO_PLUGIN_VER="1.8.0"
2525

2626
# Frontend Dependencies
27-
CHARTJS_VER="4.5.1"
2827
FONTAWESOME_VER="7.0.1"
2928
TINYFILEMANAGER_VER="2.6"
3029

0 commit comments

Comments
 (0)