debug[] = 'Found Ubuntu/Debian'; # CentOS, RHEL, Fedora } else if(file_exists('/etc/php-fpm.d/www.conf')) { $ini = parse_ini_file('/etc/php-fpm.d/www.conf', true); $this->debug[] = 'Found CentOS/RHEL/Fedora'; # fruithost } else if(file_exists('/etc/fruithost/config/php/panel.conf')) { $ini = parse_ini_file('/etc/fruithost/config/php/panel.conf', true); $this->debug[] = 'Found fruithost'; } } catch(\Exception $e) { $this->debug[] = $e->getMessage(); } if(!empty($ini)) { if(isset($ini['www'])) { if(isset($ini['www']['listen'])) { $this->socket = $ini['www']['listen']; } } else if(isset($ini['panel'])) { if(isset($ini['panel']['listen'])) { $this->socket = str_replace('$pool', 'panel', $ini['panel']['listen']); } } } $this->debug[] = sprintf('Socket: %s', $this->socket); if(!empty(shell_exec('which cgi-fcgi')) && $this->socket == null) { $this->debug[] = 'ERROR: cant find cgi-fcgi!'; $this->error = true; } } public function setPath(string $path) : void { $this->debug[] = sprintf('Set Path: %s', $path); $this->path = $path; } public function getHeader() : ?string { if(empty($this->content)) { return null; } return explode("\r\n\r\n", $this->content)[0]; } public function getBody() : ?string { if(preg_match("/\r\n\r\n/Uis", $this->content)) { return explode("\r\n\r\n", $this->content)[1]; } else if(preg_match("/(cgi\-fcgi|command not found)/Uis", $this->content)) { throw new \Exception('Can\'t access cgi-fcgi.'); } else { return $this->content; } } public function getContent() : ?string { return $this->content; } public function isAvailable() : bool { return !empty(shell_exec('which cgi-fcgi')); } public function getDebug() : array { return $this->debug; } public function hasErrors() : bool { return $this->error; } public function getInfo() : array { $file = sprintf('.fruithost.%s.php', Utils::randomString(5)); $hash = Encryption::encrypt(Utils::randomString(28), ENCRYPTION_SALT); file_put_contents(sprintf('%s%s', $this->path, $file), sprintf('', $hash)); $this->execute($file, [ 'FRUITHOST' => $hash, 'USERNAME' => Auth::getUsername() ]); @unlink(sprintf('%s%s', $this->path, $file)); $this->parse(); return $this->data; } public function execute(string $file, array $arguments = [], ?string $password = null) : void { $this->debug[] = 'cgi-fcgi NOT available, use cURL polyfill,..'; if(!is_writable($this->path)) { $this->debug[] = sprintf('Error: Path "%s" is not writeable!', $this->path); $this->error = true; return; } $args = ''; foreach(array_merge([ 'SCRIPTS_DIR' => $this->path, 'HOME' => $this->path, 'PWD' => $this->path, 'USER' => 'www-data', 'DOCUMENT_ROOT' => $this->path, 'SCRIPT_FILENAME' => sprintf('%s%s', $this->path, $file), 'REQUEST_METHOD' => 'GET' ], $arguments) as $name => $value) { $args .= sprintf('%s=%s \\%s', $name, $value, PHP_EOL); } if(!array_key_exists('FRUITHOST', $arguments)) { $arguments['FRUITHOST'] = Encryption::encrypt(Utils::randomString(28), ENCRYPTION_SALT); } // Check if cgi-fcgi available if(!empty(shell_exec('which cgi-fcgi'))) { $this->debug[] = 'cgi-fcgi is available, continue,..'; $command = sprintf('%scgi-fcgi -bind -connect "%s" 2>&1', $args, $this->socket); if($password != null) { $command = sprintf('bash -lc \'echo %s | /usr/bin/sudo -S %s\'', $password, $command); } $result = shell_exec($command); if($result === null) { $this->error = true; return; } $this->content = $result; // If cgi-fcgi not available, use a polyfill with CURL } else { $this->debug[] = 'cgi-fcgi NOT available, use cURL polyfill,..'; // @ToDo Check security(!) $additional = ''; if(array_key_exists('MODULE', $arguments)) { $additional = sprintf('require_once(\'%s\'); ', $arguments['MODULE']); } $temp = sprintf('.fruithost.check.%s.php', Utils::randomString(5)); $token = Encryption::encrypt(Utils::randomString(28), ENCRYPTION_SALT); $content = sprintf('<'.'?php define(\'DAEMON\', true); $wrapper_name = \'TOKEN\'; $wrapper_hash = \'%1$s\'; if((isset($_SERVER[$wrapper_name]) && $_SERVER[$wrapper_name] == $wrapper_hash) || (isset($_GET[$wrapper_name]) && $_GET[$wrapper_name] == $wrapper_hash)) { require_once(\'%2$s\'); %3$s } ?>', $token, sprintf('%s%s', $this->path, $file), $additional); $ch = curl_init(); file_put_contents(sprintf('%s%s', PATH, $temp), $content); // @ToDo Domain = $_SERVER['SERVER_NAME']d curl_setopt($ch, CURLOPT_URL, sprintf('https://%s/%s?TOKEN=%s&FRUITHOST=%s&USERNAME=%s', $_SERVER['SERVER_NAME'], $temp, $token, $arguments['FRUITHOST'], Auth::getUsername())); curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 2); curl_setopt($ch, CURLOPT_FRESH_CONNECT, true); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_FOLLOWLOCATION, false); curl_setopt($ch, CURLOPT_HTTPHEADER, [ 'Cookie: '.$_SERVER['HTTP_COOKIE'] ]); $result = curl_exec($ch); curl_close($ch); $this->content = $result; @unlink(sprintf('%s%s', PATH, $temp)); } } public function parse() : void { if($this->error) { return; } $entitiesToUtf8 = function($input) { // http://php.net/manual/en/function.html-entity-decode.php#104617 return preg_replace_callback("/([0-9]+;)/", function($m) { return mb_convert_encoding($m[1], "UTF-8", "HTML-ENTITIES"); }, $input); }; $plainText = function($input) use ($entitiesToUtf8) { return trim(html_entity_decode($entitiesToUtf8(strip_tags($input)))); }; $titlePlainText = function($input) use ($plainText) { return '# '.$plainText($input); }; if(!preg_match('#(.*