Source for file Util.php

Documentation is available at Util.php

  1. <?php
  2. // vim: foldmethod=marker
  3. /**
  4.  *  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: cf405a6a83b8f0300791f0010665ee04bb6937ba $
  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 (ETHNA_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.     public static 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.     public static 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("File Write Error [%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.     public static 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.     public static 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.     public static 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.     public static 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 Split Error (line continue)'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.     public static 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.     public static function escapeHtml($target)
  378.     {
  379.         $r array();
  380.         Ethna_Util::_escapeHtml($target$r);
  381.         return $r;
  382.     }
  383.  
  384.     /**
  385.      *  配列の要素を全てHTMLエスケープして返す
  386.      *
  387.      *  @access private
  388.      *  @param  mixed   $vars   HTMLエスケープ対象となる配列
  389.      *  @param  mixed   $retval HTMLエスケープ対象となる子要素
  390.      */
  391.     private static 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.     public static 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.     public static 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.     public static function getEra($t)
  500.     {
  501.         $tm localtime($ttrue);
  502.         $year $tm['tm_year'1900;
  503.  
  504.         if ($year >= 1989{
  505.             $heisei_str _et('Heisei');
  506.             return array($heisei_str$year 1988);
  507.         else if ($year >= 1926{
  508.             $showa_str _et('Showa');
  509.             return array($showa_str$year 1925);
  510.         }
  511.  
  512.         return null;
  513.     }
  514.     // }}}
  515.  
  516.     // {{{ getImageExtName
  517.     /**
  518.      *  getimagesize()の返すイメージタイプに対応する拡張子を返す
  519.      *
  520.      *  @access public
  521.      *  @param  int     $type   getimagesize()関数の返すイメージタイプ
  522.      *  @return string  $typeに対応する拡張子
  523.      */
  524.     public static function getImageExtName($type)
  525.     {
  526.         $ext_list array(
  527.             1   => 'gif',
  528.             2   => 'jpg',
  529.             3   => 'png',
  530.             4   => 'swf',
  531.             5   => 'psd',
  532.             6   => 'bmp',
  533.             7   => 'tiff',
  534.             8   => 'tiff',
  535.             9   => 'jpc',
  536.             10  => 'jp2',
  537.             11  => 'jpx',
  538.             12  => 'jb2',
  539.             13  => 'swc',
  540.             14  => 'iff',
  541.             15  => 'wbmp',
  542.             16  => 'xbm',
  543.         );
  544.  
  545.         return @$ext_list[$type];
  546.     }
  547.     // }}}
  548.  
  549.     // {{{ getRandom
  550.     /**
  551.      *  ランダムなハッシュ値を生成する
  552.      *
  553.      *  決して高速ではないので乱用は避けること
  554.      *
  555.      *  @access public
  556.      *  @param  int     $length ハッシュ値の長さ(〜64)
  557.      *  @return string  ハッシュ値
  558.      */
  559.     public static function getRandom($length 64)
  560.     {
  561.         static $srand false;
  562.  
  563.         if ($srand == false{
  564.             list($usec$secexplode(' 'microtime());
  565.             mt_srand((float) $sec ((float) $usec 100000getmypid());
  566.             $srand true;
  567.         }
  568.  
  569.         // open_basedir がオンで、かつ /proc が許可されているか?
  570.         // open_basedir が空なら許可されていると看做す
  571.         $devfile '/proc/net/dev';
  572.         $open_basedir_conf ini_get('open_basedir');
  573.         $devfile_enabled (empty($open_basedir_conf
  574.                         || (preg_match('#:/proc#'$open_basedir_conf0
  575.                         ||  preg_match('#^/proc#'$open_basedir_conf0));
  576.  
  577.         $value "";
  578.         for ($i 0$i 2$i++{
  579.             // for Linux
  580.             if ($devfile_enabled && file_exists($devfile)) {
  581.                 $rx $tx 0;
  582.                 $fp fopen($devfile'r');
  583.                 if ($fp != null{
  584.                     $header true;
  585.                     while (feof($fp=== false{
  586.                         $s fgets($fp4096);
  587.                         if ($header{
  588.                             $header false;
  589.                             continue;
  590.                         }
  591.                         $v preg_split('/[:\s]+/'$s);
  592.                         if (is_array($v&& count($v10{
  593.                             $rx += $v[2];
  594.                             $tx += $v[10];
  595.                         }
  596.                     }
  597.                 }
  598.                 $platform_value $rx $tx mt_rand(getmypid();
  599.             else {
  600.                 $platform_value mt_rand(getmypid();
  601.             }
  602.             $now strftime('%Y%m%d %T');
  603.             $time gettimeofday();
  604.             $v $now $time['usec'$platform_value mt_rand(0time());
  605.             $value .= md5($v);
  606.         }
  607.  
  608.         if ($length 64{
  609.             $value substr($value0$length);
  610.         }
  611.         return $value;
  612.     }
  613.     // }}}
  614.  
  615.     // {{{ get2dArray
  616.     /**
  617.      *  1次元配列をm x nに再構成する
  618.      *
  619.      *  @access public
  620.      *  @param  array   $array  処理対象の1次元配列
  621.      *  @param  int     $m      軸の要素数
  622.      *  @param  int     $order  $mをX軸と見做すかY軸と見做すか(0:X軸 1:Y軸)
  623.      *  @return array   m x nに再構成された配列
  624.      */
  625.     public static function get2dArray($array$m$order)
  626.     {
  627.         $r array();
  628.         
  629.         $n intval(count($array$m);
  630.         if ((count($array$m0{
  631.             $n++;
  632.         }
  633.         for ($i 0$i $n$i++{
  634.             $elts array();
  635.             for ($j 0$j $m$j++{
  636.                 if ($order == 0{
  637.                     // 横並び(横:$m列 縦:無制限)
  638.                     $key $i*$m+$j;
  639.                 else {
  640.                     // 縦並び(横:無制限 縦:$m行)
  641.                     $key $i+$n*$j;
  642.                 }
  643.                 if (array_key_exists($key$array== false{
  644.                     $array[$keynull;
  645.                 }
  646.                 $elts[$array[$key];
  647.             }
  648.             $r[$elts;
  649.         }
  650.  
  651.         return $r;
  652.     }
  653.     // }}}
  654.  
  655.     // {{{ isAbsolute
  656.     /**
  657.      *  パス名が絶対パスかどうかを返す
  658.      *
  659.      *  port from File in PEAR (for BC)
  660.      *
  661.      *  @access public
  662.      *  @param  string  $path 
  663.      *  @return bool    true:絶対パス false:相対パス
  664.      */
  665.     public static function isAbsolute($path)
  666.     {
  667.         if (preg_match("/\.\./"$path)) {
  668.             return false;
  669.         }
  670.  
  671.         if (DIRECTORY_SEPARATOR == '/'
  672.             && (substr($path01== '/' || substr($path01== '~')) {
  673.             return true;
  674.         else if (DIRECTORY_SEPARATOR == '\\' && preg_match('/^[a-z]:\\\/i'$path)) {
  675.             return true;
  676.         }
  677.  
  678.         return false;
  679.     }
  680.     // }}}
  681.  
  682.     // {{{ isRootDir
  683.     /**
  684.      *  パス名がルートディレクトリかどうかを返す
  685.      *
  686.      *  @access public
  687.      *  @param  string  $path 
  688.      *  @static
  689.      */
  690.     public static function isRootDir($path)
  691.     {
  692.         if ($path === DIRECTORY_SEPARATOR{
  693.             // avoid stat().
  694.             return true;
  695.         }
  696.         if (is_dir($path=== false{
  697.             return false;
  698.         }
  699.         return $path === basename($pathDIRECTORY_SEPARATOR;
  700.     }
  701.     // }}}
  702.  
  703.     // {{{ mkdir
  704.     /**
  705.      *  mkdir -p
  706.      *
  707.      *  @access public
  708.      *  @param  string  $dir    作成するディレクトリ
  709.      *  @param  int     $mode   パーミッション
  710.      *  @return bool    true:成功 false:失敗
  711.      *  @static
  712.      */
  713.     public static function mkdir($dir$mode)
  714.     {
  715.         if (file_exists($dir)) {
  716.             return is_dir($dir);
  717.         }
  718.  
  719.         $parent dirname($dir);
  720.         if ($dir === $parent{
  721.             return true;
  722.         }
  723.  
  724.         if (is_dir($parent=== false{
  725.             if (Ethna_Util::mkdir($parent$mode=== false{
  726.                 return false;
  727.             }
  728.         }
  729.  
  730.         return mkdir($dir$mode&& Ethna_Util::chmod($dir$mode);
  731.     }
  732.     // }}}
  733.  
  734.     // {{{ chmod
  735.     /**
  736.      *  ファイルのパーミッションを変更する
  737.      */
  738.     public static function chmod($file$mode)
  739.     {
  740.         $st stat($file);
  741.         if (($st[20777== $mode{
  742.             return true;
  743.         }
  744.         return chmod($file$mode);
  745.     }
  746.     // }}}
  747.  
  748.     // {{{ purgeDir
  749.     /**
  750.      *  ディレクトリを再帰的に削除する
  751.      *  (途中で失敗しても中断せず、削除できるものはすべて消す)
  752.      *
  753.      *  @access public
  754.      *  @param  string  $file   削除するファイルまたはディレクトリ
  755.      *  @return bool    true:成功 false:失敗
  756.      *  @static
  757.      */
  758.     public static function purgeDir($dir)
  759.     {
  760.         if (file_exists($dir=== false{
  761.             return false;
  762.         }
  763.         if (is_dir($dir=== false{
  764.             return unlink($dir);
  765.         }
  766.  
  767.         $dh opendir($dir);
  768.         if ($dh === false{
  769.             return false;
  770.         }
  771.         $ret true;
  772.         while (($entry readdir($dh)) !== false{
  773.             if ($entry === '.' || $entry === '..'{
  774.                 continue;
  775.             }
  776.             $ret $ret && Ethna_Util::purgeDir("{$dir}/{$entry}");
  777.         }
  778.         closedir($dh);
  779.         if ($ret{
  780.             return rmdir($dir);
  781.         else {
  782.             return false;
  783.         }
  784.     }
  785.     // }}}
  786.  
  787.     // {{{ purgeTmp
  788.     /**
  789.      *  テンポラリディレクトリのファイルを削除する
  790.      *
  791.      *  @access public
  792.      *  @param  string  $prefix     ファイルのプレフィクス
  793.      *  @param  int     $timeout    削除対象閾値(秒−60*60*1なら1時間)
  794.      */
  795.     public static function purgeTmp($prefix$timeout)
  796.     {
  797.         $c Ethna_Controller::getInstance();
  798.  
  799.         $dh opendir($c->getDirectory('tmp'));
  800.         if ($dh{
  801.             while (($file readdir($dh)) !== false{
  802.                 if ($file == '.' || $file == '..'{
  803.                     continue;
  804.                 else if (is_dir($c->getDirectory('tmp''/' $file)) {
  805.                     continue;
  806.                 else if (strncmp($file$prefixstrlen($prefix)) == 0{
  807.                     $f $c->getDirectory('tmp'"/" $file;
  808.                     $st stat($f);
  809.                     if ($st[9$timeout time()) {
  810.                         unlink($f);
  811.                     }
  812.                 }
  813.             }
  814.             closedir($dh);
  815.         }
  816.     }
  817.     // }}}
  818.  
  819.     // {{{ lockFile
  820.     /**
  821.      *  ファイルをロックする
  822.      *
  823.      *  @access public
  824.      *  @param  string  $file       ロックするファイル名
  825.      *  @param  int     $mode       ロックモード('r', 'rw')
  826.      *  @param  int     $timeout    ロック待ちタイムアウト(秒−0なら無限)
  827.      *  @return int     ロックハンドル(falseならエラー)
  828.      */
  829.     public static function lockFile($file$mode$timeout 0)
  830.     {
  831.         if (file_exists($file=== false{
  832.             touch($file);
  833.         }
  834.         $lh fopen($file$mode);
  835.         if ($lh == null{
  836.             return Ethna::raiseError("File Read Error [%s]"E_APP_READ$file);
  837.         }
  838.  
  839.         $lock_mode $mode == 'r' LOCK_SH LOCK_EX;
  840.  
  841.         for ($i 0$i $timeout || $timeout == 0$i++{
  842.             $r flock($lh$lock_mode LOCK_NB);
  843.             if ($r == true{
  844.                 break;
  845.             }
  846.             sleep(1);
  847.         }
  848.         if ($timeout && $i == $timeout{
  849.             // timed out
  850.             return Ethna::raiseError("File lock get error [%s]"E_APP_LOCK$file);
  851.         }
  852.  
  853.         return $lh;
  854.     }
  855.     // }}}
  856.  
  857.     // {{{ unlockFile
  858.     /**
  859.      *  ファイルのロックを解除する
  860.      *
  861.      *  @access public
  862.      *  @param  int     $lh     ロックハンドル
  863.      */
  864.     public static function unlockFile($lh)
  865.     {
  866.         fclose($lh);
  867.     }
  868.     // }}}
  869.  
  870.     // {{{ formatBacktrace
  871.     /**
  872.      *  バックトレースをフォーマットして返す
  873.      *
  874.      *  @access public
  875.      *  @param  array   $bt     debug_backtrace()関数で取得したバックトレース
  876.      *  @return string  文字列にフォーマットされたバックトレース
  877.      */
  878.     public static function formatBacktrace($bt
  879.     {
  880.         $r "";
  881.         $i 0;
  882.         foreach ($bt as $elt{
  883.             $r .= sprintf("[%02d] %s:%d:%s.%s\n"$i,
  884.                           isset($elt['file']$elt['file''unknown file',
  885.                           isset($elt['line']$elt['line''unknown line',
  886.                           isset($elt['class']$elt['class''global',
  887.                           $elt['function']);
  888.             $i++;
  889.  
  890.             if (isset($elt['args']== false || is_array($elt['args']== false{
  891.                 continue;
  892.             }
  893.  
  894.             // 引数のダンプ
  895.             foreach ($elt['args'as $arg{
  896.                 $r .= Ethna_Util::_formatBacktrace($arg);
  897.             }
  898.         }
  899.  
  900.         return $r;
  901.     }
  902.  
  903.     /**
  904.      *  バックトレース引数をフォーマットして返す
  905.      *
  906.      *  @access private
  907.      *  @param  string  $arg    バックトレースの引数
  908.      *  @param  int     $level  バックトレースのネストレベル
  909.      *  @param  int     $wrap   改行フラグ
  910.      *  @return string  文字列にフォーマットされたバックトレース
  911.      */
  912.     private static function _formatBacktrace($arg$level 0$wrap true)
  913.     {
  914.         $pad str_repeat("  "$level);
  915.         if (is_array($arg)) {
  916.             $r sprintf("     %s[array] => (\n"$pad);
  917.             if ($level+4{
  918.                 $r .= sprintf("     %s  *too deep*\n"$pad);
  919.             else {
  920.                 foreach ($arg as $key => $elt{
  921.                     $r .= Ethna_Util::_formatBacktrace($key$levelfalse);
  922.                     $r .= " => \n";
  923.                     $r .= Ethna_Util::_formatBacktrace($elt$level+1);
  924.                 }
  925.             }
  926.             $r .= sprintf("     %s)\n"$pad);
  927.         else if (is_object($arg)) {
  928.             $r sprintf("     %s[object]%s%s"$padget_class($arg)$wrap "\n" "");
  929.         else {
  930.             $r sprintf("     %s[%s]%s%s"$padgettype($arg)$arg$wrap "\n" "");
  931.         }
  932.  
  933.         return $r;
  934.     }
  935.     // }}}
  936.  
  937.     /**
  938.      *  Site url from request uri (instead of a config)
  939.      */
  940.     public static function getUrlFromRequestUri()
  941.     {
  942.         if (isset($_SERVER['HTTPS']&& ($_SERVER['HTTPS'== 'on' || $_SERVER['HTTPS'== 1)
  943.           || isset($_SERVER['HTTP_X_FORWARDED_PROTO']&& $_SERVER['HTTP_X_FORWARDED_PROTO'== 'https'
  944.         {
  945.           $protocol 'https://';
  946.         }
  947.         else {
  948.           $protocol 'http://';
  949.         }
  950.  
  951.         $url $protocol $_SERVER['HTTP_HOST'rtrim(dirname($_SERVER['SCRIPT_NAME'])'/''/';
  952.         return $url;
  953.     }
  954. }
  955. // }}}

Documentation generated on Fri, 11 Nov 2011 03:59:19 +0900 by phpDocumentor 1.4.3