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
}
}
}
}
?>バグ混入の可能性あり。
(スキン変数をネストして用いると、予期せぬセキュリティーホールが発生する可能性もありますので、使用の際は十分注意してください。)