PHP中的源代码签名(PHP源码学习快速方法)

在阅读了一篇文章后,觉得有必要写一个源码签名收集器,所以就自己动手扩展了个,
下面是实现的主要细节。另外,附我读的那篇文章的翻译。详见文章最后部分。

使用方法:
假设对应的php脚本文件,名为SourceCodeIteration.php
此时,我们在需要遍历的源码包的根目录处,新建一个脚本,名为runGetSourceCode.php,代码如下:

<?php

include("SourceCodeIteration.php");//引入库
$si = new SourceIteration();//初始化源码遍历对象
$si->GetInfo();//获取签名,并打印在页面上

效果图如下:

接下来,直接贴我改造后的代码,具体的原理详解可以点击参看,翻译部分

<?php

class SourceIteration {

    var $baseDir;
    var $type; //.php;.aspx; you can use ; to split different type
    var $displayWay;
    var $seperator;
    var $RoleArray;
    var $initIndent;
    var $indentCell;
    var $curIndent;
    var $pregFormat;

    var $currentLevel=0;
    var $currentDirName="root";
    //var $currentPostion

    function __construct($baseDir=null, $type=".php", $displayWay="page", $seperator="", $initIndent="", $indentCell="&nbsp;&nbsp;", $RoleArray=array(array("role" => "dir", "color" => "blue"), array("role" => "file", "color" => "red")), $pregFormat='/[{};]/') {
        $baseDir == null ? $this->baseDir = dirname(__FILE__) : $this->baseDir = $baseDir;
        $this->type = $type;
        $this->displayWay = $displayWay;
        $this->seperator = $seperator;
        $this->RoleArray = $RoleArray;
        $this->initIndent = $initIndent;
        $this->indentCell = $indentCell;
        $this->curIndent = array($this->initIndent);
        $this->pregFormat = $pregFormat;
    }

    function GetInfo() {
        header("Content-type: text/html; charset=utf-8");
        //$this->getJS();
        $files = new FilesystemIterator($this->baseDir);
        $this->recurGetFileTree($files);
    }

    function recurGetFileTree($files) {
        $this->currentLevel++;
        array_push($this->curIndent, $this->indentCell);
        foreach ($files as $file) {
            if ($file->isDir()) {
                if($file->getFilename()==".svn")  continue;
                $this->write($file->getFilename(), $this->seperator, $this->RoleArray[0], $this->displayWay);
                $subfiles = new FilesystemIterator($file->getPathname());

                $this->recurGetFileTree($subfiles);
                echo '</div>' . $this->seperator;
            } else {
                if ($this->isTypeFile($file)) {

                    $signature = $this->getFileSignature($file);
                    $this->write($file->getFilename() . " : " . $signature, $this->seperator, $this->RoleArray[1], $this->displayWay);
                }
            }
        }
        $this->currentLevel--;
        array_pop($this->curIndent);
    }

    function getFileSignature($file) {
        $data = file_get_contents($file);
        preg_match_all($this->pregFormat, $data, $out);
        $signature = '';
        foreach ($out[0] as $line) {
            $signature .= $line;
        }
        return $signature;
    }

    function isTypeFile($file) {
        if ($this->type == "*") {
            return true;
        } else {
            $type = explode(";", $this->type);
            if (count($type) > 1) {
                foreach ($type as &$value) {
                    $value = strtolower($value);
                }

                if (in_array(strtolower(substr($file->getFilename(), -4)), $type))
                    return true;
                else
                    return false;
            } else {
                if (strtolower(substr($file->getFilename(), -4)) == strtolower($type[0]))
                    return true;
                else
                    return false;
            }
        }
    }

    function write($content, $seperator, $role, $displayWay) {
        if ($this->displayWay == "page")
            $this->displayInPage($content, $seperator, $role);
        elseif ($this->displayWay == "console")
            $this->displayInConsole($content, $seperator, $role);
    }

    function displayInPage($content, $seperator, $role) {
        if($role["role"]==$this->RoleArray[0]["role"])
            echo '<div status="display" id=\''.$content.'\' class=\''. $role["role"].'\' style=\'color:' . $role["color"] . ';\'>' . $this->getCurrentIndent() . "|>".$content;
        else
            echo '<div id=\'\' class=\'\' style=\'color:' . $role["color"] . ';\'>' . $this->getCurrentIndent() . "|>".$content . '</div>' . $seperator;
    }

    function displayInConsole($content, $seperator, $role) {
        echo $this->getCurrentIndent() . $content . $seperator . "\n";
    }

    function getCurrentIndent() {
        $ret = $this->initIndent;
        foreach ($this->curIndent as $value) {
            $ret = $ret . $value;
        }
        return $ret;
    }

}


【翻译部分】
E文地址:http://www.codediesel.com/php/source-code-signatures-in-php/

这篇文章是基于Ward Cunningham的名为Signature Survey: A Method for Browsing Unfamiliar Code 的文章的。Ward建议,当学习新的、不熟悉的源码时,对代码结构获取直观的感受是很重要的。Ward建议了一种方法,通过从每个源文件中逐行获取标点进行总结。他称此为文件签名。这将会帮助开发者考量代码基础的复杂性。

例如,如果我们只考虑使用'{}'和';'——PHP编程中的公共标点元素。程序员可以对源文件的结构有个了解。在php中括号划定了函数或块的范围,在其他许多语言中也大多如此,所以这将告诉程序员该代码块或函数的尺寸大小(长还是短)。

以Wordpress系统的源文件为例,以括号和分号作为选择标点字符,WordPress的签名通过以下方法得到:

样本WordPress源文件——wp-blog-header.php:

<?php
/**
 * Loads the WordPress environment and template.
 *
 * @package WordPress
 */

if ( !isset($wp_did_header) ) {
    $wp_did_header = true;
    require_once( dirname(__FILE__) . '/wp-load.php' );
    wp();
    require_once( ABSPATH . WPINC . '/template-loader.php' );
}
?>

得到的上面代码的签名如下:

wp-blog-header.php : {;;;;}

这说明了该文件有一个块部分(可以是函数,类或其他的),包含了四条语句。如果我们在签名中还包含圆括号'()'的话,我们会获得以下的。但是,这看上去一点复杂,并且也不如前一个直观。

wp-blog-header.php : (()){;(());();();}
下面我们给出更多的WordPress根文件的签名:

index.php : ;;
wp-atom.php : ;;;
wp-blog-header.php : {;;;;}
wp-comments-post.php : {;;;;};;;;{;;};;{;;}{;;}{;;}{;;}{;};;;;;{;;;;
{{;;}}}{;};{;;};;;;;{;;;;};;;;
wp-commentsrss2.php : ;;;
wp-config-sample.php : {};;;;;;{};;;;;;;;;;;;;
wp-config.php : ;{};;;;;;{}}{{{;{};;{;;{;{};{{{;{;}{;;;;;;
wp-cron.php : ;;;{;};;;;{;{{;{;;};;}}};
wp-feed.php : ;;;
wp-links-opml.php : ;;;;{;;};;;;;;;;;;;;;;;;
xmlrpc.php : ;;{;};;{;;;;};;;;;;{;{;;;;;};};;;;;
wp-load.php : ;;{;}{;}{;;;;;;;;;;;;}
wp-pass.php : ;;;;;
wp-rdf.php : ;;;
wp-register.php : ;;;
wp-rss.php : ;;;
wp-rss2.php : ;;;
wp-login.php : ;{{;;}{;;}}{;;;;;;;;;;;;;;;;{;;;;{;}{;}}{{;}};;{;;;}{;;
;};;{;;}{;;{;{;;}};;}}{;;;{;;}{};;;}{;;{;{;}{;{;;}}};{;}{;}{;;{{;};}{{
;;}{}}}{;;;;;};}{;;;{;;}{;;};;{;;};;;;;;;;{;;;};;;;;;;;;;;;;}{;;;;;;;}
{;;;}{;;;{;}{;;}{;}{;}{;;;}{;};;;;;{;;;};;;};;;;;;;{;;;};;;;;{;;;;;;{;
{;;;}};;;;;;;;;;;;;{;;};{;}{;;;;};;;;;;;;;;;{;;}{;;};;{;;;{;;;}};;;;;;
;;;;;{;{{;;}}}{;;}{;};;;;{{;;{};;;}{;;;};;};;;;;;;;;;;;;;;;;;{}{;}{;}{
{{{;;}{;{;}};;}{}};}{;};;;}
wp-mail.php : ;;;;;;;;;;;;;;{;;;};;{;;;;;;;;;;{;{;}{{;;;;{;;};}{;;;;;}
{;;;}{;;{;}{;};;}{;;;{;;{;}{;;}}{;}}{;;{;};;;;;;;;;;{{;}};;;;;}}}{;;}{
;};{;;{;;};};;{;}{;};;;;;;;;;;;;;;;{;;;}{;}};
wp-settings.php : ;;;;;;;;;;;;;;;;;;;;;;;;;;;;{;;}{;};;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;{;;;};{;};{{;};};;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;{;
;};;;;;{{;;};};
wp-signup.php : ;;;{;;}{;};{;}{;;}{;;};{{;;}{;}{;;;;;}{;;;}{;;}{;;;;}{;
}{;;;;;}};;;{;;;{};;{;;;}{};;{};{};;}{;;;}{;{;};;;{}{;};}{;}{;;{;};;;;;
{;};;{{;;}};;;}{;;;;;{;;};;;;;;}{{}{}{};;;}{;;;;;;;;;;;{}{}{}}{;;{;;}{;
;};;;}{;;}{;;;;;;;;;;}{;;{;;};;{;;};;;;;;}{{}{}{};;;;;};;;;;;;;;;;;{;}{
;;;;}{;{;;;;;;;;;;;;;;{;;;};}};;
wp-trackback.php : {;;}{;;{;;;;;;}{;;;;}};{;;};;;;;;;;{;;;};;;;;{;;}{;;
;;;;;;;;;;;;;;;}
wp-activate.php : ;;;{;;};;{;};{{;}{;;}{;}{;}{;;;;;}};;{;}{;;{{;;;{;;
;}{;;;};}{;;}}{;;;;;;;;;;}};;;

产生签名除了Ward在其文中提到的perl脚本,还可以使用一下的shell脚本或php程序。
Shell脚本

for i in *.php; do
    echo -n "$i: "
    sed 's/[^{};]//g' $i | tr -d '\n'
    echo
done

PHP程序实现函数签名

<?php

/* Get all PHP files in the current directory */
$dir = './*.php';

/* Use the SPL Iterator class */
$files = new GlobIterator($dir);

/* Get the signature of each file */
foreach ($files as $file) {
    $data = file_get_contents($file);
    preg_match_all('/[{};]/',$data,$out);
    $signature = '';

    foreach($out[0] as $line) {
        $signature .= $line;
    }

    echo $file->getFilename() . " : " . $signature . "\n";
}

此外,我们还可以通过输出成HTML,并带有每个源文件的链接,来使得输出更吸引人、更友好。





 » 订阅本站:RSS订阅

发表评论

您也可以使用微博账号登陆

无觅相关文章插件,快速提升流量