PageRenderTime 65ms CodeModel.GetById 32ms RepoModel.GetById 1ms app.codeStats 0ms

/cake/libs/file.php

https://github.com/bb-dev/cakephp2x
PHP | 552 lines | 378 code | 24 blank | 150 comment | 37 complexity | 17edae0738517959d6abe6335b6ba6d3 MD5 | raw file
  1. <?php
  2. /**
  3. * Convenience class for reading, writing and appending to files.
  4. *
  5. * PHP Version 5.x
  6. *
  7. * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
  8. * Copyright 2005-2009, Cake Software Foundation, Inc. (http://cakefoundation.org)
  9. *
  10. * Licensed under The MIT License
  11. * Redistributions of files must retain the above copyright notice.
  12. *
  13. * @copyright Copyright 2005-2009, Cake Software Foundation, Inc. (http://cakefoundation.org)
  14. * @link http://cakephp.org CakePHP(tm) Project
  15. * @package cake
  16. * @subpackage cake.cake.libs
  17. * @since CakePHP(tm) v 0.2.9
  18. * @license MIT License (http://www.opensource.org/licenses/mit-license.php)
  19. */
  20. /**
  21. * Included libraries.
  22. *
  23. */
  24. if (!class_exists('Object')) {
  25. require LIBS . 'object.php';
  26. }
  27. if (!class_exists('Folder')) {
  28. require LIBS . 'folder.php';
  29. }
  30. /**
  31. * Convenience class for reading, writing and appending to files.
  32. *
  33. * @package cake
  34. * @subpackage cake.cake.libs
  35. */
  36. class File extends Object {
  37. /**
  38. * Folder object of the File
  39. *
  40. * @var Folder
  41. * @access public
  42. */
  43. public $Folder = null;
  44. /**
  45. * Filename
  46. *
  47. * @var string
  48. * @access public
  49. */
  50. public $name = null;
  51. /**
  52. * path property
  53. *
  54. * Current file's absolute path
  55. *
  56. * @var mixed null
  57. * @access public
  58. */
  59. public $path = null;
  60. /**
  61. * file info
  62. *
  63. * @var string
  64. * @access public
  65. */
  66. public $info = array();
  67. /**
  68. * Holds the file handler resource if the file is opened
  69. *
  70. * @var resource
  71. * @access public
  72. */
  73. public $handle = null;
  74. /**
  75. * enable locking for file reading and writing
  76. *
  77. * @var boolean
  78. * @access public
  79. */
  80. public $lock = null;
  81. /**
  82. * Constructor
  83. *
  84. * @param string $path Path to file
  85. * @param boolean $create Create file if it does not exist (if true)
  86. * @param integer $mode Mode to apply to the folder holding the file
  87. * @access public
  88. */
  89. public function __construct($path, $create = false, $mode = 0755) {
  90. parent::__construct();
  91. $this->Folder = new Folder(dirname($path), $create, $mode);
  92. if (!is_dir($path)) {
  93. $this->name = basename($path);
  94. }
  95. $this->pwd();
  96. if (!$this->exists()) {
  97. if ($create === true) {
  98. if ($this->safe($path) && $this->create() === false) {
  99. return false;
  100. }
  101. } else {
  102. return false;
  103. }
  104. }
  105. }
  106. /**
  107. * Closes the current file if it is opened
  108. *
  109. * @access private
  110. */
  111. public function __destruct() {
  112. $this->close();
  113. }
  114. /**
  115. * Creates the File.
  116. *
  117. * @return boolean Success
  118. * @access public
  119. */
  120. public function create() {
  121. $dir = $this->Folder->pwd();
  122. if (is_dir($dir) && is_writable($dir) && !$this->exists()) {
  123. $old = umask(0);
  124. if (touch($this->path)) {
  125. umask($old);
  126. return true;
  127. }
  128. }
  129. return false;
  130. }
  131. /**
  132. * Opens the current file with a given $mode
  133. *
  134. * @param string $mode A valid 'fopen' mode string (r|w|a ...)
  135. * @param boolean $force If true then the file will be re-opened even if its already opened, otherwise it won't
  136. * @return boolean True on success, false on failure
  137. * @access public
  138. */
  139. public function open($mode = 'r', $force = false) {
  140. if (!$force && is_resource($this->handle)) {
  141. return true;
  142. }
  143. clearstatcache();
  144. if ($this->exists() === false) {
  145. if ($this->create() === false) {
  146. return false;
  147. }
  148. }
  149. $this->handle = fopen($this->path, $mode);
  150. if (is_resource($this->handle)) {
  151. return true;
  152. }
  153. return false;
  154. }
  155. /**
  156. * Return the contents of this File as a string.
  157. *
  158. * @param string $bytes where to start
  159. * @param string $mode
  160. * @param boolean $force If true then the file will be re-opened even if its already opened, otherwise it won't
  161. * @return mixed string on success, false on failure
  162. * @access public
  163. */
  164. public function read($bytes = false, $mode = 'rb', $force = false) {
  165. if ($bytes === false && $this->lock === null) {
  166. return file_get_contents($this->path);
  167. }
  168. if ($this->open($mode, $force) === false) {
  169. return false;
  170. }
  171. if ($this->lock !== null && flock($this->handle, LOCK_SH) === false) {
  172. return false;
  173. }
  174. if (is_int($bytes)) {
  175. return fread($this->handle, $bytes);
  176. }
  177. $data = '';
  178. while (!feof($this->handle)) {
  179. $data .= fgets($this->handle, 4096);
  180. }
  181. if ($this->lock !== null) {
  182. flock($this->handle, LOCK_UN);
  183. }
  184. if ($bytes === false) {
  185. $this->close();
  186. }
  187. return $data;
  188. }
  189. /**
  190. * Sets or gets the offset for the currently opened file.
  191. *
  192. * @param mixed $offset The $offset in bytes to seek. If set to false then the current offset is returned.
  193. * @param integer $seek PHP Constant SEEK_SET | SEEK_CUR | SEEK_END determining what the $offset is relative to
  194. * @return mixed True on success, false on failure (set mode), false on failure or integer offset on success (get mode)
  195. * @access public
  196. */
  197. public function offset($offset = false, $seek = SEEK_SET) {
  198. if ($offset === false) {
  199. if (is_resource($this->handle)) {
  200. return ftell($this->handle);
  201. }
  202. } elseif ($this->open() === true) {
  203. return fseek($this->handle, $offset, $seek) === 0;
  204. }
  205. return false;
  206. }
  207. /**
  208. * Prepares a ascii string for writing
  209. * fixes line endings
  210. *
  211. * @param string $data Data to prepare for writing.
  212. * @return string
  213. * @access public
  214. */
  215. public function prepare($data, $forceWindows = false) {
  216. $lineBreak = "\n";
  217. if (DIRECTORY_SEPARATOR == '\\' || $forceWindows === true) {
  218. $lineBreak = "\r\n";
  219. }
  220. return strtr($data, array("\r\n" => $lineBreak, "\n" => $lineBreak, "\r" => $lineBreak));
  221. }
  222. /**
  223. * Write given data to this File.
  224. *
  225. * @param string $data Data to write to this File.
  226. * @param string $mode Mode of writing. {@link http://php.net/fwrite See fwrite()}.
  227. * @param string $force force the file to open
  228. * @return boolean Success
  229. * @access public
  230. */
  231. public function write($data, $mode = 'w', $force = false) {
  232. $success = false;
  233. if ($this->open($mode, $force) === true) {
  234. if ($this->lock !== null) {
  235. if (flock($this->handle, LOCK_EX) === false) {
  236. return false;
  237. }
  238. }
  239. if (fwrite($this->handle, $data) !== false) {
  240. $success = true;
  241. }
  242. if ($this->lock !== null) {
  243. flock($this->handle, LOCK_UN);
  244. }
  245. }
  246. return $success;
  247. }
  248. /**
  249. * Append given data string to this File.
  250. *
  251. * @param string $data Data to write
  252. * @param string $force force the file to open
  253. * @return boolean Success
  254. * @access public
  255. */
  256. public function append($data, $force = false) {
  257. return $this->write($data, 'a', $force);
  258. }
  259. /**
  260. * Closes the current file if it is opened.
  261. *
  262. * @return boolean True if closing was successful or file was already closed, otherwise false
  263. * @access public
  264. */
  265. public function close() {
  266. if (!is_resource($this->handle)) {
  267. return true;
  268. }
  269. return fclose($this->handle);
  270. }
  271. /**
  272. * Deletes the File.
  273. *
  274. * @return boolean Success
  275. * @access public
  276. */
  277. public function delete() {
  278. clearstatcache();
  279. if ($this->exists()) {
  280. return unlink($this->path);
  281. }
  282. return false;
  283. }
  284. /**
  285. * Returns the File info.
  286. *
  287. * @return string File information
  288. * @access public
  289. */
  290. public function info() {
  291. if ($this->info == null) {
  292. $this->info = pathinfo($this->path);
  293. }
  294. if (!isset($this->info['filename'])) {
  295. $this->info['filename'] = $this->name();
  296. }
  297. return $this->info;
  298. }
  299. /**
  300. * Returns the File extension.
  301. *
  302. * @return string The File extension
  303. * @access public
  304. */
  305. public function ext() {
  306. if ($this->info == null) {
  307. $this->info();
  308. }
  309. if (isset($this->info['extension'])) {
  310. return $this->info['extension'];
  311. }
  312. return false;
  313. }
  314. /**
  315. * Returns the File name without extension.
  316. *
  317. * @return string The File name without extension.
  318. * @access public
  319. */
  320. public function name() {
  321. if ($this->info == null) {
  322. $this->info();
  323. }
  324. if (isset($this->info['extension'])) {
  325. return basename($this->name, '.'.$this->info['extension']);
  326. } elseif ($this->name) {
  327. return $this->name;
  328. }
  329. return false;
  330. }
  331. /**
  332. * makes filename safe for saving
  333. *
  334. * @param string $name the name of the file to make safe if different from $this->name
  335. * @return string $ext the extension of the file
  336. * @access public
  337. */
  338. public function safe($name = null, $ext = null) {
  339. if (!$name) {
  340. $name = $this->name;
  341. }
  342. if (!$ext) {
  343. $ext = $this->ext();
  344. }
  345. return preg_replace( "/(?:[^\w\.-]+)/", "_", basename($name, $ext));
  346. }
  347. /**
  348. * Get md5 Checksum of file with previous check of Filesize
  349. *
  350. * @param mixed $maxsize in MB or true to force
  351. * @return string md5 Checksum {@link http://php.net/md5_file See md5_file()}
  352. * @access public
  353. */
  354. public function md5($maxsize = 5) {
  355. if ($maxsize === true) {
  356. return md5_file($this->path);
  357. }
  358. $size = $this->size();
  359. if ($size && $size < ($maxsize * 1024) * 1024) {
  360. return md5_file($this->path);
  361. }
  362. return false;
  363. }
  364. /**
  365. * Returns the full path of the File.
  366. *
  367. * @return string Full path to file
  368. * @access public
  369. */
  370. public function pwd() {
  371. if (is_null($this->path)) {
  372. $this->path = $this->Folder->slashTerm($this->Folder->pwd()) . $this->name;
  373. }
  374. return $this->path;
  375. }
  376. /**
  377. * Returns true if the File exists.
  378. *
  379. * @return boolean true if it exists, false otherwise
  380. * @access public
  381. */
  382. public function exists() {
  383. return (file_exists($this->path) && is_file($this->path));
  384. }
  385. /**
  386. * Returns the "chmod" (permissions) of the File.
  387. *
  388. * @return string Permissions for the file
  389. * @access public
  390. */
  391. public function perms() {
  392. if ($this->exists()) {
  393. return substr(sprintf('%o', fileperms($this->path)), -4);
  394. }
  395. return false;
  396. }
  397. /**
  398. * Returns the Filesize
  399. *
  400. * @return integer size of the file in bytes, or false in case of an error
  401. * @access public
  402. */
  403. public function size() {
  404. if ($this->exists()) {
  405. return filesize($this->path);
  406. }
  407. return false;
  408. }
  409. /**
  410. * Returns true if the File is writable.
  411. *
  412. * @return boolean true if its writable, false otherwise
  413. * @access public
  414. */
  415. public function writable() {
  416. return is_writable($this->path);
  417. }
  418. /**
  419. * Returns true if the File is executable.
  420. *
  421. * @return boolean true if its executable, false otherwise
  422. * @access public
  423. */
  424. public function executable() {
  425. return is_executable($this->path);
  426. }
  427. /**
  428. * Returns true if the File is readable.
  429. *
  430. * @return boolean true if file is readable, false otherwise
  431. * @access public
  432. */
  433. public function readable() {
  434. return is_readable($this->path);
  435. }
  436. /**
  437. * Returns the File's owner.
  438. *
  439. * @return integer the Fileowner
  440. * @access public
  441. */
  442. public function owner() {
  443. if ($this->exists()) {
  444. return fileowner($this->path);
  445. }
  446. return false;
  447. }
  448. /**
  449. * Returns the File group.
  450. *
  451. * @return integer the Filegroup
  452. * @access public
  453. */
  454. public function group() {
  455. if ($this->exists()) {
  456. return filegroup($this->path);
  457. }
  458. return false;
  459. }
  460. /**
  461. * Returns last access time.
  462. *
  463. * @return integer timestamp Timestamp of last access time
  464. * @access public
  465. */
  466. public function lastAccess() {
  467. if ($this->exists()) {
  468. return fileatime($this->path);
  469. }
  470. return false;
  471. }
  472. /**
  473. * Returns last modified time.
  474. *
  475. * @return integer timestamp Timestamp of last modification
  476. * @access public
  477. */
  478. public function lastChange() {
  479. if ($this->exists()) {
  480. return filemtime($this->path);
  481. }
  482. return false;
  483. }
  484. /**
  485. * Returns the current folder.
  486. *
  487. * @return Folder Current folder
  488. * @access public
  489. */
  490. public function Folder() {
  491. return $this->Folder;
  492. }
  493. /**
  494. * Copy the File to $dest
  495. *
  496. * @param string $dest destination for the copy
  497. * @param boolean $overwrite Overwrite $dest if exists
  498. * @return boolean Succes
  499. * @access public
  500. */
  501. public function copy($dest, $overwrite = true) {
  502. if (!$this->exists() || is_file($dest) && !$overwrite) {
  503. return false;
  504. }
  505. return copy($this->path, $dest);
  506. }
  507. }
  508. ?>