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

/libraries/joomla/filesystem/file.php

https://github.com/dg482/joomla-platform
PHP | 554 lines | 320 code | 69 blank | 165 comment | 48 complexity | 4275fd7161e667226f3fdf6a9966a29b MD5 | raw file
  1. <?php
  2. /**
  3. * @package Joomla.Platform
  4. * @subpackage FileSystem
  5. *
  6. * @copyright Copyright (C) 2005 - 2011 Open Source Matters, Inc. All rights reserved.
  7. * @license GNU General Public License version 2 or later; see LICENSE
  8. */
  9. defined('JPATH_PLATFORM') or die();
  10. jimport('joomla.filesystem.path');
  11. /**
  12. * A File handling class
  13. *
  14. * @package Joomla.Platform
  15. * @subpackage FileSystem
  16. * @since 11.1
  17. */
  18. class JFile
  19. {
  20. /**
  21. * Gets the extension of a file name
  22. *
  23. * @param string $file The file name
  24. *
  25. * @return string The file extension
  26. *
  27. * @since 11.1
  28. */
  29. public static function getExt($file)
  30. {
  31. $dot = strrpos($file, '.') + 1;
  32. return substr($file, $dot);
  33. }
  34. /**
  35. * Strips the last extension off of a file name
  36. *
  37. * @param string $file The file name
  38. *
  39. * @return string The file name without the extension
  40. *
  41. * @since 11.1
  42. */
  43. public static function stripExt($file)
  44. {
  45. return preg_replace('#\.[^.]*$#', '', $file);
  46. }
  47. /**
  48. * Makes file name safe to use
  49. *
  50. * @param string $file The name of the file [not full path]
  51. *
  52. * @return string The sanitised string
  53. *
  54. * @since 11.1
  55. */
  56. public static function makeSafe($file)
  57. {
  58. $regex = array('#(\.){2,}#', '#[^A-Za-z0-9\.\_\- ]#', '#^\.#');
  59. return preg_replace($regex, '', $file);
  60. }
  61. /**
  62. * Copies a file
  63. *
  64. * @param string $src The path to the source file
  65. * @param string $dest The path to the destination file
  66. * @param string $path An optional base path to prefix to the file names
  67. * @param boolean $use_streams True to use streams
  68. *
  69. * @return boolean True on success
  70. *
  71. * @since 11.1
  72. */
  73. public static function copy($src, $dest, $path = null, $use_streams = false)
  74. {
  75. // Prepend a base path if it exists
  76. if ($path)
  77. {
  78. $src = JPath::clean($path . '/' . $src);
  79. $dest = JPath::clean($path . '/' . $dest);
  80. }
  81. // Check src path
  82. if (!is_readable($src))
  83. {
  84. JError::raiseWarning(21, JText::sprintf('JLIB_FILESYSTEM_ERROR_JFILE_FIND_COPY', $src));
  85. return false;
  86. }
  87. if ($use_streams)
  88. {
  89. $stream = JFactory::getStream();
  90. if (!$stream->copy($src, $dest))
  91. {
  92. JError::raiseWarning(21, JText::sprintf('JLIB_FILESYSTEM_ERROR_JFILE_STREAMS', $src, $dest, $stream->getError()));
  93. return false;
  94. }
  95. return true;
  96. }
  97. else
  98. {
  99. // Initialise variables.
  100. jimport('joomla.client.helper');
  101. $FTPOptions = JClientHelper::getCredentials('ftp');
  102. if ($FTPOptions['enabled'] == 1)
  103. {
  104. // Connect the FTP client
  105. jimport('joomla.client.ftp');
  106. $ftp = JFTP::getInstance($FTPOptions['host'], $FTPOptions['port'], null, $FTPOptions['user'], $FTPOptions['pass']);
  107. // If the parent folder doesn't exist we must create it
  108. if (!file_exists(dirname($dest)))
  109. {
  110. jimport('joomla.filesystem.folder');
  111. JFolder::create(dirname($dest));
  112. }
  113. // Translate the destination path for the FTP account
  114. $dest = JPath::clean(str_replace(JPATH_ROOT, $FTPOptions['root'], $dest), '/');
  115. if (!$ftp->store($src, $dest))
  116. {
  117. // FTP connector throws an error
  118. return false;
  119. }
  120. $ret = true;
  121. }
  122. else
  123. {
  124. if (!@ copy($src, $dest))
  125. {
  126. JError::raiseWarning(21, JText::_('JLIB_FILESYSTEM_ERROR_COPY_FAILED'));
  127. return false;
  128. }
  129. $ret = true;
  130. }
  131. return $ret;
  132. }
  133. }
  134. /**
  135. * Delete a file or array of files
  136. *
  137. * @param mixed $file The file name or an array of file names
  138. *
  139. * @return boolean True on success
  140. *
  141. * @since 11.1
  142. */
  143. public static function delete($file)
  144. {
  145. // Initialise variables.
  146. jimport('joomla.client.helper');
  147. $FTPOptions = JClientHelper::getCredentials('ftp');
  148. if (is_array($file))
  149. {
  150. $files = $file;
  151. }
  152. else
  153. {
  154. $files[] = $file;
  155. }
  156. // Do NOT use ftp if it is not enabled
  157. if ($FTPOptions['enabled'] == 1)
  158. {
  159. // Connect the FTP client
  160. jimport('joomla.client.ftp');
  161. $ftp = JFTP::getInstance($FTPOptions['host'], $FTPOptions['port'], null, $FTPOptions['user'], $FTPOptions['pass']);
  162. }
  163. foreach ($files as $file)
  164. {
  165. $file = JPath::clean($file);
  166. // Try making the file writeable first. If it's read-only, it can't be deleted
  167. // on Windows, even if the parent folder is writeable
  168. @chmod($file, 0777);
  169. // In case of restricted permissions we zap it one way or the other
  170. // as long as the owner is either the webserver or the ftp
  171. if (@unlink($file))
  172. {
  173. // Do nothing
  174. }
  175. elseif ($FTPOptions['enabled'] == 1)
  176. {
  177. $file = JPath::clean(str_replace(JPATH_ROOT, $FTPOptions['root'], $file), '/');
  178. if (!$ftp->delete($file))
  179. {
  180. // FTP connector throws an error
  181. return false;
  182. }
  183. }
  184. else
  185. {
  186. $filename = basename($file);
  187. JError::raiseWarning('SOME_ERROR_CODE', JText::sprintf('JLIB_FILESYSTEM_DELETE_FAILED', $filename));
  188. return false;
  189. }
  190. }
  191. return true;
  192. }
  193. /**
  194. * Moves a file
  195. *
  196. * @param string $src The path to the source file
  197. * @param string $dest The path to the destination file
  198. * @param string $path An optional base path to prefix to the file names
  199. * @param boolean $use_streams True to use streams
  200. *
  201. * @return boolean True on success
  202. *
  203. * @since 11.1
  204. */
  205. public static function move($src, $dest, $path = '', $use_streams = false)
  206. {
  207. if ($path)
  208. {
  209. $src = JPath::clean($path . '/' . $src);
  210. $dest = JPath::clean($path . '/' . $dest);
  211. }
  212. // Check src path
  213. if (!is_readable($src))
  214. {
  215. return JText::_('JLIB_FILESYSTEM_CANNOT_FIND_SOURCE_FILE');
  216. }
  217. if ($use_streams)
  218. {
  219. $stream = JFactory::getStream();
  220. if (!$stream->move($src, $dest))
  221. {
  222. JError::raiseWarning(21, JText::sprintf('JLIB_FILESYSTEM_ERROR_JFILE_MOVE_STREAMS', $stream->getError()));
  223. return false;
  224. }
  225. return true;
  226. }
  227. else
  228. {
  229. // Initialise variables.
  230. jimport('joomla.client.helper');
  231. $FTPOptions = JClientHelper::getCredentials('ftp');
  232. if ($FTPOptions['enabled'] == 1)
  233. {
  234. // Connect the FTP client
  235. jimport('joomla.client.ftp');
  236. $ftp = JFTP::getInstance($FTPOptions['host'], $FTPOptions['port'], null, $FTPOptions['user'], $FTPOptions['pass']);
  237. // Translate path for the FTP account
  238. $src = JPath::clean(str_replace(JPATH_ROOT, $FTPOptions['root'], $src), '/');
  239. $dest = JPath::clean(str_replace(JPATH_ROOT, $FTPOptions['root'], $dest), '/');
  240. // Use FTP rename to simulate move
  241. if (!$ftp->rename($src, $dest))
  242. {
  243. JError::raiseWarning(21, JText::_('JLIB_FILESYSTEM_ERROR_RENAME_FILE'));
  244. return false;
  245. }
  246. }
  247. else
  248. {
  249. if (!@ rename($src, $dest))
  250. {
  251. JError::raiseWarning(21, JText::_('JLIB_FILESYSTEM_ERROR_RENAME_FILE'));
  252. return false;
  253. }
  254. }
  255. return true;
  256. }
  257. }
  258. /**
  259. * Read the contents of a file
  260. *
  261. * @param string $filename The full file path
  262. * @param boolean $incpath Use include path
  263. * @param integer $amount Amount of file to read
  264. * @param integer $chunksize Size of chunks to read
  265. * @param integer $offset Offset of the file
  266. *
  267. * @return mixed Returns file contents or boolean False if failed
  268. *
  269. * @since 11.1
  270. */
  271. public static function read($filename, $incpath = false, $amount = 0, $chunksize = 8192, $offset = 0)
  272. {
  273. // Initialise variables.
  274. $data = null;
  275. if ($amount && $chunksize > $amount)
  276. {
  277. $chunksize = $amount;
  278. }
  279. if (false === $fh = fopen($filename, 'rb', $incpath))
  280. {
  281. JError::raiseWarning(21, JText::sprintf('JLIB_FILESYSTEM_ERROR_READ_UNABLE_TO_OPEN_FILE', $filename));
  282. return false;
  283. }
  284. clearstatcache();
  285. if ($offset)
  286. {
  287. fseek($fh, $offset);
  288. }
  289. if ($fsize = @ filesize($filename))
  290. {
  291. if ($amount && $fsize > $amount)
  292. {
  293. $data = fread($fh, $amount);
  294. }
  295. else
  296. {
  297. $data = fread($fh, $fsize);
  298. }
  299. }
  300. else
  301. {
  302. $data = '';
  303. $x = 0;
  304. // While it's:
  305. // 1: Not the end of the file AND
  306. // 2a: No Max Amount set OR
  307. // 2b: The length of the data is less than the max amount we want
  308. while (!feof($fh) && (!$amount || strlen($data) < $amount))
  309. {
  310. $data .= fread($fh, $chunksize);
  311. }
  312. }
  313. fclose($fh);
  314. return $data;
  315. }
  316. /**
  317. * Write contents to a file
  318. *
  319. * @param string $file The full file path
  320. * @param string &$buffer The buffer to write
  321. * @param boolean $use_streams Use streams
  322. *
  323. * @return boolean True on success
  324. *
  325. * @since 11.1
  326. */
  327. public static function write($file, &$buffer, $use_streams = false)
  328. {
  329. @set_time_limit(ini_get('max_execution_time'));
  330. // If the destination directory doesn't exist we need to create it
  331. if (!file_exists(dirname($file)))
  332. {
  333. jimport('joomla.filesystem.folder');
  334. JFolder::create(dirname($file));
  335. }
  336. if ($use_streams)
  337. {
  338. $stream = JFactory::getStream();
  339. // Beef up the chunk size to a meg
  340. $stream->set('chunksize', (1024 * 1024 * 1024));
  341. if (!$stream->writeFile($file, $buffer))
  342. {
  343. JError::raiseWarning(21, JText::sprintf('JLIB_FILESYSTEM_ERROR_WRITE_STREAMS', $file, $stream->getError()));
  344. return false;
  345. }
  346. return true;
  347. }
  348. else
  349. {
  350. // Initialise variables.
  351. jimport('joomla.client.helper');
  352. $FTPOptions = JClientHelper::getCredentials('ftp');
  353. if ($FTPOptions['enabled'] == 1)
  354. {
  355. // Connect the FTP client
  356. jimport('joomla.client.ftp');
  357. $ftp = JFTP::getInstance($FTPOptions['host'], $FTPOptions['port'], null, $FTPOptions['user'], $FTPOptions['pass']);
  358. // Translate path for the FTP account and use FTP write buffer to file
  359. $file = JPath::clean(str_replace(JPATH_ROOT, $FTPOptions['root'], $file), '/');
  360. $ret = $ftp->write($file, $buffer);
  361. }
  362. else
  363. {
  364. $file = JPath::clean($file);
  365. $ret = is_int(file_put_contents($file, $buffer)) ? true : false;
  366. }
  367. return $ret;
  368. }
  369. }
  370. /**
  371. * Moves an uploaded file to a destination folder
  372. *
  373. * @param string $src The name of the php (temporary) uploaded file
  374. * @param string $dest The path (including filename) to move the uploaded file to
  375. * @param boolean $use_streams True to use streams
  376. *
  377. * @return boolean True on success
  378. *
  379. * @since 11.1
  380. */
  381. public static function upload($src, $dest, $use_streams = false)
  382. {
  383. // Ensure that the path is valid and clean
  384. $dest = JPath::clean($dest);
  385. // Create the destination directory if it does not exist
  386. $baseDir = dirname($dest);
  387. if (!file_exists($baseDir))
  388. {
  389. jimport('joomla.filesystem.folder');
  390. JFolder::create($baseDir);
  391. }
  392. if ($use_streams)
  393. {
  394. $stream = JFactory::getStream();
  395. if (!$stream->upload($src, $dest))
  396. {
  397. JError::raiseWarning(21, JText::sprintf('JLIB_FILESYSTEM_ERROR_UPLOAD', $stream->getError()));
  398. return false;
  399. }
  400. return true;
  401. }
  402. else
  403. {
  404. // Initialise variables.
  405. jimport('joomla.client.helper');
  406. $FTPOptions = JClientHelper::getCredentials('ftp');
  407. $ret = false;
  408. if ($FTPOptions['enabled'] == 1)
  409. {
  410. // Connect the FTP client
  411. jimport('joomla.client.ftp');
  412. $ftp = JFTP::getInstance($FTPOptions['host'], $FTPOptions['port'], null, $FTPOptions['user'], $FTPOptions['pass']);
  413. // Translate path for the FTP account
  414. $dest = JPath::clean(str_replace(JPATH_ROOT, $FTPOptions['root'], $dest), '/');
  415. // Copy the file to the destination directory
  416. if (is_uploaded_file($src) && $ftp->store($src, $dest))
  417. {
  418. unlink($src);
  419. $ret = true;
  420. }
  421. else
  422. {
  423. JError::raiseWarning(21, JText::_('JLIB_FILESYSTEM_ERROR_WARNFS_ERR02'));
  424. }
  425. }
  426. else
  427. {
  428. if (is_writeable($baseDir) && move_uploaded_file($src, $dest))
  429. { // Short circuit to prevent file permission errors
  430. if (JPath::setPermissions($dest))
  431. {
  432. $ret = true;
  433. }
  434. else
  435. {
  436. JError::raiseWarning(21, JText::_('JLIB_FILESYSTEM_ERROR_WARNFS_ERR01'));
  437. }
  438. }
  439. else
  440. {
  441. JError::raiseWarning(21, JText::_('JLIB_FILESYSTEM_ERROR_WARNFS_ERR02'));
  442. }
  443. }
  444. return $ret;
  445. }
  446. }
  447. /**
  448. * Wrapper for the standard file_exists function
  449. *
  450. * @param string $file File path
  451. *
  452. * @return boolean True if path is a file
  453. *
  454. * @since 11.1
  455. */
  456. public static function exists($file)
  457. {
  458. return is_file(JPath::clean($file));
  459. }
  460. /**
  461. * Returns the name, without any path.
  462. *
  463. * @param string $file File path
  464. *
  465. * @return string filename
  466. *
  467. * @since 11.1
  468. */
  469. public static function getName($file)
  470. {
  471. // Convert back slashes to forward slashes
  472. $file = str_replace('\\', '/', $file);
  473. $slash = strrpos($file, '/');
  474. if ($slash !== false)
  475. {
  476. return substr($file, $slash + 1);
  477. }
  478. else
  479. {
  480. return $file;
  481. }
  482. }
  483. }