<?php
class FileUtil {
	private function path($path) {
		$path = str_replace('\\', '/', $path);
		$path && substr($path, -1) != '/' && $path .= '/';
		return $path;
	}
	// return 0失败，1成功，2本来就存在
	public function create($path) {
		if (is_dir($path)) {
			@chmod($path, 0777);
			return 2;
		}
		$path = str_replace('\\', '/', $path);
		$rootLen = strlen(JXCMS_ROOT);
		if (substr($path, 0, $rootLen) == JXCMS_ROOT) {
			$curDir = JXCMS_ROOT;
			$path = substr($path, $rootLen);
		} else $curDir = '';
		$temp = explode('/', $path);
		$max = count($temp);
		for($i = 0; $i < $max; $i++) {
			$curDir .= $temp[$i] . '/';
			if (is_dir($curDir)) continue;
			@mkdir($curDir, 0777);
		}
		return is_dir($path);
	}
	/**
	 * 删除目录
	 *
	 * @access public
	 * @param  $dir 要删除的完整目录
	 * @param  $flag 是否保留根目录,1 保留 0 不保留
	 * @return boolean
	 */
	public function del($dir, $flag = 0) {
		$dir = self :: path($dir);
		if (!is_dir($dir) || $dir == JXCMS_ROOT) return false;
		$list = glob($dir . '*');
		foreach($list as $v) is_dir($v) ? self :: del($v, 0) : @unlink($v);
		return $flag ? true : @rmdir($dir);
	}
	// 复制目录
	public function copy($fromdir, $todir) {
		$fromdir = self :: path($fromdir);
		$todir = self :: path($todir);
		if (!is_dir($fromdir)) return false;
		if (!is_dir($todir)) self :: create($todir);
		$list = glob($fromdir . '*');
		if (is_array($list)) {
			foreach($list as $v) {
				$path = $todir . basename($v);
				if (file_exists($path) && !is_writable($path)) return false;
				if (is_dir($v)) self :: copy($v, $path);
				else {
					copy($v, $path);
					@chmod($path, 0777);
				}
			}
		}
		return true;
	}
	/**
	 * 写入文件
	 *
	 * @access public
	 * @param  $path 文件路径
	 * @param  $content 内容
	 * @return intval 文件字节数
	 */
	public function write($path, $content) {
		if (empty($content)) return false;
		substr($path, 0, strlen(JXCMS_ROOT)) == JXCMS_ROOT or $path = JXCMS_ROOT . $path;
		$dir = dirname($path);
		self :: create($dir);
		if (!is_writable($dir)) show_error($dir . L('IS_NOT_WRITEABLE'));
		$strlen = file_put_contents($path, $content);
		@chmod($path, 0777);
		return $strlen;
	}
	// 批量改文件扩展名 2010.6
	public function multiModifyExt($dir, $sExt, $tExt) {
		$dir = str_replace('\\', '/', $dir);
		substr($dir, -1) == '/' or $dir .= '/';
		$n = strlen($sExt);
		foreach(glob($dir . '*' . $sExt) as $sName) {
			$tName = substr($sName, 0, - $n) . $tExt;
			rename($sName, $tName);
		}
		return true;
	}
	// 返回目录大小
	public function size($fileDir, $isUnit = false, $precision = 2) {
		$handle = opendir($fileDir);
		$size = 0;
		while ($fileName = readdir($handle)) {
			if ('.' != $fileName && '..' != $fileName) {
				$size += is_dir($fileDir . '/' . $fileName) ? self :: size($fileDir . '/' . $fileName) : (int)filesize($fileDir . '/' . $fileName);
			}
		}
		if ($isUnit) {
			$unit = array('B', 'KB', 'MB');
			$i = 0;
			while ($size > 1024 && $i < 3) {
				$size /= 1024;
				$i++;
			}
			$size = round($size, $precision) . $unit[$i];
		}
		return $size;
	}
	public function fileExt($fileName) {
		$tmp = pathinfo($fileName);
		return strtolower($tmp['extension']);
	}
	public function download($filePath, $fileName = '') {
		if (!is_file($filePath))show_error(L('FILE_NOT_EXIST'));
		$fileName or $fileName = basename($filePath);
		$useragent = strtolower($_SERVER['HTTP_USER_AGENT']);
		if (strpos($useragent, 'msie')) $fileName = rawurlencode($fileName);
		$fileType = self :: fileExt($fileName);
		$fileSize = sprintf("%u", filesize($filePath));
		if (ob_get_length() !== false) @ob_end_clean();
		header('Pragma: public');
		header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
		header('Cache-Control: no-store, no-cache, must-revalidate');
		header('Cache-Control: pre-check=0, post-check=0, max-age=0');
		header('Content-Transfer-Encoding: binary');
		header('Content-Encoding: none');
		header('Content-type: ' . $fileType);
		header('Content-Disposition: attachment; filename="' . $fileName . '"');
		header('Content-length: ' . $fileSize);
		readfile($filePath);
		exit;
	}
	public function fsockGetContents($url) {
		$tmp = parse_url($url);
		$host = $tmp['host'];
		$path = $tmp['path'];
		empty($tmp['query']) or $path .= '?' . $tmp['query'];
		if (empty($tmp['port'])) {
			$port = $tmp['scheme'] == 'https' ? 443 : 80;
		}
		$fp = @fsockopen($host, $port, $errno, $errstr);
		$data = '';
		if (!$fp) {
			echo "$errstr ($errno)<br />\n";
		} else {
			$user_agent = $_SERVER['HTTP_USER_AGENT'];
			$tmp = "GET $path HTTP/1.1\r\n";
			$tmp .= "Host: $host\r\n";
			$tmp .= "User-Agent: $user_agent\r\n";
			$tmp .= "Connection: Close\r\n\r\n";
			fwrite($fp , $tmp);
			while (!feof($fp)) $data .= fgets($fp, 4096);
			$data = trim(substr($data, strpos($data, "\r\n\r\n") + 4));
			fclose($fp);
		}
		return $data;
	}
	/**
	 * 批量获取内容
	 *
	 * @param  $urls 一维数组array(url1, url2, ...)
	 * @access public
	 */
	public function getMoreContent($urls) {
		$rs = array();
		$sockets = array();
		$userAgent = $_SERVER['HTTP_USER_AGENT'];
		foreach($urls as $id => $url) {
			$url = str_replace(' ', '%20', $url);
			$tmp = parse_url($url);
			$host = $tmp['host'];
			$path = isset($tmp['path'])?$tmp['path']:'/';
			empty($tmp['query']) or $path .= '?' . $tmp['query'];
			if (empty($tmp['port'])) {
				$port = $tmp['scheme'] == 'https'?443:80;
			} else $port = $tmp['port'];
			$fp = stream_socket_client("$host:$port", $errno, $errstr, 20);
			if ($fp) {
				$rs[$id] = '';
				$sockets[$id] = $fp;
				fwrite($fp, "GET $path HTTP/1.1\r\nHost: $host\r\nUser-Agent: $userAgent\r\nConnection: Close\r\n\r\n");
			}
		}
		// Now, wait for the results to come back in
		while (count($sockets)) {
			$read = $sockets;
			// This is the magic function - explained below
			if (stream_select($read, $write = null, $e = null, 20)) {
				// readable sockets either have data for us, or are failed connection attempts
				foreach ($read as $r) {
					$id = array_search($r, $sockets);
					if(!feof($r)) $rs[$id] .= @stream_get_line($r, 4096);
					else {
						fclose($r);
						$tmp = explode("\r\n\r\n", $rs[$id], 2);
						$rs[$id] = strpos($tmp[0], '200')?$tmp[1]:'';
						unset($sockets[$id]);
					}
				}
			}
		}
		return $rs;
	}
}
