Source for file Ethna_Util.php

Documentation is available at Ethna_Util.php

  1. <?php
  2. // vim: foldmethod=marker
  3. /**
  4.  *  Ethna_Util.php
  5.  *
  6.  *  @author     Masaki Fujimoto <fujimoto@php.net>
  7.  *  @license    http://www.opensource.org/licenses/bsd-license.php The BSD License
  8.  *  @package    Ethna
  9.  *  @version    $Id: Ethna_Util.php 468 2007-07-07 07:52:30Z mumumu-org $
  10.  */
  11.  
  12. // {{{ to_array
  13. /**
  14.  *  グローバルユーティリティ関数: スカラー値を要素数1の配列として返す
  15.  *
  16.  *  @param  mixed   $v  配列として扱う値
  17.  *  @return array   配列に変換された値
  18.  */
  19. function to_array($v)
  20. {
  21.     if (is_array($v)) {
  22.         return $v;
  23.     else {
  24.         return array($v);
  25.     }
  26. }
  27. // }}}
  28.  
  29. // {{{ is_error
  30. /**
  31.  *  グローバルユーティリティ関数: 指定されたフォーム項目にエラーがあるかどうかを返す
  32.  *
  33.  *  @param  string  $name   フォーム項目名
  34.  *  @return bool    true:エラー有り false:エラー無し
  35.  */
  36. function is_error($name null)
  37. {
  38.     $c =Ethna_Controller::getInstance();
  39.     $action_error =$c->getActionError();
  40.     if ($name !== null{
  41.         return $action_error->isError($name);
  42.     else {
  43.         return $action_error->count(0;
  44.     }
  45. }
  46. // }}}
  47.  
  48. // {{{ file_exists_ex
  49. /**
  50.  *  グローバルユーティリティ関数: include_pathを検索しつつfile_exists()する
  51.  *
  52.  *  @param  string  $path               ファイル名
  53.  *  @param  bool    $use_include_path   include_pathをチェックするかどうか
  54.  *  @return bool    true:有り false:無し
  55.  */
  56. function file_exists_ex($path$use_include_path true)
  57. {
  58.     if ($use_include_path == false{
  59.         return file_exists($path);
  60.     }
  61.  
  62.     // check if absolute
  63.     if (is_absolute_path($path)) {
  64.         return file_exists($path);
  65.     }
  66.  
  67.     $include_path_list explode(PATH_SEPARATORget_include_path());
  68.     if (is_array($include_path_list== false{
  69.         return file_exists($path);
  70.     }
  71.  
  72.     foreach ($include_path_list as $include_path{
  73.         if (file_exists($include_path DIRECTORY_SEPARATOR $path)) {
  74.             return true;
  75.         }
  76.     }
  77.     return false;
  78. }
  79. // }}}
  80.  
  81. // {{{ is_absolute_path
  82. /**
  83.  *  グローバルユーティリティ関数: 絶対パスかどうかを返す
  84.  *
  85.  *  @param  string  $path               ファイル名
  86.  *  @return bool    true:絶対 false:相対
  87.  */
  88. function is_absolute_path($path)
  89. {
  90.     if (OS_WINDOWS{
  91.         if (preg_match('/^[a-z]:/i'$path&& $path{2== DIRECTORY_SEPARATOR{
  92.             return true;
  93.         }
  94.     else {
  95.         if ($path{0== DIRECTORY_SEPARATOR{
  96.             return true;
  97.         }
  98.     }
  99.     return false;
  100. }
  101. // }}}
  102.  
  103. // {{{ Ethna_Util
  104. /**
  105.  *  ユーティリティクラス
  106.  *
  107.  *  @author     Masaki Fujimoto <fujimoto@php.net>
  108.  *  @access     public
  109.  *  @package    Ethna
  110.  */
  111. class Ethna_Util
  112. {
  113.     // {{{ isDuplicatePost
  114.     /**
  115.      *  POSTのユニークチェックを行う
  116.      *
  117.      *  @access public
  118.      *  @return bool    true:2回目以降のPOST false:1回目のPOST
  119.      */
  120.     function isDuplicatePost()
  121.     {
  122.         $c =Ethna_Controller::getInstance();
  123.  
  124.         // use raw post data
  125.         if (isset($_POST['uniqid'])) {
  126.             $uniqid $_POST['uniqid'];
  127.         else if (isset($_GET['uniqid'])) {
  128.             $uniqid $_GET['uniqid'];
  129.         else {
  130.             return false;
  131.         }
  132.  
  133.         // purge old files
  134.         Ethna_Util::purgeTmp("uniqid_"60*60*1);
  135.  
  136.         $filename sprintf("%s/uniqid_%s_%s",
  137.                             $c->getDirectory('tmp'),
  138.                             $_SERVER['REMOTE_ADDR'],
  139.                             $uniqid);
  140.         if (file_exists($filename== false{
  141.             touch($filename);
  142.             return false;
  143.         }
  144.  
  145.         $st stat($filename);
  146.         if ($st[960*60*time()) {
  147.             // too old
  148.             return false;
  149.         }
  150.  
  151.         return true;
  152.     }
  153.     // }}}
  154.  
  155.     // {{{ clearDuplicatePost
  156.     /**
  157.      *  POSTのユニークチェックフラグをクリアする
  158.      *
  159.      *  @acccess public
  160.      *  @return mixed   0:正常終了 Ethna_Error:エラー
  161.      */
  162.     function clearDuplicatePost()
  163.     {
  164.         $c =Ethna_Controller::getInstance();
  165.  
  166.         // use raw post data
  167.         if (isset($_POST['uniqid'])) {
  168.             $uniqid $_POST['uniqid'];
  169.         else {
  170.             return 0;
  171.         }
  172.  
  173.         $filename sprintf("%s/uniqid_%s_%s",
  174.                             $c->getDirectory('tmp'),
  175.                             $_SERVER['REMOTE_ADDR'],
  176.                             $uniqid);
  177.         if (file_exists($filename)) {
  178.             if (unlink($filename== false{
  179.                 return Ethna::raiseWarning("ファイル書き込みエラー[%s]"E_APP_WRITE$filename);
  180.             }
  181.         }
  182.  
  183.         return 0;
  184.     }
  185.     // }}}
  186.  
  187.     // {{{ isCsrfSafeValid
  188.     /**
  189.      *  CSRFをチェックする
  190.      *
  191.      *  @access public
  192.      *  @return bool    true:正常なPOST false:不正なPOST
  193.      */
  194.     function isCsrfSafe()
  195.     {
  196.         $c =Ethna_Controller::getInstance();
  197.         $name $c->config->get('csrf');
  198.         
  199.         if (is_null($name)) {
  200.             $name 'Session';
  201.         }
  202.         
  203.         $plugin =$c->getPlugin('Csrf'$name);
  204.         $csrf =$plugin->getPlugin('Csrf'$name);
  205.         return $csrf->isValid();
  206.     }
  207.     // }}}
  208.  
  209.     // {{{ setCsrfID
  210.     /**
  211.      *  CSRFをチェックする
  212.      *
  213.      *  @access public
  214.      *  @return bool    true:成功
  215.      */
  216.     function setCsrfID()
  217.     {
  218.         $c =Ethna_Controller::getInstance();
  219.         $name $c->config->get('csrf');
  220.         
  221.         if (is_null($name)) {
  222.             $name 'Session';
  223.         }
  224.         
  225.         $plugin =$c->getPlugin('Csrf'$name);
  226.         $csrf =$plugin->getPlugin('Csrf'$name);
  227.         return $csrf->set();
  228.     }
  229.     // }}}
  230.  
  231.     // {{{ checkMailAddress
  232.     /**
  233.      *  メールアドレスが正しいかどうかをチェックする
  234.      *
  235.      *  @access public
  236.      *  @param  string  $mailaddress    チェックするメールアドレス
  237.      *  @return bool    true: 正しいメールアドレス false: 不正な形式
  238.      */
  239.     function checkMailAddress($mailaddress)
  240.     {
  241.         if (preg_match('/^([a-z0-9_]|\-|\.|\+)+@(([a-z0-9_]|\-)+\.)+[a-z]{2,6}$/i',
  242.                        $mailaddress)) {
  243.             return true;
  244.         }
  245.         return false;
  246.     }
  247.     // }}}
  248.  
  249.     // {{{ explodeCSV
  250.     /**
  251.      *  CSV形式の文字列を配列に分割する
  252.      *
  253.      *  @access public
  254.      *  @param  string  $csv        CSV形式の文字列(1行分)
  255.      *  @param  string  $delimiter  フィールドの区切り文字
  256.      *  @return mixed   (array):分割結果 Ethna_Error:エラー(行継続)
  257.      */
  258.     function explodeCSV($csv$delimiter ",")
  259.     {
  260.         $space_list '';
  261.         foreach (array(" ""\t""\r""\n"as $c{
  262.             if ($c != $delimiter{
  263.                 $space_list .= $c;
  264.             }
  265.         }
  266.  
  267.         $line_end "";
  268.         if (preg_match("/([$space_list]+)\$/sS"$csv$match)) {
  269.             $line_end $match[1];
  270.         }
  271.         $csv substr($csv0strlen($csv)-strlen($line_end));
  272.         $csv .= ' ';
  273.  
  274.         $field '';
  275.         $retval array();
  276.  
  277.         $index 0;
  278.         $csv_len strlen($csv);
  279.         do {
  280.             // 1. skip leading spaces
  281.             if (preg_match("/^([$space_list]+)/sS"substr($csv$index)$match)) {
  282.                 $index += strlen($match[1]);
  283.             }
  284.             if ($index >= $csv_len{
  285.                 break;
  286.             }
  287.  
  288.             // 2. read field
  289.             if ($csv{$index== '"'{
  290.                 // 2A. handle quote delimited field
  291.                 $index++;
  292.                 while ($index $csv_len{
  293.                     if ($csv{$index== '"'{
  294.                         // handle double quote
  295.                         if ($csv{$index+1== '"'{
  296.                             $field .= $csv{$index};
  297.                             $index += 2;
  298.                         else {
  299.                             // must be end of string
  300.                             while ($csv{$index!= $delimiter && $index $csv_len{
  301.                                 $index++;
  302.                             }
  303.                             if ($csv{$index== $delimiter{
  304.                                 $index++;
  305.                             }
  306.                             break;
  307.                         }
  308.                     else {
  309.                         // normal character
  310.                         if (preg_match("/^([^\"]*)/S"substr($csv$index)$match)) {
  311.                             $field .= $match[1];
  312.                             $index += strlen($match[1]);
  313.                         }
  314.  
  315.                         if ($index == $csv_len{
  316.                             $field substr($field0strlen($field)-1);
  317.                             $field .= $line_end;
  318.  
  319.                             // request one more line
  320.                             return Ethna::raiseNotice('CSV分割エラー(行継続)'E_UTIL_CSV_CONTINUE);
  321.                         }
  322.                     }
  323.                 }
  324.             else {
  325.                 // 2B. handle non-quoted field
  326.                 if (preg_match("/^([^$delimiter]*)/S"substr($csv$index)$match)) {
  327.                     $field .= $match[1];
  328.                     $index += strlen($match[1]);
  329.                 }
  330.  
  331.                 // remove trailing spaces
  332.                 $field preg_replace("/[$space_list]+\$/S"''$field);
  333.                 if ($csv{$index== $delimiter{
  334.                     $index++;
  335.                 }
  336.             }
  337.             $retval[$field;
  338.             $field '';
  339.         while ($index $csv_len);
  340.  
  341.         return $retval;
  342.     }
  343.     // }}}
  344.  
  345.     // {{{ escapeCSV
  346.     /**
  347.      *  CSVエスケープ処理を行う
  348.      *
  349.      *  @access public
  350.      *  @param  string  $csv        エスケープ対象の文字列(CSVの各要素)
  351.      *  @param  bool    $escape_nl  改行文字(\r/\n)のエスケープフラグ
  352.      *  @return string  CSVエスケープされた文字列
  353.      */
  354.     function escapeCSV($csv$escape_nl false)
  355.     {
  356.         if (preg_match('/[,"\r\n]/'$csv)) {
  357.             if ($escape_nl{
  358.                 $csv preg_replace('/\r/'"\\r"$csv);
  359.                 $csv preg_replace('/\n/'"\\n"$csv);
  360.             }
  361.             $csv preg_replace('/"/'"\"\""$csv);
  362.             $csv "\"$csv\"";
  363.         }
  364.  
  365.         return $csv;
  366.     }
  367.     // }}}
  368.  
  369.     // {{{ escapeHtml
  370.     /**
  371.      *  配列の要素を全てHTMLエスケープして返す
  372.      *
  373.      *  @access public
  374.      *  @param  array   $target     HTMLエスケープ対象となる配列
  375.      *  @return array   エスケープされた配列
  376.      */
  377.     function escapeHtml($target)
  378.     {
  379.         $r array();
  380.         Ethna_Util::_escapeHtml($target$r);
  381.         return $r;
  382.     }
  383.  
  384.     /**
  385.      *  配列の要素を全てHTMLエスケープして返す
  386.      *
  387.      *  @access public
  388.      *  @param  mixed   $vars   HTMLエスケープ対象となる配列
  389.      *  @param  mixed   $retval HTMLエスケープ対象となる子要素
  390.      */
  391.     function _escapeHtml(&$vars&$retval)
  392.     {
  393.         foreach (array_keys($varsas $name{
  394.             if (is_array($vars[$name])) {
  395.                 $retval[$namearray();
  396.                 Ethna_Util::_escapeHtml($vars[$name]$retval[$name]);
  397.             else if (!is_object($vars[$name])) {
  398.                 $retval[$namehtmlspecialchars($vars[$name]ENT_QUOTES);
  399.             }
  400.         }
  401.     }
  402.     // }}}
  403.  
  404.     // {{{ encode_MIME
  405.     /**
  406.      *  文字列をMIMEエンコードする
  407.      *
  408.      *  @access public
  409.      *  @param  string  $string     MIMEエンコードする文字列
  410.      *  @return エンコード済みの文字列 
  411.      */
  412.     function encode_MIME($string)
  413.     {
  414.         $pos 0;
  415.         $split 36;
  416.         $_string "";
  417.         while ($pos mb_strlen($string))
  418.         {
  419.             $tmp mb_strimwidth($string$pos$split"");
  420.             $pos += mb_strlen($tmp);
  421.             $_string .= (($_string)' ' ''mb_encode_mimeheader($tmp'ISO-2022-JP');
  422.         }
  423.         return $_string;
  424.     }
  425.     // }}}
  426.  
  427.     // {{{ getDirectLinkList
  428.     /**
  429.      *  Google風リンクリストを返す
  430.      *
  431.      *  @access public
  432.      *  @param  int     $total      検索総件数
  433.      *  @param  int     $offset     表示オフセット
  434.      *  @param  int     $count      表示件数
  435.      *  @return array   リンク情報を格納した配列
  436.      */
  437.     function getDirectLinkList($total$offset$count)
  438.     {
  439.         $direct_link_list array();
  440.  
  441.         if ($total == 0{
  442.             return array();
  443.         }
  444.  
  445.         // backwards
  446.         $current $offset $count;
  447.         while ($current 0{
  448.             array_unshift($direct_link_list$current);
  449.             $current -= $count;
  450.         }
  451.         if ($offset != && $current <= 0{
  452.             array_unshift($direct_link_list0);
  453.         }
  454.  
  455.         // current
  456.         $backward_count count($direct_link_list);
  457.         array_push($direct_link_list$offset);
  458.  
  459.         // forwards
  460.         $current $offset $count;
  461.         for ($i 0$i 10$i++{
  462.             if ($current >= $total{
  463.                 break;
  464.             }
  465.             array_push($direct_link_list$current);
  466.             $current += $count;
  467.         }
  468.         $forward_count count($direct_link_list$backward_count 1;
  469.  
  470.         $backward_count -= 4;
  471.         if ($forward_count 5{
  472.             $backward_count -= $forward_count;
  473.         }
  474.         if ($backward_count 0{
  475.             $backward_count 0;
  476.         }
  477.  
  478.         // add index
  479.         $n 1;
  480.         $r array();
  481.         foreach ($direct_link_list as $direct_link{
  482.             $v array('offset' => $direct_link'index' => $n);
  483.             $r[$v;
  484.             $n++;
  485.         }
  486.  
  487.         return array_splice($r$backward_count10);
  488.     }
  489.     // }}}
  490.  
  491.     // {{{ getEra
  492.     /**
  493.      *  元号制での年を返す
  494.      *
  495.      *  @access public
  496.      *  @param  int     $t      unix time
  497.      *  @return string  元号(不明な場合はnull)
  498.      */
  499.     function getEra($t)
  500.     {
  501.         $tm localtime($ttrue);
  502.         $year $tm['tm_year'1900;
  503.  
  504.         if ($year >= 1989{
  505.             return array('平成'$year 1988);
  506.         else if ($year >= 1926{
  507.             return array('昭和'$year 1925);
  508.         }
  509.  
  510.         return null;
  511.     }
  512.     // }}}
  513.  
  514.     // {{{ getImageExtName
  515.     /**
  516.      *  getimagesize()の返すイメージタイプに対応する拡張子を返す
  517.      *
  518.      *  @access public
  519.      *  @param  int     $type   getimagesize()関数の返すイメージタイプ
  520.      *  @return string  $typeに対応する拡張子
  521.      */
  522.     function getImageExtName($type)
  523.     {
  524.         $ext_list array(
  525.             1   => 'gif',
  526.             2   => 'jpg',
  527.             3   => 'png',
  528.             4   => 'swf',
  529.             5   => 'psd',
  530.             6   => 'bmp',
  531.             7   => 'tiff',
  532.             8   => 'tiff',
  533.             9   => 'jpc',
  534.             10  => 'jp2',
  535.             11  => 'jpx',
  536.             12  => 'jb2',
  537.             13  => 'swc',
  538.             14  => 'iff',
  539.             15  => 'wbmp',
  540.             16  => 'xbm',
  541.         );
  542.  
  543.         return @$ext_list[$type];
  544.     }
  545.     // }}}
  546.  
  547.     // {{{ getRandom
  548.     /**
  549.      *  ランダムなハッシュ値を生成する
  550.      *
  551.      *  決して高速ではないので乱用は避けること
  552.      *
  553.      *  @access public
  554.      *  @param  int     $length ハッシュ値の長さ(〜64)
  555.      *  @return string  ハッシュ値
  556.      */
  557.     function getRandom($length 64)
  558.     {
  559.         static $srand false;
  560.  
  561.         if ($srand == false{
  562.             list($usec$secexplode(' 'microtime());
  563.             mt_srand((float) $sec ((float) $usec 100000getmypid());
  564.             $srand true;
  565.         }
  566.  
  567.         $value "";
  568.         for ($i 0$i 2$i++{
  569.             // for Linux
  570.             if (file_exists('/proc/net/dev')) {
  571.                 $rx $tx 0;
  572.                 $fp fopen('/proc/net/dev''r');
  573.                 if ($fp != null{
  574.                     $header true;
  575.                     while (feof($fp=== false{
  576.                         $s fgets($fp4096);
  577.                         if ($header{
  578.                             $header false;
  579.                             continue;
  580.                         }
  581.                         $v preg_split('/[:\s]+/'$s);
  582.                         if (is_array($v&& count($v10{
  583.                             $rx += $v[2];
  584.                             $tx += $v[10];
  585.                         }
  586.                     }
  587.                 }
  588.                 $platform_value $rx $tx mt_rand(getmypid();
  589.             else {
  590.                 $platform_value mt_rand(getmypid();
  591.             }
  592.             $now strftime('%Y%m%d %T');
  593.             $time gettimeofday();
  594.             $v $now $time['usec'$platform_value mt_rand(0time());
  595.             $value .= md5($v);
  596.         }
  597.  
  598.         if ($length 64{
  599.             $value substr($value0$length);
  600.         }
  601.         return $value;
  602.     }
  603.     // }}}
  604.  
  605.     // {{{ get2dArray
  606.     /**
  607.      *  1次元配列をm x nに再構成する
  608.      *
  609.      *  @access public
  610.      *  @param  array   $array  処理対象の1次元配列
  611.      *  @param  int     $m      軸の要素数
  612.      *  @param  int     $order  $mをX軸と見做すかY軸と見做すか(0:X軸 1:Y軸)
  613.      *  @return array   m x nに再構成された配列
  614.      */
  615.     function get2dArray($array$m$order)
  616.     {
  617.         $r array();
  618.         
  619.         $n intval(count($array$m);
  620.         if ((count($array$m0{
  621.             $n++;
  622.         }
  623.         for ($i 0$i $n$i++{
  624.             $elts array();
  625.             for ($j 0$j $m$j++{
  626.                 if ($order == 0{
  627.                     // 横並び(横:$m列 縦:無制限)
  628.                     $key $i*$m+$j;
  629.                 else {
  630.                     // 縦並び(横:無制限 縦:$m行)
  631.                     $key $i+$n*$j;
  632.                 }
  633.                 if (array_key_exists($key$array== false{
  634.                     $array[$keynull;
  635.                 }
  636.                 $elts[$array[$key];
  637.             }
  638.             $r[$elts;
  639.         }
  640.  
  641.         return $r;
  642.     }
  643.     // }}}
  644.  
  645.     // {{{ isAbsolute
  646.     /**
  647.      *  パス名が絶対パスかどうかを返す
  648.      *
  649.      *  port from File in PEAR (for BC)
  650.      *
  651.      *  @access public
  652.      *  @param  string  $path 
  653.      *  @return bool    true:絶対パス false:相対パス
  654.      */
  655.     function isAbsolute($path)
  656.     {
  657.         if (preg_match("/\.\./"$path)) {
  658.             return false;
  659.         }
  660.  
  661.         if (DIRECTORY_SEPARATOR == '/'
  662.             && (substr($path01== '/' || substr($path01== '~')) {
  663.             return true;
  664.         else if (DIRECTORY_SEPARATOR == '\\' && preg_match('/^[a-z]:\\\/i'$path)) {
  665.             return true;
  666.         }
  667.  
  668.         return false;
  669.     }
  670.     // }}}
  671.  
  672.     // {{{ isRootDir
  673.     /**
  674.      *  パス名がルートディレクトリかどうかを返す
  675.      *
  676.      *  @access public
  677.      *  @param  string  $path 
  678.      *  @static
  679.      */
  680.     function isRootDir($path)
  681.     {
  682.         if ($path === DIRECTORY_SEPARATOR{
  683.             // avoid stat().
  684.             return true;
  685.         }
  686.         if (is_dir($path=== false{
  687.             return false;
  688.         }
  689.         return $path === basename($pathDIRECTORY_SEPARATOR;
  690.     }
  691.     // }}}
  692.  
  693.     // {{{ mkdir
  694.     /**
  695.      *  mkdir -p
  696.      *
  697.      *  @access public
  698.      *  @param  string  $dir    作成するディレクトリ
  699.      *  @param  int     $mode   パーミッション
  700.      *  @return bool    true:成功 false:失敗
  701.      *  @static
  702.      */
  703.     function mkdir($dir$mode)
  704.     {
  705.         if (file_exists($dir)) {
  706.             return is_dir($dir);
  707.         }
  708.  
  709.         $parent dirname($dir);
  710.         if ($dir === $parent{
  711.             return true;
  712.         }
  713.  
  714.         if (is_dir($parent=== false{
  715.             if (Ethna_Util::mkdir($parent$mode=== false{
  716.                 return false;
  717.             }
  718.         }
  719.  
  720.         return mkdir($dir$mode&& Ethna_Util::chmod($dir$mode);
  721.     }
  722.     // }}}
  723.  
  724.     // {{{ chmod
  725.     /**
  726.      *  ファイルのパーミッションを変更する
  727.      */
  728.     function chmod($file$mode)
  729.     {
  730.         $st stat($file);
  731.         if (($st[20777== $mode{
  732.             return true;
  733.         }
  734.         return chmod($file$mode);
  735.     }
  736.     // }}}
  737.  
  738.     // {{{ purgeDir
  739.     /**
  740.      *  ディレクトリを再帰的に削除する
  741.      *  (途中で失敗しても中断せず、削除できるものはすべて消す)
  742.      *
  743.      *  @access public
  744.      *  @param  string  $file   削除するファイルまたはディレクトリ
  745.      *  @return bool    true:成功 false:失敗
  746.      *  @static
  747.      */
  748.     function purgeDir($dir)
  749.     {
  750.         if (file_exists($dir=== false{
  751.             return false;
  752.         }
  753.         if (is_dir($dir=== false{
  754.             return unlink($dir);
  755.         }
  756.  
  757.         $dh opendir($dir);
  758.         if ($dh === false{
  759.             return false;
  760.         }
  761.         $ret true;
  762.         while (($entry readdir($dh)) !== false{
  763.             if ($entry === '.' || $entry === '..'{
  764.                 continue;
  765.             }
  766.             $ret $ret && Ethna_Util::purgeDir("{$dir}/{$entry}");
  767.         }
  768.         closedir($dh);
  769.         if ($ret{
  770.             return rmdir($dir);
  771.         else {
  772.             return false;
  773.         }
  774.     }
  775.     // }}}
  776.  
  777.     // {{{ purgeTmp
  778.     /**
  779.      *  テンポラリディレクトリのファイルを削除する
  780.      *
  781.      *  @access public
  782.      *  @param  string  $prefix     ファイルのプレフィクス
  783.      *  @param  int     $timeout    削除対象閾値(秒−60*60*1なら1時間)
  784.      */
  785.     function purgeTmp($prefix$timeout)
  786.     {
  787.         $c =Ethna_Controller::getInstance();
  788.  
  789.         $dh opendir($c->getDirectory('tmp'));
  790.         if ($dh{
  791.             while (($file readdir($dh)) !== false{
  792.                 if ($file == '.' || $file == '..'{
  793.                     continue;
  794.                 else if (is_dir($c->getDirectory('tmp''/' $file)) {
  795.                     continue;
  796.                 else if (strncmp($file$prefixstrlen($prefix)) == 0{
  797.                     $f $c->getDirectory('tmp'"/" $file;
  798.                     $st stat($f);
  799.                     if ($st[9$timeout time()) {
  800.                         unlink($f);
  801.                     }
  802.                 }
  803.             }
  804.             closedir($dh);
  805.         }
  806.     }
  807.     // }}}
  808.  
  809.     // {{{ lockFile
  810.     /**
  811.      *  ファイルをロックする
  812.      *
  813.      *  @access public
  814.      *  @param  string  $file       ロックするファイル名
  815.      *  @param  int     $mode       ロックモード('r', 'rw')
  816.      *  @param  int     $timeout    ロック待ちタイムアウト(秒−0なら無限)
  817.      *  @return int     ロックハンドル(falseならエラー)
  818.      */
  819.     function lockFile($file$mode$timeout 0)
  820.     {
  821.         if (file_exists($file=== false{
  822.             touch($file);
  823.         }
  824.         $lh fopen($file'r');
  825.         if ($lh == null{
  826.             return Ethna::raiseError("ファイル読み込みエラー[%s]"E_APP_READ$file);
  827.         }
  828.  
  829.         $lock_mode $mode == 'r' LOCK_SH LOCK_EX;
  830.  
  831.         for ($i 0$i $timeout || $timeout == 0$i++{
  832.             $r flock($lh$lock_mode LOCK_NB);
  833.             if ($r == true{
  834.                 break;
  835.             }
  836.             sleep(1);
  837.         }
  838.         if ($timeout && $i == $timeout{
  839.             // timed out
  840.             return Ethna::raiseError("ファイルロック取得エラー[%s]"E_APP_LOCK$file);
  841.         }
  842.  
  843.         return $lh;
  844.     }
  845.     // }}}
  846.  
  847.     // {{{ unlockFile
  848.     /**
  849.      *  ファイルのロックを解除する
  850.      *
  851.      *  @access public
  852.      *  @param  int     $lh     ロックハンドル
  853.      */
  854.     function unlockFile($lh)
  855.     {
  856.         fclose($lh);
  857.     }
  858.     // }}}
  859.  
  860.     // {{{ formatBacktrace
  861.     /**
  862.      *  バックトレースをフォーマットして返す
  863.      *
  864.      *  @access public
  865.      *  @param  array   $bt     debug_backtrace()関数で取得したバックトレース
  866.      *  @return string  文字列にフォーマットされたバックトレース
  867.      */
  868.     function formatBacktrace($bt
  869.     {
  870.         $r "";
  871.         $i 0;
  872.         foreach ($bt as $elt{
  873.             $r .= sprintf("[%02d] %s:%d:%s.%s\n"$i,
  874.                           isset($elt['file']$elt['file''unknown file',
  875.                           isset($elt['line']$elt['line''unknown line',
  876.                           isset($elt['class']$elt['class''global',
  877.                           $elt['function']);
  878.             $i++;
  879.  
  880.             if (isset($elt['args']== false || is_array($elt['args']== false{
  881.                 continue;
  882.             }
  883.  
  884.             // 引数のダンプ
  885.             foreach ($elt['args'as $arg{
  886.                 $r .= Ethna_Util::_formatBacktrace($arg);
  887.             }
  888.         }
  889.  
  890.         return $r;
  891.     }
  892.  
  893.     /**
  894.      *  バックトレース引数をフォーマットして返す
  895.      *
  896.      *  @access private
  897.      *  @param  string  $arg    バックトレースの引数
  898.      *  @param  int     $level  バックトレースのネストレベル
  899.      *  @param  int     $wrap   改行フラグ
  900.      *  @return string  文字列にフォーマットされたバックトレース
  901.      */
  902.     function _formatBacktrace($arg$level 0$wrap true)
  903.     {
  904.         $pad str_repeat("  "$level);
  905.         if (is_array($arg)) {
  906.             $r sprintf("     %s[array] => (\n"$pad);
  907.             if ($level+4{
  908.                 $r .= sprintf("     %s  *too deep*\n"$pad);
  909.             else {
  910.                 foreach ($arg as $key => $elt{
  911.                     $r .= Ethna_Util::_formatBacktrace($key$levelfalse);
  912.                     $r .= " => \n";
  913.                     $r .= Ethna_Util::_formatBacktrace($elt$level+1);
  914.                 }
  915.             }
  916.             $r .= sprintf("     %s)\n"$pad);
  917.         else if (is_object($arg)) {
  918.             $r sprintf("     %s[object]%s%s"$padget_class($arg)$wrap "\n" "");
  919.         else {
  920.             $r sprintf("     %s[%s]%s%s"$padgettype($arg)$arg$wrap "\n" "");
  921.         }
  922.  
  923.         return $r;
  924.     }
  925.     // }}}
  926. }
  927. // }}}
  928. ?>

Documentation generated on Thu, 08 May 2008 00:15:37 +0900 by phpDocumentor 1.4.2