Smarty の math 関数
Smarty の math 関数 Smarty の math で、剰余を得る % 演算子を使いたいなと思ってマニュアルを調べると、 <blockquote class="tr_bq">+, -, /, *, abs, ceil, cos, exp, floor, log, log10, max, min, pi, pow, rand, round, sin, sqrt, srans and tan are all valid operators. Check the PHP documentation for further information on these math functions.</blockquote> としか書かれていない。四則演算はいいけど % はダメなのかと思ったが、実際にコードを書くと問題なく動く。 そこで math 関数の実装を覗いてみた。 http://smarty-php.googlecode.com/svn/trunk/distribution/libs/plugins/function.math.php 許される関数は <blockquote class="tr_bq"> static $_allowed_funcs = array( ‘int’ => true, ‘abs’ => true, ‘ceil’ => true, ‘cos’ => true, ‘exp’ => true, ‘floor’ => true, ‘log’ => true, ‘log10’ => true, ‘max’ => true, ‘min’ => true, ‘pi’ => true, ‘pow’ => true, ‘rand’ => true, ‘round’ => true, ‘sin’ => true, ‘sqrt’ => true, ‘srand’ => true ,’tan’ => true );</blockquote>と決まっている。 まず丸カッコの個数が合っていることを確認する。 <blockquote class="tr_bq"> if (substr_count($equation,”(“) != substr_count($equation,”)”)) { trigger_error(“math: unbalanced parenthesis”,E_USER_WARNING); return; }</blockquote> 次に equation で渡された数式を要素に分ける。16進数または文字列(変数名または関数名)を探して $match に入れる。 <blockquote class="tr_bq"> preg_match_all(“!(?:0x[a-fA-F0-9]+) |
([a-zA-Z][a-zA-Z0-9_]*)!”,$equation, $match);</blockquote> $match[1] には文字列の配列が入っている。正規表現の (?: により16進数はキャプチャされない。文字列が引数として渡された変数名でもなく、$_allowed_funcs で定義された関数名でもなければエラー。 <blockquote class="tr_bq"> foreach($match[1] as $curr_var) { if ($curr_var && !isset($params[$curr_var]) && !isset($_allowed_funcs[$curr_var])) { trigger_error(“math: function call $curr_var not allowed”,E_USER_WARNING); return; } }</blockquote> 引数として渡された変数が空ではなく、さらに数値であることを確認する。問題なければ $equation 中の変数を変数値で置き換える。 <blockquote class="tr_bq"> foreach($params as $key => $val) { if ($key != “equation” && $key != “format” && $key != “assign”) { // make sure value is not empty if (strlen($val)==0) { trigger_error(“math: parameter $key is empty”,E_USER_WARNING); return; } if (!is_numeric($val)) { trigger_error(“math: parameter $key: is not numeric”,E_USER_WARNING); return; } $equation = preg_replace(“/\b$key\b/”, “ $params[‘$key’] “, $equation); } }</blockquote> 最後に eval() で評価する。 <blockquote class="tr_bq"> $smarty_math_result = null; eval(“$smarty_math_result = “.$equation.”;”);</blockquote> ということで、演算子はチェック対象外なので、なんでも通る、ということがわかった。 <div> </div> |