Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/usr/bin/sh
- searchPathForPhp() {
- ( IFS=:
- for p in $PATH; do
- phppath="$(command -v "$p"/php[0-9]*)" 2>/dev/null
- if test "0$?" -eq 0; then echo "$phppath" | tail -n1; return 0; fi
- done
- )
- return 1;
- }
- zenitylogin() {
- prompter="$1"; shift 1
- if test -z "$username" -eq 0; then
- msg='Please enter username and password so that PHP can be installed so things can continue to work smoothly'
- logininfo="$("$prompter" --forms --text="$msg" --add-entry='Username' --add-password='Password' --separator='
- ')"
- # If the user clicked "cancel" or a Zenity error, then don't even try:
- if test "0$?" -ne 0; then exit 1; fi
- username="$(printf '%s' "$logininfo" | head -n1)"
- password="$(printf '%s' "$logininfo" | tail -n1)"
- fi
- printf "%s\n" "$password" | sudo -S -u "$username" -- "$@"
- }
- run-su-cmd() {
- sucmd="$1"; program="$2"; shift 2
- "$sucmd" -c "'""$program""'"' "$@"' - "$USER" -- "$0" "$@"
- }
- phppath="$(command -v php)" 2>/dev/null
- if test "0$?" -ne 0; then
- # calling searchPathForPhp will set the status code to 1 if not available
- phppath="$(searchPathForPhp)"
- fi
- if test "0$?" -ne 0; then
- # Prompt the user about installing packages and confirm
- confmsg="$(pwd) needs to install PHP in order to work. Are you OKAY with this script installing PHP automatically?"
- if test -x "$(command -v xmessage)" 2>/dev/null; then
- test "$(xmessage -buttons Yes,No -default No -print "$confmsg")" = "No"
- else
- # Prompt the user about installing packages
- test "$(osascript -e 'display dialog "'"$confmsg"'" buttons {"Yes", "No"} default button "No"')" = "No"
- fi
- if test "0$?" -ne 0; then exit 1; fi # Exit if we don't have consent
- e=""
- if test "$(id -u)" -ne 0; then
- case "$-" in
- "*i*")
- if test -x "$(command -v sudo)" 2>/dev/null; then
- # Most Linux distros
- e=sudo
- else
- # BSD
- e="run-su-cmd su"
- fi
- ;;
- *)
- if test -x "$(command -v pkexec)" 2>/dev/null; then
- e="pkexec env DISPLAY=$DISPLAY XAUTHORITY=$XAUTHORITY"
- elif test -x "$(command -v gksudo)" 2>/dev/null; then
- e=gksudo
- elif test -x "$(command -v gksu)" 2>/dev/null; then
- e="run-su-cmd gksu"
- elif test -x "$(command -v zenity)" 2>/dev/null; then
- e="zenitylogin zenity"
- elif test -x "$(command -v yad)" 2>/dev/null; then
- e="zenitylogin yad"
- fi
- ;;
- esac
- fi
- if test -x "$(command -v apt)" 2>/dev/null; then $e apt install -y php-cgi && $e apt install -y php72 || $e apt install -y php
- elif test -x "$(command -v apk)" 2>/dev/null; then $e apk add --no-cache php72 || $e apk add --no-cache php
- elif test -x "$(command -v apt-get)" 2>/dev/null; then $e apt-get install -y php-cgi && $e apt-get install -y php72 || $e apt-get install -y php
- elif test -x "$(command -v yum)" 2>/dev/null; then $e yum install php72-cli || yum install php-cli
- elif test -x "$(command -v pacman)" 2>/dev/null; then $e pacman -S php72 || $e pacman -S php
- elif test -x "$(command -v brew)" 2>/dev/null; then $e brew install php72 || $e brew install php
- elif test -x "$(command -v dnf)" 2>/dev/null; then $e dnf install php72-cli || $e dnf install php-cli
- elif test -x "$(command -v zypper)" 2>/dev/null; then $e zypper install php-cli || $e zypper install php
- elif test -x "$(command -v pkg)" 2>/dev/null; then $e pkg install php72
- elif test -x "$(command -v emerge)" 2>/dev/null; then $e emerge --ask dev-lang/php:7.2
- elif test -x "$(command -v pkgman)" 2>/dev/null; then $e pkgman install cmd:install
- fi
- phppath="$(sh -c 'command -v php7.2')" 2>/dev/null
- if test "0$?" -ne 0; then
- phppath="$(sh -c 'command -v php')" 2>/dev/null
- if test "0$?" -ne 0; then
- # failed to install PHP
- echo "FAILED TO INSTALL PACKAGE: Package manager not found, you have no internet connection, or another error occured. You must manually install PHP (>=5.4)">&2
- exit 1
- fi
- fi
- fi
- if test -x "$(command -v grep)" 2>/dev/null; then
- grep -A1073741823 '<''?php' "$0" | php -- "$@"
- else
- echo '/PHP_SCRIPT_''STARTS_AFTER_HERE/+1,$p' | ed -s "$0" | php -- "$@"
- fi
- exit 0
- PHP_SCRIPT_STARTS_AFTER_HERE
- <?php
- // The most likely break I see potentially happening in a far future PHP release is deprecating and removing
- // case-insensitive booleans. However, we do not know yet whether they will become uppercase/lowercase
- if (!defined('false')) define('false', !1);
- if (!defined('true')) define('true', !0);
- if (function_exists('set_time_limit')) set_time_limit( 0 );
- $isTheOsWindows = strcasecmp(PHP_SHLIB_SUFFIX, 'dll') === 0;
- $isEffectivelyRoot = @is_writable($isTheOsWindows ? "/usr/bin/env" : @getenv("COMSPEC")) ?: false;
- // Random ports between these two values will be attempted until one is found
- define("TCP_SERVER_MAX_LISTEN_PORT", 65535);
- define("TCP_SERVER_MIN_LISTEN_PORT", 1025);
- $preferedListeningIPArray = array_merge(
- ["localhost", "127.0.0.1", "[::1]"],
- @gethostbynamel("localhost") ?: []
- );
- $localHostIpv6s = @dns_get_record("localhost", DNS_AAAA);
- if ($localHostIpv6s) foreach ($localHostIpv6s as $record)
- if (filter_var($record["ipv6"], FILTER_VALIDATE_IP, FILTER_FLAG_IPV6) !== false)
- array_push( $preferedListeningIPArray, '[' . strtolower($record["ipv6"]) . ']' );
- unset( $localHostIpv6s );
- $preferedListeningIPArray = array_unique( $preferedListeningIPArray );
- function getPathToProcessByPID($pid) {
- global $isTheOsWindows;
- if ($isTheOsWindows) {
- $procInfo = @shell_exec('wmic process where processID=' . $pid . ' get ExecutablePath /format:value');
- $procInfo = trim($procInfo);
- $eqIndex = strpos($procInfo, '=');
- return $eqIndex === false ? $procInfo : substr($procInfo, $eqIndex+1);
- } elseif (file_exists('/proc/' . $pid . '/exe')) {
- return readlink('/proc/' . $pid . '/exe'); // ultra fast
- } else {
- @exec('lsof -Fn -p ' . $pid . ' 2>/dev/null' . $pid, $linesList);
- $isInTheZone = false;
- foreach($linesList as $line) {
- if ($line[0] === 'f') $isInTheZone = $line === 'ftxt';
- if ($line[0] === 'n' && $isInTheZone) return str_replace(
- ["\\\\", "\\n"],
- ["\\", "\n"],
- substr($line, 1)
- );
- }
- }
- return false;
- }
- $bothBracketsArray = ['[', ']'];
- function doIpsAndPortsEqual($a, $b) {
- global $bothBracketsArray;
- $lastPosA = strrpos($a, ":"); // port #
- $lastPosB = strrpos($b, ":"); // port #
- if (substr($a, $lastPosA+1) !== substr($b, $lastPosB+1)) return false;
- $ipA = substr($a, 0, $lastPosA);
- $ipB = substr($a, 0, $lastPosB);
- if (strpos($ipA, ':') !== false) { // Ipv6
- return inet_pton(str_replace($bothBracketsArray, '', $ipA)) === inet_pton(str_replace($bothBracketsArray, '', $ipB));
- } else { // Ipv4
- return $ipA === $ipB;
- }
- }
- function getAllPIDSConnectingToTheSocket($possibleIpsAndPorts) {
- global $isTheOsWindows, $supportsNetStat;
- // Basically cross-platform execution and parsing of netstat with lsof as backup
- $out = array();
- if ($isTheOsWindows) {
- if (!$supportsNetStat) return false;
- @exec(escapeshellarg($supportsNetStat) . " -n -o", $outputLines, $statInt);
- if ($statInt !== 0) return false;
- if (!empty($outputLines)) foreach ($outputLines as $line) {
- if (strcasecmp(substr($line, 0, 4), " tcp") !== 0) continue;
- $arr = preg_split('/\s+/', ' ', strtolower(trim($line)));
- foreach ($possibleIpsAndPorts as $ip)
- if (doIpsAndPortsEqual($arr[2], $ip)) {
- array_push($out, $arr[4]);
- break;
- }
- }
- } elseif ($supportsNetStat) {
- @exec(escapeshellarg($supportsNetStat) . " -W -p -n --tcp || netstat -W -p -n 2>/dev/null", $outputLines, $statInt);
- if ($statInt !== 0) return false;
- if (!empty($outputLines)) foreach ($outputLines as $line) {
- if (substr($line, 0, 3) !== "tcp") continue;
- $arr = preg_split('/\s+/', ' ', $line);
- foreach ($possibleIpsAndPorts as $ip)
- if (doIpsAndPortsEqual($arr[4], $ip)) {
- array_push($out, $arr[4]);
- break;
- }
- }
- } else { // much slower version but works on MacOS:
- @exec("lsof -iTCP -n -P -F", $outputLines, $statInt);
- if ($statInt !== 0) return false;
- $pid = false;
- if (!empty($outputLines)) foreach ($outputLines as $line) {
- if ($line[0] === 'p') { $pid = @intval(substr($line, 1)) ?: false; continue; }
- if ($line[0] !== 'n') { continue; }
- $destAddress = substr($line, strpos($line, '->')+2);
- foreach ($possibleIpsAndPorts as $ip)
- if (doIpsAndPortsEqual($destAddress, $ip)) {
- if ($pid !== false) { array_push($out, $pid); $pid = false; }
- break;
- }
- }
- }
- return $out;
- }
- function isSocketConnectionSafe() {
- global $possibleIpsAndPorts;
- // whether items in the $browserFolders are the only things connected to the socket
- $possiblePIDs = getAllPIDSConnectingToTheSocket( $possibleIpsAndPorts );
- $myOwnPID = getmypid(); // a core PHP function
- if (!empty($possiblePIDs)) foreach ($possiblePIDs as $pid) {
- if ($pid == $myOwnPID) continue; // deliberate double equals
- $proc = strtolower( getPathToProcessByPID($pid) );
- if ($proc === false) continue; // there's nothing we can do
- $isSafe = false;
- foreach ($possibleIpsAndPorts as $path) {
- $len = strlen( $path );
- if ($proc[$len] === DIRECTORY_SEPARATOR && substr($proc, $len) === $path) {
- $isSafe = true;
- }
- }
- if (!$isSafe) return false;
- }
- return true;
- }
- function is_browser_safe($enforcePerms, $fullPath, &$resolvedPath) {
- global $isTheOsWindows, $isEffectivelyRoot;
- // checks to make sure its executable and only editable by the root
- if (!is_executable($fullPath)) return false;
- $resolved = @realpath( $fullPath ) ?: $fullPath;
- if ($enforcePerms) {
- if (!$isEffectivelyRoot && is_writable($resolved)) return false;
- if (!$isTheOsWindows) {
- if ((@fileowner($resolved) ?: 0) !== 0) return false; // ensure owner is root
- $perms = @fileperms( $resolved ) ?: 0;
- if ((@filegroup($resolved) ?: 0) !== 0 && ($perms & 16)) return false;
- if ($perms & 2) return false; // if the world can write to it
- }
- }
- $resolvedPath = $resolved;
- return true;
- }
- $foundBrowser = NULL; // MacOS does not support su; Haiku doesn't support getent, only id:
- $fullBrowserPath = NULL;
- $supportsNohup = $supportsNetStat = $supportsCScript = $supportsSudo = $supportsId = $supportsLogger = false;
- if ($isTheOsWindows) {
- // Search the registry for the user's internet browsers
- // TODO: How to avoid the temporary file? That could be a security liability because a fast-polling program
- // might be able to slip in and modify it right before PHP reads it
- $programFiles = strtolower( @getenv('ProgramFiles') );
- // Vivaldi and Amigo browsers install locally and are too insecure to be used safely
- $browserFolders = ["$programFiles\\google", "$programFiles\\mozilla firefox", "$programFiles\\bravesoftware\brave-browser",
- "$programFiles\\tencent\\qqintl\\bin", "$programFiles\\yandex\\yandexbrowser", "$programFiles\\opera", "$programFiles\\baidu",
- "$programFiles\\ucbrowser", "$programFiles\\maxthon", "$programFiles\\internet explorer", "$programFiles\\safari"];
- if (!empty($sysWindowsDir = @getenv("SystemRoot")) array_push($browserFolders, "$sysWindowsDir\\SystemApps"); // Microsoft Edge
- $tmpWindowsTegFile = tempnam(sys_get_temp_dir(), bin2hex(openssl_random_pseudo_bytes(6)));
- //shell_exec('reg export "HKLM\\SOFTWARE\\Clients\\StartMenuInternet" ' . escapeshellarg($tmpWindowsTegFile) . ' /y');
- //$regLines = @file($tmpWindowsTegFile) ?: [];
- if (!empty($programFiles = strtolower( @getenv('ProgramFiles(x86)') ))) {
- //shell_exec('reg export "HKLM\\SOFTWARE\\Wow6432Node\\Clients\\StartMenuInternet" ' . escapeshellarg($tmpWindowsTegFile) . ' /y');
- //$regLines = array_merge($regLines, @file($tmpWindowsTegFile) ?: []);
- array_push($browserFolders, "$programFiles\\google", "$programFiles\\mozilla firefox", "$programFiles\\yandex\\yandexbrowser",
- "$programFiles\\bravesoftware\brave-browser", "$programFiles\\opera", "$programFiles\\maxthon", "$programFiles\\ucbrowser",
- "$programFiles\\tencent\\qqintl\\bin", "$programFiles\\internet explorer", "$programFiles\\baidu", "$programFiles\\safari");
- }
- $foundBrowser = "explorer.exe"; // On windows, we use explorer.exe only
- $sysWindowsDir = $sysWindowsDir ?: "C:\\Windows";
- $fullBrowserPath = is_executable("$sysWindowsDir\\explorer.exe") ? "$sysWindowsDir\\explorer.exe"
- : "$sysWindowsDir\\System32\\explorer.exe";
- $pathDirs = explode(PATH_SEPARATOR, @getenv('PATH') ?: "$sysWindowsDir\system32;$sysWindowsDir" );
- foreach($pathDirs as $path) {
- $files = @scandir( $path );
- if (!empty($files)) foreach ($files as $filename) {
- switch (basename(strtolower($filename), ".exe")) {
- case "netstat": $supportsNetStat = $path . DIRECTORY_SEPARATOR . $filename; continue;
- case "cscript": $supportsCScript = $path . DIRECTORY_SEPARATOR . $filename; continue;
- }
- }
- }
- /*$usePathToTheCommand = false;
- foreach ($regLines as $line) {
- $trimmedLine = trim($line);
- if (empty($trimmedLine)) { $usePathToTheCommand = false; continue; }
- if (substr($trimmedLine,-9) !== "\\command]" || !$usePathToTheCommand) { continue; }
- $usePathToTheCommand = true;
- $eqIndex = strpos($trimmedLine, "=");
- if ($eqIndex === false || $trimmedLine[$eqIndex+1] !== '"') continue;
- $fullCommandLine = @json_decode( substr($trimmedLine, $eqIndex+1) );
- if (empty($fullCommandLine)) return;
- if ($fullCommandLine[0] === '"') $fullCommandLine = substr($fullCommandLine, 1, strpos($fullCommandLine, '"', 1)-1);
- else $fullCommandLine = substr($fullCommandLine, 0, strpos($fullCommandLine, ' ', 1)-1);
- array_push( $browserFolders, dirname($fullCommandLine) );
- }*/
- unlink($tmpWindowsTegFile); unset($tmpWindowsTegFile); unset($regLines); unset($sysWindowsDir); unset($programFiles);
- } else $browserFolders = ["/opt/google/chrome", "/usr/lib/firefox"];
- function readEtcEnv() {
- $etcEnv = @file("/etc/environment");
- if (!empty($etcEnv)) foreach ($etcEnv as $line) {
- if (substr($line, 0, 5) === 'PATH=') return $line[5] === '"' ? @json_decode( substr($line, 5) ) : substr($line, 5);
- }
- }
- function findBrowserProgram($enforcePerms) {
- global $foundBrowser, $supportsNohup, $supportsSudo, $supportsCScript, $supportsId,
- $supportsNetStat, $browserFolders, $isTheOsWindows, $fullBrowserPath;
- if ($fullBrowserPath !== NULL) return $fullBrowserPath;
- //$suffix = $isTheOsWindows ? '.exe' : '';
- $preferedPrograms = ["x-www-browser","git$suffix","xdg-open","sensible-browser","open","gnome-open"];
- $specificBrowsers = [
- "firefox", "iceweasel", "google-chrome", "chrome", "chromium", "chromium-browser", "opera", "brave", "kfmclient",
- "konqueror", "seamonkey", "iceape", "w3m", "elinks", "links", "lynx", "dillo", "python", "python3", "python2"];
- $pathDirs=explode(PATH_SEPARATOR,@getenv('PATH')?:readEtcEnv()?:"/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin");
- $resolvedPath = "";
- $tmpResolvedPath = '';
- $found = "";
- $bestSpecificBrowser = "";
- $priority = 99;
- foreach($pathDirs as $path) {
- if (!in_array($path, $browserFolders) && ($isEffectivelyRoot ? /*$isTheOsWindows ||*/ @fileowner($path) === 0
- && @filegroup($path) === 0 && (@fileperms($path) & 2) === 0 : !is_writable($path)))
- array_push($browserFolders, $path);
- $contents = @opendir($path, SCANDIR_SORT_NONE);
- if ($contents === false) continue;
- while (($filename = readdir($contents)) !== false) {
- $lowered = strtolower($filename);
- switch (/*$isTheOsWindows ? basename($lowered, ".exe") :*/ $filename) {
- case "nohup": $supportsNohup = $path . DIRECTORY_SEPARATOR . $filename; continue;
- case "sudo": $supportsSudo = $path . DIRECTORY_SEPARATOR . $filename; continue;
- case "id": $supportsId = $path . DIRECTORY_SEPARATOR . $filename; continue;
- case "netstat": $supportsNetStat = $path . DIRECTORY_SEPARATOR . $filename; continue;
- case "logger": $supportsLogger = $path . DIRECTORY_SEPARATOR . $filename; continue;
- }
- if ($priority !== -1 && in_array($lowered, $preferedPrograms)
- && is_browser_safe($enforcePerms, $path . DIRECTORY_SEPARATOR . $filename, $resolvedPath)) {
- if (!in_array(dirname(strtolower($resolvedPath)), $browserFolders))
- array_push($browserFolders, dirname(strtolower($resolvedPath)));
- $found = $filename;
- $priority = -1;
- break;
- }
- $specificBrowserIndex = array_search($lowered, $specificBrowsers, true);
- if ($specificBrowserIndex !== false && 0 <= $specificBrowserIndex
- && is_browser_safe($enforcePerms, $path . DIRECTORY_SEPARATOR . $filename, $tmpResolvedPath)) {
- if (!in_array(dirname(strtolower($browserDir)), $browserFolders))
- array_push($browserFolders, dirname(strtolower($browserDir)));
- if ($specificBrowserIndex < $priority && $priority !== -1) {
- $resolvedPath = $tmpResolvedPath;
- $found = $filename;
- $priority = $specificBrowserIndex;
- }
- }
- }
- @closedir( $contents );
- }
- if ($enforcePerms && empty($found)) return findBrowserProgram( false );
- $fullBrowserPath = $resolvedPath;
- $foundBrowser = $found;
- return $fullBrowserPath;
- }
- function openURLInBrowser($weburl) {
- $browserProgram = findBrowserProgram( true );
- if (empty($browserProgram)) throw Exception("Cannot open a browser to the specified URL");
- $cmdLine = escapeshellarg($browserProgram) . ' ';
- switch (basename(strtolower($browserProgram), ".exe")) { // elegant concise PHP
- // a lot came from https://github.com/git/git/blob/master/git-web--browse.sh
- case "firefox": case "iceweasel": case "seamonkey": case "iceape":
- $ffversion = shell_exec($browserProgram . ' -version');
- $ffversion = intval( end( explode(" ", $ffversion) ), 10 );
- if ($ffversion <= 2) $cmdLine = $cmdLine . '-new-tab ';
- break;
- case "git":
- $cmdLine = $cmdLine . 'web--browse ';
- break;
- case "python": case "python2": case "python3":
- $cmdLine = $cmdLine . '-mwebbrowser ';
- break;
- case "google-chrome": case "chrome": case "chromium": case "chromium-browser":
- break; // nothing to do here
- case "w3m": case "elinks": case "links": case "lynx": case"cygstart":
- break; // nothing to do here
- case "konqueror": case "kfmclient":
- $cmdLine = $cmdLine . 'newTab ';
- break;
- case "explorer.exe": case "xdg-open": case "sensible-browser":
- case "open": case "gnome-open": case "x-www-browser":
- break; // nothing to do here
- }
- $cmdLine = $cmdLine . escapeshellarg($weburl); // append the URL we want
- // Now, open the browser by using proc_open + writing to STDIN to hide the UUID we pass
- executeCmdHidden( $cmdLine );
- }
- function readProcessStreamToCompletion($proc, $pipes) {
- stream_get_contents($pipes[1]); // read to completion
- fclose($pipes[0]);
- fclose($pipes[1]);
- proc_close($process);
- }
- function nopeRoot($str) {
- // empty catches the cases of undefined from error supression and
- return empty($str) || $str === "root" ? false : $str;
- }
- function show_fatality($msg) {
- global $supportsLogger;
- if ($supportsLogger) @shell_exec('logger -p daemon.alert -s ' . escapeshellarg($msg));
- if (@is_writable('/dev/kmsg')) @file_put_contents('/dev/kmsg', '<3>' . $msg, FILE_APPEND);
- // xmessage may be ugly but it is available on every device with a desktop in the Linux universe
- @shell_exec('xmessage -center '.escapeshellarg(wordwrap('ERROR in '.dirname(__FILE__).': '.$msg,80,"\n",true)));
- exit( 1 );
- }
- function executeCmdHidden($cmdLine) {
- global $isTheOsWindows, $supportsNohup, $supportsSudo, $supportsCScript, $supportsId,
- $isEffectivelyRoot;
- // This function pipes into the shell to hide the UUID passed to the web browser
- $realProcCMD = "";
- $commandToPipeIn = "";
- if (!$isTheOsWindows) {
- $realProcCMD = "sh";
- $cmdLine = ($supportsNohup ? 'nohup ' : '') . $cmdLine . ' >/dev/null 2>&1 &';
- //if ($displayEnv = @getenv("DISPLAY")) $cmdLine = escapeshellarg("DISPLAY=".$displayEnv)." ".$cmdLine;
- if ($isEffectivelyRoot) {
- // if we are root, then we need to tone down who to run as
- $runAsUser = nopeRoot(@getenv("SUDO_USER")) ?: nopeRoot(@shell_exec("logname")) ?: nopeRoot(@getenv("USER"));
- if ($runAsUser === false && !empty($xauthvar = @getenv("XAUTHORITY"))) {
- $userId = intval(substr($xauthvar, strcspn($xauthvar, '0123456789'))) ?: 0;
- if ($userId !== 0 && $supportsId) {
- $runAsUser = @shell_exec("id -nu " . $userId) ?: false;
- } elseif ($userId !== 0) {
- $runAsUser = @shell_exec("getent passwd " . $userId) ?: false;
- if ($runAsUser !== false) $runAsUser = substr($runAsUser, strpos($runAsUser, ":")-1);
- }
- } elseif ($runAsUser === false) { // MacOS doesn't do X11
- $whoText = explode("\n", @shell_exec("who") ?: "");
- foreach ($whoText as $line) {
- $lineTrimmed = trim( $line );
- if (stripos($lineTrimmed, " console ") !== false)
- $runAsUser = nopeRoot(substr($lineTrimmed, 0, strpos($lineTrimmed, " ")-1));
- }
- }
- if ($runAsUser === false) { // last-ditch effort to try to find a suitable directory
- $openedHome = @opendir("/home");
- if (!empty($openedHome)) while (($dir = readdir($openedHome)) !== false)
- if (is_readable("/home/$dir")) {
- $runAsUser = $dir;
- break;
- }
- closedir( $openedHome );
- }
- if ($runAsUser === false) show_fatality('this is running as root and cannot find user to log into as to ' .
- 'start the web browser so you can have a GUI. Please open issue with details on GitHub. Many thanks.');
- if ($supportsSudo) {
- $commandToPipeIn = 'sudu -u ' . escapeshellarg($runAsUser) . ' -- ' . $cmdLine . "\n";
- } else {
- $commandToPipeIn = 'su -c '.escapeshellarg($cmdLine)." ".escapeshellarg($runAsUser)."\n";
- }
- } else {
- $commandToPipeIn = $cmdLine . "\n";
- }
- if (!$supportsNohup) {
- $realProcCMD = substr($commandToPipeIn, 0, -1);
- $commandToPipeIn = '';
- }
- } elseif ($supportsCScript && $isTheOsWindows) {
- $replacedCharacters = explode("", '\\"\'|^&'); // let's be conservative as IDK VBScript
- $replacementChars = [];
- foreach ($replacedCharacters as $char) {
- // Source: https://www.learnqtp.com/how-can-you-display-quot-in-qtp/
- array_push($replacementChars, '" & Chr(' . ord($char) . ') & "');
- }
- $escapedCmd = str_replace(
- $replacedCharacters,
- $replacementChars,
- $cmdLine
- );
- $realProcCMD = "CScript.exe /nologo execStdIn.vbs 2>&1";
- $commandToPipeIn = 'Call WScript.CreateObject("WScript.Shell").Run("' . $escapedCmd . '", 9, false)' . "\r\n";
- } else {
- // when all else fails, we must wait for the process to exit and waste memory
- $realProcCMD = $cmdLine;
- }
- $proc = proc_open($realProcCMD, [["pipe","r"], ["pipe","w"]], $pipes);
- if (!empty($commandToPipeIn)) fwrite($pipes[0], $commandToPipeIn, strlen($commandToPipeIn));
- register_shutdown_function('readProcessStreamToCompletion', $proc, $pipes); // because readProcessStreamToCompletion may block
- }
- function findAvailableSocketIpAndPort() {
- global $preferedListeningIPArray;
- // stream_socket_server is (suprise, suprise!) part of the core library and available even if all extensions are disabled
- $testedListenerPorts = [];
- $thresholdLength = round((TCP_SERVER_MAX_LISTEN_PORT - TCP_SERVER_MIN_LISTEN_PORT + 2) * 0.875); // threshold is 1 in 8 chance
- while (count($testedListenerPorts) < $thresholdLength) {
- $port = random_int(TCP_SERVER_MIN_LISTEN_PORT, TCP_SERVER_MAX_LISTEN_PORT);
- if (in_array($port, $testedListenerPorts)) continue;
- foreach($preferedListeningIPArray as $ip) {
- // try to open a socket on the port at the ip address. If succeed, we are good to go.
- $socket = stream_socket_server("tcp://" . $ip . ':' . $port, $errno, $errstr);
- if ($socket !== false) {
- return [$socket, $ip . ':' . $port];
- }
- }
- array_push($testedListenerPorts, $port);
- }
- // linear search through remaining ports to avoid
- for ($port = TCP_SERVER_MIN_LISTEN_PORT; $port <= TCP_SERVER_MAX_LISTEN_PORT; $port++) {
- if (in_array($port, $testedListenerPorts)) continue;
- foreach($preferedListeningIPArray as $ip) {
- // try to open a socket on the port at the ip address. If succeed, we are good to go.
- $socket = stream_socket_server("tcp://" . $ip . ':' . $port, $errno, $errstr);
- if ($socket !== false) {
- return [$socket, $ip . ':' . $port];
- }
- }
- }
- }
- if (!function_exists('random_int')) {
- if (!function_exists('mcrypt_create_iv')) {
- // This is still decently secure because you need 512 entries from Mersenne Twister in order to guess next one,
- // and >99% of the time the first attempt will succeed.
- mt_srand( @microtime() ?: mt_rand() );
- function random_int($min, $max) {
- return return mt_rand($min, $max);
- }
- } else {
- function random_int($min, $max) {
- return $min + (hexdec(bin2hex(
- mcrypt_create_iv($bytes, MCRYPT_DEV_URANDOM)
- )) % ($max - $min + 1));
- }
- }
- }
- if (!function_exists("openssl_random_pseudo_bytes")) {
- function openssl_random_pseudo_bytes($n) {
- $str = '';
- for ($i = 0; ($i+3) <= $len; $i=$i+3) {
- $int = random_int(0, 16777216);
- $str = $str . chr($int) . chr($int >> 8) . chr($int >> 16);
- }
- for ( ; $i < $len; $i++)
- $str = $str . chr(random_int(0, 256));
- return $str;
- }
- }
- if (!function_exists('password_hash')) {
- $password_hash_salt = base64_encode(openssl_random_pseudo_bytes(18));
- $password_hash_salt = str_replace(['+','/','='], '', $password_hash_salt);
- $password_hash_param = '$' . implode('$', [
- phpversion() < "5.3.7" ? "2a" : "2y", // I only use phpversion when I have to
- phpversion() < "5.3.7" ? "09" : "06", // add the cost in two digits
- substr($password_hash_salt, 0, 22) // add the salt
- ]);
- function password_hash($input, $_algo) {
- global $password_hash_param;
- if (defined('CRYPT_BLOWFISH') && CRYPT_BLOWFISH == 1) {
- return crypt( base64_encode($input), $password_hash_param );
- } else {
- return hash("sha256", $input, false);
- }
- }
- }
- $secretKey = str_replace(['+','/','='], ['-','_',''], base64_encode(openssl_random_pseudo_bytes(384)));
- $usedHashAlgo = defined('PASSWORD_BCRYPT') ? PASSWORD_BCRYPT : PASSWORD_DEFAULT;
- $publicHash = password_hash($secretKey, $usedHashAlgo, ['cost'=>6]);
- // Here, we start the actual GUI:
- list($serverSocket, $serverIpAndPort) = findAvailableSocketIpAndPort();
- fclose( $serverSocket );
- executeCmdHidden(
- 'php ' .
- (empty($password_hash_salt) ? '' : '-d custom_public_gui_param=' . $password_hash_param . ' ') .
- '-d custom_public_gui_hash=' . $publicHash . ' ' .
- '-S ' . escapeshellarg($serverIpAndPort) . ' ' .
- '-t ' . escapeshellarg(getcwd() . DIRECTORY_SEPARATOR . 'gui-root') . ' ' .
- '> ' . ($isTheOsWindows ? 'NUL' : '/dev/null')
- );
- list($startSocket, $startIpAndPort) = findAvailableSocketIpAndPort();
- // HTTP is no less secure than HTTPS at localhost:
- openURLInBrowser('http://' . $startIpAndPort);
- do {
- // accept the web browser's request and feed in the real key
- $socketresource = stream_socket_accept($startSocket);
- if (!isSocketConnectionSafe()) {
- fclose( $socketresource );
- continue; // keep attempting the connection until we know it is safe
- }
- stream_get_contents( $socketresource );
- } while(false);
- // wait for the server to finish opening before opening the web browser
- while (file_get_contents('http://' . $serverIpAndPort . '/ping-wait-for-server-to-become-open.txt') === false) @time_nanosleep(0, 8e6);
- $contentText = (
- "<!doctype html>\r\n" .
- '<html lang="en"><head><meta http-equiv="refresh" content="0;url=http://' . $serverIpAndPort . '/?uuid=' . $secretKey . '"/>' .
- '<title>Redirecting...</title></head><body><script type="text/javascript">location="' .
- 'http://' . $serverIpAndPort . "/?uuid=" . $secretKey . '"</script></body></html>'
- );
- $stringToWrite = (
- "HTTP/1.1 302 OK\r\n" .
- "Content-Encoding: identity\r\n" .
- "Age: 0\r\n" .
- "Content-Type: text/html; charset=UTF-8\r\n" .
- "Date: " . gmdate('D, d M Y H:i:s T') . "\r\n" .
- "Content-Length: " . strlen($contentText) . "\r\n" .
- "Location: http://" . $serverIpAndPort . "/?uuid=" . $secretKey . "\r\n" .
- "Connection: close\r\n" .
- "\r\n" . // second line ending ends header fields
- $contentText // Finally the actualtext content
- );
- fflush($socketresource);
- fclose($socketresource);
- fclose($startSocket);
Add Comment
Please, Sign In to add comment