swoole compiler加密一些框架时产生的问题

在使用Swoole Compiler加密PHP框架如Drupal时,由于file_get_contents和token_get_all的组合导致项目运行错误。Drupal和Symfony的某些功能会读取并解析PHP源码,而加密后的代码无法正常处理。为解决此问题,建议使用反射函数替代token_get_all获取类名和注释,对于use信息则依赖swoole_loader.so扩展。目前,针对Symfony的缓存文件机制和Drupal的setting.php文件的处理方案仍在寻求中。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

问题:使用swoole compiler加密类似drupal这样的项目的时候在不做处理的情况下会出现项目无法运行的情况,分析了drupal的源码发现在drupal的方法中有一个方法会通过file_get_contents直接获取php文件的内容,然后将获取的内容用token_get_all函数进行代码分割,然后分析分割后的代码获取该文件的注释和use的类,因为file_get_contents所获取的代码是加密后的代码,所以也就产生了错误,当然不止这一处存在这样的问题,drupal加载了symfony,symfony中文件缓存也有类似的操作,通过读取php文件,对文件进行正则匹配然后缓存到新文件中

解决方案:对于获取类名,注释等,可以通过反射函数代替token_get_all函数,一些反射无法获取的信息比如use信息,则通过swoole_loader.so扩展进行获取

待解决:symfony的缓存文件机制和drupal的setting.php文件的处理暂时未想到合理的解决方案,因为两者都是通过分析php源码,然后在源码的基础上添加新的代码在存入文件的

StaticReflectionParser.php文件的改动主要如下,获取文件如果是加密文件则走新添加的代码,如果不是加密文件则还是走老方法

/**
 * @return void
 */
protected function parse()
{
    if ($this->parsed || !$fileName = $this->finder->findFile($this->className)) {
        return;
    }
    $this->parsed = true;
    $contents = file_get_contents($fileName);
    if (strpos($contents, 'SWOOLEC') === false) {
        if ($this->classAnnotationOptimize) {
            if (preg_match("/\A.*^\s*((abstract|final)\s+)?class\s+{$this->shortClassName}\s+/sm", $contents, $matches)) {
                $contents = $matches[0];
            }
        }
        $tokenParser = new TokenParser($contents);
        $docComment = '';
        while ($token = $tokenParser->next(false)) {
            if (is_array($token)) {
                switch ($token[0]) {
                    case T_USE:
                        $this->useStatements = array_merge($this->useStatements, $tokenParser->parseUseStatement());
                        break;
                    case T_DOC_COMMENT:
                        $docComment = $token[1];
                        break;
                    case T_CLASS:
                        $this->docComment['class'] = $docComment;
                        $docComment = '';
                        break;
                    case T_VAR:
                    case T_PRIVATE:
                    case T_PROTECTED:
                    case T_PUBLIC:
                        $token = $tokenParser->next();
                        if ($token[0] === T_VARIABLE) {
                            $propertyName = substr($token[1], 1);
                            $this->docComment['property'][$propertyName] = $docComment;
                            continue 2;
                        }
                        if ($token[0] !== T_FUNCTION) {
                            // For example, it can be T_FINAL.
                            continue 2;
                        }
                    // No break.
                    case T_FUNCTION:
                        // The next string after function is the name, but
                        // there can be & before the function name so find the
                        // string.
                        while (($token = $tokenParser->next()) && $token[0] !== T_STRING) ;
                        $methodName = $token[1];
                        $this->docComment['method'][$methodName] = $docComment;
                        $docComment = '';
                        break;
                    case T_EXTENDS:
                        $this->parentClassName = $tokenParser->parseClass();
                        $nsPos = strpos($this->parentClassName, '\\');
                        $fullySpecified = false;
                        if ($nsPos === 0) {
                            $fullySpecified = true;
                        } else {
                            if ($nsPos) {
                                $prefix = strtolower(substr($this->parentClassName, 0, $nsPos));
                                $postfix = substr($this->parentClassName, $nsPos);
                            } else {
                                $prefix = strtolower($this->parentClassName);
                                $postfix = '';
                            }
                            foreach ($this->useStatements as $alias => $use) {
                                if ($alias == $prefix) {
                                    $this->parentClassName = '\\' . $use . $postfix;
                                    $fullySpecified = true;
                                }
                            }
                        }
                        if (!$fullySpecified) {
                            $this->parentClassName = '\\' . $this->namespace . '\\' . $this->parentClassName;
                        }
                        break;
                }
            }
        }
    }else{
        $ref = new \ReflectionClass($this->className);

        $parent_ref = $ref->getParentClass();

        $this->docComment['class'] = $ref->getDocComment()?:'';

        if ($this->classAnnotationOptimize) {
            return;
        }

        if (is_file($fileName)) {
            $php_file_info = unserialize(naloinwenraswwww(realpath($fileName)));
            foreach ($php_file_info as $key => $info) {
                if ($key == 'swoole_namespaces' || $key == 'swoole_class_name') {
                    continue;
                }
                $this->useStatements[$key] = $info;
            }
        }

        $this->parentClassName = $parent_ref->getName();

        if (strpos($this->parentClassName, '\\')!==0) {
            $this->parentClassName = '\\'.$this->parentClassName;
        }

        $static_properties = [];

        $properties = $ref->getProperties();

        $parent_properties = $this->createNewArrKey($parent_ref->getProperties());

        foreach ($properties as $property) {
            if (isset($parent_properties[$property->name]) && $property->class == $parent_properties[$property->name]->class) {
                continue;
            }
            $static_properties[] = $property;
        }

        $last_comment = '';//兼容框架bug
        foreach ($static_properties as $property) {
            $property_comment = $property->getDocComment()?:$last_comment;
            if ($property_comment) $last_comment = $property_comment;
            $this->docComment['property'][$property->name] = $property_comment;
        }


        $static_methods = [];

        $methods = $ref->getMethods();

        $parent_methods = $this->createNewArrKey($parent_ref->getMethods());

        foreach ($methods as $method) {
            if (isset($parent_methods[$method->name]) && $method->class == $parent_methods[$method->name]->class) {
                continue;
            }
            $static_methods[] = $method;
        }

        $i = 0;//兼容框架bug
        foreach ($static_methods as $method) {
            $method_comment = $method->getDocComment()?:'';
            if (empty($method_comment) && $i == 0) $method_comment = $last_comment;
            $this->docComment['method'][$method->name] = $method_comment;
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值