NP_nestedinclude
2007年5月15日
前の記事の続き。
NP_nestedinclude は、スキン変数の入れ子構造に対応したスキンパースを行う。<%parsedinclude%>と置き換えて使用。
スキンとテンプレートの両方で使用できる。テンプレートは、アイテム本体と、コメント本体でのみ使用可能。
とりあえずのソースコード:
バグ混入の可能性あり。
(スキン変数をネストして用いると、予期せぬセキュリティーホールが発生する可能性もありますので、使用の際は十分注意してください。)
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.rad51.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 } } } } ?>
バグ混入の可能性あり。
(スキン変数をネストして用いると、予期せぬセキュリティーホールが発生する可能性もありますので、使用の際は十分注意してください。)