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

/libraries/joomla/filesystem/file.php

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