<?php defined('SYSPATH') or die('No direct script access.');
/**
 * File helper class.
 *
 * $Id: file.php 3237 2008-07-30 12:10:20Z Geert $
 *
 * @package    Core
 * @author     Kohana Team
 * @copyright  (c) 2007-2008 Kohana Team
 * @license    http://kohanaphp.com/license.html
 */
class file_Core {

	/**
	 * Attempt to get the mime type from a file. This method is horribly
	 * unreliable, due to PHP being horribly unreliable when it comes to
	 * determining the mime-type of a file.
	 *
	 * @param   string   filename
	 * @return  string   mime-type, if found
	 * @return  boolean  FALSE, if not found
	 */
	public static function mime($filename)
	{
		// Make sure the file is readable
		if ( ! (is_file($filename) AND is_readable($filename)))
		return FALSE;

		// Get the extension from the filename
		$extension = strtolower(substr(strrchr($filename, '.'), 1));

		if (preg_match('/^(?:jpe?g|png|[gt]if|bmp|swf)$/', $extension))
		{
			// Disable error reporting
			$ER = error_reporting(0);

			// Use getimagesize() to find the mime type on images
			$mime = getimagesize($filename);

			// Turn error reporting back on
			error_reporting($ER);

			// Return the mime type
			if (isset($mime['mime']))
			return $mime['mime'];
		}

		if (function_exists('finfo_open'))
		{
			// Use the fileinfo extension
			$finfo = finfo_open(FILEINFO_MIME);
			$mime  = finfo_file($finfo, $filename);
			finfo_close($finfo);

			// Return the mime type
			return $mime;
		}

		if (ini_get('mime_magic.magicfile') AND function_exists('mime_content_type'))
		{
			// Return the mime type using mime_content_type
			return mime_content_type($filename);
		}

		if ( ! empty($extension) AND is_array($mime = Kohana::config('mimes.'.$extension)))
		{
			// Return the mime-type guess, based on the extension
			return $mime[0];
		}

		// Unable to find the mime-type
		return FALSE;
	}

	/**
	 * Split a file into pieces matching a specific size.
	 *
	 * @param   string   file to be split
	 * @param   string   directory to output to, defaults to the same directory as the file
	 * @param   integer  size, in MB, for each chunk to be
	 * @return  integer  The number of pieces that were created.
	 */
	public static function split($filename, $output_dir = FALSE, $piece_size = 10)
	{
		// Find output dir
		$output_dir = ($output_dir == FALSE) ? pathinfo(str_replace('\\', '/', realpath($filename)), PATHINFO_DIRNAME) : str_replace('\\', '/', realpath($output_dir));
		$output_dir = rtrim($output_dir, '/').'/';

		// Open files for writing
		$input_file = fopen($filename, 'rb');

		// Change the piece size to bytes
		$piece_size = 1024 * 1024 * (int) $piece_size; // Size in bytes

		// Set up reading variables
		$read  = 0; // Number of bytes read
		$piece = 1; // Current piece
		$chunk = 1024 * 8; // Chunk size to read

		// Split the file
		while ( ! feof($input_file))
		{
			// Open a new piece
			$piece_name = $filename.'.'.str_pad($piece, 3, '0', STR_PAD_LEFT);
			$piece_open = @fopen($piece_name, 'wb+') or die('Could not write piece '.$piece_name);

			// Fill the current piece
			while ($read < $piece_size AND $data = fread($input_file, $chunk))
			{
				fwrite($piece_open, $data) or die('Could not write to open piece '.$piece_name);
				$read += $chunk;
			}

			// Close the current piece
			fclose($piece_open);

			// Prepare to open a new piece
			$read = 0;
			$piece++;

			// Make sure that piece is valid
			($piece < 999) or die('Maximum of 999 pieces exceeded, try a larger piece size');
		}

		// Close input file
		fclose($input_file);

		// Returns the number of pieces that were created
		return ($piece - 1);
	}

	/**
	 * Join a split file into a whole file.
	 *
	 * @param   string   split filename, without .000 extension
	 * @param   string   output filename, if different then an the filename
	 * @return  integer  The number of pieces that were joined.
	 */
	public static function join($filename, $output = FALSE)
	{
		if ($output == FALSE)
		$output = $filename;

		// Set up reading variables
		$piece = 1; // Current piece
		$chunk = 1024 * 8; // Chunk size to read

		// Open output file
		$output_file = @fopen($output, 'wb+') or die('Could not open output file '.$output);

		// Read each piece
		while ($piece_open = @fopen(($piece_name = $filename.'.'.str_pad($piece, 3, '0', STR_PAD_LEFT)), 'rb'))
		{
			// Write the piece into the output file
			while ( ! feof($piece_open))
			{
				fwrite($output_file, fread($piece_open, $chunk));
			}

			// Close the current piece
			fclose($piece_open);

			// Prepare for a new piece
			$piece++;

			// Make sure piece is valid
			($piece < 999) or die('Maximum of 999 pieces exceeded');
		}

		// Close the output file
		fclose($output_file);

		// Return the number of pieces joined
		return ($piece - 1);
	}
	/**
 * Read File
 *
 * Opens the file specfied in the path and returns it as a string.
 *
 * @access	public
 * @param	string	path to file
 * @return	string
 */	
	function read_file($file)
	{
		if ( ! file_exists($file))
		{
			return FALSE;
		}

		if (function_exists('file_get_contents'))
		{
			return file_get_contents($file);
		}

		if ( ! $fp = @fopen($file, 'rb'))
		{
			return FALSE;
		}

		flock($fp, LOCK_SH);

		$data = '';
		if (filesize($file) > 0)
		{
			$data =& fread($fp, filesize($file));
		}

		flock($fp, LOCK_UN);
		fclose($fp);

		return $data;
	}

	// ------------------------------------------------------------------------

	/**
 * Write File
 *
 * Writes data to the file specified in the path.
 * Creates a new file if non-existent.
 *
 * @access	public
 * @param	string	path to file
 * @param	string	file data
 * @return	bool
 */	
	function write_file($path, $data, $mode = 'wb')
	{
		if ( ! $fp = @fopen($path, $mode))
		{
			return FALSE;
		}

		flock($fp, LOCK_EX);
		fwrite($fp, $data);
		flock($fp, LOCK_UN);
		fclose($fp);

		return TRUE;
	}

	// ------------------------------------------------------------------------

	/**
 * Delete Files
 *
 * Deletes all files contained in the supplied directory path.
 * Files must be writable or owned by the system in order to be deleted.
 * If the second parameter is set to TRUE, any directories contained
 * within the supplied base directory will be nuked as well.
 *
 * @access	public
 * @param	string	path to file
 * @param	bool	whether to delete any directories found in the path
 * @return	bool
 */	
	function delete_files($path, $del_dir = FALSE, $level = 0)
	{
		// Trim the trailing slash
		$path = preg_replace("|^(.+?)/*$|", "\\1", $path);
		if(file_exists($path)){
			if ( ! $current_dir = @opendir($path)){
				return;
			}
		}
		else{
			return true;
		}

		while(FALSE !== ($filename = @readdir($current_dir)))
		{
			if ($filename != "." and $filename != "..")
			{
				if (is_dir($path.'/'.$filename))
				{
					self::delete_files($path.'/'.$filename, $del_dir, $level + 1);
				}
				else
				{
					if(file_exists($path.'/'.$filename)){
						unlink($path.'/'.$filename);
					}
				}
			}
		}
		@closedir($current_dir);

		if ($del_dir == TRUE AND $level >= 0)
		{
			if(file_exists($path)){
				if(rmdir($path)){
					return true;
				}
			}
			else{
				return true;
			}
		}
		return true;
	}

	// ------------------------------------------------------------------------

	/**
 * Get Filenames
 *
 * Reads the specified directory and builds an array containing the filenames.  
 * Any sub-folders contained within the specified path are read as well.
 *
 * @access	public
 * @param	string	path to source
 * @param	bool	whether to include the path as part of the filename
 * @return	array
 */	
	function get_filenames($source_dir, $include_path = FALSE)
	{
		$_filedata = array();

		if ($fp = @opendir($source_dir))
		{
			while (FALSE !== ($file = readdir($fp)))
			{
				if (@is_dir($source_dir.$file) && substr($file, 0, 1) != '.')
				{
					get_filenames($source_dir.$file."/", $include_path);
				}
				elseif (substr($file, 0, 1) != ".")
				{

					$_filedata[] = ($include_path == TRUE) ? $source_dir.$file : $file;
				}
			}
			return $_filedata;
		}
	}
	/**
     * 删除目录和里面所有文件
     *
     * @param unknown_type $dir
     * @return unknown
     */
	function deldir($dir){
		if(file_exists($dir)){
			$dh=opendir($dir);
			while ($file=readdir($dh)) {
				if($file!="." && $file!="..") {
					$fullpath=$dir."/".$file;
					if(!is_dir($fullpath)) {
						unlink($fullpath);
					}
					else {
						deldir($fullpath);
					}
				}
			}
			closedir($dh);
			if(rmdir($dir)) {
				return true;
			}
			else {
				return false;
			}
		}
		else{
			return true;
		}
	}
	function truncate_dir($dirPath,$is_currend_dir=false){
		$dh=opendir($dirPath);
		while ($file=readdir($dh)) {
			if($file!="." && $file!="..") {
				$fullpath=$dirPath."/".$file;
				if(!is_dir($fullpath)) {
					unlink($fullpath);
				}
				else {
					truncate_dir($fullpath);
					rmdir($fullpath);
				}
			}
		}
		closedir($dh);
		if($is_currend_dir){
			if(rmdir($dirPath)) {
				return true;
			}
			else {
				return false;
			}
		}
		else{
			return true;
		}
	}
	function scan_dir($dirPath,$is_dir=true,$extends=array("jpeg","jpg","rar","gif","png","zip","txt","doc"),$is_circ=false,$filter="thumb_"){
		if(empty($is_start)){
			$this->filepaths	=	array();
			$is_start			=	true;
			$i					=	0;
		}
		$dh=opendir($dirPath);
		while ($file=readdir($dh)) {
			if($file!="." && $file!="..") {
				$fullpath=$dirPath."/".$file;
				if(!is_dir($fullpath)) {
					$extend	=	strtolower(pathinfo($fullpath,PATHINFO_EXTENSION));
					if(in_array($extend,$extends)){
						if(preg_match("#".$filter."#i",$fullpath)){
							continue;
						}
						$filesize							=	filesize($fullpath);
						$this->filepaths[$i]['file_size']	=	intval($filesize/1024);
						$this->filepaths[$i]['file_name']	=	basename($fullpath);
						$this->filepaths[$i]['filemtime']	=	date("Y-m-d H:i:s",filemtime($fullpath));
						$this->filepaths[$i]['path']		=	$fullpath;
						$this->filepaths[$i]['ext']			=	$extend;
						$this->filepaths[$i]['type']		=	'file';
						$this->filepaths[$i]['is_image']	=	in_array($extend,array("jpeg","jpg","png","gif","bmp"))?true:false;
						$i++;
					}
				}
				else {
					if($is_dir){
						$this->filepaths[$i]['path']		=	$fullpath;
						$this->filepaths[$i]['file_name']	=	basename($fullpath);
						$this->filepaths[$i]['type']		=	'dir';
						$i++;
					}
					if($is_circ)self::scan_dir($fullpath,$is_dir,$extends,$is_circ);
				}
			}
		}
		closedir($dh);
		
		$filepath				=	$this->filepaths;
		return $filepath;
	}
		/**
 * 创建目录
 *
 * @param string $dir 待创建的目录
 * @return boolen
 */
	function create_dir_path( $dir , $make_index_file = false ){

		$dir = str_replace( '\\' , '/' , $dir );
		$dir = trim( trim( $dir ) , '/' );

		$dir = explode( '/' , $dir );
		$path = $dir[0];
		unset( $dir[0] );
		if ( is_array( $dir) ) 
		foreach( $dir as $v )
		{
			if ( !is_dir( $path ) )
			{
				if ( !mkdir( $path , 0777 ) || !chmod( $path , 0777 ) )  return false;
				if ( $make_index_file ) fclose( @fopen( $path . '/index.htm' ,'w' ) );
			}
			$path .= '/' . $v;
		}
		if ( !is_dir( $path ) )
		{
			if ( !mkdir( $path , 0777 ) || !chmod( $path , 0777 ) ) return false;
			if ( $make_index_file ) fclose( @fopen( $path . '/index.htm' ,'w' ) );
		}
		return true;
	}
} // End file