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