PageRenderTime 46ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/Admin/plugins/tinymce/plugins/moxiemanager/classes/Vfs/Local/File.php

https://gitlab.com/hoanghung.dev/phunuvadoisong.com
PHP | 456 lines | 259 code | 59 blank | 138 comment | 47 complexity | 8dc7a7f5229347b99271ec4d4827b18f MD5 | raw file
  1. <?php
  2. /**
  3. * LocalFile.php
  4. *
  5. * Copyright 2003-2013, Moxiecode Systems AB, All rights reserved.
  6. */
  7. setlocale(LC_CTYPE, 'UTF8', 'en_US.UTF-8'); // Forces Linux to use proper UTF-8 for file names
  8. /**
  9. * This is the local file system implementation of MOXMAN_Vfs_IFile.
  10. *
  11. * @package MOXMAN_Vfs_Local
  12. */
  13. class MOXMAN_Vfs_Local_File extends MOXMAN_Vfs_BaseFile {
  14. private $internalPath;
  15. /**
  16. * Creates a new absolute file.
  17. *
  18. * @param MOXMAN_Vfs_FileSystem $fileSystem MCManager reference.
  19. * @param string $path Absolute path to local file.
  20. */
  21. public function __construct($fileSystem, $path) {
  22. parent::__construct($fileSystem, $path);
  23. $this->internalPath = $this->fromUtf($path);
  24. MOXMAN_Util_PathUtils::verifyPath($path, true);
  25. }
  26. /**
  27. * Returns true if the file exists.
  28. *
  29. * @return boolean true if the file exists.
  30. */
  31. public function exists() {
  32. return file_exists($this->internalPath);
  33. }
  34. /**
  35. * Returns true if the file is a directory.
  36. *
  37. * @return boolean true if the file is a directory.
  38. */
  39. public function isDirectory() {
  40. return $this->exists() && is_dir($this->internalPath);
  41. }
  42. /**
  43. * Returns true if the file is a file.
  44. *
  45. * @return boolean true if the file is a file.
  46. */
  47. public function isFile() {
  48. return $this->exists() && is_file($this->internalPath);
  49. }
  50. /**
  51. * Returns last modification date in ms as an long.
  52. *
  53. * @return long last modification date in ms as an long.
  54. */
  55. public function getLastModified() {
  56. return $this->exists() ? filemtime($this->internalPath) : 0;
  57. }
  58. /**
  59. * Returns true if the files is readable.
  60. *
  61. * @return boolean true if the files is readable.
  62. */
  63. public function canRead() {
  64. if (!parent::canRead()) {
  65. return false;
  66. }
  67. // Check parent
  68. if (!$this->exists()) {
  69. return $this->getParentFile()->canRead();
  70. }
  71. return is_readable($this->internalPath);
  72. }
  73. /**
  74. * Returns true if the files is writable.
  75. *
  76. * @return boolean true if the files is writable.
  77. */
  78. public function canWrite() {
  79. if (!parent::canWrite()) {
  80. return false;
  81. }
  82. // Check parent
  83. if (!$this->exists()) {
  84. return $this->getParentFile()->canWrite();
  85. }
  86. // Is windows we need to check if we can really write by accessing files
  87. // @codeCoverageIgnoreStart
  88. /*if (DIRECTORY_SEPARATOR === "\\") {
  89. if (is_file($this->internalPath)) {
  90. $fp = @fopen($this->internalPath, 'ab');
  91. if ($fp) {
  92. fclose($fp);
  93. return true;
  94. }
  95. } else if (is_dir($this->internalPath)) {
  96. $tmpnam = time() . md5(uniqid('iswritable'));
  97. if (@touch($this->internalPath . '\\' . $tmpnam)) {
  98. unlink($this->internalPath . '\\' . $tmpnam);
  99. return true;
  100. }
  101. }
  102. return false;
  103. }*/
  104. return is_writeable($this->internalPath);
  105. // @codeCoverageIgnoreEnd
  106. }
  107. /**
  108. * Returns file size as an long.
  109. *
  110. * @return long file size as an long.
  111. */
  112. public function getSize() {
  113. return $this->exists() ? filesize($this->internalPath) : 0;
  114. }
  115. /**
  116. * Renames/Moves this file to the specified file instance.
  117. *
  118. * @param MOXMAN_Vfs_IFile $dest File to rename/move to.
  119. */
  120. public function moveTo(MOXMAN_Vfs_IFile $dest) {
  121. if (!$this->exists()) {
  122. throw new Exception("Source file doesn't exist: " . $dest->getPublicPath());
  123. }
  124. $isSameFile = strtolower($this->getPath()) != strtolower($dest->getPath()) || $this->getName() == $dest->getName();
  125. if ($dest->exists()) {
  126. if ($isSameFile) {
  127. throw new Exception("Destination file already exists: " . $dest->getPublicPath());
  128. }
  129. }
  130. if ($isSameFile && MOXMAN_Util_PathUtils::isChildOf($dest->getPath(), $this->getPath())) {
  131. throw new Exception("You can't move the file into it self.");
  132. }
  133. $status = rename($this->internalPath, $this->fromUtf($dest->getPath()));
  134. }
  135. /**
  136. * Copies this file to the specified file instance.
  137. *
  138. * @param MOXMAN_Vfs_IFile $dest File to copy to.
  139. */
  140. public function copyTo(MOXMAN_Vfs_IFile $dest) {
  141. if (!$this->exists()) {
  142. throw new Exception("Source file doesn't exist: " . $dest->getPublicPath());
  143. }
  144. if (MOXMAN_Util_PathUtils::isChildOf($dest->getPath(), $this->getPath())) {
  145. throw new Exception("You can't copy the file into it self.");
  146. }
  147. // File copy or dir copy
  148. if ($this->isFile()) {
  149. if ($dest instanceof MOXMAN_Vfs_Local_File) {
  150. copy($this->internalPath, $this->fromUtf($dest->getPath()));
  151. } else {
  152. // Copy between file systems
  153. $in = $this->open(MOXMAN_Vfs_IFileStream::READ);
  154. $out = $dest->open(MOXMAN_Vfs_IFileStream::WRITE);
  155. // Stream in file to out file
  156. while (($data = $in->read()) !== "") {
  157. $out->write($data);
  158. }
  159. $in->close();
  160. $out->close();
  161. }
  162. } else {
  163. // Copy dir to dir
  164. $this->copyDir($this, $dest);
  165. }
  166. }
  167. /**
  168. * Deletes the file.
  169. *
  170. * @param boolean $deep If this option is enabled files will be deleted recurive.
  171. */
  172. public function delete($deep = false) {
  173. if (!$this->exists()) {
  174. throw new Exception("Could not delete file since it doesn't exist: " . $this->getPublicPath());
  175. }
  176. if ($this->isDirectory()) {
  177. $files = array_reverse($this->getFiles($this->internalPath));
  178. if ($deep) {
  179. foreach ($files as $path) {
  180. if (is_dir($path)) {
  181. rmdir($path);
  182. } else {
  183. unlink($path);
  184. }
  185. }
  186. } else {
  187. if (count($files) > 1) {
  188. throw new Exception("Could not delete directory since it's not empty.");
  189. }
  190. rmdir($this->internalPath);
  191. }
  192. } else {
  193. unlink($this->internalPath);
  194. }
  195. }
  196. /**
  197. * Returns an array of File instances.
  198. *
  199. * @return array array of File instances.
  200. */
  201. public function listFiles() {
  202. $files = $this->listFilesFiltered(new MOXMAN_Vfs_BasicFileFilter());
  203. return $files;
  204. }
  205. /**
  206. * Returns an array of BaseFile instances based on the specified filter instance.
  207. *
  208. * @param MOXMAN_Vfs_IFileFilter $filter FileFilter instance to filter files by.
  209. * @return array array of File instances based on the specified filter instance.
  210. */
  211. public function listFilesFiltered(MOXMAN_Vfs_IFileFilter $filter) {
  212. $files = array();
  213. $dirs = array();
  214. $accessFileName = $this->getConfig()->get("filesystem.local.access_file_name");
  215. if ($this->isFile()) {
  216. return $files;
  217. }
  218. if ($fHnd = opendir($this->internalPath)) {
  219. while (false !== ($file = readdir($fHnd))) {
  220. // Ignore current and parent
  221. if ($file === "." || $file === ".." || $file === $accessFileName) {
  222. continue;
  223. }
  224. // Returns false if safe mode is on and the user/group is not the same as apache
  225. $path = $this->internalPath . "/" . $file;
  226. if (file_exists($path)) {
  227. if (is_file($path)) {
  228. $files[] = $file;
  229. } else {
  230. $dirs[] = $file;
  231. }
  232. }
  233. }
  234. // Close handle
  235. closedir($fHnd);
  236. // Add dirs
  237. sort($dirs);
  238. $list = array();
  239. foreach ($dirs as $dir) {
  240. $file = $this->internalPath . "/" . $dir;
  241. // Ignore files that isn't valid
  242. try {
  243. MOXMAN_Util_PathUtils::verifyPath($file, true, "dir");
  244. } catch (Exception $e) {
  245. continue;
  246. }
  247. // Hack
  248. if (!@json_encode($file)) {
  249. continue;
  250. }
  251. $file = $this->fileSystem->getFile($this->toUtf($file));
  252. if ($filter->accept($file) === MOXMAN_Vfs_BasicFileFilter::ACCEPTED) {
  253. $list[] = $file;
  254. }
  255. }
  256. $dirs = $list;
  257. // Add files
  258. sort($files);
  259. $list = array();
  260. foreach ($files as $file) {
  261. $file = $this->internalPath . "/" . $file;
  262. // Ignore files that isn't valid
  263. try {
  264. MOXMAN_Util_PathUtils::verifyPath($file, true, "file");
  265. } catch (Exception $e) {
  266. continue;
  267. }
  268. // Hack
  269. if (!@json_encode($file)) {
  270. continue;
  271. }
  272. $file = $this->fileSystem->getFile($this->toUtf($file));
  273. if ($filter->accept($file) === MOXMAN_Vfs_BasicFileFilter::ACCEPTED) {
  274. $list[] = $file;
  275. }
  276. }
  277. $files = $list;
  278. }
  279. $files = array_merge($dirs, $files);
  280. return $files;
  281. }
  282. /**
  283. * Creates a new directory.
  284. */
  285. public function mkdir() {
  286. MOXMAN_Util_PathUtils::verifyPath($this->internalPath, true, "dir");
  287. mkdir($this->internalPath);
  288. }
  289. /**
  290. * Opens a file stream by the specified mode. The default mode is rb.
  291. *
  292. * @param string $mode Mode to open file by, r, rb, w, wb etc.
  293. * @return MOXMAN_Vfs_IStream File stream implementation for the file system.
  294. */
  295. public function open($mode = MOXMAN_Vfs_IStream::READ) {
  296. $stream = new MOXMAN_Vfs_Local_FileStream($this->internalPath, $mode);
  297. return $stream;
  298. }
  299. /**
  300. * Exports the file to a local path. This is used by some operations that can be done in memory.
  301. *
  302. * @param string $localPath Local path to export file to.
  303. * @return string Local path that the file was exported to.
  304. */
  305. public function exportTo($localPath) {
  306. if ($this->internalPath !== $localPath) {
  307. copy($this->internalPath, $localPath);
  308. }
  309. return $localPath;
  310. }
  311. /**
  312. * Imports a local file into the file system.
  313. *
  314. * @param string $localPath Local file system path to import.
  315. */
  316. public function importFrom($localPath) {
  317. if ($this->internalPath !== $localPath) {
  318. copy($localPath, $this->internalPath);
  319. }
  320. }
  321. public function getInternalPath() {
  322. return $this->internalPath;
  323. }
  324. /** @ignore */
  325. private function getFiles($path) {
  326. $files = array();
  327. $files[] = $path;
  328. if ($dir = opendir($path)) {
  329. while (false !== ($file = readdir($dir))) {
  330. if ($file == "." || $file == "..") {
  331. continue;
  332. }
  333. $file = $path . "/" . $file;
  334. if (is_dir($file)) {
  335. $files = array_merge($files, $this->getFiles($file));
  336. } else {
  337. $files[] = $file;
  338. }
  339. }
  340. closedir($dir);
  341. }
  342. return $files;
  343. }
  344. /** @ignore */
  345. private function copyDir($from, $to) {
  346. $fromPathRoot = $from->getPath();
  347. $files = $this->getFiles($fromPathRoot);
  348. foreach ($files as $fromPath) {
  349. $toPath = MOXMAN_Util_PathUtils::combine($to->getPath(), substr($fromPath, strlen($fromPathRoot)));
  350. if (is_file($fromPath)) {
  351. if ($to instanceof MOXMAN_Vfs_Local_File) {
  352. copy($fromPath, $toPath);
  353. } else {
  354. $to->getFileSystem()->getFile($toPath)->importFrom($fromPath);
  355. }
  356. } else {
  357. if ($to instanceof MOXMAN_Vfs_Local_File) {
  358. MOXMAN_Util_PathUtils::verifyPath($toPath, true, "dir");
  359. mkdir($toPath);
  360. } else {
  361. $to->getFileSystem()->getFile($toPath)->mkdir();
  362. }
  363. }
  364. }
  365. }
  366. private function fromUtf($path) {
  367. if (DIRECTORY_SEPARATOR == "\\") {
  368. // $path = mb_convert_encoding($path, "Windows-1252", "UTF-8");
  369. $path = iconv("Windows-1252", "UTF-8",$path);
  370. // Detect any characters outside the Win32 filename byte range
  371. if (strpos($path, '?') !== false) {
  372. throw new MOXMAN_Exception("PHP doesn't support the specified characters on Windows.", MOXMAN_Exception::INVALID_FILE_NAME);
  373. }
  374. }
  375. return $path;
  376. }
  377. private function toUtf($path) {
  378. if (DIRECTORY_SEPARATOR == "\\") {
  379. return iconv("UTF-8", "Windows-1252", $path);
  380. }
  381. return $path;
  382. }
  383. }
  384. ?>