Signed-off-by: ale <ale@manalejandro.com>
Este commit está contenido en:
ale
2025-12-11 22:40:24 +01:00
padre bf8fbde307
commit 15ebcc7898

455
pack.php
Ver fichero

@@ -117,7 +117,7 @@ echo "Collecting source files...\n";
/**
* Extract PHP code from file (without opening tag and namespace)
*/
function extractPhpCode(string $filePath, bool $minify = false): string {
function extractPhpCode(string $filePath, bool $minify = false, bool $isPacked = false): string {
$content = file_get_contents($filePath);
// Remove opening PHP tag
@@ -133,6 +133,12 @@ function extractPhpCode(string $filePath, bool $minify = false): string {
// Only match 'use' at the start of a line (namespace imports), not closure 'use' clauses
$content = preg_replace('/^use\s+[A-Z\\\\][^;]*;\s*/im', '', $content);
// For packed version, replace ALESHELL_SRC references with packed equivalents
if ($isPacked) {
// Replace View::render calls to use PackedView for embedded views
$content = str_replace('ALESHELL_SRC', '__DIR__', $content);
}
if ($minify) {
// Remove multi-line comments but preserve strings
$content = preg_replace('/\/\*(?!.*?\*\/).*?\*\//s', '', $content);
@@ -184,6 +190,9 @@ declare(strict_types=1);
// CONFIGURATION
// ============================================================================
define('ALESHELL_VERSION', '2.0.0');
define('ALESHELL_PACKED', true);
HEADER;
// Add configuration
@@ -223,7 +232,7 @@ $output .= "// =================================================================
foreach ($coreFiles as $file) {
$path = __DIR__ . '/' . $file;
if (file_exists($path)) {
$code = extractPhpCode($path, $minify);
$code = extractPhpCode($path, $minify, true);
// Replace namespace references with inline
$code = str_replace('AleShell2\\Core\\', 'AleShell2_', $code);
$code = str_replace('AleShell2\\Security\\', 'AleShell2_', $code);
@@ -233,6 +242,83 @@ foreach ($coreFiles as $file) {
$className = basename($file, '.php');
$code = preg_replace('/class\s+' . $className . '/', 'class AleShell2_' . $className, $code);
// Transform type hints for internal classes (Session, Auth, Request, Response, Router, View)
$internalClasses = ['Session', 'Auth', 'Request', 'Response', 'Router', 'View'];
foreach ($internalClasses as $internalClass) {
$code = preg_replace('/private\s+' . $internalClass . '\s+\$/', 'private AleShell2_' . $internalClass . ' $', $code);
$code = preg_replace('/public\s+' . $internalClass . '\s+\$/', 'public AleShell2_' . $internalClass . ' $', $code);
$code = preg_replace('/,\s*' . $internalClass . '\s+\$/', ', AleShell2_' . $internalClass . ' $', $code);
$code = preg_replace('/\(\s*' . $internalClass . '\s+\$/', '(AleShell2_' . $internalClass . ' $', $code);
$code = preg_replace('/:\s*' . $internalClass . '(\s|\)|,|$)/', ': AleShell2_' . $internalClass . '$1', $code);
$code = preg_replace('/new\s+' . $internalClass . '\s*\(/', 'new AleShell2_' . $internalClass . '(', $code);
}
// Fix redirect paths for packed version - convert path-based to query parameter format
$code = str_replace("\$response->redirect('/login')", "\$response->redirect('?action=login')", $code);
$code = str_replace("\$response->redirect('/logout')", "\$response->redirect('?action=logout')", $code);
// Special handling for View class - make it use embedded views
if ($className === 'View') {
$code = str_replace(
"\$viewPath = __DIR__ . '/Views/' . str_replace('.', '/', \$view) . '.php';",
"\$viewPath = \$view; // Using embedded views",
$code
);
$code = preg_replace(
'/if\s*\(\s*!file_exists\s*\(\s*\$viewPath\s*\)\s*\)[\s\S]*?throw new \\\\RuntimeException\s*\([^)]+\)\s*;[\s\S]*?\}/',
'global $ALESHELL_VIEWS;
$templateKey = $view;
if (!isset($ALESHELL_VIEWS[$templateKey])) {
throw new \\RuntimeException("View not found: {$view}");
}',
$code
);
$code = preg_replace(
'/ob_start\s*\(\s*\)\s*;\s*\n\s*include\s+\$viewPath\s*;\s*\n\s*return\s+ob_get_clean\s*\(\s*\)\s*;/',
'ob_start();
eval(\'?>\' . $ALESHELL_VIEWS[$templateKey]);
return ob_get_clean();',
$code
);
}
// Special handling for Application class - skip config file loading
if ($className === 'Application') {
$code = preg_replace(
'/\$configFile = __DIR__ . \'\/Config\/config\.php\';[\s\S]*?if \(file_exists\(\$configFile\)\) \{[\s\S]*?\$this->config = require \$configFile;[\s\S]*?\} else \{/',
'// Packed mode: use default config directly
{',
$code
);
}
// Special handling for Response class - fix PHP 8.4 deprecation warnings
// Convert "string $param = null" to "?string $param = null"
if ($className === 'Response') {
$code = preg_replace('/string\s+(\$\w+)\s*=\s*null/', '?string $1 = null', $code);
}
// Special handling for Request class - parse JSON body for AJAX requests
if ($className === 'Request') {
$code = preg_replace(
'/\$this->post = \$_POST;/',
'$this->post = $_POST;
// Parse JSON body for AJAX requests
$contentType = $_SERVER[\'CONTENT_TYPE\'] ?? \'\';
if (stripos($contentType, \'application/json\') !== false) {
$rawBody = file_get_contents(\'php://input\');
if ($rawBody) {
$jsonData = json_decode($rawBody, true);
if (is_array($jsonData)) {
$this->post = array_merge($this->post, $jsonData);
}
}
}',
$code
);
}
$output .= "// Source: {$file}\n";
$output .= $code . "\n\n";
echo " Added core: {$className}\n";
@@ -247,7 +333,7 @@ $output .= "// =================================================================
foreach ($securityFiles as $file) {
$path = __DIR__ . '/' . $file;
if (file_exists($path)) {
$code = extractPhpCode($path, $minify);
$code = extractPhpCode($path, $minify, true);
$code = str_replace('AleShell2\\Core\\', 'AleShell2_', $code);
$code = str_replace('AleShell2\\Security\\', 'AleShell2_', $code);
$code = str_replace('AleShell2\\Modules\\', 'AleShell2_', $code);
@@ -255,6 +341,13 @@ foreach ($securityFiles as $file) {
$className = basename($file, '.php');
$code = preg_replace('/class\s+' . $className . '/', 'class AleShell2_' . $className, $code);
// Transform type hints for internal classes
$code = preg_replace('/private\s+Session\s+\$/', 'private AleShell2_Session $', $code);
$code = preg_replace('/public\s+Session\s+\$/', 'public AleShell2_Session $', $code);
$code = preg_replace('/,\s*Session\s+\$/', ', AleShell2_Session $', $code);
$code = preg_replace('/\(\s*Session\s+\$/', '(AleShell2_Session $', $code);
$code = preg_replace('/:\s*Session(\s|$)/', ': AleShell2_Session$1', $code);
$output .= "// Source: {$file}\n";
$output .= $code . "\n\n";
echo " Added security: {$className}\n";
@@ -269,7 +362,7 @@ $output .= "// =================================================================
foreach ($moduleFiles as $file) {
$path = __DIR__ . '/' . $file;
if (file_exists($path)) {
$code = extractPhpCode($path, $minify);
$code = extractPhpCode($path, $minify, true);
$code = str_replace('AleShell2\\Core\\', 'AleShell2_', $code);
$code = str_replace('AleShell2\\Security\\', 'AleShell2_', $code);
$code = str_replace('AleShell2\\Modules\\', 'AleShell2_', $code);
@@ -290,6 +383,231 @@ foreach ($moduleFiles as $file) {
$code = preg_replace('/extends\s+' . $className . '/', 'extends AleShell2_' . $className, $code);
$code = preg_replace('/extends\s+BaseController/', 'extends AleShell2_BaseController', $code);
// Fix redirect paths for packed version - convert path-based to query parameter format
$code = str_replace("\$response->redirect('/')", "\$response->redirect('?module=dashboard')", $code);
$code = str_replace("\$response->redirect('/login')", "\$response->redirect('?action=login')", $code);
$code = str_replace("\$response->redirect('/logout')", "\$response->redirect('?action=logout')", $code);
$code = str_replace("\$response->redirect('/dashboard')", "\$response->redirect('?module=dashboard')", $code);
$code = str_replace("\$response->redirect('/files')", "\$response->redirect('?module=files')", $code);
$code = str_replace("\$response->redirect('/terminal')", "\$response->redirect('?module=terminal')", $code);
$code = str_replace("\$response->redirect('/editor')", "\$response->redirect('?module=editor')", $code);
$code = str_replace("\$response->redirect('/processes')", "\$response->redirect('?module=processes')", $code);
$code = str_replace("\$response->redirect('/network')", "\$response->redirect('?module=network')", $code);
$code = str_replace("\$response->redirect('/database')", "\$response->redirect('?module=database')", $code);
$code = str_replace("\$response->redirect('/system')", "\$response->redirect('?module=system')", $code);
// Transform type hints for internal classes (Session, Auth, Request, Response, Router, View)
$internalClasses = ['Session', 'Auth', 'Request', 'Response', 'Router', 'View'];
foreach ($internalClasses as $internalClass) {
$code = preg_replace('/protected\s+' . $internalClass . '\s+\$/', 'protected AleShell2_' . $internalClass . ' $', $code);
$code = preg_replace('/private\s+' . $internalClass . '\s+\$/', 'private AleShell2_' . $internalClass . ' $', $code);
$code = preg_replace('/public\s+' . $internalClass . '\s+\$/', 'public AleShell2_' . $internalClass . ' $', $code);
$code = preg_replace('/,\s*' . $internalClass . '\s+\$/', ', AleShell2_' . $internalClass . ' $', $code);
$code = preg_replace('/\(\s*' . $internalClass . '\s+\$/', '(AleShell2_' . $internalClass . ' $', $code);
$code = preg_replace('/:\s*' . $internalClass . '(\s|\)|,|$)/', ': AleShell2_' . $internalClass . '$1', $code);
$code = preg_replace('/new\s+' . $internalClass . '\s*\(/', 'new AleShell2_' . $internalClass . '(', $code);
// Also transform static method calls like View::render() to AleShell2_View::render()
$code = preg_replace('/\b' . $internalClass . '::/', 'AleShell2_' . $internalClass . '::', $code);
}
// Fix PHP 8.4 deprecation: float modulo in SystemController and BaseController
if ($className === 'SystemController' || $className === 'BaseController') {
// Cast $seconds to int before modulo operations
$code = str_replace('($seconds % 86400)', '((int)$seconds % 86400)', $code);
$code = str_replace('($seconds % 3600)', '((int)$seconds % 3600)', $code);
}
// Fix SystemController: formatBytes expects int but disk functions return float
if ($className === 'SystemController') {
// Cast disk space values to int before passing to formatBytes
$code = str_replace(
'$totalSpace ? $this->formatBytes($totalSpace)',
'$totalSpace ? $this->formatBytes((int)$totalSpace)',
$code
);
$code = str_replace(
'$freeSpace ? $this->formatBytes($freeSpace)',
'$freeSpace ? $this->formatBytes((int)$freeSpace)',
$code
);
$code = str_replace(
'$this->formatBytes($totalSpace - $freeSpace)',
'$this->formatBytes((int)($totalSpace - $freeSpace))',
$code
);
}
// Fix TerminalController: Replace Application::getInstance() with direct session access
if ($className === 'TerminalController') {
// Replace the pattern used to get session in terminal controller
$code = str_replace(
'$app = Application::getInstance();
$session = $app->getSession();',
'// Packed version: use $_SESSION directly',
$code
);
// Fix session get calls
$code = str_replace('$session->get(\'terminal_history\', [])', '($_SESSION[\'terminal_history\'] ?? [])', $code);
$code = str_replace('$session->set(\'terminal_history\', $history)', '$_SESSION[\'terminal_history\'] = $history', $code);
$code = str_replace('$session->remove(\'terminal_history\')', 'unset($_SESSION[\'terminal_history\'])', $code);
$code = str_replace('$session->get(\'terminal_cwd\')', '($_SESSION[\'terminal_cwd\'] ?? null)', $code);
$code = str_replace('$session->set(\'terminal_cwd\', $newDir)', '$_SESSION[\'terminal_cwd\'] = $newDir', $code);
}
// Fix FilesController: list method uses post() but is called via GET with query params
// Change to input() which checks both POST and query params
if ($className === 'FilesController') {
// In the list method, change $request->post() to $request->input() for path
$code = str_replace(
'$path = $request->post(\'path\', getcwd());',
'$path = $request->input(\'path\', getcwd());',
$code
);
$code = str_replace(
'$showHidden = (bool)$request->post(\'hidden\', false);',
'$showHidden = (bool)$request->input(\'hidden\', false);',
$code
);
$code = str_replace(
'$sortBy = $request->post(\'sort\', \'name\');',
'$sortBy = $request->input(\'sort\', \'name\');',
$code
);
$code = str_replace(
'$sortOrder = $request->post(\'order\', \'asc\');',
'$sortOrder = $request->input(\'order\', \'asc\');',
$code
);
// Add 'type' field to scanDirectory output - JS expects file.type but API returns is_directory
$code = str_replace(
"'is_directory' => \$isDir,",
"'is_directory' => \$isDir,\n 'type' => \$isDir ? 'directory' : (is_link(\$fullPath) ? 'link' : 'file'),",
$code
);
}
// Fix DashboardController: The view expects 'systemInfo' but controller passes 'data' with system info
// We need to make the dashboard controller get detailed system info like SystemController does
if ($className === 'DashboardController') {
// Replace the render call to pass systemInfo directly
$code = str_replace(
"'data' => \$this->getDashboardData(),",
"'systemInfo' => \$this->getDetailedSystemInfo(),\n 'data' => \$this->getDashboardData(),",
$code
);
// Add the getDetailedSystemInfo method (copy from SystemController logic)
$dashboardMethodsToAdd = <<<'DASHBOARD_METHODS'
/**
* Get detailed system info for dashboard (same as SystemController)
*/
private function getDetailedSystemInfo(): array
{
return [
'server' => $this->getServerInfoDetailed(),
'php' => $this->getPhpInfoDetailed(),
'hardware' => $this->getHardwareInfoDetailed(),
'disk' => $this->getDiskInfoDetailed(),
];
}
private function getServerInfoDetailed(): array
{
$info = [
'hostname' => gethostname() ?: 'unknown',
'os' => PHP_OS_FAMILY,
'os_detail' => php_uname(),
'server_software' => $_SERVER['SERVER_SOFTWARE'] ?? 'unknown',
'server_name' => $_SERVER['SERVER_NAME'] ?? 'unknown',
'server_addr' => $_SERVER['SERVER_ADDR'] ?? 'unknown',
'server_port' => $_SERVER['SERVER_PORT'] ?? 'unknown',
'document_root' => $_SERVER['DOCUMENT_ROOT'] ?? '',
'current_user' => get_current_user(),
'current_uid' => getmyuid(),
'current_gid' => getmygid(),
'process_id' => getmypid(),
'uptime' => $this->getUptime(),
'load_average' => function_exists('sys_getloadavg') ? (function() {
$load = sys_getloadavg();
return $load ? ['1min' => round($load[0], 2), '5min' => round($load[1], 2), '15min' => round($load[2], 2)] : null;
})() : null,
];
return $info;
}
private function getPhpInfoDetailed(): array
{
return [
'version' => PHP_VERSION,
'version_id' => PHP_VERSION_ID,
'sapi' => php_sapi_name(),
'ini_path' => php_ini_loaded_file() ?: 'unknown',
'extension_dir' => ini_get('extension_dir'),
'include_path' => ini_get('include_path'),
'memory_limit' => ini_get('memory_limit'),
'max_execution_time' => ini_get('max_execution_time'),
'max_input_time' => ini_get('max_input_time'),
'post_max_size' => ini_get('post_max_size'),
'upload_max_filesize' => ini_get('upload_max_filesize'),
'max_file_uploads' => ini_get('max_file_uploads'),
'display_errors' => ini_get('display_errors'),
'error_reporting' => error_reporting(),
'date_timezone' => date_default_timezone_get(),
'disabled_functions' => ini_get('disable_functions') ?: 'none',
];
}
private function getHardwareInfoDetailed(): array
{
$info = ['cpu' => 'unknown', 'cpu_cores' => 0, 'memory_total' => 'unknown', 'memory_free' => 'unknown', 'memory_available' => 'unknown'];
if (is_readable('/proc/cpuinfo')) {
$cpuinfo = file_get_contents('/proc/cpuinfo');
if (preg_match('/model name\s*:\s*(.+)/i', $cpuinfo, $matches)) {
$info['cpu'] = trim($matches[1]);
}
$info['cpu_cores'] = substr_count($cpuinfo, 'processor');
}
if (is_readable('/proc/meminfo')) {
$meminfo = file_get_contents('/proc/meminfo');
if (preg_match('/MemTotal:\s*(\d+)\s*kB/i', $meminfo, $matches)) {
$info['memory_total'] = $this->formatBytes((int)$matches[1] * 1024);
}
if (preg_match('/MemFree:\s*(\d+)\s*kB/i', $meminfo, $matches)) {
$info['memory_free'] = $this->formatBytes((int)$matches[1] * 1024);
}
if (preg_match('/MemAvailable:\s*(\d+)\s*kB/i', $meminfo, $matches)) {
$info['memory_available'] = $this->formatBytes((int)$matches[1] * 1024);
}
}
return $info;
}
private function getDiskInfoDetailed(): array
{
$disks = [];
if (PHP_OS_FAMILY === 'Linux') {
$df = @shell_exec('df -h 2>/dev/null');
if ($df) {
$lines = explode("\n", trim($df));
array_shift($lines);
foreach ($lines as $line) {
$parts = preg_split('/\s+/', $line);
if (count($parts) >= 6 && strpos($parts[0], '/dev/') === 0) {
$disks[] = [
'device' => $parts[0], 'total' => $parts[1], 'used' => $parts[2],
'free' => $parts[3], 'percent_used' => $parts[4], 'mount' => $parts[5],
];
}
}
}
}
return $disks;
}
DASHBOARD_METHODS;
// Insert the methods before the closing brace of the class
$code = preg_replace('/}\s*$/', $dashboardMethodsToAdd . "\n}\n", $code);
}
$output .= "// Source: {$file}\n";
$output .= $code . "\n\n";
echo " Added module: {$className}\n";
@@ -364,11 +682,48 @@ class AleShell2_PackedView {
}
}
// Simplified Router for packed version
class AleShell2_PackedRouter {
private array $routes = [];
private $app;
public function __construct($app) {
$this->app = $app;
}
public function get(string $action, callable $handler): void {
$this->routes['GET'][$action] = $handler;
}
public function post(string $action, callable $handler): void {
$this->routes['POST'][$action] = $handler;
}
public function dispatch(AleShell2_Request $request, AleShell2_Response $response): void {
$method = $request->getMethod();
$action = $request->get('action', '');
$module = $request->get('module', '');
// Determine route key - module takes priority for navigation routes
// action is used for standalone routes like 'login', 'logout'
// When module is present, use module as route key (action is handled inside the module)
$routeKey = $module ?: $action ?: '';
if (isset($this->routes[$method][$routeKey])) {
$handler = $this->routes[$method][$routeKey];
$handler($request, $response, []);
} else {
// Default route - redirect to login or dashboard
$response->redirect('?action=login');
}
}
}
// Modified Application for packed version
class AleShell2_PackedApplication {
private AleShell2_Request $request;
private AleShell2_Response $response;
private AleShell2_Router $router;
private AleShell2_PackedRouter $router;
private AleShell2_Session $session;
private AleShell2_Auth $auth;
private AleShell2_PackedView $view;
@@ -384,15 +739,25 @@ class AleShell2_PackedApplication {
// Initialize components
$this->request = new AleShell2_Request();
$this->response = new AleShell2_Response();
$this->session = new AleShell2_Session($this->config['session_timeout'] ?? 3600);
$this->auth = new AleShell2_Auth(
$this->config['password_hash'],
$this->session,
$this->config['max_login_attempts'] ?? 5,
$this->config['lockout_duration'] ?? 900
);
// Create a config array compatible with Session class
$sessionConfig = [
'security' => [
'session_timeout' => $this->config['session_timeout'] ?? 3600,
]
];
$this->session = new AleShell2_Session($sessionConfig);
// Create a config array compatible with Auth class
$authConfig = [
'security' => [
'password' => $this->config['password_hash'],
'max_attempts' => $this->config['max_login_attempts'] ?? 5,
'lockout_time' => $this->config['lockout_duration'] ?? 900,
'csrf_protection' => true,
]
];
$this->auth = new AleShell2_Auth($authConfig, $this->session);
$this->view = new AleShell2_PackedView();
$this->router = new AleShell2_Router($this);
$this->router = new AleShell2_PackedRouter($this);
// Set security headers
$this->setSecurityHeaders();
@@ -450,17 +815,17 @@ class AleShell2_PackedApplication {
private function setupRoutes(): void {
// Auth routes (public)
$this->router->get('login', function($req, $res, $params) {
$controller = new AleShell2_AuthController($this);
$controller->showLogin($req, $res, $params);
$controller = new AleShell2_AuthController($this->getControllerConfig(), $this->auth);
$controller->login($req, $res, $params);
});
$this->router->post('login', function($req, $res, $params) {
$controller = new AleShell2_AuthController($this);
$controller = new AleShell2_AuthController($this->getControllerConfig(), $this->auth);
$controller->login($req, $res, $params);
});
$this->router->get('logout', function($req, $res, $params) {
$controller = new AleShell2_AuthController($this);
$controller = new AleShell2_AuthController($this->getControllerConfig(), $this->auth);
$controller->logout($req, $res, $params);
});
@@ -477,13 +842,13 @@ class AleShell2_PackedApplication {
// Dashboard
$this->router->get('dashboard', $authMiddleware(function($req, $res, $params) {
$controller = new AleShell2_DashboardController($this);
$controller = new AleShell2_DashboardController($this->getControllerConfig(), $this->auth);
$controller->index($req, $res, $params);
}));
// Files
$this->router->get('files', $authMiddleware(function($req, $res, $params) {
$controller = new AleShell2_FilesController($this);
$controller = new AleShell2_FilesController($this->getControllerConfig(), $this->auth);
$action = $req->get('action', 'index');
match($action) {
'list' => $controller->list($req, $res, $params),
@@ -495,7 +860,7 @@ class AleShell2_PackedApplication {
}));
$this->router->post('files', $authMiddleware(function($req, $res, $params) {
$controller = new AleShell2_FilesController($this);
$controller = new AleShell2_FilesController($this->getControllerConfig(), $this->auth);
$action = $req->get('action', 'index');
match($action) {
'write' => $controller->write($req, $res, $params),
@@ -511,12 +876,12 @@ class AleShell2_PackedApplication {
// Terminal
$this->router->get('terminal', $authMiddleware(function($req, $res, $params) {
$controller = new AleShell2_TerminalController($this);
$controller = new AleShell2_TerminalController($this->getControllerConfig(), $this->auth);
$controller->index($req, $res, $params);
}));
$this->router->post('terminal', $authMiddleware(function($req, $res, $params) {
$controller = new AleShell2_TerminalController($this);
$controller = new AleShell2_TerminalController($this->getControllerConfig(), $this->auth);
$action = $req->get('action', 'exec');
if ($action === 'exec') {
$controller->execute($req, $res, $params);
@@ -525,18 +890,18 @@ class AleShell2_PackedApplication {
// Editor
$this->router->get('editor', $authMiddleware(function($req, $res, $params) {
$controller = new AleShell2_EditorController($this);
$controller = new AleShell2_EditorController($this->getControllerConfig(), $this->auth);
$controller->index($req, $res, $params);
}));
$this->router->post('editor', $authMiddleware(function($req, $res, $params) {
$controller = new AleShell2_EditorController($this);
$controller = new AleShell2_EditorController($this->getControllerConfig(), $this->auth);
$controller->save($req, $res, $params);
}));
// Processes
$this->router->get('processes', $authMiddleware(function($req, $res, $params) {
$controller = new AleShell2_ProcessesController($this);
$controller = new AleShell2_ProcessesController($this->getControllerConfig(), $this->auth);
$action = $req->get('action', 'index');
if ($action === 'list') {
$controller->list($req, $res, $params);
@@ -546,7 +911,7 @@ class AleShell2_PackedApplication {
}));
$this->router->post('processes', $authMiddleware(function($req, $res, $params) {
$controller = new AleShell2_ProcessesController($this);
$controller = new AleShell2_ProcessesController($this->getControllerConfig(), $this->auth);
$action = $req->get('action', 'kill');
if ($action === 'kill') {
$controller->kill($req, $res, $params);
@@ -555,7 +920,7 @@ class AleShell2_PackedApplication {
// Network
$this->router->get('network', $authMiddleware(function($req, $res, $params) {
$controller = new AleShell2_NetworkController($this);
$controller = new AleShell2_NetworkController($this->getControllerConfig(), $this->auth);
$action = $req->get('action', 'index');
if ($action === 'connections') {
$controller->connections($req, $res, $params);
@@ -565,7 +930,7 @@ class AleShell2_PackedApplication {
}));
$this->router->post('network', $authMiddleware(function($req, $res, $params) {
$controller = new AleShell2_NetworkController($this);
$controller = new AleShell2_NetworkController($this->getControllerConfig(), $this->auth);
$action = $req->get('action');
match($action) {
'ping' => $controller->ping($req, $res, $params),
@@ -577,7 +942,7 @@ class AleShell2_PackedApplication {
// Database
$this->router->get('database', $authMiddleware(function($req, $res, $params) {
$controller = new AleShell2_DatabaseController($this);
$controller = new AleShell2_DatabaseController($this->getControllerConfig(), $this->auth);
$action = $req->get('action', 'index');
match($action) {
'tables' => $controller->tables($req, $res, $params),
@@ -588,7 +953,7 @@ class AleShell2_PackedApplication {
}));
$this->router->post('database', $authMiddleware(function($req, $res, $params) {
$controller = new AleShell2_DatabaseController($this);
$controller = new AleShell2_DatabaseController($this->getControllerConfig(), $this->auth);
$action = $req->get('action');
match($action) {
'connect' => $controller->connect($req, $res, $params),
@@ -601,7 +966,7 @@ class AleShell2_PackedApplication {
// System
$this->router->get('system', $authMiddleware(function($req, $res, $params) {
$controller = new AleShell2_SystemController($this);
$controller = new AleShell2_SystemController($this->getControllerConfig(), $this->auth);
$action = $req->get('action', 'index');
match($action) {
'info' => $controller->info($req, $res, $params),
@@ -614,7 +979,7 @@ class AleShell2_PackedApplication {
// API
$this->router->get('api', $authMiddleware(function($req, $res, $params) {
$controller = new AleShell2_ApiController($this);
$controller = new AleShell2_ApiController($this->getControllerConfig(), $this->auth);
$action = $req->get('action', 'status');
match($action) {
'status' => $controller->status($req, $res, $params),
@@ -626,7 +991,7 @@ class AleShell2_PackedApplication {
}));
$this->router->post('api', $authMiddleware(function($req, $res, $params) {
$controller = new AleShell2_ApiController($this);
$controller = new AleShell2_ApiController($this->getControllerConfig(), $this->auth);
$action = $req->get('action');
match($action) {
'exec' => $controller->exec($req, $res, $params),
@@ -659,6 +1024,30 @@ class AleShell2_PackedApplication {
public function getAuth(): AleShell2_Auth { return $this->auth; }
public function getView(): AleShell2_PackedView { return $this->view; }
public function getConfig(): array { return $this->config; }
// Get config in the format expected by controllers
public function getControllerConfig(): array {
return [
'security' => [
'password' => $this->config['password_hash'],
'max_attempts' => $this->config['max_login_attempts'] ?? 5,
'lockout_time' => $this->config['lockout_duration'] ?? 900,
'session_timeout' => $this->config['session_timeout'] ?? 3600,
'csrf_protection' => true,
'restricted_paths' => [],
'blocked_commands' => [],
],
'features' => [
'file_manager' => true,
'terminal' => true,
'code_editor' => true,
'process_manager' => true,
'network_tools' => true,
'database_tools' => true,
'system_info' => true,
],
];
}
}
// Run the application