Nucleus

NP_nestedinclude

2007年5月15日

前の記事の続き。

NP_nestedinclude は、スキン変数の入れ子構造に対応したスキンパースを行う。<%parsedinclude%>と置き換えて使用。

スキンとテンプレートの両方で使用できる。テンプレートは、アイテム本体と、コメント本体でのみ使用可能。

とりあえずのソースコード:

<?php 
class NP_nestedinclude extends NucleusPlugin { 
    function getName() { return 'NP_nestedinclude'; }
    function getMinNucleusVersion() { return 220; }
    function getAuthor()  { return 'Katsumi'; }
    function getVersion() { return '0.1'; }
    function getURL() {return 'http://www.recfor.net/nucleus/?itemid=317';}
    function getDescription() { return $this->getName().' plugin'; } 
    function supportsFeature($what) { return (int)($what=='SqlTablePrefix'); }
    var $skin=array('handler'=>false,'parser'=>false);
    function doSkinVar($skinType,$type) {
        $handler=&$this->skin['handler'];
        $parser=&$this->skin['parser'];
        if (!$handler) {// See SKIN::parse()
            $actions=SKIN::getAllowedActionsForType($skinType);
            $handler =& new ACTIONS($skinType);
            $parser =& new NP_nestedinclude_PARSER($actions, $handler);
            $handler->setParser($parser);
        }
        $handler->parse_parsedinclude($type);
    }
    var $template=array('actions'=>false,'parser'=>false);
    function doTemplateVar(&$item,$type) {
        $actions=&$this->template['actions'];
        $parser=&$this->template['parser'];
        if (!$actions) {// See BLOG::ShowUsingQuery()
            global $blog;
            $actions =& new ITEMACTIONS($blog);
            $parser =& new NP_nestedinclude_PARSER($actions->getDefinedActions(),$actions);
            $actions->setParser($parser);
        }
        $actions->setCurrentItem($item);
        $actions->parse_parsedinclude($type);
    }
    var $comment=array('actions'=>false,'parser'=>false);
    function doTemplateCommentsVar(&$item, &$comment,$type) {
        $actions=&$this->comment['actions'];
        $parser=&$this->comment['parser'];
        if (!$actions) {// See COMMENTS::ShowCommens()
            $actions =& new COMMENTACTIONS($this);
            $parser =& new NP_nestedinclude_PARSER($actions->getDefinedActions(),$actions);
            $actions->setParser($parser);
        }
        $actions->setCurrentComment($comment);
        $actions->parse_parsedinclude($type);
    }
}
class NP_nestedinclude_PARSER extends PARSER {
    // Override following function.
    function parse($contents) {
        $delim=preg_replace('/^\((.*)\)$/','$1',$this->delim);
        list($begin,$end)=explode('|',$delim);
        if (!$begin || !$end) list($begin,$end)=array('<%','%>');
        $stack=array();
        while (strlen($contents)) {
            if (count($stack)==0) {
                // Outside the tag
                $i=strpos($contents,$begin /*'<%'*/);
                if ($i===false) {
                    echo $contents;
                    return;
                }
                echo substr($contents,0,$i);                            // Left side
                $contents=substr($contents,$i+strlen($begin /*'<%'*/)); // Right side
                array_push($stack,'');
            }
            // Now, we are in the tag.
            $i=strpos($contents,$begin /*'<%'*/);
            $j=strpos($contents,$end /*'%>'*/);
            if ($i===false && $j===false) {
                // Both '<%' and '%>' are not found.
                $this->doAction($contents);
                return;
            } else if ($j!==false && ($j<$i || $i===false)) {
                // '%>' found. The right characters are outside the tag.
                $action=substr($contents,0,$j);                       // Left side
                $contents=substr($contents,$j+strlen($end /*'%>'*/)); // Right side
                $actionlc=preg_replace('/^([^\(]+)[\(](.*)$/','$1',strtolower($action));
                if (preg_match('/^(if[.]*|else|endif|ifnot|elseif|elseifnot)$/',$actionlc)) {
                    // if, else, endif etc.
                    // ob_start() cannot be used here because it's used below.
                    // In addition, on_start() isn't needed here (if etc. doesn't parse anything).
                    $this->doAction($action);
                } else {
                    ob_start();
                    $this->doAction($action);
                    $contents=ob_get_contents().$contents;
                    ob_end_clean();
                }
                if (count($stack)) $contents=array_pop($stack).$contents;
            } else {
                // '<%' found.
                array_push($stack,substr($contents,0,$i));              // Left side
                $contents=substr($contents,$i+strlen($begin /*'<%'*/)); // Right side
            }
        }
    }
}
?>

バグ混入の可能性あり。

(スキン変数をネストして用いると、予期せぬセキュリティーホールが発生する可能性もありますので、使用の際は十分注意してください。)

コメント

コメントはありません

コメント送信