PageRenderTime 43ms CodeModel.GetById 14ms RepoModel.GetById 1ms app.codeStats 0ms

/libraries/Gelato/FileSystem/File.php

https://github.com/ravilrrr/monstra-cms
PHP | 577 lines | 406 code | 28 blank | 143 comment | 24 complexity | e7dae18c9a45f592a1885b83a34b619c MD5 | raw file
Possible License(s): GPL-3.0
  1. <?php
  2. /**
  3. * Gelato Library
  4. *
  5. * This source file is part of the Gelato Library. More information,
  6. * documentation and tutorials can be found at http://gelato.monstra.org
  7. *
  8. * @package Gelato
  9. *
  10. * @author Romanenko Sergey / Awilum <awilum@msn.com>
  11. * @copyright 2012-2014 Romanenko Sergey / Awilum <awilum@msn.com>
  12. *
  13. * For the full copyright and license information, please view the LICENSE
  14. * file that was distributed with this source code.
  15. */
  16. class File
  17. {
  18. /**
  19. * Mime type list
  20. *
  21. * @var array
  22. */
  23. public static $mime_types = array(
  24. 'aac' => 'audio/aac',
  25. 'atom' => 'application/atom+xml',
  26. 'avi' => 'video/avi',
  27. 'bmp' => 'image/x-ms-bmp',
  28. 'c' => 'text/x-c',
  29. 'class' => 'application/octet-stream',
  30. 'css' => 'text/css',
  31. 'csv' => 'text/csv',
  32. 'deb' => 'application/x-deb',
  33. 'dll' => 'application/x-msdownload',
  34. 'dmg' => 'application/x-apple-diskimage',
  35. 'doc' => 'application/msword',
  36. 'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
  37. 'exe' => 'application/octet-stream',
  38. 'flv' => 'video/x-flv',
  39. 'gif' => 'image/gif',
  40. 'gz' => 'application/x-gzip',
  41. 'h' => 'text/x-c',
  42. 'htm' => 'text/html',
  43. 'html' => 'text/html',
  44. 'ini' => 'text/plain',
  45. 'jar' => 'application/java-archive',
  46. 'java' => 'text/x-java',
  47. 'jpeg' => 'image/jpeg',
  48. 'jpg' => 'image/jpeg',
  49. 'js' => 'text/javascript',
  50. 'json' => 'application/json',
  51. 'mid' => 'audio/midi',
  52. 'midi' => 'audio/midi',
  53. 'mka' => 'audio/x-matroska',
  54. 'mkv' => 'video/x-matroska',
  55. 'mp3' => 'audio/mpeg',
  56. 'mp4' => 'application/mp4',
  57. 'mpeg' => 'video/mpeg',
  58. 'mpg' => 'video/mpeg',
  59. 'odt' => 'application/vnd.oasis.opendocument.text',
  60. 'ogg' => 'audio/ogg',
  61. 'pdf' => 'application/pdf',
  62. 'php' => 'text/x-php',
  63. 'png' => 'image/png',
  64. 'psd' => 'image/vnd.adobe.photoshop',
  65. 'py' => 'application/x-python',
  66. 'ra' => 'audio/vnd.rn-realaudio',
  67. 'ram' => 'audio/vnd.rn-realaudio',
  68. 'rar' => 'application/x-rar-compressed',
  69. 'rss' => 'application/rss+xml',
  70. 'safariextz' => 'application/x-safari-extension',
  71. 'sh' => 'text/x-shellscript',
  72. 'shtml' => 'text/html',
  73. 'swf' => 'application/x-shockwave-flash',
  74. 'tar' => 'application/x-tar',
  75. 'tif' => 'image/tiff',
  76. 'tiff' => 'image/tiff',
  77. 'torrent' => 'application/x-bittorrent',
  78. 'txt' => 'text/plain',
  79. 'wav' => 'audio/wav',
  80. 'webp' => 'image/webp',
  81. 'wma' => 'audio/x-ms-wma',
  82. 'xls' => 'application/vnd.ms-excel',
  83. 'xml' => 'text/xml',
  84. 'zip' => 'application/zip',
  85. );
  86. /**
  87. * Protected constructor since this is a static class.
  88. *
  89. * @access protected
  90. */
  91. protected function __construct()
  92. {
  93. // Nothing here
  94. }
  95. /**
  96. * Returns true if the File exists.
  97. *
  98. * <code>
  99. * if (File::exists('filename.txt')) {
  100. * // Do something...
  101. * }
  102. * </code>
  103. *
  104. * @param string $filename The file name
  105. * @return boolean
  106. */
  107. public static function exists($filename)
  108. {
  109. // Redefine vars
  110. $filename = (string) $filename;
  111. // Return
  112. return (file_exists($filename) && is_file($filename));
  113. }
  114. /**
  115. * Delete file
  116. *
  117. * <code>
  118. * File::delete('filename.txt');
  119. * </code>
  120. *
  121. * @param mixed $filename The file name or array of files
  122. * @return boolean
  123. */
  124. public static function delete($filename)
  125. {
  126. // Is array
  127. if (is_array($filename)) {
  128. // Delete each file in $filename array
  129. foreach ($filename as $file) {
  130. @unlink((string) $file);
  131. }
  132. } else {
  133. // Is string
  134. return @unlink((string) $filename);
  135. }
  136. }
  137. /**
  138. * Rename file
  139. *
  140. * <code>
  141. * File::rename('filename1.txt', 'filename2.txt');
  142. * </code>
  143. *
  144. * @param string $from Original file location
  145. * @param string $to Desitination location of the file
  146. * @return boolean
  147. */
  148. public static function rename($from, $to)
  149. {
  150. // Redefine vars
  151. $from = (string) $from;
  152. $to = (string) $to;
  153. // If file exists $to than rename it
  154. if ( ! File::exists($to)) return rename($from, $to);
  155. // Else return false
  156. return false;
  157. }
  158. /**
  159. * Copy file
  160. *
  161. * <code>
  162. * File::copy('folder1/filename.txt', 'folder2/filename.txt');
  163. * </code>
  164. *
  165. * @param string $from Original file location
  166. * @param string $to Desitination location of the file
  167. * @return boolean
  168. */
  169. public static function copy($from, $to)
  170. {
  171. // Redefine vars
  172. $from = (string) $from;
  173. $to = (string) $to;
  174. // If file !exists $from and exists $to then return false
  175. if ( ! File::exists($from) || File::exists($to)) return false;
  176. // Else copy file
  177. return copy($from, $to);
  178. }
  179. /**
  180. * Get the File extension.
  181. *
  182. * <code>
  183. * echo File::ext('filename.txt');
  184. * </code>
  185. *
  186. * @param string $filename The file name
  187. * @return string
  188. */
  189. public static function ext($filename)
  190. {
  191. // Redefine vars
  192. $filename = (string) $filename;
  193. // Return file extension
  194. return substr(strrchr($filename, '.'), 1);
  195. }
  196. /**
  197. * Get the File name
  198. *
  199. * <code>
  200. * echo File::name('filename.txt');
  201. * </code>
  202. *
  203. * @param string $filename The file name
  204. * @return string
  205. */
  206. public static function name($filename)
  207. {
  208. // Redefine vars
  209. $filename = (string) $filename;
  210. // Return filename
  211. return basename($filename, '.'.File::ext($filename));
  212. }
  213. /**
  214. * Get list of files in directory recursive
  215. *
  216. * <code>
  217. * $files = File::scan('folder');
  218. * $files = File::scan('folder', 'txt');
  219. * $files = File::scan('folder', array('txt', 'log'));
  220. * </code>
  221. *
  222. * @param string $folder Folder
  223. * @param mixed $type Files types
  224. * @return array
  225. */
  226. public static function scan($folder, $type = null)
  227. {
  228. $data = array();
  229. if (is_dir($folder)) {
  230. $iterator = new RecursiveDirectoryIterator($folder);
  231. foreach (new RecursiveIteratorIterator($iterator) as $file) {
  232. if ($type !== null) {
  233. if (is_array($type)) {
  234. $file_ext = substr(strrchr($file->getFilename(), '.'), 1);
  235. if (in_array($file_ext, $type)) {
  236. if (strpos($file->getFilename(), $file_ext, 1)) {
  237. $data[] = $file->getFilename();
  238. }
  239. }
  240. } else {
  241. if (strpos($file->getFilename(), $type, 1)) {
  242. $data[] = $file->getFilename();
  243. }
  244. }
  245. } else {
  246. if ($file->getFilename() !== '.' && $file->getFilename() !== '..') $data[] = $file->getFilename();
  247. }
  248. }
  249. return $data;
  250. } else {
  251. return false;
  252. }
  253. }
  254. /**
  255. * Fetch the content from a file or URL.
  256. *
  257. * <code>
  258. * echo File::getContent('filename.txt');
  259. * </code>
  260. *
  261. * @param string $filename The file name
  262. * @return boolean
  263. */
  264. public static function getContent($filename)
  265. {
  266. // Redefine vars
  267. $filename = (string) $filename;
  268. // If file exists load it
  269. if (File::exists($filename)) {
  270. return file_get_contents($filename);
  271. }
  272. }
  273. /**
  274. * Writes a string to a file.
  275. *
  276. * @param string $filename The path of the file.
  277. * @param string $content The content that should be written.
  278. * @param boolean $createFile Should the file be created if it doesn't exists?
  279. * @param boolean $append Should the content be appended if the file already exists?
  280. * @param integer $chmod Mode that should be applied on the file.
  281. * @return boolean
  282. */
  283. public static function setContent($filename, $content, $create_file = true, $append = false, $chmod = 0666)
  284. {
  285. // Redefine vars
  286. $filename = (string) $filename;
  287. $content = (string) $content;
  288. $create_file = (bool) $create_file;
  289. $append = (bool) $append;
  290. // File may not be created, but it doesn't exist either
  291. if ( ! $create_file && File::exists($filename)) throw new RuntimeException(vsprintf("%s(): The file '{$filename}' doesn't exist", array(__METHOD__)));
  292. // Create directory recursively if needed
  293. Dir::create(dirname($filename));
  294. // Create file & open for writing
  295. $handler = ($append) ? @fopen($filename, 'a') : @fopen($filename, 'w');
  296. // Something went wrong
  297. if ($handler === false) throw new RuntimeException(vsprintf("%s(): The file '{$filename}' could not be created. Check if PHP has enough permissions.", array(__METHOD__)));
  298. // Store error reporting level
  299. $level = error_reporting();
  300. // Disable errors
  301. error_reporting(0);
  302. // Write to file
  303. $write = fwrite($handler, $content);
  304. // Validate write
  305. if($write === false) throw new RuntimeException(vsprintf("%s(): The file '{$filename}' could not be created. Check if PHP has enough permissions.", array(__METHOD__)));
  306. // Close the file
  307. fclose($handler);
  308. // Chmod file
  309. chmod($filename, $chmod);
  310. // Restore error reporting level
  311. error_reporting($level);
  312. // Return
  313. return true;
  314. }
  315. /**
  316. * Get time(in Unix timestamp) the file was last changed
  317. *
  318. * <code>
  319. * echo File::lastChange('filename.txt');
  320. * </code>
  321. *
  322. * @param string $filename The file name
  323. * @return boolean
  324. */
  325. public static function lastChange($filename)
  326. {
  327. // Redefine vars
  328. $filename = (string) $filename;
  329. // If file exists return filemtime
  330. if (File::exists($filename)) {
  331. return filemtime($filename);
  332. }
  333. // Return
  334. return false;
  335. }
  336. /**
  337. * Get last access time
  338. *
  339. * <code>
  340. * echo File::lastAccess('filename.txt');
  341. * </code>
  342. *
  343. * @param string $filename The file name
  344. * @return boolean
  345. */
  346. public static function lastAccess($filename)
  347. {
  348. // Redefine vars
  349. $filename = (string) $filename;
  350. // If file exists return fileatime
  351. if (File::exists($filename)) {
  352. return fileatime($filename);
  353. }
  354. // Return
  355. return false;
  356. }
  357. /**
  358. * Returns the mime type of a file. Returns false if the mime type is not found.
  359. *
  360. * <code>
  361. * echo File::mime('filename.txt');
  362. * </code>
  363. *
  364. * @param string $file Full path to the file
  365. * @param boolean $guess Set to false to disable mime type guessing
  366. * @return string
  367. */
  368. public static function mime($file, $guess = true)
  369. {
  370. // Redefine vars
  371. $file = (string) $file;
  372. $guess = (bool) $guess;
  373. // Get mime using the file information functions
  374. if (function_exists('finfo_open')) {
  375. $info = finfo_open(FILEINFO_MIME_TYPE);
  376. $mime = finfo_file($info, $file);
  377. finfo_close($info);
  378. return $mime;
  379. } else {
  380. // Just guess mime by using the file extension
  381. if ($guess === true) {
  382. $mime_types = File::$mime_types;
  383. $extension = pathinfo($file, PATHINFO_EXTENSION);
  384. return isset($mime_types[$extension]) ? $mime_types[$extension] : false;
  385. } else {
  386. return false;
  387. }
  388. }
  389. }
  390. /**
  391. * Forces a file to be downloaded.
  392. *
  393. * <code>
  394. * File::download('filename.txt');
  395. * </code>
  396. *
  397. * @param string $file Full path to file
  398. * @param string $content_type Content type of the file
  399. * @param string $filename Filename of the download
  400. * @param integer $kbps Max download speed in KiB/s
  401. */
  402. public static function download($file, $content_type = null, $filename = null, $kbps = 0)
  403. {
  404. // Redefine vars
  405. $file = (string) $file;
  406. $content_type = ($content_type === null) ? null : (string) $content_type;
  407. $filename = ($filename === null) ? null : (string) $filename;
  408. $kbps = (int) $kbps;
  409. // Check that the file exists and that its readable
  410. if (file_exists($file) === false || is_readable($file) === false) {
  411. throw new RuntimeException(vsprintf("%s(): Failed to open stream.", array(__METHOD__)));
  412. }
  413. // Empty output buffers
  414. while (ob_get_level() > 0) ob_end_clean();
  415. // Send headers
  416. if ($content_type === null) $content_type = File::mime($file);
  417. if ($filename === null) $filename = basename($file);
  418. header('Content-type: ' . $content_type);
  419. header('Content-Disposition: attachment; filename="' . $filename . '"');
  420. header('Content-Length: ' . filesize($file));
  421. // Read file and write it to the output
  422. @set_time_limit(0);
  423. if ($kbps === 0) {
  424. readfile($file);
  425. } else {
  426. $handle = fopen($file, 'r');
  427. while ( ! feof($handle) && !connection_aborted()) {
  428. $s = microtime(true);
  429. echo fread($handle, round($kbps * 1024));
  430. if (($wait = 1e6 - (microtime(true) - $s)) > 0) usleep($wait);
  431. }
  432. fclose($handle);
  433. }
  434. exit();
  435. }
  436. /**
  437. * Display a file in the browser.
  438. *
  439. * <code>
  440. * File::display('filename.txt');
  441. * </code>
  442. *
  443. * @param string $file Full path to file
  444. * @param string $content_type Content type of the file
  445. * @param string $filename Filename of the download
  446. */
  447. public static function display($file, $content_type = null, $filename = null)
  448. {
  449. // Redefine vars
  450. $file = (string) $file;
  451. $content_type = ($content_type === null) ? null : (string) $content_type;
  452. $filename = ($filename === null) ? null : (string) $filename;
  453. // Check that the file exists and that its readable
  454. if (file_exists($file) === false || is_readable($file) === false) {
  455. throw new RuntimeException(vsprintf("%s(): Failed to open stream.", array(__METHOD__)));
  456. }
  457. // Empty output buffers
  458. while (ob_get_level() > 0) ob_end_clean();
  459. // Send headers
  460. if ($content_type === null) $content_type = File::mime($file);
  461. if($filename === null) $filename = basename($file);
  462. header('Content-type: ' . $content_type);
  463. header('Content-Disposition: inline; filename="' . $filename . '"');
  464. header('Content-Length: ' . filesize($file));
  465. // Read file and write to output
  466. readfile($file);
  467. exit();
  468. }
  469. /**
  470. * Tests whether a file is writable for anyone.
  471. *
  472. * <code>
  473. * if (File::writable('filename.txt')) {
  474. * // do something...
  475. * }
  476. * </code>
  477. *
  478. * @param string $file File to check
  479. * @return boolean
  480. */
  481. public static function writable($file)
  482. {
  483. // Redefine vars
  484. $file = (string) $file;
  485. // Is file exists ?
  486. if ( ! file_exists($file)) throw new RuntimeException(vsprintf("%s(): The file '{$file}' doesn't exist", array(__METHOD__)));
  487. // Gets file permissions
  488. $perms = fileperms($file);
  489. // Is writable ?
  490. if (is_writable($file) || ($perms & 0x0080) || ($perms & 0x0010) || ($perms & 0x0002)) return true;
  491. }
  492. }