<?php
namespace imcat;

// Files类
class comFiles{    

    
// 重定义file_get_contents来兼容不支持此函数的PHP
    // $kbom : 移除BOM标记
    
static function get($fname$kbom=0){
        
//return file_get_contents($fname);
        
if(!file_exists($fname) || is_dir($fname)){
            return 
'';
        }else{
            
$fp fopen($fname'r');
            
$size filesize($fname);
            if(
$size==0) return '';
            
$ct fread($fp$size);
            
fclose($fp);
            
$kbom && $ct self::killBOM($ct);
            return 
$ct;
        }
    }

    
//重定义file_put_contents来兼容不支持此函数的PHP
    
static function put($fname$data){
        
//return file_put_contents($fname, $data);
        
$fp = @fopen($fname"w");
        if(!
$fp){
            
$re FALSE;
        }elseif(
flock($fp,LOCK_EX)){ // 排它性的锁定
            
fwrite($fp$data);
            
flock($fp,LOCK_UN); // release lock
            
fclose($fp);
            
$re TRUE;
        }else{
            
$re FALSE;
        }
        return 
$re;
    }

    
// 移除BOM
    
static function killBOM($str){ 
        
$len strlen($str); 
        if(
$len==0) return $str;
        
$start 0;
        for(
$i=0$i<$len$i++) {
            
$chr ord($str[$i]);
            if(
in_array($chr,array(239,187,191))){
                
$start++;
            }else{
                return 
$start substr($str,$start) : $str;
                break;
            }
        }
        return 
$str;
    }

    static function 
getTIcon($file){ 
        
$cfg glbConfig::read('filetype','sy');
        
$type $icon 'unknow';
        
$ext strtolower(strrchr($file,"."));
        
$ext substr($ext,1);
        foreach(
$cfg as $k=>$v){
            if(
in_array($ext,$v)){
                
$icon $v[0];
                
$type $k;
                break;
            }
        }
        return array(
'type'=>$type,'icon'=>$icon); //'unknow';
    
}

    
// glob效率比readdir低
    
static function listFast($dir){
        
$re = array(); 
        
$list glob(str_replace('//','/',"$dir/*"));
        foreach (
$list as $file) {
            if(
$file=='.'||$file=='..') continue;
            if(
is_dir($file)){ //不用:file_exists
                
$re array_merge($re,self::listFast($file));
            }else{
                
$re[] = $file;
            }
        }
        return 
$re;
    }

    static function 
listScan($dir,$sub='',$skips=array()){
        
$re = array(); $mCount 6400;
        if(!
is_dir($dir)) return [];
        
$handle opendir($dir);
        while (
$file readdir($handle)) {
            if(
$file=='.'||$file=='..') continue;
            
$key "{$sub}$file";
            
$fp "$dir/$file"
            if(
count($re)<$mCount && is_dir($fp)){ //不用:file_exists
                
if(empty($sub) && !empty($skips) && in_array($file,$skips)) continue; 
                
$re array_merge($re,self::listScan($fp,"$sub$file/"));
            }else{ 
                
$mtime filemtime($fp);
                if(
count($re)<$mCount){
                    
$re[$key] = array($mtime,filesize($fp));
                }
            }
        }
        
closedir($handle);
        return 
$re;
    }

    static function 
listDir($dir,$key=''){
        
$re = array('dir'=>array(),'file'=>array());
        if(!
is_dir($dir)) return $re
        
// --- scandir();
        
$handle opendir($dir);
        while (
$file readdir($handle)) {
            if(
$file=='.'||$file=='..') continue;
            
$fp "$dir/$file";
            
$mtime filemtime($fp);
            if(
is_file($fp)){
                
$re['file'][$file] = array($mtime,filesize($fp));
            }else{
                
$re['dir'][$file] = $mtime
            }
        }
        
closedir($handle);
        if(
$key){ return $re[$key]; }
        return 
$re;
    }
    
    
// 目录状态统计(大小,文件数,目录数)
    
static function statDir($path){
        
$msize 0;
        
$fcount 0;
        
$dcount 0;
        if (
$handle opendir ($path)){
            while (
false !== ($file readdir($handle))){
                
$nextpath $path '/' $file;
                if (
$file != '.' && $file != '..' && !is_link ($nextpath)){
                    if (
is_dir ($nextpath)){
                        
$dcount++;
                        
$result self::statDir($nextpath);
                        
$msize += $result['nsize'];
                        
$fcount += $result['cfile'];
                        
$dcount += $result['cdir'];
                    }elseif (
is_file ($nextpath)){
                        
$msize += filesize ($nextpath);
                        
$fcount++;
                    }
                }
            }
        }
        
closedir($handle);
        
$total['nsize'] = $msize;
        
$total['cfile'] = $fcount;
        
$total['cdir'] = $dcount;
        return 
$total;
    }

    static function 
chkDirs($subs$flag=''$isfile=1){ 
        if(empty(
$subs)) return;
        if(
strstr($subs,'../')) return;
        if(
$isfile){
            return 
self::chkDirs(dirname($subs),$flag,0);
        }
        
$check basStr::filKey($subs,'!()-@_~/'); //.+,;^`
        
if($check!=$subs) return;
        
$path comStore::cfgDirPath($flag,'dir');
        
$path || $path DIR_DTMP;
        
$a explode('/',$subs); 
        
$i 0$tmp '';
        if(
count($a)>0){
            foreach(
$a as $d){ 
                
//if(empty($d)) return;
                
if(!is_dir($path."$tmp/$d")){ 
                    
mkdir($path."$tmp/$d"0777true);    
                    foreach(array(
'htm','html') as $var) @touch($path."$tmp/$d".'/index.'.$var);    
                }
                
$tmp .= "/$d"$i++;
                if(
$i==12) break;
            }
        }
    }

    
//遍历删除目录和目录下所有文件
    
static function delDir($dir,$delself=0,$keep='',$first=1){
        if(
strlen($dir)<6) return false//  /a/b  c:/a/b
        
if(!defined('indo_Verset')){
            if(
strstr($dir,DIR_IMCAT) || strstr($dir,DIR_ROOT) || strstr($dir,DIR_STATIC) || strstr($dir,DIR_VENDUI) || strstr($dir,DIR_VENDOR)) return false;
        }
        if(
$first){
            if(
is_file($dir)){ return @unlink($dir); };
            if(
in_array(substr($dir,-1,1),array('/',"\\"))){ $dir substr($dir,strlen($dir)-1); }
            if(!
is_dir($dir)){ return false; };
        }
        
$handle opendir($dir);
        while ((
$file readdir($handle)) !== false){
            if (
$file != "." && $file != ".."){
                if(
in_array($file,array('index.htm','index.html')) && empty($delself)) continue;
                if(
$keep && strstr($keep,$file)) continue;
                
is_dir("$dir/$file") ? self::delDir("$dir/$file",1,'',0):@unlink("$dir/$file");
            }
        }
        if(!empty(
$delself)){
            if (
readdir($handle) == false){
                
closedir($handle);
                @
rmdir($dir);
            }
        }
    }
    
    
// 是否可写 //if(is_writable($pfile)){}
    
static function canWrite($dir){
        if(
is_dir($dir)){
            
$pfile str_replace('','',$dir.'/@can_Write.test');
            @
unlink($pfile);
            if(
$fp = @fopen($pfile'w')) {
                @
fclose($fp);
                
$fwrite 1;
            }else 
$fwrite 0;
        }elseif(
is_file($dir)){
            
$fwrite is_writable($dir);
        }else{
            
$fwrite 0;    
        }
        return 
$fwrite;
    }
    
    
// 复制目录 : $src -> $dst
    // $skip : 忽略目录
    
static function copyDir($src,$dst,$skip=array(),$skfile=array()) {  // 原目录,复制到的目录
        
$dir opendir($src);
        @
mkdir($dst);
        while(
false !== ( $file readdir($dir)) ) {
            if (( 
$file != '.' ) && ( $file != '..' )) {
                if(
is_dir($src.'/'.$file)){
                    if(!empty(
$skip) && in_array($file,$skip)) continue;
                    
self::copyDir($src.'/'.$file$dst.'/'.$file,$skip,$skfile);
                }else{
                    if(!empty(
$skfile) && in_array($file,$skfile)) continue;
                    @
copy($src.'/'.$file$dst.'/'.$file);
                }
            }
        }
        
closedir($dir);
    }
    
}