File.php 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309
  1. <?php
  2. /**
  3. * The Feeler framework, licensed under LGPL license
  4. * Author: Rick Guo
  5. */
  6. defined("HEAD") or define("HEAD", 1);
  7. defined("END") or define("END", 2);
  8. class File{
  9. public $segLength = 524288; //to read and write slice in segments, this set every segment's length
  10. public $state = true;
  11. public $position = 0;
  12. protected $handle;
  13. protected $fileSize;
  14. protected $file;
  15. function __construct($file, $mode = "r", $pointer = null, $override = false){
  16. $this->init($file, $mode, $pointer, $override);
  17. }
  18. function __destruct(){
  19. if(is_resource($this->handle))
  20. fclose($this->handle);
  21. }
  22. public function init($file, $mode = "r", $pointer = null, $override = false){
  23. if(!is_file($file)){
  24. $this->state = false;
  25. return false;
  26. }
  27. $lockMode = LOCK_SH;
  28. if($mode == "r"){
  29. $modeParam = "r";
  30. }
  31. else if($mode == "w"){
  32. if(!$pointer)
  33. $pointer = END;
  34. if($override)
  35. $modeParam = "w";
  36. else{
  37. if($pointer == HEAD){
  38. $modeParam = "c";
  39. }
  40. else if($pointer == END){
  41. $modeParam = "a";
  42. }
  43. }
  44. }
  45. else if($mode == "rw"){
  46. if(!$pointer)
  47. $pointer = HEAD;
  48. if($override)
  49. $modeParam = "w+";
  50. else{
  51. if($pointer == HEAD){
  52. $modeParam = "r+";
  53. }
  54. else if($pointer == END){
  55. $modeParam = "a+";
  56. }
  57. }
  58. }
  59. else{
  60. $this->state = false;
  61. return false;
  62. }
  63. if($modeParam != "r")
  64. $lockMode = LOCK_EX;
  65. $this->handle = fopen($file, $modeParam);
  66. if(!$this->lock($lockMode)){
  67. $this->state = false;
  68. return false;
  69. }
  70. $this->file = $file;
  71. $this->fileSize = filesize($this->file);
  72. }
  73. public function getContent($length = -1, $position = null){
  74. if(!$this->state)
  75. return null;
  76. if($position === null)
  77. $position = $this->position;
  78. if($position < 0)
  79. return null;
  80. if($length === -1)
  81. $length = $this->fileSize;
  82. $this->seek($position);
  83. if($length <= $this->segLength || ($this->fileSize - $position) < $this->segLength){
  84. return fread($this->handle, $length);
  85. }
  86. $data = null;
  87. $round = ceil($length / $this->segLength);
  88. for($i = 0; $i < $round; $i++){
  89. $data .= fread($this->handle, $this->segLength);
  90. if($position == 0){
  91. $this->seek(($position += $this->segLength + 1));
  92. }
  93. else{
  94. $this->seek(($position += $this->segLength));
  95. }
  96. }
  97. return $data;
  98. }
  99. public function seek($position = 0){
  100. return fseek($this->handle, $position);
  101. }
  102. public function write($data, $length = -1){
  103. if(!$this->state || !$data)
  104. return false;
  105. if($length === -1)
  106. return fwrite($this->handle, $data);
  107. if($length > 0)
  108. return fwrite($this->handle, $data, $length);
  109. return false;
  110. }
  111. public function lock($mode = LOCK_EX){
  112. return flock($this->handle, $mode);
  113. }
  114. public function unlock(){
  115. return flock($this->handle, LOCK_UN);
  116. }
  117. public static function create($file){
  118. return fopen($file, "w") !== false ? true : false;
  119. }
  120. public static function save($file, $content, $length = -1){
  121. $fileObj = new self($file, "w", null, true);
  122. return $fileObj->write($content, $length);
  123. }
  124. //make new dirs, will create all unexist dirs on the path
  125. public static function mkdir($path, $chmod = 0755){
  126. return is_dir($path) || (self::mkdir(dirname($path), $chmod) && mkdir($path, $chmod));
  127. }
  128. public static function rm($target, $recursive = false){
  129. if(file_exists($target)){
  130. if($recursive){
  131. if(is_dir($target)){
  132. $handle = opendir($target);
  133. while($subTarget = readdir($handle)){
  134. if($subTarget !== "." && $subTarget !== ".."){
  135. $position = "{$target}/{$subTarget}";
  136. if(is_dir($position)){
  137. self::rm($position);
  138. }
  139. else{
  140. unlink($position);
  141. }
  142. }
  143. }
  144. closedir($handle);
  145. if(rmdir($target)){
  146. return true;
  147. }
  148. }
  149. }
  150. if(is_file($target)){
  151. return unlink($target);
  152. }
  153. }
  154. return false;
  155. }
  156. public static function rmdir($dir){
  157. return self::rm($dir, true);
  158. }
  159. //read the first and last 512byte data and convert to hex then check it whether have trojans signature code or not
  160. public static function checkHex($file){
  161. $handle = fopen($file, "rb");
  162. $fileSize = filesize($file);
  163. fseek($handle, 0);
  164. if($fileSize > 512){
  165. $hexCode = bin2hex(fread($handle, 512));
  166. fseek($handle, $fileSize - 512);
  167. $hexCode .= bin2hex(fread($handle, 512));
  168. }
  169. else{
  170. $hexCode = bin2hex(fread($handle, $fileSize));
  171. }
  172. fclose($handle);
  173. /**
  174. * match <% ( ) %>
  175. * <? ( ) ?>
  176. * <script /script>
  177. */
  178. if(preg_match("/(3c25.*?28.*?29.*?253e)|(3c3f.*?28.*?29.*?3f3e)|(3C534352495054.*?2F5343524950543E)|(3C736372697074.*?2F7363726970743E)/is", $hexCode))
  179. return false;
  180. else
  181. return true;
  182. }
  183. //get the extension of the file
  184. public static function getExt($fileName){
  185. if(is_file($fileName)){
  186. $fileInfo = pathinfo($fileName);
  187. return isset($fileInfo["extension"]) ? $fileInfo["extension"] : null;
  188. }
  189. else{
  190. return strtolower(substr(strrchr($fileName, "."), 1));
  191. }
  192. }
  193. public static function getName($fileName){
  194. if(preg_match("/^.*\/(.*)(?:\..*)$/", $fileName, $matches)){
  195. return $matches[1];
  196. }
  197. return null;
  198. }
  199. public static function getFullName($file){
  200. if(preg_match("/^.*\/(.*\..*)$/", $file, $matches)){
  201. return $matches[1];
  202. }
  203. return null;
  204. }
  205. public static function getPath($file){
  206. if(preg_match("/^(.*\/)(.*\..*)$/", $file, $matches)){
  207. return $matches[1];
  208. }
  209. return null;
  210. }
  211. //get file size
  212. public static function getSize($file){
  213. return is_file($file) ? filesize($file) : null;
  214. }
  215. public static function getTypeList(){
  216. return array(
  217. "255216" => "jpg",
  218. "13780" => "png",
  219. "7173" => "gif",
  220. "6677" => "bmp",
  221. "6063" => "xml",
  222. "60104" => "html",
  223. "208207" => array("xls", "doc"),
  224. "8075" => array("zip", "docx", "xlsx"),
  225. "8297" => "rar",
  226. );
  227. }
  228. //get file's type according to start of 2bytes binary data
  229. public static function getType($file){
  230. if(!is_file($file)){
  231. return null;
  232. }
  233. $handle = fopen($file, "rb");
  234. if(!$handle){
  235. return null;
  236. }
  237. $bin = fread($handle, 2);
  238. fclose($handle);
  239. if($bin){
  240. $strs = unpack("C2str", $bin);
  241. $typeCode = $strs["str1"].$strs["str2"];
  242. $types = self::getTypeList();
  243. foreach($types as $key => $type){
  244. if((string)$key === $typeCode){
  245. return $type;
  246. }
  247. }
  248. }
  249. return null;
  250. }
  251. }