ID)) { return $conf; } $sqlite3Version = class_exists('SQLite3') ? SQLite3::version() : false; $conf[$this->ID] = array( 'sqlite3' => $sqlite3Version ? $sqlite3Version['versionString'] : false, 'sqliteLibversion' => \function_exists('sqlite_libversion') ? sqlite_libversion() : false, 'mysqliClientVersion' => \function_exists('mysqli_get_client_version') ? mysqli_get_client_version() : false, 'mongo' => class_exists('Mongo'), 'mongoDb' => class_exists('MongoDB'), 'postgreSql' => \function_exists('pg_connect'), 'paradox' => \function_exists('px_new'), 'msSql' => \function_exists('sqlsrv_server_info'), 'pdo' => class_exists('PDO') ? implode(',', PDO::getAvailableDrivers()) : false, ); return $conf; }); } } namespace InnStudio\Prober\Components\Database; class DatabaseConstants { protected $ID = 'database'; } namespace InnStudio\Prober\Components\Database; final class Database { public function __construct() { new Conf(); } } namespace InnStudio\Prober\Components\Nodes; use InnStudio\Prober\Components\Events\EventsApi; use InnStudio\Prober\Components\Rest\RestResponse; use InnStudio\Prober\Components\Rest\StatusCode; final class Fetch extends NodesApi { public function __construct() { EventsApi::on('init', function ($action) { switch ($action) { case 'nodes': EventsApi::emit('fetchNodesBefore'); $response = new RestResponse(EventsApi::emit('nodes', array())); $response->json()->end(); case 'node': EventsApi::emit('fetchNodeBefore'); $nodeId = filter_input(\INPUT_GET, 'nodeId', \FILTER_DEFAULT); $response = new RestResponse(); if ( ! $nodeId) { $response->setStatus(StatusCode::$BAD_REQUEST)->json()->end(); } $data = $this->getNodeData($nodeId); if ( ! $data) { $response->setStatus(StatusCode::$NO_CONTENT)->json()->end(); } $response->setData($data)->json()->end(); } return $action; }, 100); } private function getNodeData($nodeId) { foreach ($this->getNodes() as $item) { if ( ! isset($item['id']) || ! isset($item['url']) || $item['id'] !== $nodeId) { continue; } return $this->getRemoteContent("{$item['url']}?action=fetch"); } } private function getRemoteContent($url) { $content = ''; if (\function_exists('curl_init')) { $ch = curl_init(); curl_setopt_array($ch, array( \CURLOPT_URL => $url, \CURLOPT_RETURNTRANSFER => true, )); $content = curl_exec($ch); curl_close($ch); return json_decode($content, true) ?: null; } return json_decode(file_get_contents($url), true) ?: null; } } namespace InnStudio\Prober\Components\Nodes; use InnStudio\Prober\Components\Events\EventsApi; use InnStudio\Prober\Components\Xconfig\XconfigApi; final class Conf extends NodesApi { public function __construct() { EventsApi::on('conf', function (array $conf) { if (XconfigApi::isDisabled($this->ID)) { return $conf; } $conf[$this->ID] = array( 'items' => $this->getNodes(), ); return $conf; }); } } namespace InnStudio\Prober\Components\Nodes; final class Nodes { public function __construct() { new Conf(); new Fetch(); } } namespace InnStudio\Prober\Components\Nodes; use InnStudio\Prober\Components\Xconfig\XconfigApi; class NodesApi { public $ID = 'nodes'; public function getNodes() { $items = XconfigApi::getNodes(); if ( ! $items || ! \is_array($items)) { return array(); } return array_filter(array_map(function ($item) { if (2 !== \count($item)) { return; } return array( 'id' => $item[0], 'url' => $item[1], ); }, $items)); } } namespace InnStudio\Prober\Components\ServerInfo; class ServerInfoConstants { protected $ID = 'serverInfo'; protected $FEATURE_SERVER_IP = 'serverIp'; } namespace InnStudio\Prober\Components\ServerInfo; use InnStudio\Prober\Components\Events\EventsApi; use InnStudio\Prober\Components\Utils\UtilsDisk; use InnStudio\Prober\Components\Utils\UtilsTime; use InnStudio\Prober\Components\Xconfig\XconfigApi; final class Fetch extends ServerInfoConstants { public function __construct() { EventsApi::on('fetch', array($this, 'filter')); EventsApi::on('nodes', array($this, 'filter')); } public function filter(array $items) { if (XconfigApi::isDisabled($this->ID)) { return $items; } $items[$this->ID] = array( 'serverUtcTime' => UtilsTime::getUtcTime(), 'serverTime' => UtilsTime::getTime(), 'serverUptime' => UtilsTime::getUptime(), 'diskUsage' => array( 'value' => UtilsDisk::getTotal() - UtilsDisk::getFree(), 'max' => UtilsDisk::getTotal(), ), ); return $items; } } namespace InnStudio\Prober\Components\ServerInfo; use InnStudio\Prober\Components\Events\EventsApi; use InnStudio\Prober\Components\Rest\RestResponse; use InnStudio\Prober\Components\Utils\UtilsServerIp; use InnStudio\Prober\Components\Xconfig\XconfigApi; final class ServerInitIpv4 extends ServerInfoConstants { public function __construct() { EventsApi::on('init', function ($action) { if ('serverIpv4' !== $action) { return $action; } if (XconfigApi::isDisabled($this->ID)) { return $action; } if (XconfigApi::isDisabled($this->FEATURE_SERVER_IP)) { return $action; } $response = new RestResponse(); $response->setData(array( 'ip' => UtilsServerIp::getV4(), ))->json()->end(); }); } } namespace InnStudio\Prober\Components\ServerInfo; use InnStudio\Prober\Components\Events\EventsApi; use InnStudio\Prober\Components\Rest\RestResponse; use InnStudio\Prober\Components\Rest\StatusCode; use InnStudio\Prober\Components\Utils\UtilsLocation; use InnStudio\Prober\Components\Utils\UtilsServerIp; use InnStudio\Prober\Components\Xconfig\XconfigApi; final class ServerLocationIpv4 extends ServerInfoConstants { public function __construct() { EventsApi::on('init', function ($action) { if ('serverLocationIpv4' !== $action) { return $action; } if (XconfigApi::isDisabled($this->ID)) { return $action; } if (XconfigApi::isDisabled($this->FEATURE_SERVER_IP)) { return $action; } $response = new RestResponse(); $ip = UtilsServerIp::getV4(); if ( ! $ip) { $response->setStatus(StatusCode::$BAD_REQUEST)->json()->end(); } $response->setData(UtilsLocation::getLocation($ip))->json()->end(); }); } } namespace InnStudio\Prober\Components\ServerInfo; use InnStudio\Prober\Components\Events\EventsApi; use InnStudio\Prober\Components\Utils\UtilsCpu; use InnStudio\Prober\Components\Utils\UtilsDisk; use InnStudio\Prober\Components\Utils\UtilsTime; use InnStudio\Prober\Components\Xconfig\XconfigApi; final class Conf extends ServerInfoConstants { public function __construct() { EventsApi::on('conf', function (array $conf) { if (XconfigApi::isDisabled($this->ID)) { return $conf; } $conf[$this->ID] = array( 'serverName' => $this->getServerInfo('SERVER_NAME'), 'serverUtcTime' => UtilsTime::getUtcTime(), 'serverTime' => UtilsTime::getTime(), 'serverUptime' => UtilsTime::getUptime(), 'serverIp' => XconfigApi::isDisabled('serverIp') ? '-' : $this->getServerInfo('SERVER_ADDR'), 'serverSoftware' => $this->getServerInfo('SERVER_SOFTWARE'), 'phpVersion' => \PHP_VERSION, 'cpuModel' => UtilsCpu::getModel(), 'serverOs' => php_uname(), 'scriptPath' => __FILE__, 'diskUsage' => array( 'value' => UtilsDisk::getTotal() - UtilsDisk::getFree(), 'max' => UtilsDisk::getTotal(), ), ); return $conf; }); } private function getServerInfo($key) { return isset($_SERVER[$key]) ? $_SERVER[$key] : ''; } } namespace InnStudio\Prober\Components\ServerInfo; final class ServerInfo { public function __construct() { new Conf(); new Fetch(); new ServerInitIpv4(); new ServerInitIpv6(); new ServerLocationIpv4(); } } namespace InnStudio\Prober\Components\ServerInfo; use InnStudio\Prober\Components\Events\EventsApi; use InnStudio\Prober\Components\Rest\RestResponse; use InnStudio\Prober\Components\Utils\UtilsServerIp; use InnStudio\Prober\Components\Xconfig\XconfigApi; final class ServerInitIpv6 extends ServerInfoConstants { public function __construct() { EventsApi::on('init', function ($action) { if ('serverIpv6' !== $action) { return $action; } if (XconfigApi::isDisabled($this->ID)) { return $action; } if (XconfigApi::isDisabled($this->FEATURE_SERVER_IP)) { return $action; } $response = new RestResponse(); $response->setData(array( 'ip' => UtilsServerIp::getV6(), ))->json()->end(); }); } } namespace InnStudio\Prober\Components\Bootstrap; use InnStudio\Prober\Components\Config\ConfigApi; use InnStudio\Prober\Components\Events\EventsApi; final class Conf extends BootstrapConstants { public function __construct() { EventsApi::on('conf', function (array $conf) { $conf[$this->ID] = array( 'isDev' => XPROBER_IS_DEV, 'version' => ConfigApi::$APP_VERSION, 'appName' => ConfigApi::$APP_NAME, 'appUrl' => ConfigApi::$APP_URL, 'appConfigUrls' => ConfigApi::$APP_CONFIG_URLS, 'appConfigUrlDev' => ConfigApi::$APP_CONFIG_URL_DEV, 'authorUrl' => ConfigApi::$AUTHOR_URL, 'authorName' => ConfigApi::$AUTHOR_NAME, 'authorization' => isset($_SERVER['HTTP_AUTHORIZATION']) ? $_SERVER['HTTP_AUTHORIZATION'] : '', ); return $conf; }); } } namespace InnStudio\Prober\Components\Bootstrap; use InnStudio\Prober\Components\Config\ConfigApi; use InnStudio\Prober\Components\Events\EventsApi; final class Render { public function __construct() { $appName = ConfigApi::$APP_NAME; $version = ConfigApi::$APP_VERSION; $scriptConf = json_encode(EventsApi::emit('conf', array())); $styleUrl = \defined('XPROBER_IS_DEV') && XPROBER_IS_DEV ? 'app.css' : "?action=style&v={$version}"; $scriptUrl = \defined('XPROBER_IS_DEV') && XPROBER_IS_DEV ? 'app.js' : "?action=script&v={$version}"; echo << {$appName} v{$version}
⏳ Loading...
HTML; } } namespace InnStudio\Prober\Components\Bootstrap; final class Bootstrap { public function __construct() { new Action(); new Conf(); new Render(); } } namespace InnStudio\Prober\Components\Bootstrap; class BootstrapConstants { protected $ID = 'bootstrap'; } namespace InnStudio\Prober\Components\Bootstrap; use InnStudio\Prober\Components\Events\EventsApi; final class Action { public function __construct() { $action = (string) filter_input(\INPUT_GET, 'action', \FILTER_DEFAULT); EventsApi::emit('init', $action); if ($action) { http_response_code(400); exit; } } } namespace InnStudio\Prober\Components\Xconfig; use InnStudio\Prober\Components\Utils\UtilsApi; final class XconfigApi { private static $conf; private static $filename = 'xconfig.json'; public static function isDisabled($id) { return \in_array($id, self::get('disabled') ?: array(), true); } public static function getNodes() { return self::get('nodes') ?: array(); } public static function get($id = null) { self::setConf(); if ($id) { return isset(self::$conf[$id]) ? self::$conf[$id] : null; } return self::$conf; } private static function getFilePath() { if ( ! \defined('\\XPROBER_DIR')) { return ''; } if (\defined('\\XPROBER_IS_DEV') && XPROBER_IS_DEV) { return \dirname(XPROBER_DIR) . '/' . self::$filename; } return XPROBER_DIR . '/' . self::$filename; } private static function setConf() { if (null !== self::$conf) { return; } if ( ! is_readable(self::getFilePath())) { self::$conf = null; return; } $conf = UtilsApi::jsonDecode(file_get_contents(self::getFilePath())); if ( ! $conf) { self::$conf = null; return; } self::$conf = $conf; } } namespace InnStudio\Prober\Components\Updater; use InnStudio\Prober\Components\Config\ConfigApi; use InnStudio\Prober\Components\Events\EventsApi; use InnStudio\Prober\Components\Rest\RestResponse; use InnStudio\Prober\Components\Rest\StatusCode; final class Updater { public function __construct() { EventsApi::on('init', function ($action) { if ('update' !== $action) { return $action; } $response = new RestResponse(); if ( ! is_writable(__FILE__)) { $response->setStatus(StatusCode::$INSUFFICIENT_STORAGE)->end(); } $code = ''; foreach (ConfigApi::$UPDATE_PHP_URLS as $url) { $code = (string) file_get_contents($url); if ('' !== trim($code)) { break; } } if ( ! $code) { $response->setStatus(StatusCode::$NOT_FOUND)->end(); } if (\defined('XPROBER_IS_DEV') && XPROBER_IS_DEV) { $response->end(); } if ((bool) file_put_contents(__FILE__, $code)) { if (\function_exists('opcache_invalidate')) { opcache_invalidate(__FILE__, true) || opcache_reset(); } $response->end(); } $response->setStatus(StatusCode::$INTERNAL_SERVER_ERROR)->end(); }); } } namespace InnStudio\Prober\Components\Fetch; use InnStudio\Prober\Components\Events\EventsApi; use InnStudio\Prober\Components\Rest\RestResponse; final class Fetch { public function __construct() { EventsApi::on('init', function ($action) { if ('fetch' === $action) { EventsApi::emit('fetchBefore'); $response = new RestResponse(EventsApi::emit('fetch', array())); $response->json()->end(); } return $action; }, 100); } } namespace InnStudio\Prober\Components\ServerBenchmark; class ServerBenchmarkConstants { protected $ID = 'serverBenchmark'; } namespace InnStudio\Prober\Components\ServerBenchmark; use InnStudio\Prober\Components\Events\EventsApi; final class FetchBefore extends ServerBenchmarkApi { public function __construct() { EventsApi::on('fetchBefore', array($this, 'filter')); EventsApi::on('fetchNodesBefore', array($this, 'filter')); EventsApi::on('fetchNodeBefore', array($this, 'filter')); } public function filter() { while ($this->isRunning()) { sleep(2); } } } namespace InnStudio\Prober\Components\ServerBenchmark; use InnStudio\Prober\Components\Events\EventsApi; use InnStudio\Prober\Components\Xconfig\XconfigApi; final class Conf extends ServerBenchmarkConstants { public function __construct() { EventsApi::on('conf', function (array $conf) { $conf[$this->ID] = array( 'disabledMyServerBenchmark' => XconfigApi::isDisabled('myServerBenchmark'), ); return $conf; }); } } namespace InnStudio\Prober\Components\ServerBenchmark; final class ServerBenchmark { public function __construct() { new Init(); new Conf(); new FetchBefore(); } } namespace InnStudio\Prober\Components\ServerBenchmark; use InnStudio\Prober\Components\Xconfig\XconfigApi; class ServerBenchmarkApi { public function getTmpRecorderPath() { return sys_get_temp_dir() . \DIRECTORY_SEPARATOR . 'xproberBenchmarkCool'; } public function setRecorder(array $data) { return (bool) file_put_contents($this->getTmpRecorderPath(), json_encode(array_merge($this->getRecorder(), $data))); } public function setExpired() { return (bool) $this->setRecorder(array( 'expired' => (int) $_SERVER['REQUEST_TIME'] + $this->cooldown(), )); } public function setIsRunning($isRunning) { return (bool) $this->setRecorder(array( 'isRunning' => true === (bool) $isRunning ? 1 : 0, )); } public function isRunning() { $recorder = $this->getRecorder(); return isset($recorder['isRunning']) ? 1 === (int) $recorder['isRunning'] : false; } public function getRemainingSeconds() { $recorder = $this->getRecorder(); $expired = isset($recorder['expired']) ? (int) $recorder['expired'] : 0; if ( ! $expired) { return 0; } return $expired > (int) $_SERVER['REQUEST_TIME'] ? $expired - (int) $_SERVER['REQUEST_TIME'] : 0; } public function getPointsByTime($time) { return pow(10, 3) - (int) ($time * pow(10, 3)); } public function getCpuPoints() { $data = 'inn-studio.com'; $hash = array('md5', 'sha512', 'sha256', 'crc32'); $start = microtime(true); $i = 0; while (microtime(true) - $start < .5) { foreach ($hash as $v) { hash($v, $data); } ++$i; } return $i; } public function getWritePoints() { $tmpDir = sys_get_temp_dir(); if ( ! is_writable($tmpDir)) { return 0; } $i = 0; $start = microtime(true); while (microtime(true) - $start < .5) { $filePath = "{$tmpDir}/innStudioWriteBenchmark:{$i}"; clearstatcache(true, $filePath); file_put_contents($filePath, $filePath); unlink($filePath); ++$i; } return $i; } public function getReadPoints() { $tmpDir = sys_get_temp_dir(); if ( ! is_readable($tmpDir)) { return 0; } $i = 0; $start = microtime(true); $filePath = "{$tmpDir}/innStudioIoBenchmark"; if ( ! file_exists($filePath)) { file_put_contents($filePath, 'innStudioReadBenchmark'); } while (microtime(true) - $start < .5) { clearstatcache(true, $filePath); file_get_contents($filePath); ++$i; } return $i; } public function getPoints() { return array( 'cpu' => $this->getMedian(array( $this->getCpuPoints(), $this->getCpuPoints(), $this->getCpuPoints(), )), 'write' => $this->getMedian(array( $this->getWritePoints(), $this->getWritePoints(), $this->getWritePoints(), )), 'read' => $this->getMedian(array( $this->getReadPoints(), $this->getReadPoints(), $this->getReadPoints(), )), ); } private function cooldown() { return (int) XconfigApi::get('serverBenchmarkCd') ?: 60; } private function getRecorder() { $path = $this->getTmpRecorderPath(); $defaults = array( 'expired' => 0, 'running' => 0, ); if ( ! @is_readable($path)) { return $defaults; } $data = (string) file_get_contents($path); if ( ! $data) { return $defaults; } $data = json_decode($data, true); if ( ! $data) { return $defaults; } return array_merge($defaults, $data); } private function getMedian(array $arr) { $count = \count($arr); sort($arr); $mid = floor(($count - 1) / 2); return ($arr[$mid] + $arr[$mid + 1 - $count % 2]) / 2; } } namespace InnStudio\Prober\Components\ServerBenchmark; use InnStudio\Prober\Components\Events\EventsApi; use InnStudio\Prober\Components\Rest\RestResponse; use InnStudio\Prober\Components\Rest\StatusCode; use InnStudio\Prober\Components\Xconfig\XconfigApi; final class Init extends ServerBenchmarkApi { public function __construct() { EventsApi::on('init', function ($action) { if (XconfigApi::isDisabled('myServerBenchmark')) { return $action; } if ('benchmark' !== $action) { return $action; } $this->render(); }); } private function render() { $remainingSeconds = $this->getRemainingSeconds(); $response = new RestResponse(); if ($remainingSeconds) { $response->setStatus(StatusCode::$TOO_MANY_REQUESTS); $response->setData(array( 'seconds' => $remainingSeconds, ))->json()->end(); } set_time_limit(0); $this->setExpired(); $this->setIsRunning(true); $marks = $this->getPoints(); $this->setIsRunning(false); $response->setData(array( 'marks' => $marks, ))->json()->end(); } } namespace InnStudio\Prober\Components\Timezone; use InnStudio\Prober\Components\Events\EventsApi; final class Timezone { public function __construct() { EventsApi::on('init', function ($action) { if ( ! \ini_get('date.timezone')) { date_default_timezone_set('PRC'); } return $action; }, 1); } } namespace InnStudio\Prober\Components\TemperatureSensor; use Exception; use InnStudio\Prober\Components\Config\ConfigApi; use InnStudio\Prober\Components\Events\EventsApi; use InnStudio\Prober\Components\Rest\RestResponse; use InnStudio\Prober\Components\Rest\StatusCode; final class TemperatureSensor { public function __construct() { EventsApi::on('init', function ($action) { if ('temperature-sensor' !== $action) { return $action; } $response = new RestResponse(); $items = $this->getItems(); if ($items) { $response->setData($items)->json()->end(); } $cpuTemp = $this->getCpuTemp(); if ( ! $cpuTemp) { $response->setStatus(StatusCode::$NO_CONTENT); } $items[] = array( 'id' => 'cpu', 'name' => 'CPU', 'celsius' => round((float) $cpuTemp / 1000, 2), ); $response->setData($items)->json()->end(); }); } private function curl($url) { if ( ! \function_exists('curl_init')) { return; } $ch = curl_init(); curl_setopt_array($ch, array( \CURLOPT_URL => $url, \CURLOPT_RETURNTRANSFER => true, )); $res = curl_exec($ch); curl_close($ch); return (string) $res; } private function getItems() { $items = array(); foreach (ConfigApi::$APP_TEMPERATURE_SENSOR_PORTS as $port) { $res = $this->curl(ConfigApi::$APP_TEMPERATURE_SENSOR_URL . ":{$port}"); if ( ! $res) { continue; } $item = json_decode($res, true); if ( ! $item || ! \is_array($item)) { continue; } $items = $item; break; } return $items; } private function getCpuTemp() { try { $path = '/sys/class/thermal/thermal_zone0/temp'; return file_exists($path) ? (int) file_get_contents($path) : 0; } catch (Exception $e) { return 0; } } } namespace InnStudio\Prober\Components\PhpExtensions; use InnStudio\Prober\Components\Events\EventsApi; use InnStudio\Prober\Components\Xconfig\XconfigApi; final class Conf extends PhpExtensionsConstants { public function __construct() { EventsApi::on('conf', function (array $conf) { if (XconfigApi::isDisabled($this->ID)) { return $conf; } $jitEnabled = false; if (\function_exists('opcache_get_status')) { $status = opcache_get_status(); if (isset($status['jit']['enabled']) && true === $status['jit']['enabled']) { $jitEnabled = true; } } $conf[$this->ID] = array( 'redis' => \extension_loaded('redis') && class_exists('Redis'), 'sqlite3' => \extension_loaded('sqlite3') && class_exists('Sqlite3'), 'memcache' => \extension_loaded('memcache') && class_exists('Memcache'), 'memcached' => \extension_loaded('memcached') && class_exists('Memcached'), 'opcache' => \function_exists('opcache_get_status'), 'opcacheEnabled' => $this->isOpcEnabled(), 'opcacheJitEnabled' => $jitEnabled, 'swoole' => \extension_loaded('swoole') && \function_exists('swoole_version'), 'imagick' => \extension_loaded('imagick') && class_exists('Imagick'), 'gmagick' => \extension_loaded('gmagick'), 'exif' => \extension_loaded('exif') && \function_exists('exif_imagetype'), 'fileinfo' => \extension_loaded('fileinfo'), 'simplexml' => \extension_loaded('simplexml'), 'sockets' => \extension_loaded('sockets') && \function_exists('socket_accept'), 'mysqli' => \extension_loaded('mysqli') && class_exists('mysqli'), 'zip' => \extension_loaded('zip') && class_exists('ZipArchive'), 'mbstring' => \extension_loaded('mbstring') && \function_exists('mb_substr'), 'phalcon' => \extension_loaded('phalcon'), 'xdebug' => \extension_loaded('xdebug'), 'zendOptimizer' => \function_exists('zend_optimizer_version'), 'ionCube' => \extension_loaded('ioncube loader'), 'sourceGuardian' => \extension_loaded('sourceguardian'), 'ldap' => \function_exists('ldap_connect'), 'curl' => \function_exists('curl_init'), 'loadedExtensions' => XconfigApi::isDisabled('phpExtensionsLoaded') ? array() : get_loaded_extensions(), ); return $conf; }); } private function isOpcEnabled() { $isOpcEnabled = \function_exists('opcache_get_configuration'); if ($isOpcEnabled) { $isOpcEnabled = opcache_get_configuration(); $isOpcEnabled = isset($isOpcEnabled['directives']['opcache.enable']) && true === $isOpcEnabled['directives']['opcache.enable']; } return $isOpcEnabled; } } namespace InnStudio\Prober\Components\PhpExtensions; class PhpExtensionsConstants { protected $ID = 'phpExtensions'; } namespace InnStudio\Prober\Components\PhpExtensions; final class PhpExtensions { public function __construct() { new Conf(); } } namespace InnStudio\Prober\Components\NetworkStats; use InnStudio\Prober\Components\Events\EventsApi; use InnStudio\Prober\Components\Utils\UtilsApi; use InnStudio\Prober\Components\Utils\UtilsNetwork; use InnStudio\Prober\Components\Xconfig\XconfigApi; final class Fetch extends NetworkStatsConstants { public function __construct() { if ( ! UtilsApi::isWin()) { EventsApi::on('fetch', array($this, 'filter')); EventsApi::on('nodes', array($this, 'filter')); } } public function filter(array $items) { if (XconfigApi::isDisabled($this->ID)) { return $items; } $items[$this->ID] = array( 'networks' => UtilsNetwork::getStats(), 'timestamp' => time(), ); return $items; } } namespace InnStudio\Prober\Components\NetworkStats; use InnStudio\Prober\Components\Events\EventsApi; use InnStudio\Prober\Components\Utils\UtilsApi; use InnStudio\Prober\Components\Utils\UtilsNetwork; use InnStudio\Prober\Components\Xconfig\XconfigApi; final class Conf extends NetworkStatsConstants { public function __construct() { UtilsApi::isWin() || EventsApi::on('conf', function (array $conf) { if (XconfigApi::isDisabled($this->ID)) { return $conf; } $conf[$this->ID] = array( 'networks' => UtilsNetwork::getStats(), 'timestamp' => time(), ); return $conf; }); } } namespace InnStudio\Prober\Components\NetworkStats; final class NetworkStats { public function __construct() { new Conf(); new Fetch(); } } namespace InnStudio\Prober\Components\NetworkStats; class NetworkStatsConstants { protected $ID = 'networkStats'; } namespace InnStudio\Prober\Components\Config; class ConfigApi { public static $APP_VERSION = '8.16'; public static $APP_NAME = '海纳思系统探针'; public static $APP_URL = 'https://github.com/teasiu/x-prober'; public static $APP_CONFIG_URLS = array('https://raw.histb.eu.org/teasiu/x-prober/master/AppConfig.json'); public static $APP_CONFIG_URL_DEV = 'http://localhost:8000/AppConfig.json'; public static $APP_TEMPERATURE_SENSOR_URL = 'http://127.0.0.1'; public static $APP_TEMPERATURE_SENSOR_PORTS = array(2048, 4096); public static $AUTHOR_URL = 'https://www.ecoo.top'; public static $UPDATE_PHP_URLS = array('https://www.ecoo.top', 'https://bbs.histb.com'); public static $AUTHOR_NAME = '海纳思系统'; public static $LATEST_PHP_STABLE_VERSION = '8'; public static $LATEST_NGINX_STABLE_VERSION = '1.22.0'; } namespace InnStudio\Prober\Components\PhpInfo; use InnStudio\Prober\Components\Config\ConfigApi; use InnStudio\Prober\Components\Events\EventsApi; use InnStudio\Prober\Components\Rest\RestResponse; use InnStudio\Prober\Components\Rest\StatusCode; use InnStudio\Prober\Components\Xconfig\XconfigApi; final class FetchLatestPhpVersion extends PhpInfoConstants { public function __construct() { EventsApi::on('init', function ($action) { if (XconfigApi::isDisabled($this->ID)) { return $action; } if ('latest-php-version' !== $action) { return $action; } $response = new RestResponse(); $content = file_get_contents('https://www.php.net/releases/?json'); if ( ! $content) { $response->setStatus(StatusCode::$NOT_FOUND)->end(); } $versions = json_decode($content, true); if ( ! $versions) { $response->setStatus(StatusCode::$NOT_FOUND)->end(); } $version = isset($versions[ConfigApi::$LATEST_PHP_STABLE_VERSION]['version']) ? $versions[ConfigApi::$LATEST_PHP_STABLE_VERSION]['version'] : ''; if ( ! $version) { $response->setStatus(StatusCode::$NOT_FOUND)->end(); } $response->setData(array( 'version' => $version, 'date' => $versions[ConfigApi::$LATEST_PHP_STABLE_VERSION]['date'], ))->json()->end(); }); } } namespace InnStudio\Prober\Components\PhpInfo; use InnStudio\Prober\Components\Events\EventsApi; use InnStudio\Prober\Components\Xconfig\XconfigApi; final class Conf extends PhpInfoConstants { public function __construct() { EventsApi::on('conf', function (array $conf) { if (XconfigApi::isDisabled($this->ID)) { return $conf; } $conf[$this->ID] = array( 'version' => \PHP_VERSION, 'sapi' => \PHP_SAPI, 'displayErrors' => (bool) \ini_get('display_errors'), 'errorReporting' => (int) \ini_get('error_reporting'), 'memoryLimit' => (string) \ini_get('memory_limit'), 'postMaxSize' => (string) \ini_get('post_max_size'), 'uploadMaxFilesize' => (string) \ini_get('upload_max_filesize'), 'maxInputVars' => (int) \ini_get('max_input_vars'), 'maxExecutionTime' => (int) \ini_get('max_execution_time'), 'defaultSocketTimeout' => (int) \ini_get('default_socket_timeout'), 'allowUrlFopen' => (bool) \ini_get('allow_url_fopen'), 'smtp' => (bool) \ini_get('SMTP'), 'disableFunctions' => XconfigApi::isDisabled('phpDisabledFunctions') ? array() : array_filter(explode(',', (string) \ini_get('disable_functions'))), 'disableClasses' => XconfigApi::isDisabled('phpDisabledClasses') ? array() : array_filter(explode(',', (string) \ini_get('disable_classes'))), ); return $conf; }); } } namespace InnStudio\Prober\Components\PhpInfo; final class PhpInfo { public function __construct() { new Conf(); new FetchLatestPhpVersion(); } } namespace InnStudio\Prober\Components\PhpInfo; class PhpInfoConstants { protected $ID = 'phpInfo'; } namespace InnStudio\Prober\Components\Ping; use InnStudio\Prober\Components\Events\EventsApi; use InnStudio\Prober\Components\Xconfig\XconfigApi; final class Conf extends PingConstants { public function __construct() { EventsApi::on('conf', function (array $conf) { if (XconfigApi::isDisabled($this->ID)) { return $conf; } $conf[$this->ID] = array(); return $conf; }); } } namespace InnStudio\Prober\Components\Ping; class PingConstants { protected $ID = 'ping'; } namespace InnStudio\Prober\Components\Ping; use InnStudio\Prober\Components\Events\EventsApi; use InnStudio\Prober\Components\Rest\RestResponse; use InnStudio\Prober\Components\Xconfig\XconfigApi; final class Ping extends PingConstants { public function __construct() { new Conf(); EventsApi::on('init', function ($action) { if (XconfigApi::isDisabled($this->ID)) { return $action; } if ($this->ID !== $action) { return $action; } $response = new RestResponse(array( 'time' => \defined('XPROBER_TIMER') ? microtime(true) - XPROBER_TIMER : 0, )); $response->json()->end(); }); } } namespace InnStudio\Prober\Components\Script; use InnStudio\Prober\Components\Events\EventsApi; use InnStudio\Prober\Components\Utils\UtilsApi; final class Script { public function __construct() { EventsApi::on('init', function ($action) { if ('script' !== $action) { return $action; } $this->output(); }); } private function output() { UtilsApi::setFileCacheHeader(); header('Content-type: application/javascript'); echo <<<'HTML' !function(){var e={640:function(e,t,n){"use strict";var r=n(742),a={"text/plain":"Text","text/html":"Url",default:"Text"};e.exports=function(e,t){var n,i,o,l,s,u,c=!1;t||(t={}),n=t.debug||!1;try{if(o=r(),l=document.createRange(),s=document.getSelection(),(u=document.createElement("span")).textContent=e,u.ariaHidden="true",u.style.all="unset",u.style.position="fixed",u.style.top=0,u.style.clip="rect(0, 0, 0, 0)",u.style.whiteSpace="pre",u.style.webkitUserSelect="text",u.style.MozUserSelect="text",u.style.msUserSelect="text",u.style.userSelect="text",u.addEventListener("copy",(function(r){if(r.stopPropagation(),t.format)if(r.preventDefault(),void 0===r.clipboardData){n&&console.warn("unable to use e.clipboardData"),n&&console.warn("trying IE specific stuff"),window.clipboardData.clearData();var i=a[t.format]||a.default;window.clipboardData.setData(i,e)}else r.clipboardData.clearData(),r.clipboardData.setData(t.format,e);t.onCopy&&(r.preventDefault(),t.onCopy(r.clipboardData))})),document.body.appendChild(u),l.selectNodeContents(u),s.addRange(l),!document.execCommand("copy"))throw new Error("copy command was unsuccessful");c=!0}catch(r){n&&console.error("unable to copy using execCommand: ",r),n&&console.warn("trying IE specific stuff");try{window.clipboardData.setData(t.format||"text",e),t.onCopy&&t.onCopy(window.clipboardData),c=!0}catch(r){n&&console.error("unable to copy using clipboardData: ",r),n&&console.error("falling back to prompt"),i=function(e){var t=(/mac os x/i.test(navigator.userAgent)?"\u2318":"Ctrl")+"+C";return e.replace(/#{\s*key\s*}/g,t)}("message"in t?t.message:"Copy to clipboard: #{key}, Enter"),window.prompt(i,e)}}finally{s&&("function"==typeof s.removeRange?s.removeRange(l):s.removeAllRanges()),u&&document.body.removeChild(u),o()}return c}},448:function(e,t,n){"use strict";var r=n(294),a=n(840);function i(e){for(var t="https://reactjs.org/docs/error-decoder.html?invariant="+e,n=1;n