PageRenderTime 56ms CodeModel.GetById 24ms RepoModel.GetById 1ms app.codeStats 0ms

/libraries/chola/filesystem/file.php

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