PHP 之源代码批量加密解密
一、加密方式一
function encode_file_contents($filename, $dst = '') { $type=strtolower(substr(strrchr($filename,'.'),1)); if ('php' == $type && is_file($filename) && is_writable($filename)) { // 如果是PHP文件 并且可写 则进行压缩编码 $contents = file_get_contents($filename); // 判断文件是否已经被编码处理 $contents = php_strip_whitespace($filename); // 去除PHP头部和尾部标识 $headerPos = strpos($contents,'<?php'); $footerPos = strrpos($contents,'?>'); $contents = substr($contents, $headerPos + 5, $footerPos !== false ? ($footerPos - $headerPos) : strlen($contents)); $encode = base64_encode(gzdeflate($contents)); // 开始编码 $encode = '<?php'."\n eval(gzinflate(base64_decode("."'".$encode."'".")));\n\n?>"; return file_put_contents($dst, $encode); } return false; }
二、加密方式二
require_once 'encipher.php'; $path = './source'; $target = './dst'; $encipher = new Encipher($path, $target); $encipher->encode();
encipher.php
<?php /** * Created by PhpStorm. * User: Mr.Yang * Date: 2022/5/4 * Time: 9:08 * QQ: 2575404985 */ class Encipher { private $c = ''; private $_sourceFile = ''; private $_sourceFileArray = array(); private $_targetFile = ''; private $_writeContent = ''; private $_comments = array( 'Author: Yang', 'Email: 1017836267@qq.com' ); public function __construct($sourceFile, $targetFile, $comments = array()) { !empty($sourceFile) && $this->_sourceFile = $sourceFile; !empty($targetFile) && $this->_targetFile = $targetFile; !empty($comments) && $this->comments = (array)$comments; if (empty($this->_sourceFile) || !file_exists($this->_sourceFile)) { exit("Source file does not exist."); } if (is_dir($this->_sourceFile)){ $this->_sourceFileArray = $this->getSourceFile($this->_sourceFile); } if (is_dir($this->_targetFile)){ $this->mkdirs($this->_targetFile); }else{ if (empty($this->_targetFile) || !file_exists($this->_targetFile)) { //如果源文件不存在,则创建 fopen($this->_targetFile, "a+"); } } $this->init(); } private function init() { $this->q1 = "O00O0O";//base64_decode $this->q2 = "O0O000";//$c(原文经过strtr置换后的密文,由 目标字符+替换字符+base64_encode(‘原文内容’)构成) $this->q3 = "O0OO00";//strtr $this->q4 = "OO0O00";//substr $this->q5 = "OO0000";//52 $this->q6 = "O00OO0";//urldecode解析过的字符串(n1zb/ma5\vt0i28-pxuqy*6%6Crkdg9_ehcswo4+f37j) } private function getSourceFile($path) { static $arr = array(); if (is_dir($path)) { $array = glob($path . '/*'); foreach ($array as $k => $v) { if (is_dir($v)) { $target = $this->_targetFile.str_replace($this->_sourceFile, '', $v); $this->mkdirs($target); $this->getSourceFile($v); } else { $arr[] = $v; } } } else { $arr = $path; } return $arr; } /** * 递归创建目录 * @param $dir * @return bool */ private function mkdirs($dir) { if(!is_dir($dir)) { if(!$this->mkdirs(dirname($dir))){ return false; } if(!mkdir($dir,0777)){ return false; } } return true; } /** * 返回随机字符串 * @return string */ private function createRandKey() { // 返回随机字符串 $str = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; return str_shuffle($str); } /** * 写入文件 * @param $targetFile 写入文件的路径 * @return $this */ private function write($targetFile) { $file = fopen($targetFile, 'w'); fwrite($file, $this->_writeContent) or die('写文件错误'); fclose($file); return $this; } /** * 对明文内容进行加密处理 * @param $sourceFile 要加密的文件路径 * @return $this */ private function encodeText($sourceFile) { //随机密匙1 $k1 = $this->createRandKey(); //随机密匙2 $k2 = $this->createRandKey(); // 获取源文件内容 $sourceContent = file_get_contents($sourceFile); //base64加密 $base64 = base64_encode($sourceContent); //根据密匙替换对应字符。 $c = strtr($base64, $k1, $k2); $this->c = $k1 . $k2 . $c; return $this; } private function encodeTemplate() { $encodeContent = '$' . $this->q6 . '=urldecode("%6E1%7A%62%2F%6D%615%5C%76%740%6928%2D%70%78%75%71%79%2A6%6C%72%6B%64%679%5F%65%68%63%73%77%6F4%2B%6637%6A");$' . $this->q1 . '=$' . $this->q6 . '{3}.$' . $this->q6 . '{6}.$' . $this->q6 . '{33}.$' . $this->q6 . '{30};$' . $this->q3 . '=$' . $this->q6 . '{33}.$' . $this->q6 . '{10}.$' . $this->q6 . '{24}.$' . $this->q6 . '{10}.$' . $this->q6 . '{24};$' . $this->q4 . '=$' . $this->q3 . '{0}.$' . $this->q6 . '{18}.$' . $this->q6 . '{3}.$' . $this->q3 . '{0}.$' . $this->q3 . '{1}.$' . $this->q6 . '{24};$' . $this->q5 . '=$' . $this->q6 . '{7}.$' . $this->q6 . '{13};$' . $this->q1 . '.=$' . $this->q6 . '{22}.$' . $this->q6 . '{36}.$' . $this->q6 . '{29}.$' . $this->q6 . '{26}.$' . $this->q6 . '{30}.$' . $this->q6 . '{32}.$' . $this->q6 . '{35}.$' . $this->q6 . '{26}.$' . $this->q6 . '{30};eval($' . $this->q1 . '("' . base64_encode('$' . $this->q2 . '="' . $this->c . '";eval(\'?>\'.$' . $this->q1 . '($' . $this->q3 . '($' . $this->q4 . '($' . $this->q2 . ',$' . $this->q5 . '*2),$' . $this->q4 . '($' . $this->q2 . ',$' . $this->q5 . ',$' . $this->q5 . '),$' . $this->q4 . '($' . $this->q2 . ',0,$' . $this->q5 . '))));') . '"));'; $headers = array_map('trim', array_merge(array('/*'), $this->_comments, array('*/'))); $this->_writeContent = "<?php" . "\r\n" . implode("\r\n", $headers) . "\r\n" . $encodeContent . "\r\n" . "?>"; return $this; } /** * 获取解密后内容 * @param $sourceFileContent 解密前内容 * @return $this */ private function decodeTemplate($sourceFileContent) { //以eval为标志 截取为数组,前半部分为密文中的替换掉的函数名,后半部分为密文 $m = explode('eval',$sourceFileContent); //对系统函数的替换部分进行执行,得到系统变量 $varStr = substr($m[0],strpos($m[0],'$')); //执行后,后续就可以使用替换后的系统函数名 eval($varStr); //判断是否有密文 if(!isset($m[1])){ return $this; } //对密文进行截取 {$this->q4} substr $star = strripos($m[1],'('); $end = strpos($m[1],')'); $str = ${$this->q4}($m[1],$star,$end); //对密文解密 {$this->q1} base64_decode $str = ${$this->q1}($str); //截取出解密后的 核心密文 $evallen = strpos($str,'eval'); $str = substr($str,0,$evallen); //执行核心密文 使系统变量被赋予值 $O0O000 eval($str); $this->_writeContent = ${$this->q1}( ${$this->q3}( ${$this->q4}( ${$this->q2},${$this->q5}*2 ), ${$this->q4}( ${$this->q2},${$this->q5},${$this->q5} ), ${$this->q4}( ${$this->q2},0,${$this->q5} ) ) ); return $this; } /** * 加密函数 */ public function encode() { if (is_dir($this->_sourceFile)){ foreach ($this->_sourceFileArray as $k => $v){ $target = $this->_targetFile.str_replace($this->_sourceFile, '', $v); $this->encodeText($v)->encodeTemplate()->write($target); echo 'encode-----加密前文件:'.$v.'-----加密后文件:'.$target.'-----ok<br/>'; } }else{ $this->encodeText($this->_sourceFile)->encodeTemplate()->write($this->_targetFile); echo 'encode-----加密前文件:'.$this->_sourceFile.'-----加密后文件:'.$this->_targetFile.'-----ok<br/>'; } } /** * 解密函数 */ public function decode() { if (is_dir($this->_sourceFile)){ foreach ($this->_sourceFileArray as $k => $v){ $sourceFileContent = file_get_contents($v); $target = $this->_targetFile.str_replace($this->_sourceFile, '', $v); $this->decodeTemplate($sourceFileContent)->write($target); echo 'decode-----解密前文件:'.$v.'-----解密后文件:'.$target.'-----ok<br/>'; } }else{ $sourceFileContent = file_get_contents($this->_sourceFile); $this->decodeTemplate($sourceFileContent)->write($this->_targetFile); echo 'decode-----解密前文件:'.$this->_sourceFile.'-----解密后文件:'.$this->_targetFile.'-----ok<br/>'; } } }
三、方式三
<?php include_once 'func_v2.php'; $dir = __DIR__ . '/test/'; mkdir(__DIR__ . '/encoded/'); $files = glob($dir . '*.php'); $gen_count = 0; chdir($dir); foreach ($files as $file) { echo "\r\n", str_repeat("===", 5), "\r\n\r\n"; $target_file = $file; $target_file = str_replace('/test/', '/encoded/', $target_file); $options = array( //混淆方法名 1=字母混淆 2=乱码混淆 'ob_function' => 2, //混淆函数产生变量最大长度 'ob_function_length' => 3, //混淆函数调用 1=混淆 0=不混淆 或者 array('eval', 'strpos') 为混淆指定方法 'ob_call' => 1, //随机插入乱码 'insert_mess' => 0, //混淆函数调用变量产生模式 1=字母混淆 2=乱码混淆 'encode_call' => 2, //混淆class 'ob_class' => 0, //混淆变量 方法参数 1=字母混淆 2=乱码混淆 'encode_var' => 2, //混淆变量最大长度 'encode_var_length' => 5, //混淆字符串常量 1=字母混淆 2=乱码混淆 'encode_str' => 2, //混淆字符串常量变量最大长度 'encode_str_length' => 3, // 混淆html 1=混淆 0=不混淆 'encode_html' => 2, // 混淆数字 1=混淆为0x00a 0=不混淆 'encode_number' => 1, // 混淆的字符串 以 gzencode 形式压缩 1=压缩 0=不压缩 'encode_gz' => 1, // 加换行(增加可阅读性) 'new_line' => 0, // 移除注释 1=移除 0=保留 'remove_comment' => 1, // debug 'debug' => 1, // 重复加密次数,加密次数越多反编译可能性越小,但性能会成倍降低 'deep' => 1, // PHP 版本 'php' => 7, ); // encode target enphp_file($file, $target_file, $options); log::info('encoded', $target_file); $old_output = $output = array(); // run encoded & old script exec('php -d error_reporting=0 "' . $target_file . '"', $output); exec('php -d error_reporting=0 "' . $file . '"', $old_output); $output = implode("\n", $output); $old_output = implode("\n", $old_output); $old_output = strtr($old_output, [realpath($file) => realpath($target_file)]); // compare result if ($old_output == $output) { log::info('SUCCESS_TEST'); } else { log::info('FAILURE_TEST'); echo str_repeat('===', 5); echo "\r\nold=", trim($old_output), "\r\n"; echo str_repeat('===', 5); echo "\r\nnew=", trim($output), "\r\n"; break; } }
func_v2.php
<?php $_SERVER['starttime'] = microtime(1); $starttime = explode(' ', $_SERVER['starttime']); $_SERVER['time'] = $starttime[1]; /** * enphp content * * @param $file * @param array $options * * @return string */ function enphp($content, $options = array()) { $deep = max(1, isset($options['deep']) ? (int)$options['deep'] : 1); $deep = min($deep, 10); $options['deep'] = max(1, min($deep, 1)); foreach (range(1, $deep) as $loop) { $content = strip_whitespace($content, $options); } return $content; } /** * enphp file * * @param $file * @param $target_file * @param $options * * @return string */ function enphp_file($file, $target_file, $options = array()) { $content = file_get_contents($file); check_bom($content); $content = enphp($content, $options); if ($target_file) { file_put_contents($target_file, $content); } return $content; } /** * strip white space * * @param $content * @param array $options * * @return string */ function strip_whitespace($content, $options = array()) { format_code($content); $list = token_get_all($content); $last_space = false; $is_function = false; $function_var_list = array(); $static_fun_list = array(); $use_var_list = array(); $is_global = true; $function_stack = array(); $str_var_list = array(); $is_class = false; $class_name = array(); $class_stack = 0; $function_var_close = 1; $function_alias = array(); $is_string_var = false; $is_static_var = false; $is_interface = false; $is_namespace = false; $namespace_name = ''; $is_catch = false; $is_throw = false; $is_ns_separator = false; $is_static_call = false; $is_if = false; $is_short_if = false; $is_for = false; $is_elseif = false; $is_function_use = false; $is_quote = false; $is_abstract_function = false; $is_abstract_class = false; $heredoc_end = false; $global_vars = array(); $function_start_point = array(); $options = array_merge(array( //混淆方法名 1=字母混淆 2=乱码混淆 0=不混淆 'ob_function' => 2, //混淆函数产生变量最大长度 'ob_function_length' => 3, //混淆函数调用 1=混淆 0=不混淆 或者 array('eval', 'strpos') 为混淆指定方法 'ob_call' => 1, //随机插入乱码 'insert_mess' => 1, //混淆方法调用 1=字母混淆 2=乱码混淆 0=不混淆 'ob_class' => 2, //混淆函数调用变量产生模式 1=字母混淆 2=乱码混淆 0=不混淆 'encode_call' => 2, //混淆变量 方法参数 1=字母混淆 2=乱码混淆 0=不混淆 'encode_var' => 2, //混淆变量最大长度 'encode_var_length' => 5, //混淆字符串常量 1=字母混淆 2=乱码混淆 0=不混淆 'encode_str' => 2, //混淆字符串常量变量最大长度 'encode_str_length' => 3, // 混淆html 1=混淆 0=不混淆 'encode_html' => 1, // 混淆数字 1=混淆为0x00a 0=不混淆 'encode_number' => 1, // 混淆的字符串 以 gzencode 形式压缩 1=压缩 0=不压缩 'encode_gz' => 1, // 加换行(增加可阅读性) 'new_line' => 0, // 移除注释 1=移除 0=保留 'remove_comment' => 1, // 文件头部增加的注释 'comment' => '-- Author: Yang', // debug 'debug' => 1, // 重复加密次数,加密次数越多反编译可能性越小,但性能会成倍降低 'deep' => 1, // 默认PHP版本 'php' => 5, ), $options); $is_debug = $options['debug']; $php_version = $options['php']; $str_var_name = substr(generate_name($options['encode_str'], $options['encode_str_length']), 1); $str_define_name = substr(generate_name($options['encode_str'], $options['encode_str_length']), 1); // 这里必须要多个字符防止多重混淆时,产生碰撞导致分隔符失效 static $str_var_splits = array(); $str_var_char = ''; while (true) { $str_var_char = ''; foreach (range(1, max($options['deep'], 3)) as $deep) { $str_var_char .= '|' . ($options['encode_gz'] ? chr(rand(1, 3 + min($deep, 6))) : strip_str(chr(rand(32, 64)))); } if (isset($str_var_splits[$str_var_char])) { continue; } $str_var_splits[$str_var_char] = 1; break; } $str_index = 0; $str_var_str = array(); $global_vars = array('$' . 'GLOBALS', '$_' . 'GET', '$' . '_SERVER'); shuffle($global_vars); $str_global = end($global_vars); $str_global_var = $str_global . '{' . $str_define_name . '}'; $same_quotes = array('{' => '[', '}' => ']'); $len_global_var = strlen($str_global_var); $all_start_time = time(); $insert_list = array(); $is_ob_array = is_array($options['ob_call']); $allow_modify_variables = array('T_VARIABLE', 'T_INLINE_HTML', 'T_STRING', 'T_CONSTANT_ENCAPSED_STRING'); for ($key = 0; $key < count($list); $key++) { $start_time = microtime_float(); //list($time, $start_time) = explode('.', ); $val = &$list[$key]; //log::info($val); $trim_last = false; if (is_array($val)) { $token_idx = $val[0]; $token_name = is_numeric($token_idx) ? token_name($token_idx) : ''; $token_str = $val[1]; //echo $token_str, "\r\n"; switch ($token_idx) { //过滤空格 case T_WHITESPACE: $is_static_call && $is_static_call = 0; if (!$last_space) { $last_space = true; $val[1] = ' '; } else if (!$options['new_line']) { $val[1] = ''; } break; case T_NAMESPACE: $is_namespace = 1; $namespace_name = ''; $val[1] = ' ' . trim($val[1]) . ' '; $last_space = true; break; case T_INTERFACE: $is_interface = 1; $last_space = false; $is_class = 1; $class_name = array(); break; case T_ABSTRACT: if (find_next_token($list, $key + 1, array('function'))) { $is_abstract_function = 1; } else if (find_next_token($list, $key + 1, array('class'))) { $is_abstract_class = 1; } $last_space = false; break; case T_NS_SEPARATOR: !$is_ns_separator && $is_ns_separator = 1; break; case T_VARIABLE: if (in_array($token_str, array('$_SERVER', '$_GET', '$_POST', '$_COOKIE', '$_REQUEST', '$this', '$GLOBALS', '$_SESSION', '$_FILES', '$_ENV')) ) { } else { // 非 function 而且是静态变量 if (!$function_stack[$is_function] && $is_static_var) { break; } // use global for this if ($is_function_use) { // find in function params $_is_use_find = 0; foreach ($function_var_list as $_func_var_index => $_func_var_list) { if (isset($_func_var_list[$token_str])) { $val[1] = $_func_var_list[$token_str]; $_is_use_find = 1; break; } } if ($_is_use_find) { $use_var_list[$is_function][$token_str] = $val[1]; break; } // find in global if (isset($global_vars[$token_str])) { $val[1] = $global_vars[$token_str]; $use_var_list[0][$token_str] = $val[1]; } break; } $is_get_func_var = false; if ($is_static_call) { if (find_last_token($list, $key, array('(', ','))) { $is_get_func_var = 1; } else { break; } } // 定义的静态变量 if ($is_static_var && $is_function) { if ($options['encode_var']) { $static_fun_list[$is_function][$token_str] = generate_name($options['encode_var'], $options['encode_var_length']); $val[1] = $static_fun_list[$is_function][$token_str]; } else { $static_fun_list[$is_function][$token_str] = $token_str; } break; } $_function_var_list = &$function_var_list[$is_function]; $_use_var_list = &$use_var_list[$is_function]; $_global_use_var_list = &$use_var_list[0]; if ($is_global) { if ($is_function) { $_function_var_list[$token_str] = $val[1]; } else { $global_vars[$token_str] = $val[1]; } } elseif (($is_get_func_var || $is_function) && isset($_function_var_list[$token_str])) { $val[1] = $_function_var_list[$token_str]; // in use function variables } elseif (($is_get_func_var || $is_function) && isset($_use_var_list[$token_str])) { $val[1] = $_use_var_list[$token_str]; // in use global variables } elseif (($is_get_func_var || $is_function) && isset($_global_use_var_list[$token_str])) { $val[1] = $_global_use_var_list[$token_str]; } elseif ($is_function && isset($static_fun_list[$is_function][$token_str])) { $val[1] = $static_fun_list[$is_function][$token_str]; } elseif ($is_get_func_var || $is_function) { if ($options['encode_var']) { $val[1] = generate_name($options['encode_var'], $options['encode_var_length']); } $_function_var_list[$token_str] = $val[1]; } } $last_space = true; break; case T_CONSTANT_ENCAPSED_STRING: if ($is_static_var || $is_interface == 1) { // skip static var } else if ($function_var_close && $options['encode_str']) { if (!isset($str_var_list[$token_str])) { // todo : eval performance //$val_no_quote = substr($val[1], 1, -1); //$val_no_quote = stripslashes($val_no_quote); $eval_str = '$_GET["____"]=' . $val[1] . ';'; eval($eval_str); $val[1] = $_GET["____"]; //assert($val_no_quote == $val[1], $val_no_quote . '!=' . $val[1]); //$val[1] = $val_no_quote; // add list $str_index = array_push($str_var_str, $val[1]) - 1; //$str_var_index++ $val[1] = $str_global_var . rand_quote(num_hex($options['encode_number'], $str_index)); $str_var_list[$token_str] = $val[1]; } else { $val[1] = $str_var_list[$token_str]; } } // $last_space = false; break; case T_GLOBAL: $is_global = true; //$val[1] = ($last_space ? '' : ' ' ).$val[1]. ' '; break; case T_CATCH: $is_catch = true; break; case T_CLASS: $last_space = false; $is_global = false; $is_class = 1; $class_name = array(); $is_function = 0; $last_space = false; break; case T_THROW: $is_throw = true; $val[1] = ($last_space ? '' : ' ') . $val[1]; $last_space = false; break; case T_IF: $is_if = true; $is_short_if = 1; break; case T_FUNCTION: $is_global = false; // first deep function if (!$is_function) { $is_function = 1; $function_var_list = array( 1 => array() ); $function_start_point = array( 1 => $key, ); $use_var_list = array( 1 => array(), ); $static_fun_list = array( 1 => array(), ); } else { $function_var_list[++$is_function] = array(); $use_var_list[$is_function] = array(); $function_start_point[$is_function] = $key; } $function_var_close = false; $is_static_var = false; $val[1] = ($last_space ? '' : ' ') . $val[1]; $last_space = false; break; // detect class static use this case T_STRING: if ($is_function && !$function_var_close) { break; } if ($is_namespace == 1 && !$namespace_name) { $namespace_name = $val[1]; if ($namespace_name) { $namespace_name = '\\' . $namespace_name . '\\'; } break; } // get class name if ($options['ob_class'] && $is_class == 1 && !$class_name) { if (!$is_abstract_class) { $class_name = array( 'alias' => generate_name($options['ob_class'], $options['encode_var_length'], 0), 'name' => $val[1], ); $val[1] = $class_name['alias']; break; } } // is catch if ($is_string_var || $is_interface == 1 || $is_static_var || $is_catch || $is_throw /*|| $is_ns_separator*/) { break; } $lower_token = strtolower($val[1]); // skip boolean if ($lower_token == 'true') { $val[1] = '!0'; break; } if ($lower_token == 'false') { $val[1] = '!1'; break; } if (in_array($lower_token, array('null', 'self', 'parent'))) { break; } $is_ob = $options['ob_call']; // check ob call if ($is_ob_array && in_array($lower_token, $options['ob_call'])) { $is_ob = true; } // wont ob call if (!$is_ob) { break; } //log::info('find1', $val[1]); if ($is_class == 1 || $is_namespace == 1) { break; } if (find_last_token($list, $key, array('class', 'namespace', 'extends', 'implements'))) { break; } //namespace if ($list[$key + 1][1] == '\\' || $list[$key - 1]['content'] == '\\') { break; } //log::info('find2', $is_ob, find_last_token($list, $key, array('->', '::')), $val[1]); // skip object call or static call $last_is_call = find_last_token($list, $key, array('->', '::')); if ($is_ob && $last_is_call) { // only method encode if (!find_next_token($list, $key, array('('))) { break; }/* if (find_last_token($list, $key - 1, array('self'))) { break; }*/ $pattern_str_var = '%s'; $remove_dollar = 1; if (find_next_token($list, $key, array('['))) { $pattern_str_var = '{%s}'; $remove_dollar = 0; } if (isset($str_var_list['__call' . $token_str])) { $val[1] = $str_var_list['__call' . $token_str]; break; } // add list $str_index = array_push($str_var_str, $val[1]) - 1; if (!$is_quote) { $remove_dollar = $remove_dollar ? substr($str_global_var, 1) : $str_global_var; if ($php_version == 7) { $val[1] = '{$' . $remove_dollar . rand_quote(num_hex($options['encode_number'], $str_index)) . '}'; } else { $val[1] = '$' . $remove_dollar . rand_quote(num_hex($options['encode_number'], $str_index)) . ''; } //log::info('var', $val[1]); $str_var_list['__call' . $token_str] = sprintf($pattern_str_var, $val[1]); } else { $str_var_list['__call' . $token_str] = $val[1]; } break; } // check in cache for performance if (isset($str_var_list[$token_str])) { $val[1] = $str_var_list[$token_str]; break; } if ($is_ob) { $next_is_static = find_next_token($list, $key, array('.', ',', ')', ';', '+', '-', '/', '%', '&', '|', ':',//三元操作符 '>>', '!=', '!==', '==', '>=', '<=', '!==', '<>', '^', '?>', '::', '&&', '||', '[',//support new php const array 'and', 'or', 'xor', '?')); // is constant if ($next_is_static) { break; } // is namespace / if (!isset($str_var_list[$token_str])) { // add list $str_index = array_push($str_var_str, $val[1]) - 1; if (!$is_quote) { $is_str_defined = get_defined($val[1]); $val[1] = $str_global_var . rand_quote(num_hex($options['encode_number'], $str_index)); $str_var_list[$token_str] = sprintf($is_str_defined ? 'constant(%s)' : '%s', $val[1]); } else { $str_var_list[$token_str] = $val[1]; } } else { $val[1] = $str_var_list[$token_str]; } } break; case T_DOUBLE_COLON: $is_static_call = 1; break; case T_USE: if ($is_function) { $is_function_use = true; } $val[1] = ($last_space ? '' : ' ') . trim($val[1]) . ' '; !$last_space && $last_space = true; break; case T_INSTANCEOF: case T_AS: $val[1] = ' ' . trim($val[1]) . ' '; !$last_space && $last_space = true; $is_static_call && $is_static_call = 0; break; //过滤各种PHP注释 case T_COMMENT: case T_DOC_COMMENT: $val[1] = $options['remove_comment'] ? '' : $val[1]; break; //case T_DNUMBER: // float case T_LNUMBER: $val[1] = num_hex($options['encode_number'], $val[1]); break; case T_IS_NOT_EQUAL: case T_IS_GREATER_OR_EQUAL: case T_IS_EQUAL: case T_IS_IDENTICAL: case T_IS_NOT_IDENTICAL: case T_IS_SMALLER_OR_EQUAL: case T_DOUBLE_ARROW: $val[1] = trim($val[1]); break; // html compress case T_INLINE_HTML: if ($options['encode_html'] && strlen($val[1]) > 32) { if (!isset($str_var_list[$token_str])) { // add list $str_index = array_push($str_var_str, $val[1]) - 1; //$str_var_index++ $val[1] = $str_global_var . rand_quote(num_hex($options['encode_number'], $str_index)); $str_var_list[$token_str] = $val[1]; } else { $val[1] = $str_var_list[$token_str]; } $val[1] = '<' . '?=' . $val[1] . ';?' . '>'; } break; case T_PRIVATE: case T_PROTECTED: case T_PUBLIC: case T_VAR: case T_CONST: $is_static_var = true; $val[1] = ($last_space ? '' : ' ') . trim($val[1]) . ' '; $last_space = true; break; case T_STATIC: $is_static_var = true; $val[1] = ($last_space ? '' : ' ') . trim($val[1]) . ' '; $last_space = true; break; // { in string variable // complex variable parsed syntax case T_CURLY_OPEN: $is_string_var = true; $is_class && $is_class++; $is_namespace && $is_namespace++; break; case T_EXTENDS: case T_IMPLEMENTS: $val[1] = ' ' . trim($val[1]) . ' '; $last_space = true; break; case T_FOR: $is_for = 2; case T_ELSEIF: $is_elseif = 1; break; case T_LOGICAL_AND: $val[1] = '&&'; $last_space = true; $is_static_call && $is_static_call = 0; break; case T_LOGICAL_OR: $val[1] = '||'; $last_space = true; $is_static_call && $is_static_call = 0; break; case T_OPEN_TAG_WITH_ECHO: break; case T_END_HEREDOC: $heredoc_end = true; break; default: $last_space = false; break; } if (is_numeric($val[1]) || $val[1]) { $val = array( 'token_name' => $token_name, 'content' => $val[1], 'line_num' => $val[2], ); if ($options['ob_function']) { if (!$is_class && $is_function && !$function_var_close) { if ($token_idx == T_FUNCTION) { continue; } else if ($token_idx == T_STRING) { $function_alias[] = generate_name($options['ob_function'], $options['ob_function_length'], 0); } else { $function_alias[] = $val['content']; } } } } } else { switch ($val) { case ';': $trim_last = 1; if ($heredoc_end) { $heredoc_end = false; $val .= "\r\n"; } if (!$is_string_var && !$is_abstract_function && !$is_interface && !$is_for && !$is_short_if && !$is_elseif && $is_function == 1 ) { $mess_code = ''; if ($options['insert_mess'] && rand(0, $options['insert_mess'])) { $mess_code = generate_name(2, rand(10, 100), 0, 0, chr(144)) . ';'; } $val .= ($options['new_line'] ? "\r\n" : "") . $mess_code; } $is_short_if == 1 && $is_short_if--; $is_elseif == 1 && $is_elseif--; $is_for && $is_for--; if ($is_static_var) { $is_static_var = false; } if ($is_function && $is_global) { $is_global = false; } // is abstract if ($is_abstract_function && $is_function) { $is_function = 0; $function_stack = array(); } $is_abstract_function && $is_abstract_function = 0; $is_static_call && $is_static_call = 0; $is_namespace && $is_namespace = 0; $is_throw && $is_throw = 0; $is_ns_separator && $is_ns_separator--; break; case '{': $trim_last = 1; if ($is_catch) { $is_catch = false; } $is_elseif && $is_elseif++; $is_short_if && $is_short_if++; $is_interface && $is_interface++; $is_class && $is_class++; $is_abstract_function && $is_abstract_function = 0; if (!$is_string_var) { $is_function && $function_stack[$is_function]++; // get start point if ($is_function && $function_stack[$is_function] == 1) { $function_start_point[$is_function] = $key; } $is_class && $class_stack++; } if ($is_static_var) { $is_static_var = false; } $is_static_call && $is_static_call = 0; $is_namespace && $is_namespace--; break; case '}': $trim_last = 1; $is_namespace && $is_namespace--; $is_elseif && $is_elseif--; $is_short_if && $is_short_if--; if ($is_namespace == 1) { $is_namespace = 0; $namespace_name = ''; } $is_interface && $is_interface--; if ($is_class && --$is_class == 1 && $class_name) { if (!$is_abstract_class) { $_class_alias = get_str_list($str_var_list, $str_var_str, $namespace_name . $class_name['alias'], $str_global_var, $options); $_class_name = get_str_list($str_var_list, $str_var_str, $namespace_name . $class_name['name'], $str_global_var, $options); $is_ob = find_ob_function($options, 'class_alias'); $gz_func = get_func_param($is_ob, $options['encode_call'], $str_index, $str_var_list, $str_var_str, $str_global_var, 'class_alias'); $val .= $gz_func . "({$_class_alias},{$_class_name},0);print_R({$_class_alias});print_R({$_class_name});"; // reset class detect $class_name = array(); $is_class = 0; $is_abstract_class = 0; } } else if ($is_string_var) { $is_string_var = false; } else { if ($is_function && --$function_stack[$is_function] === 0) { // set static function variable empty $static_fun_list[$is_function] = array(); // find all of variables contains global; $index_key = $key; //print_R(array_splice($list, 0, $key));exit; // // 绑定全局变量 $find_global_var = 0; $_function_stack = array( 0 => 1, ); $_function_index = 0; //$lower_global_var = strtolower($str_global_var); $str_global_var_same_quote = strtr($str_global_var, $same_quotes); while ($options['encode_var'] && $index_key-- > -1) { $token = $list[$index_key]; $token_str = isset($token['content']) ? strtolower(rtrim($token['content'])) : $token; $token_var = substr($token['content'], 0, $len_global_var); if (strtr($token_var, $same_quotes) == $str_global_var_same_quote) { $find_global_var++; } switch ($token_str) { case 'function': //$_function_stack[++$_function_index] = 0; break; case '{': if (--$_function_stack[$_function_index] == 0) { //$_function_index--; } break; case '}': $_function_stack[$_function_index]++; break; } if ($_function_stack[0] == 0 && $token_str == 'function') { // 少于2次引用,不使用别名模式 if ($find_global_var < 2) { break; } $function_global_var = generate_name($options['encode_var'], $options['encode_var_length']); // 这里不能插入了,如果文件太大,导致list太大 // 内存复制太慢,插入list中太慢, // 新建一个 list 在生成新文件的时候插入 $_function_start_pos = $function_start_point[$is_function] + 1; $insert_list[$_function_start_pos] = $function_global_var . '=&' . $str_global_var . ';'; // replace all variable form new var $_function_stack = array( 0 => 1, ); $_function_index = 0; for ($rollback_key = $index_key + 2; $rollback_key < $key; $rollback_key++) { $token = &$list[$rollback_key]; // for anonymous function switch (strtolower(trim($token['content']))) { case 'function': $_function_stack[++$_function_index] = 0; break; case '{': $_function_stack[$_function_index]++; break; case '}': if (--$_function_stack[$_function_index] == 0) { $_function_index--; } break; } if ($_function_index == 0 && in_array($token['token_name'], $allow_modify_variables)) { $is_modify = substr($token['content'], 0, 3) == '<?=' ? 4 : 1; $_var_start = substr($token['content'], $is_modify - 1, $len_global_var); if (strtr($_var_start, $same_quotes) == $str_global_var_same_quote) { $token['content'] = substr_replace($token['content'], $function_global_var, $is_modify - 1, $len_global_var); } } } unset($token); break; } } $is_function--; } if ($is_class && --$class_stack == 0) { $is_class = false; } } if (!$is_function && !$is_class) { $is_global = true; } break; case '(': $trim_last = 1; if ($is_static_var && find_left_quote($list, $key, 1)) { $is_static_var = false; } if ($options['ob_function']) { if (!$is_class && $is_function && !$function_var_close) { $function_alias[] = $val; } } $is_static_call && $is_static_call = 0; break; case ')': $trim_last = 1; if ($is_class) { if ($is_function && !$function_var_close && find_left_quote($list, $key)) { $function_var_close = 1; } else { } break; } if ($is_if) { if (find_left_quote($list, $key)) { $is_if = 0; } break; } // function () use() $is_function_use && $is_function_use = 0; if (!$function_var_close && !find_left_quote($list, $key)) { $options['ob_function'] && $function_alias[] = ')'; break; } $function_var_close = 1; if (!$options['ob_function']) { break; } if (!$function_alias) { break; } $function_alias[] = ')'; //print_r($function_alias); $old_function = array(); $index_key = $key; $token = 0; while ($index_key-- > -1) { $token = $list[$index_key]; $old_function[] = $token['content']; if (trim(strtolower($token['content'])) == 'function') { break; } } if (!$token) { break; } // 匿名方法 if (!trim($function_alias[0])) { break; } $func_unset = 0; foreach ($function_alias as $func_index => $func_str) { switch (strtolower($func_str)) { case '=': $func_unset = 1; break; case 'array': if ($func_unset > 0) { $func_unset = 0; } $func_unset -= 2; break; case ',': if ($func_unset == 1) { $func_unset = 0; } elseif ($func_unset > 0) { $func_unset = 1; } break; case ')': if ($func_unset < 0) { $func_unset += 2; if ($func_unset == 0) { unset($function_alias[$func_index]); } } else { $func_unset = 0; } // $func_unset = 0; break; } if ($func_unset) { unset($function_alias[$func_index]); } } $function_new = implode('', $function_alias); $old_function = array_reverse($old_function); $old_function = implode('', $old_function) . '){return ' . $function_new . ';}'; $list[$index_key]['content'] = $old_function; // unset all function for ($i = $index_key + 1; $i < $key; $i++) { $list[$i]['content'] = ''; } $val = 'function ' . ltrim($function_new); $function_alias = array(); break; case '[': case '.': $is_static_call && $is_static_call = 0; break; case '=': case ',': $is_static_call && $is_static_call = 0; if ($options['ob_function']) { if (!$is_class && $is_function && !$function_var_close) { $function_alias[] = $val; } } $trim_last = 1; break; case "\r": case "\n": $val = ' '; break; case '"': $is_quote = $is_quote ? 0 : 1; break; } if ($val) { $val = array( 'content' => $val, ); } $last_space = true; } if ($trim_last && !$options['new_line']) { if (isset($list[$key - 1]['content'])) { $list[$key - 1]['content'] = rtrim($list[$key - 1]['content']); } } } $vars = ''; $comment = $options['comment'] ? '/* ' . $options['comment'] . ' */' : ''; if ($str_var_str) { // delete last char //substr($str_var_str, 0, 0 - strlen($str_var_char)); $str_var_str = implode($str_var_char, $str_var_str); //echo $str_var_str;exit; $vars = 'error_reporting(E_ALL^E_NOTICE);'; $vars .= 'define(\'' . $str_define_name . '\', \'' . $str_var_name . '\');'; $vars .= $options['insert_mess'] ? generate_name(2, rand(100, 200), 0, 0) . ';' : ''; $vars .= $str_global . '[' . $str_define_name . '] = explode(\'' . $str_var_char . '\', ' . output_gz($str_var_str, 'gzinflate', 'substr', $options['encode_number'], $options['encode_gz']) . ');'; $vars .= $options['insert_mess'] ? generate_name(2, rand(100, 200), 0, 0) . ';' : ''; //$vars .= '?'.'>'; } $str = ''; $is_namespace = false; $namespace_str = ''; foreach ($list as $key => $c) { if (isset($insert_list[$key])) { $str .= $insert_list[$key]; } $str .= isset($c['content']) ? $c['content'] : ''; if ($c['token_name'] == 'T_NAMESPACE') { $is_namespace = true; } else if ($is_namespace) { if ($is_namespace && (trim($c['content']) == ';' || trim($c['content']) == '{')) { $str .= $vars; $vars = ''; $is_namespace = false; } } } if ($vars) { $vars = '<?php ' . $vars . '?>'; } if ($comment) { $namespace_str = '<?php ' . $comment . '?>' . $namespace_str; } $str = $namespace_str . $vars . $str; $str = str_replace('?' . '><?' . 'php', '', $str); return $str; } /** * cut string from $start to $end * * @param $html * @param string $start * @param string $end * * @return string */ function enphp_cut_str($html, $start = '', $end = '') { if ($start) { $html = stristr($html, $start, false); $html = substr($html, strlen($start)); } $end && $html = stristr($html, $end, true); return $html; } // /* */ /** * mask match string: * * spider::mask_match('123abc123', '123(*)123') = abc * spider::mask_match('abc123', '(*)123') = abc * spider::mask_match('123abcabc', '(*)abc') = 123 * spider::mask_match('123abcdef', '(*)abc', true) = 123abc * * @param $html * @param $pattern * @param bool|false $returnfull * * @return string */ function enphp_mask_match($html, $pattern, $returnfull = false) { $part = explode('(*)', $pattern); if (count($part) == 1) { return ''; } else { if ($part[0] && $part[1]) { $res = enphp_cut_str($html, $part[0], $part[1]); if ($res) { return $returnfull ? $part[0] . $res . $part[1] : $res; } } else { //pattern=xxx(*) if ($part[0]) { if (strpos($html, $part[0]) !== false) { $html = explode($part[0], $html); if ($html[1]) { return $returnfull ? $part[0] . $html[1] : $html[1]; } } } elseif ($part[1]) { //pattern=(*)xxx if (strpos($html, $part[1]) !== false) { $html = explode($part[1], $html); if ($html[0]) { return $returnfull ? $html[0] . $part[1] : $html[0]; } } } } return ''; } } function format_code(&$source) { $patterns = array( '#<hi' . 'de>(*)#</hi' . 'de>' => '', '/*<hi' . 'de>*/(*)/*</hi' . 'de>*/' => '', ); // replace hide block foreach ($patterns as $pattern => $replace) { $search = enphp_mask_match($source, $pattern, true); $source = str_replace($search, $replace, $source); } $encode_str = '/*<en' . 'code>*/'; $encode_str_len = strlen($encode_str); $encode_str_end = '/*</en' . 'code>*/'; $encode_str_end_len = strlen($encode_str_end); while (strpos($source, $encode_str) !== false) { $start_pos = strpos($source, $encode_str); $end_pos = strpos($source, $encode_str_end); $end_pos = $end_pos - $encode_str_end_len - $start_pos + 1; $enstr = substr($source, $start_pos + $encode_str_len, $end_pos); $enstr = trim($enstr); if (is_numeric($enstr)) { $str = encode_num($enstr); } else if ($enstr[0] != substr($enstr, -1) || !in_array($enstr[0], array('"', "'"))) { $str = $enstr; } else { $str = ''; try { $str = encode_str(parse_string_var($enstr)); } catch (Exception $e) { continue; } } $source = substr_replace($source, ($str), $start_pos, $end_pos + $encode_str_end_len * 2 - 1); } } function encode_num($s, $rand = 0) { $n1 = rand(1, 100); $n2 = rand(2, 200); $n3 = rand(300, 500); switch (rand(1, 4)) { case 1: $n1 = rand(10, 100); $n2 = rand(2, 20); return '(' . ($s * $n1 - $n2) . '+' . $n2 . ')/' . $n1; break; case 2: return ($s - $n2 * $n1) . '+' . $n2 . '*' . $n1; break; case 3: return ($s + $n3 - $n2 * $n1) . '-' . $n3 . '+' . $n2 . '*' . $n1; break; case 4: return ($s - $n3 - $n2 * $n1) . '+' . $n3 . '+' . $n2 . '*' . $n1; break; } } /** * encode str * * @param $s */ function encode_str($s, $rand = 0) { switch (rand(1, 4 + $rand)) { case 1: $s = base64_encode($s); $s = strtr($s, array('=' => '')); return 'base64_decode(\'' . $s . '\')'; break; case 2: $s = base64_encode($s); $s = strtr($s, array('=' => '')); return 'base64_decode(\'' . $s . '\')'; break; case 3: $s = base64_encode(gzencode($s)); $s = strtr($s, array('=' => '')); return 'gzinflate(substr(base64_decode(\'' . $s . '\'), 10, -8))'; break; case 4: $s = str_rot13(base64_encode($s)); $s = strtr($s, array('=' => '')); return 'base64_decode(str_rot13(\'' . $s . '\'))'; break; } } /** * @param $str_var_list * @param $token_str * @param $str_global_var * @param $options */ function get_str_list(&$str_var_list, &$str_var_str, $token_str, $str_global_var, &$options) { if (!isset($str_var_list[$token_str])) { // add list $str_index = array_push($str_var_str, $token_str) - 1; $is_str_defined = get_defined($token_str); $result = $str_global_var . rand_quote(num_hex($options['encode_number'], $str_index)); $str_var_list[$token_str] = sprintf($is_str_defined ? 'constant(\'%s\')' : '%s', $result); } else { $result = $str_var_list[$token_str]; } return $result; } /** * microtime float * * @return float */ function microtime_float() { list($usec, $sec) = explode(" ", microtime()); return ((float)$usec + (float)$sec); } /** * insert array in array by position * * @param $list * @param $position * @param $array * * @return array */ function array_insert(&$list, $position, $array) { log::info('insertStart'); array_splice($list, $position + 1, 0, $array); log::info('insertOver'); } /** * check utf8 bom * * @param $content */ function check_bom(&$content) { $charset[1] = substr($content, 0, 1); $charset[2] = substr($content, 1, 1); $charset[3] = substr($content, 2, 1); if (ord($charset[1]) == 239 && ord($charset[2]) == 187 && ord($charset[3]) == 191) { $content = substr($content, 3); } } /** * find ob function * * @param $options * * @return int */ function find_ob_function($options, $func) { $is_ob = $options['ob_call']; if (is_array($options['ob_call']) && in_array($func, $options['ob_call'])) { $is_ob = 1; } return $is_ob; } /** * find last token is keyword * * @param $list * @param $index * @param $keywords * * @return int */ function find_last_token(&$list, $index, $keywords) { while (--$index && $index > -1) { $keyword = strtolower(trim($list[$index]['content'])); if (!$keyword) { continue; } if (in_array($keyword, $keywords)) { return 1; } else { return 0; } } } /** * find next token * * @param $list * @param $index * @param $keywords * * @return int */ function find_next_token(&$list, $index, $keywords) { $len = count($list); while (++$index && $index < $len) { $str = isset($list[$index]['content']) ? $list[$index]['content'] : (isset($list[$index][1]) ? $list[$index][1] : $list[$index]); $keyword = trim($str); if (!$keyword) { continue; } if (in_array(strtolower($keyword), $keywords)) { return 1; } else { return 0; } } } function find_next_is_not_statment(&$list, $index, $keywords) { $len = count($list); $is_var = 0; while (++$index && $index < $len) { $str = isset($list[$index]['content']) ? $list[$index]['content'] : (isset($list[$index][1]) ? $list[$index][1] : $list[$index]); $keyword = trim($str); if (!$keyword) { continue; } log::info('next_statment', $keyword); if (!in_array(strtolower($keyword), $keywords)) { return 1; } else { return 0; } } } /** * find quote left or right * * @param $list * @param $index * @param int $left * * @return int */ function find_left_quote(&$list, $index, $left = 0) { $right_quote = $left ? 0 : 1; $left_quote = $left; $quit = 0; while (--$index && $index > -1) { $word = strtolower(trim($list[$index]['content'])); switch ($word) { case 'protected': case 'private': case 'public': case 'static': case 'var'; case 'function': case 'if': case 'use': $quit = 1; break; case '=': //return ($right_quote - $left_quote == 1) ? 1 : 0; break; case '(': $left_quote++; break; case ')': $right_quote++; break; } if ($quit) { break; } } if ($right_quote - $left_quote == 0) { return 1; } else { return 0; } } /** * insert new param * * @param $is_ob * @param $encode * @param $str_index * @param $str_var_list * @param $str_var_str * @param $str_var_char * @param $str_global_var * @param $func * * @return string */ function get_func_param($is_ob, $encode, &$str_index, &$str_var_list, &$str_var_str, &$str_global_var, $func) { //return $func; if (!$is_ob) { return $func; } if (!isset($str_var_list[$func])) { // add list $str_index = array_push($str_var_str, $func) - 1; $result = $str_global_var . rand_quote(num_hex($encode, $str_index++)); $str_var_list[$func] = $result; } else { $result = $str_var_list[$func]; } return $result; } /** * generate variables name * * @param int $encode * @param int $len * @param int $add_dollar * @param int $check_exists * * @return mixed|string */ function generate_name($encode = 1, $len = 4, $add_dollar = 1, $check_exists = 1, $pre = '') { global $gen_count; static $exists_name = array(); static $exists_index = 0; $varname = ''; while (true) { $gen_count++; $varname = ''; if ($encode == 2) { foreach (range(1, rand(1, $len)) as $i) { $varname .= chr(rand(128, 254)); } } else if ($encode == 1) { $exists_index++; $varname .= decbin($exists_index); $varname = str_replace('1', 'O', $varname); } else { $exists_index++; $zero_length = $len - strlen($exists_index); $varname .= 'v' . ($zero_length > 0 ? str_repeat(0, rand(1, $zero_length)) : '') . $exists_index; } $varname = $pre . $varname; if (!$check_exists) { break; } // is exists variable if (isset($exists_name[$varname])) { continue; } // add array $exists_name[$varname] = 1; break; } return ($add_dollar ? '$' : '') . $varname; } /** strip str * * @param $str * * @return mixed */ function strip_str($str) { $replaces = array( '\\' => '\\\\', '\'' => '\\\'', ); foreach ($replaces as $from => $to) { $str = str_replace($from, $to, $str); } return $str; } /** * 随机括号 * * @param $str * * @return string */ function rand_quote($str) { static $index = 0; return $index++ % 2 == 1 ? '{' . $str . '}' : '[' . $str . ']'; } /** * out put gzencode * * @param $str * @param $gz_func * @param $sub_func * @param $encode_number * * @return string */ function output_gz($str, $gz_func, $sub_func, $encode_number, $is_gz = 0) { if (!$is_gz) { return '\'' . strip_str($str) . '\''; } else { return $gz_func . '(' . $sub_func . '(\'' . strip_str(gzencode($str)) . '\',' . num_hex($encode_number, 10) . ', -8))'; } } /** * hex for number * * @param $encode * @param $num * * @return string */ function num_hex($encode, $num) { if ($encode == 1) { if (strpos($num, '0') === 0) { return $num; } if (strpos($num, '0x') === 0) { $num = base_convert($num, 16, 10); } $repeat = ($num % 5) + 1; $str = '0x' . str_repeat('0', $repeat) . base_convert($num, 10, 16); return $str; } else { return $num; } } /** * get defined by cache * * @param $name * * @return mixed */ function get_defined($name) { static $define_list = array(); if (!isset($define_list[$name])) { $define_list[$name] = defined($name); } return $define_list[$name]; } /** * get usedtime * * @return string */ function usedtime() { return number_format(microtime(1) - $_SERVER['starttime'], 6) * 1000; } /** * parse string variable * * @param $s * * @return string|void */ function parse_string_var($s) { $quote = substr($s, 0, 1); $val_no_quote = substr($s, 1, -1); if ($quote == '"') { } else { } $val_no_quote = stripslashes($val_no_quote); return $val_no_quote; } if (!class_exists('log', false)) { class log { /** * @var int log file name */ public static $log_file = 0; /** * @var int|resource log file file pointer */ public static $log_fp = 0; /** * init to log * * @param $file */ public static function set_logfile($file) { if ($file == 1) { $file = 'data/log/' . date('Y-m-d') . '.log'; } self::$log_file = $file; self::$log_fp = fopen($file, 'a+'); } /** * alias set log file * * @param $file */ public static function set_file($file) { self::set_logfile($file); } /** * dump variable for log * * @param $data * * @return string */ public static function dump_var($data) { if (is_array($data)) { $str = ''; foreach ($data as $k => $v) { if (is_array($v)) { $str .= '[' . $k . '=' . self::dump_var($v) . ']'; } else { $str .= '[' . $k . '=' . $v . ']'; } } return $str; } else { return '[' . $data . ']'; } } /** * log::info($arg1,$arg2....$argn); * * @param mixed */ public static function info() { self::add_log('info', func_get_args(), func_num_args()); } /** * log::error($arg1,$arg2....$argn); * * @param mixed */ public static function error() { self::add_log('error', func_get_args(), func_num_args()); throw new Exception('error'); } /** * add log * * @param $type * @param $arg_list * @param $arg_count */ private static function add_log($type, $arg_list, $arg_count) { $log = ''; for ($i = 0, $l = $arg_count; $i < $l; $i++) { $log .= self::dump_var($arg_list[$i]); } $log .= '[' . usedtime() . "ms]"; $log = "[" . date('H:i:s') . "]" . $log . "\r\n"; if (self::$log_fp) { fputs(self::$log_fp, $log); } if (php_sapi_name() == 'cli') { echo $log; } else { if (isset($_SERVER['log'])) { $_SERVER['log'] = array( 'info' => array(), 'error' => array(), ); } $_SERVER['log'][$type][] = $log; } } } } /** * hex dump * * @param $data * @param string $newline */ function hex_dump($data, $newline = "\n") { static $from = ''; static $to = ''; static $width = 16; // 每行宽度 static $pad = '.'; if ($from === '') { for ($i = 0; $i <= 0xFF; $i++) { $from .= chr($i); $to .= ($i >= 0x20 && $i <= 0x7E) ? chr($i) : $pad; } } $hex = str_split(bin2hex($data), $width * 2); $chars = str_split(strtr($data, $from, $to), $width); $offset = 0; foreach ($hex as $i => $line) { echo sprintf('%6X', $offset) . ' : ' . implode(' ', str_split($line, 2)) . ' [' . $chars[$i] . ']' . $newline; $offset += $width; } } ?>