PHP Classes

File: example.php

Recommend this page to a friend!
  Classes of Henrik Skov   Network Tools Queued   example.php   Download  
File: example.php
Role: Example script
Content typex: text/plain
Description: Short example
Class: Network Tools Queued
Asynchronous diagnostics to test Internet services
Author: By
Last change: Fixed some errors that stem from the fact that the class is used from within another class
Date: 4 days ago
Size: 13,792 bytes
 

Contents

Class file image Download
<?php require_once __DIR__ . '/vendor/autoload.php'; require_once __DIR__ . '/NetworkToolsQueued.php'; use Colors\Color; use function Laravel\Prompts\spin; function isWSL(): bool { return str_contains(strtolower(php_uname('r')), 'microsoft') || file_exists('/proc/sys/fs/binfmt_misc/WSLInterop'); } /** * Open an URL in system browser * * * @param string $url * @return void */ function openBrowser(string $url) : void { if (isWSL()) { if (strpos($url, 'file://') === 0) { $filePath = substr($url, 7); // Remove 'file://' // Copy to accessible location and open with cmd $windowsTempFile = '/mnt/c/Windows/Temp/' . basename($filePath); shell_exec("cp " . escapeshellarg($filePath) . " " . escapeshellarg($windowsTempFile)); $windowsPath = 'C:\\Windows\\Temp\\' . basename($filePath); shell_exec("cmd.exe /c start \"\" \"" . $windowsPath . "\" 2>/dev/null"); } else { shell_exec("wslview \"$url\""); } } else { shell_exec("xdg-open \"$url\""); } } class StdinHelper { /** * Check if there is any data available on STDIN using select() * This is the most reliable method for real-time checking * * @param int $timeout Timeout in seconds (0 for immediate return) * @return bool True if data is available, false otherwise */ public static function hasDataSelect(float $timeout = 0): bool { $read = array(STDIN); $write = null; $except = null; return stream_select($read, $write, $except, $timeout) > 0; } /** * Forward stdin to a subprocess * * * @param string $cmd * @return void */ public static function forwardStdInTo(string $cmd) : void { // Make STDIN non-blocking stream_set_blocking(STDIN, false); // Create a subprocess (example using 'cat', replace with your desired command) $descriptorspec = array( 0 => array("pipe", "r"), // stdin 1 => array("pipe", "w"), // stdout 2 => array("pipe", "w") // stderr ); $process = proc_open($cmd, $descriptorspec, $pipes); if (is_resource($process)) { // Make subprocess input/output streams non-blocking stream_set_blocking($pipes[0], false); stream_set_blocking($pipes[1], false); stream_set_blocking($pipes[2], false); while (true) { // Read from STDIN $input = fgets(STDIN); if ($input !== false) { // Write to subprocess stdin fwrite($pipes[0], $input); // Flush the pipe to ensure immediate writing fflush($pipes[0]); } // Read from subprocess stdout $output = fgets($pipes[1]); if ($output !== false) { echo $output; } // Read from subprocess stderr $error = fgets($pipes[2]); if ($error !== false) { fwrite(STDERR, $error); } // Small delay to prevent CPU overload usleep(10000); // 10ms delay // Check if STDIN has closed if (feof(STDIN)) { break; } } // Clean up fclose($pipes[0]); fclose($pipes[1]); fclose($pipes[2]); // Close the process proc_close($process); } } /** * Check if STDIN is connected to a pipe or redirected file * Useful for detecting if script is running interactively * * @return bool True if STDIN is a pipe/file, false if it's a terminal */ public static function isPiped(): bool { return !posix_isatty(STDIN); } /** * Check if there is any data using non-blocking read * This method might be less reliable but doesn't require stream_select * * @return bool True if data is available, false otherwise */ public static function hasDataNonBlocking(): bool { static $buffer = null; // If we previously read a byte, return true if ($buffer !== null) { return true; } // Store current blocking state $meta = stream_get_meta_data(STDIN); $blocking = $meta['blocked'] ?? true; // Temporarily set to non-blocking stream_set_blocking(STDIN, false); // Try to read one byte $char = fgetc(STDIN); // Restore original blocking state stream_set_blocking(STDIN, $blocking); if ($char !== false) { // Store the character for later retrieval $buffer = $char; return true; } return false; } public static function getStdInData(): string { static $buffer = null; $data = ''; // If we previously read a byte, prepend it to the read data if ($buffer !== null) { $data .= $buffer; $buffer = null; } // Read the rest of the input $data .= stream_get_contents(STDIN); return $data; } /** * Comprehensive check that combines multiple methods * * @return array Array with detailed information about STDIN state */ public static function getStdinInfo(): array { return [ 'has_data' => self::hasDataSelect(), 'is_piped' => self::isPiped(), 'is_readable' => is_readable("php://stdin"), 'stream_type' => stream_get_meta_data(STDIN)['stream_type'], 'blocked' => stream_get_meta_data(STDIN)['blocked'], 'eof' => feof(STDIN) ]; } } //============================================================ // MAIN EXAMPLE CODE //============================================================ try { define('OPS',[ 'a', 'mx', 'txt', 'cert', 'cname', 'soa', 'spf', 'ptr', 'tcp', 'smtp', 'http', 'https', 'ping', 'simulatedping', 'trace', 'simulatedtrace', 'fulldomain', 'fullip', 'securityscan', 'emailanalysis', 'quickcheck', 'serverscan', 'whois' ]); $output = NULL; if ($idx = array_search('--output', $_SERVER['argv'])) { $output = $_SERVER['argv'][$idx+1]; } $c = new Color(); // See: https://github.com/kevinlebrun/colors.php $operation = $_SERVER['argv'][1]; $operation = strtolower($operation); // Validation if (!in_array($operation, OPS)) { throw new Exception(sprintf('Invalid operation: "%s" - Valid operations: %s', $operation, implode(', ', OPS))); } $input = $_SERVER['argv'][2]; $stdInData = ''; if (StdInHelper::hasDataSelect()) { $stdInData = StdinHelper::getStdInData(); } $inputs = match(TRUE) { (!empty($input) && is_file($input)) => file($input, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES), (!empty($stdInData)) => explode(PHP_EOL, trim($stdInData)), (!empty($input) && !is_file($input)) => [$input], default => [] }; // Abort if no inputs if (empty($inputs)) { throw new Exception(sprintf('No inputs for "%s" operation - Use an IP or domain as argument or send a list on STDIN', $operation)); } $tools = new NetworkToolsQueued(); // Enable auto-PTR if flag set //if ($this->enableAutoPtr) $tools->enableAutoPTR(); // Enable problem summary //if ($this->enableProblemSummary) $tools->enableProblemSummary(); // Determine if operation requires IP or domain $requiresIP = in_array($operation, ['ping', 'simulatedping', 'ptr']); $requiresDomain = !$requiresIP; // Validate and queue all targets foreach($inputs as $target) { $target = trim($target); if (empty($target)) continue; // Handle special chained operations if (in_array($operation, ['fulldomain', 'securityscan', 'emailanalysis', 'quickcheck', 'whois'])) { // Domain operations if (filter_var($target, FILTER_VALIDATE_DOMAIN) === FALSE) { throw new Exception(sprintf('Invalid target for "%s": "%s" - Requires a domain', $operation, $target)); } if ($operation == 'fulldomain') { $tools->fulldomain($target, in_array('--portscan', $_SERVER['argv'])); } else { $tools->$operation($target); } } elseif ($operation === 'fullip') { // IP operation if (filter_var($target, FILTER_VALIDATE_IP) === FALSE) { throw new Exception(sprintf('Invalid target for "%s": "%s" - Requires an IP', $operation, $target)); } $tools->$operation($target, TRUE, TRUE); } elseif ($operation === 'serverscan') { // Works with both IP and domain $tools->$operation($target); } else { // Original single operations if ($requiresIP) { if (filter_var($target, FILTER_VALIDATE_IP) === FALSE) { throw new Exception(sprintf('Invalid target for "%s": "%s" - Requires an IP', $operation, $target)); } } elseif ($requiresDomain) { if (empty($target) || preg_match('/^[a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,}$/i', $target) === 0) { throw new Exception(sprintf('Invalid target for "%s": "%s" - Requires a domain', $operation, $target)); } } $tools->$operation($target); } } // JSON output mode if (in_array('--json', $_SERVER['argv'])) { if (posix_isatty(STDOUT)) { $m = ($output) ? '<light_yellow>One moment please ...</light_yellow> - <light_cyan>Generating report</light_cyan> - <white>Will write</white> <light_green>'.$this->output.'</light_green> <white>momentarily...</white>' : '<light_yellow>One moment please ...</light_yellow> - <light_cyan>Generating report</light_cyan>'; $array = spin(function() use($tools) { $tools->exec(); return $tools->getResults(); }, $c->colorize($m)); // Group by target $byTarget = []; foreach ($array as $r) { $byTarget[$r['target']][] = $r; } ksort($byTarget); // Calculate and add scores to output $scores = $tools->getTargetScores(); $output = [ 'targets' => $byTarget, 'scores' => $scores ]; if ($output) { file_put_contents($output, json_encode($output, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES)); echo self::TAB.$c->colorize("<light_green>&#10003;</light_green> Results written to: <light_cyan>{$output}</light_cyan>\n"); } else { echo json_encode($output, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES) . "\n"; } } else { $tools->exec(); $array = $tools->getResults(); // Group by target $byTarget = []; foreach ($array as $r) { $byTarget[$r['target']][] = $r; } ksort($byTarget); // Calculate and add scores to output $scores = $tools->getTargetScores(); $output = [ 'targets' => $byTarget, 'scores' => $scores ]; if ($output) { file_put_contents($output, json_encode($output, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES)); } else { echo json_encode($output, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES) . "\n"; } } return; } // HTML output mode (default) if (posix_isatty(STDOUT)) { $html = spin(function() use($tools) { // Spin is part of Laravel\Prompts\ package $tools->exec(); // Enable grouping by target for better organization return $tools->getReport(TRUE); }, $c->colorize('<light_yellow>One moment please ...</light_yellow> - <light_cyan>Generating report</light_cyan> - <white>Will open in</white> <light_green>browser</light_green> <white>momentarily...</white>')); } else { $tools->exec(); $html = $tools->getReport(TRUE); // Group by target } // Save and open HTML report $file = tempnam(sys_get_temp_dir(), 'nettool_') . '.html'; file_put_contents($file, $html); openBrowser('file://'.$file); } catch(Exception $ex) { echo('ERROR :: ' . $ex->getMessage()); exit(1); }