<?php
/**
	 * file listing
	 * @author Logan Cai (cailongqun [at] yahoo [dot] com [dot] cn)
	 * @link www.phpletter.com
	 * @since 22/April/2007
	 *
	 */
require_once(dirname(__FILE__) . DIRECTORY_SEPARATOR . "class.file.php");
class manager
{
	var $currentFolderPath;
	var $sessionAction = null; //object to session action
	var $flags = array('no'=>'noFlag', 'cut'=>'cutFlag', 'copy'=>'copyFlag');
	var $forceFolderOnTop = false; //forced to have folder shown on the top of the list
	var $currentFolderInfo = array(
	'name'=>'',
	'subdir'=>0,
	'file'=>0,
	'ctime'=>'',
	'mtime'=>'',
	'is_readable'=>'',
	'is_writable'=>'',
	'size'=>0,
	'path'=>'',
	'type'=>'folder',
	'flag'=>'noFlag',
	'friendly_path'=>'',
	);
	
	var $lastVisitedFolderPathIndex = 'ajax_last_visited_folder';
	var $folderPathIndex = "path";
	var $calculateSubdir = true;
	var $fileTypes = array(
			array(array("exe", "com"), "fileExe", SEARCH_TYPE_EXE, 0),
			array(array("gif", "jpg", "png", "bmp", "tif"), "filePicture", SEARCH_TYPE_IMG, 1),
			array(array("zip", "sit", "rar", "gz", "tar"), "fileZip", SEARCH_TYPE_ARCHIVE, 0),
			array(array("htm", "html", "php", "jsp", "asp", 'js', 'css'), "fileCode", SEARCH_TYPE_HTML, 1),
			array(array("mov", "ram", "rm", "asx", "dcr", "wmv"), "fileVideo", SEARCH_TYPE_VIDEO, 1),
			array(array("mpg", "avi", "asf", "mpeg"), "fileVideo", SEARCH_TYPE_MOVIE, 1),
			array(array("aif", "aiff", "wav", "mp3", "wma"), "fileMusic", SEARCH_TYPE_MUSIC, 1),
			array(array("swf", 'flv'), "fileFlash", SEARCH_TYPE_FLASH, 1),
			array(array("ppt"), "filePPT", SEARCH_TYPE_PPT, 0),
			array(array("rtf"), "fileRTF", SEARCH_TYPE_DOC, 0),
			array(array("doc"), "fileWord", SEARCH_TYPE_WORD, 0),
			array(array("pdf"), "fileAcrobat", SEARCH_TYPE_PDF, 0),
			array(array("xls", "csv"), "fileExcel", SEARCH_TYPE_EXCEL, 0),
			array(array("txt"), "fileText", SEARCH_TYPE_TEXT, 1),
			array(array("xml", "xsl", "dtd"), "fileXml", SEARCH_TYPE_XML, 1)
	);
	
	/**
		 * constructor
		 * @path the path to a folder
		 * @calculateSubdir force to get the subdirectories information
		 */		
	function __construct($path = null, $calculateSubdir=true)
	{

		$this->calculateSubdir = $calculateSubdir;
		if (defined('CONFIG_SYS_FOLDER_SHOWN_ON_TOP'))
		{
			$this->forceFolderOnTop = CONFIG_SYS_FOLDER_SHOWN_ON_TOP;
		}
		if (!is_null($path))
		{
			$this->currentFolderPath = $path;

		}elseif (isset($_GET[$this->folderPathIndex]) && file_exists($_GET[$this->folderPathIndex]) && !is_file($_GET[$this->folderPathIndex]) )
		{
			$this->currentFolderPath = $_GET[$this->folderPathIndex];
		}
		elseif (isset($_SESSION[$this->lastVisitedFolderPathIndex]) && file_exists($_SESSION[$this->lastVisitedFolderPathIndex]) && !is_file($_SESSION[$this->lastVisitedFolderPathIndex]))
		{
			$this->currentFolderPath = $_SESSION[$this->lastVisitedFolderPathIndex];
		}else
		{
			$this->currentFolderPath = CONFIG_SYS_DEFAULT_PATH;
		}
		
		$this->currentFolderPath = (isUnderRoot($this->currentFolderPath)?backslashToSlash((addTrailingSlash($this->currentFolderPath))):CONFIG_SYS_DEFAULT_PATH);
		
		if ($this->calculateSubdir)
		{// keep track of this folder path in session 
			$_SESSION[$this->lastVisitedFolderPathIndex] = $this->currentFolderPath;
		}
		if (is_dir($this->currentFolderPath))
		{
			$file = new file($this->currentFolderPath);
			$folderInfo = $file->getFileInfo();
			if (sizeof($folderInfo))
			{
				$this->currentFolderInfo['name']=basename($this->currentFolderPath);
				$this->currentFolderInfo['subdir']=0;
				$this->currentFolderInfo['file']=0;
				$this->currentFolderInfo['ctime']=$folderInfo['ctime'];
				$this->currentFolderInfo['mtime']=$folderInfo['mtime'];
				$this->currentFolderInfo['is_readable']=$folderInfo['is_readable'];
				$this->currentFolderInfo['is_writable']=$folderInfo['is_writable'];	
				$this->currentFolderInfo['path']  = $this->currentFolderPath;
				$this->currentFolderInfo['friendly_path'] = transformFilePath($this->currentFolderPath);
				$this->currentFolderInfo['type'] = "folder";
				$this->currentFolderInfo['cssClass']='folder';
				
				//$this->currentFolderInfo['flag'] = $folderInfo['flag'];
			}			
		}
		if ($calculateSubdir && !file_exists($this->currentFolderPath))
		{
			die(ERR_FOLDER_NOT_FOUND . $this->currentFolderPath);
		}


	
	}
	
	function setSessionAction(&$session)
	{
		$this->sessionAction = $session;	
	}
	/**
		 * constructor
		 */
	function manager($path = null, $calculateSubdir=true)
	{
		$this->__construct($path, $calculateSubdir);
	}
	/**
		 * get current folder path
		 * @return  string
		 */
	function getCurrentFolderPath()
	{
		return $this->currentFolderPath;
	}
	/**
		 * get the list of files and folders under this current fold
		 *	@return array
		 */
	function getFileList()
	{
		$outputs = array();
		$files = array();
		$folders = array();
		$tem = array();
		$dirHandler = @opendir($this->currentFolderPath);
		if ($dirHandler)
		{
			while (false !== ($file = readdir($dirHandler)))
			{
				if ($file != '.' && $file != '..')
				{
					$flag = $this->flags['no'];
				
					if ($this->sessionAction->getFolder() == $this->currentFolderPath)
					{//check if any flag associated with this folder or file
						$folder = addTrailingSlash(backslashToSlash($this->currentFolderPath));
						if (in_array($folder . $file, $this->sessionAction->get()))
						{
							if ($this->sessionAction->getAction() == "copy")
							{
								$flag = $this->flags['copy'];
							}else 
							{
								$flag = $this->flags['cut'];
							}
						}
					}					
					$path=$this->currentFolderPath.$file;
					if (is_dir($path) && isListingDocument($path) )
					{
						$this->currentFolderInfo['subdir']++;
						if (!$this->calculateSubdir)
						{			
						}else 
						{
							
								$folder = $this->getFolderInfo($path);
								$folder['flag'] = $flag;
								$folders[$file] = $folder;
								$outputs[$file] = $folders[$file];							
						}

						
					}elseif (is_file($path) && isListingDocument($path))
					{

							$obj = new file($path);
							$tem = $obj->getFileInfo();
							if (sizeof($tem))
							{
								$fileType = $this->getFileType($file);
								foreach($fileType as $k=>$v)
								{
									$tem[$k] = $v;
								}
								$this->currentFolderInfo['size'] += $tem['size'];
								$this->currentFolderInfo['file']++;		
								$tem['path'] = backslashToSlash($path);		
								$tem['type'] = "file";
								$tem['flag'] = $flag;
								$files[$file] = $tem;
								$outputs[$file] = $tem;
								$tem = array();
								$obj->close();
								
							}							

				
					}
					
				}
			}
			if ($this->forceFolderOnTop)
			{
				uksort($folders, "strnatcasecmp");
				uksort($files, "strnatcasecmp");
				$outputs = array();
				foreach($folders as $v)
				{
					$outputs[] = $v;
				}
				foreach ($files as $v)
				{
					$outputs[] = $v;
				}
			}else 
			{
				uksort($outputs, "strnatcasecmp");
			}
			
			@closedir($dirHandler);
		}else
		{
			trigger_error('Unable to locate the folder ' . $this->currentFolderPath, E_NOTICE);
		}
		return $outputs;
	}


	/**
	 * get current or the specified dir information
	 *
	 * @param string $path
	 * @return array
	 */
	function getFolderInfo($path=null)
	{
		if (is_null($path))
		{
			return $this->currentFolderInfo;
		}else 
		{
			$obj = new manager($path, false);
			$obj->setSessionAction($this->sessionAction);
			$obj->getFileList();
			return $obj->getFolderInfo();			
		}

	}

		/**
		 * return the file type of a file.
		 *
		 * @param string file name
		 * @return array
		 */
		function getFileType($fileName, $checkIfDir = false) 
		{
			
			$ext = strtolower($this->_getExtension($fileName, $checkIfDir));
			
			foreach ($this->fileTypes as $fileType) 
			{
				if (in_array($ext, $fileType[0]))
				{
					return array("cssClass" => $fileType[1], "fileType" => $fileType[2], "preview" => $fileType[3], 'test'=>5);
				}
			}
			if (!empty($fileName))
			{//this is folder
				if (empty($ext))
				{
					if (is_dir($fileName))
					{

						return array("cssClass" => ($checkIfDir && $this->isDirEmpty($fileName)?'folderEmpty':"folder") , "fileType" => "Folder", "preview" => 0, 'test'=>1);
					}else 
					{
						return array("cssClass" => "fileUnknown", "fileType" => SEARCH_TYPE_UNKNOWN, "preview" => 0, 'test'=>2);
					}
				}else 
				{
					return array("cssClass" => "fileUnknown", "fileType" => SEARCH_TYPE_UNKNOWN, "preview" => 0, 'test'=>3, 'ext'=>$ext , 'filename'=>$fileName);
				}
				
			}else
			{//this is unknown file
				return array("cssClass" => "fileUnknown", "fileType" => SEARCH_TYPE_UNKNOWN, "preview" => 0, 'test'=>4);
			}
		
		
		}

	/**
		 * return the predefined file types
		 *
		 * @return arrray
		 */
	function getFileTypes()
	{
		return $this->fileTypes;
	}
	/**
		 * print out the file types
		 *
		 */
	function printFileTypes()
	{
		foreach($fileTypes as $fileType)
		{
			if (isset($fileType[0]) && is_array($fileType[0]))
			{
				foreach($fileType[0] as $type)
				{
					echo $type. ",";
				}
			}
		}
	}

    /**
	 * Get the extension of a file name
	 * 
	 * @param  string $file
 	 * @return string
     * @copyright this function originally come from Andy's php 
	 */
    function _getExtension($file, $checkIfDir = false)
    {
    	if ($checkIfDir && file_exists($file) && is_dir($file))
    	{
    		return '';
    	}else 
    	{
    		return @substr(@strrchr($file, "."), 1);
    	}
    	
    	
    }	

	function isDirEmpty($path)
	{
		$dirHandler = @opendir($path);
		if ($dirHandler)
		{
			while (false !== ($file = readdir($dirHandler)))
			{
				if ($file != '.' && $file != '..')
				{
					@closedir($dirHandler);
					return false;
					
				}
			}
			
			@closedir($dirHandler);
				
		}	
		return true;	
	}
}
?>