|
|
|
@ -25,6 +25,12 @@ function str($code, $indent = '') // {{{
|
|
|
|
|
return (string) $code;
|
|
|
|
|
}
|
|
|
|
|
// }}}
|
|
|
|
|
function unsetArray(&$array, $name) // {{{
|
|
|
|
|
{
|
|
|
|
|
unset($array[$name]);
|
|
|
|
|
}
|
|
|
|
|
// }}}
|
|
|
|
|
|
|
|
|
|
function foldToCode($src, $indent = '') // {{{ wrap or rewrap anything to Decompiler_Code
|
|
|
|
|
{
|
|
|
|
|
if (is_array($indent)) {
|
|
|
|
@ -47,7 +53,7 @@ function foldToCode($src, $indent = '') // {{{ wrap or rewrap anything to Decomp
|
|
|
|
|
return $src;
|
|
|
|
|
}
|
|
|
|
|
// }}}
|
|
|
|
|
function value($value) // {{{
|
|
|
|
|
function value($value, &$EX) // {{{
|
|
|
|
|
{
|
|
|
|
|
$spec = xcache_get_special_value($value);
|
|
|
|
|
if (isset($spec)) {
|
|
|
|
@ -62,10 +68,15 @@ function value($value) // {{{
|
|
|
|
|
// use as is
|
|
|
|
|
}
|
|
|
|
|
else if (is_array($value)) {
|
|
|
|
|
$value = new Decompiler_ConstArray($value);
|
|
|
|
|
$value = new Decompiler_ConstArray($value, $EX);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
$value = new Decompiler_Value($value);
|
|
|
|
|
if (isset($EX['value2constant'][$value])) {
|
|
|
|
|
$value = new Decompiler_Code($EX['value2constant'][$value]);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
$value = new Decompiler_Value($value);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return $value;
|
|
|
|
|
}
|
|
|
|
@ -440,11 +451,11 @@ class Decompiler_Array extends Decompiler_Value // {{{
|
|
|
|
|
// }}}
|
|
|
|
|
class Decompiler_ConstArray extends Decompiler_Array // {{{
|
|
|
|
|
{
|
|
|
|
|
function Decompiler_ConstArray($array)
|
|
|
|
|
function Decompiler_ConstArray($array, &$EX)
|
|
|
|
|
{
|
|
|
|
|
$elements = array();
|
|
|
|
|
foreach ($array as $key => $value) {
|
|
|
|
|
$elements[] = array(value($key), value($value));
|
|
|
|
|
$elements[] = array(value($key, $EX), value($value, $EX));
|
|
|
|
|
}
|
|
|
|
|
$this->value = $elements;
|
|
|
|
|
}
|
|
|
|
@ -465,6 +476,9 @@ class Decompiler
|
|
|
|
|
{
|
|
|
|
|
public $namespace;
|
|
|
|
|
public $namespaceDecided;
|
|
|
|
|
public $activeClass;
|
|
|
|
|
public $activeMethod;
|
|
|
|
|
public $activeFunction;
|
|
|
|
|
|
|
|
|
|
function Decompiler()
|
|
|
|
|
{
|
|
|
|
@ -612,7 +626,7 @@ class Decompiler
|
|
|
|
|
{
|
|
|
|
|
switch ($op['op_type']) {
|
|
|
|
|
case XC_IS_CONST:
|
|
|
|
|
return value($op['constant']);
|
|
|
|
|
return value($op['constant'], $EX);
|
|
|
|
|
|
|
|
|
|
case XC_IS_VAR:
|
|
|
|
|
case XC_IS_TMP_VAR:
|
|
|
|
@ -1344,6 +1358,16 @@ class Decompiler
|
|
|
|
|
$EX['recvs'] = array();
|
|
|
|
|
$EX['uses'] = array();
|
|
|
|
|
$EX['lastBlock'] = null;
|
|
|
|
|
$EX['value2constant'] = array();
|
|
|
|
|
if (isset($this->activeClass)) {
|
|
|
|
|
$EX['value2constant'][$this->activeClass] = '__CLASS__';
|
|
|
|
|
}
|
|
|
|
|
if (isset($this->activeMethod)) {
|
|
|
|
|
$EX['value2constant'][$this->activeMethod] = '__METHOD__';
|
|
|
|
|
}
|
|
|
|
|
if (isset($this->activeFunction)) {
|
|
|
|
|
$EX['value2constant'][$this->activeFunction] = '__FUNCTION__';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* dump whole array
|
|
|
|
|
$this->keepTs = true;
|
|
|
|
@ -1362,8 +1386,9 @@ class Decompiler
|
|
|
|
|
$T = &$EX['Ts'];
|
|
|
|
|
$opcodes = &$EX['opcodes'];
|
|
|
|
|
$lastphpop = null;
|
|
|
|
|
$currentSourceLine = null;
|
|
|
|
|
|
|
|
|
|
for ($i = $range[0]; $i <= $range[1]; $i ++) {
|
|
|
|
|
for ($i = $range[0]; $i <= $range[1]; $i ++, unsetArray($EX['value2constant'], $currentSourceLine)) {
|
|
|
|
|
// {{{ prepair
|
|
|
|
|
$op = &$opcodes[$i];
|
|
|
|
|
$opc = $op['opcode'];
|
|
|
|
@ -1376,6 +1401,8 @@ class Decompiler
|
|
|
|
|
$op2 = $op['op2'];
|
|
|
|
|
$res = $op['result'];
|
|
|
|
|
$ext = $op['extended_value'];
|
|
|
|
|
$currentSourceLine = $op['line'];
|
|
|
|
|
$EX['value2constant'][$currentSourceLine] = '__LINE__';
|
|
|
|
|
|
|
|
|
|
$opname = xcache_get_opcode($opc);
|
|
|
|
|
|
|
|
|
@ -1440,10 +1467,7 @@ class Decompiler
|
|
|
|
|
$istmpres = true;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
$class = $this->getOpVal($op2, $EX);
|
|
|
|
|
if (isset($op2['constant'])) {
|
|
|
|
|
$class = $this->stripNamespace(unquoteName($class));
|
|
|
|
|
}
|
|
|
|
|
$class = isset($op2['constant']) ? $op2['constant'] : $this->getOpVal($op2, $EX);
|
|
|
|
|
}
|
|
|
|
|
$resvar = $class;
|
|
|
|
|
break;
|
|
|
|
@ -1475,8 +1499,7 @@ class Decompiler
|
|
|
|
|
$rvalue = $this->getOpVal($op1, $EX);
|
|
|
|
|
$fetchtype = defined('ZEND_FETCH_TYPE_MASK') ? ($ext & ZEND_FETCH_TYPE_MASK) : $op2['EA.type'];
|
|
|
|
|
if ($fetchtype == ZEND_FETCH_STATIC_MEMBER) {
|
|
|
|
|
$class = $this->getOpVal($op2, $EX);
|
|
|
|
|
$rvalue = unquoteName(str($class)) . '::$' . unquoteName($rvalue, $EX);
|
|
|
|
|
$rvalue = $this->stripNamespace($op2['constant']) . '::$' . unquoteName($rvalue, $EX);
|
|
|
|
|
}
|
|
|
|
|
else if ($opc != XC_UNSET_VAR) {
|
|
|
|
|
$name = unquoteName($rvalue, $EX);
|
|
|
|
@ -1625,7 +1648,7 @@ class Decompiler
|
|
|
|
|
if (isset($statics[$name])) {
|
|
|
|
|
$var = $statics[$name];
|
|
|
|
|
$resvar .= ' = ';
|
|
|
|
|
$resvar .= str(value($var), $EX);
|
|
|
|
|
$resvar .= str(value($var, $EX), $EX);
|
|
|
|
|
}
|
|
|
|
|
unset($statics);
|
|
|
|
|
break 2;
|
|
|
|
@ -1673,8 +1696,7 @@ class Decompiler
|
|
|
|
|
}
|
|
|
|
|
$fetchtype = defined('ZEND_FETCH_TYPE_MASK') ? ($ext & ZEND_FETCH_TYPE_MASK) : $op2['EA.type'];
|
|
|
|
|
if ($fetchtype == ZEND_FETCH_STATIC_MEMBER) {
|
|
|
|
|
$class = $this->getOpVal($op2, $EX);
|
|
|
|
|
$rvalue = unquoteName(str($class)) . '::' . unquoteName($rvalue, $EX);
|
|
|
|
|
$rvalue = $this->stripNamespace($op2['constant']) . '::' . unquoteName($rvalue, $EX);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if ($opc == XC_ISSET_ISEMPTY) {
|
|
|
|
@ -1739,7 +1761,7 @@ class Decompiler
|
|
|
|
|
$EX['called_scope'] = null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$EX['fbc'] = $this->getOpVal($op2, $EX);
|
|
|
|
|
$EX['fbc'] = isset($op2['constant']) ? $op2['constant'] : $this->getOpVal($op2, $EX);
|
|
|
|
|
if (($opc == XC_INIT_STATIC_METHOD_CALL || $opc == XC_INIT_METHOD_CALL) && !isset($EX['fbc'])) {
|
|
|
|
|
$EX['fbc'] = '__construct';
|
|
|
|
|
}
|
|
|
|
@ -1845,7 +1867,9 @@ class Decompiler
|
|
|
|
|
unset($fetchop, $addop);
|
|
|
|
|
$i += 2;
|
|
|
|
|
}
|
|
|
|
|
$this->activeClass = $class['name'];
|
|
|
|
|
$this->dclass($class, $EX['indent']);
|
|
|
|
|
$this->activeClass = null;
|
|
|
|
|
echo "\n";
|
|
|
|
|
unset($class);
|
|
|
|
|
break;
|
|
|
|
@ -1861,7 +1885,7 @@ class Decompiler
|
|
|
|
|
$op2val = $this->getOpVal($op2, $EX);
|
|
|
|
|
switch ($opc) {
|
|
|
|
|
case XC_ADD_CHAR:
|
|
|
|
|
$op2val = value(chr(str($op2val)));
|
|
|
|
|
$op2val = value(chr(str($op2val)), $EX);
|
|
|
|
|
break;
|
|
|
|
|
case XC_ADD_STRING:
|
|
|
|
|
break;
|
|
|
|
@ -2023,7 +2047,7 @@ class Decompiler
|
|
|
|
|
$offset = isset($op1['var']) ? $op1['var'] : $op1['constant'];
|
|
|
|
|
$lvalue = $this->getOpVal($op['result'], $EX);
|
|
|
|
|
if ($opc == XC_RECV_INIT) {
|
|
|
|
|
$default = value($op['op2']['constant']);
|
|
|
|
|
$default = value($op['op2']['constant'], $EX);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
$default = null;
|
|
|
|
@ -2430,7 +2454,7 @@ class Decompiler
|
|
|
|
|
foreach ($class[$type] as $name => $v) {
|
|
|
|
|
echo $newindent;
|
|
|
|
|
echo $prefix, $name, ' = ';
|
|
|
|
|
echo str(value($v), $newindent);
|
|
|
|
|
echo str(value($v, $EX), $newindent);
|
|
|
|
|
echo ";\n";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -2501,7 +2525,7 @@ class Decompiler
|
|
|
|
|
}
|
|
|
|
|
if (isset($value)) {
|
|
|
|
|
echo ' = ';
|
|
|
|
|
echo str(value($value), $newindent);
|
|
|
|
|
echo str(value($value, $EX), $newindent);
|
|
|
|
|
}
|
|
|
|
|
echo ";\n";
|
|
|
|
|
}
|
|
|
|
@ -2548,7 +2572,11 @@ class Decompiler
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
$this->activeMethod = $this->activeClass . '::' . $opa['function_name'];
|
|
|
|
|
$this->activeFunction = $opa['function_name'];
|
|
|
|
|
$this->dfunction($func, $newindent, $decorations, $isInterface || $isAbstractMethod);
|
|
|
|
|
$this->activeFunction = null;
|
|
|
|
|
$this->activeMethod = null;
|
|
|
|
|
if ($opa['function_name'] == 'Decompiler') {
|
|
|
|
|
//exit;
|
|
|
|
|
}
|
|
|
|
@ -2590,14 +2618,18 @@ class Decompiler
|
|
|
|
|
echo "<?". "php\n\n";
|
|
|
|
|
foreach ($this->dc['class_table'] as $key => $class) {
|
|
|
|
|
if ($key{0} != "\0") {
|
|
|
|
|
$this->activeClass = $class['name'];
|
|
|
|
|
$this->dclass($class);
|
|
|
|
|
$this->activeClass = null;
|
|
|
|
|
echo "\n";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
foreach ($this->dc['function_table'] as $key => $func) {
|
|
|
|
|
if ($key{0} != "\0") {
|
|
|
|
|
$this->activeFunction = $key;
|
|
|
|
|
$this->dfunction($func);
|
|
|
|
|
$this->activeFunction = null;
|
|
|
|
|
echo "\n";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|