blob: 99850a9e5e892dc9fa784f70e2aa63b3e414f073 [file] [log] [blame]
Andrey Andreev0a75d6e2011-12-22 19:45:33 +02001<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
Derek Allard2067d1a2008-11-13 22:59:24 +00002/**
3 * CodeIgniter
4 *
Greg Aker741de1c2010-11-10 14:52:57 -06005 * An open source application development framework for PHP 5.1.6 or newer
Derek Allard2067d1a2008-11-13 22:59:24 +00006 *
Derek Jonesf4a4bd82011-10-20 12:18:42 -05007 * NOTICE OF LICENSE
Andrey Andreev0a75d6e2011-12-22 19:45:33 +02008 *
Derek Jonesf4a4bd82011-10-20 12:18:42 -05009 * Licensed under the Open Software License version 3.0
Andrey Andreev0a75d6e2011-12-22 19:45:33 +020010 *
Derek Jonesf4a4bd82011-10-20 12:18:42 -050011 * This source file is subject to the Open Software License (OSL 3.0) that is
12 * bundled with this package in the files license.txt / license.rst. It is
13 * also available through the world wide web at this URL:
14 * http://opensource.org/licenses/OSL-3.0
15 * If you did not receive a copy of the license and are unable to obtain it
16 * through the world wide web, please send an email to
17 * licensing@ellislab.com so we can send you a copy immediately.
18 *
Derek Allard2067d1a2008-11-13 22:59:24 +000019 * @package CodeIgniter
Derek Jonesf4a4bd82011-10-20 12:18:42 -050020 * @author EllisLab Dev Team
21 * @copyright Copyright (c) 2008 - 2011, EllisLab, Inc. (http://ellislab.com/)
22 * @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
Derek Allard2067d1a2008-11-13 22:59:24 +000023 * @link http://codeigniter.com
24 * @since Version 1.0
25 * @filesource
26 */
27
28// ------------------------------------------------------------------------
29
30/**
31 * FTP Class
32 *
33 * @package CodeIgniter
34 * @subpackage Libraries
35 * @category Libraries
Derek Jonesf4a4bd82011-10-20 12:18:42 -050036 * @author EllisLab Dev Team
Derek Allard2067d1a2008-11-13 22:59:24 +000037 * @link http://codeigniter.com/user_guide/libraries/ftp.html
38 */
39class CI_FTP {
40
Andrey Andreev0a75d6e2011-12-22 19:45:33 +020041 public $hostname = '';
42 public $username = '';
43 public $password = '';
44 public $port = 21;
45 public $passive = TRUE;
46 public $debug = FALSE;
47 public $conn_id = FALSE;
Derek Allard2067d1a2008-11-13 22:59:24 +000048
49
50 /**
51 * Constructor - Sets Preferences
52 *
53 * The constructor can be passed an array of config values
54 */
Greg Akera9263282010-11-10 15:26:43 -060055 public function __construct($config = array())
Derek Allard2067d1a2008-11-13 22:59:24 +000056 {
57 if (count($config) > 0)
58 {
59 $this->initialize($config);
60 }
61
62 log_message('debug', "FTP Class Initialized");
63 }
64
65 // --------------------------------------------------------------------
66
67 /**
68 * Initialize preferences
69 *
70 * @access public
71 * @param array
72 * @return void
73 */
Andrey Andreev0a75d6e2011-12-22 19:45:33 +020074 public function initialize($config = array())
Derek Allard2067d1a2008-11-13 22:59:24 +000075 {
76 foreach ($config as $key => $val)
77 {
78 if (isset($this->$key))
79 {
80 $this->$key = $val;
81 }
82 }
83
84 // Prep the hostname
85 $this->hostname = preg_replace('|.+?://|', '', $this->hostname);
86 }
87
88 // --------------------------------------------------------------------
89
90 /**
91 * FTP Connect
92 *
93 * @access public
94 * @param array the connection values
95 * @return bool
96 */
Andrey Andreev0a75d6e2011-12-22 19:45:33 +020097 public function connect($config = array())
Derek Allard2067d1a2008-11-13 22:59:24 +000098 {
99 if (count($config) > 0)
100 {
101 $this->initialize($config);
102 }
103
104 if (FALSE === ($this->conn_id = @ftp_connect($this->hostname, $this->port)))
105 {
106 if ($this->debug == TRUE)
107 {
108 $this->_error('ftp_unable_to_connect');
109 }
110 return FALSE;
111 }
112
113 if ( ! $this->_login())
114 {
115 if ($this->debug == TRUE)
116 {
117 $this->_error('ftp_unable_to_login');
118 }
119 return FALSE;
120 }
121
122 // Set passive mode if needed
123 if ($this->passive == TRUE)
124 {
125 ftp_pasv($this->conn_id, TRUE);
126 }
127
128 return TRUE;
129 }
130
131 // --------------------------------------------------------------------
132
133 /**
134 * FTP Login
135 *
136 * @access private
137 * @return bool
138 */
Andrey Andreev0a75d6e2011-12-22 19:45:33 +0200139 private function _login()
Derek Allard2067d1a2008-11-13 22:59:24 +0000140 {
141 return @ftp_login($this->conn_id, $this->username, $this->password);
142 }
143
144 // --------------------------------------------------------------------
145
146 /**
147 * Validates the connection ID
148 *
149 * @access private
150 * @return bool
151 */
Andrey Andreev0a75d6e2011-12-22 19:45:33 +0200152 private function _is_conn()
Derek Allard2067d1a2008-11-13 22:59:24 +0000153 {
154 if ( ! is_resource($this->conn_id))
155 {
156 if ($this->debug == TRUE)
157 {
158 $this->_error('ftp_no_connection');
159 }
160 return FALSE;
161 }
162 return TRUE;
163 }
164
165 // --------------------------------------------------------------------
166
167
168 /**
Derek Allarda14ab122009-07-13 12:01:01 +0000169 * Change directory
Derek Allard2067d1a2008-11-13 22:59:24 +0000170 *
171 * The second parameter lets us momentarily turn off debugging so that
Derek Allarda14ab122009-07-13 12:01:01 +0000172 * this function can be used to test for the existence of a folder
Derek Jones37f4b9c2011-07-01 17:56:50 -0500173 * without throwing an error. There's no FTP equivalent to is_dir()
Derek Allard2067d1a2008-11-13 22:59:24 +0000174 * so we do it by trying to change to a particular directory.
Derek Allarda14ab122009-07-13 12:01:01 +0000175 * Internally, this parameter is only used by the "mirror" function below.
Derek Allard2067d1a2008-11-13 22:59:24 +0000176 *
177 * @access public
178 * @param string
179 * @param bool
180 * @return bool
181 */
Andrey Andreev0a75d6e2011-12-22 19:45:33 +0200182 public function changedir($path = '', $supress_debug = FALSE)
Derek Allard2067d1a2008-11-13 22:59:24 +0000183 {
184 if ($path == '' OR ! $this->_is_conn())
185 {
186 return FALSE;
187 }
188
189 $result = @ftp_chdir($this->conn_id, $path);
190
191 if ($result === FALSE)
192 {
193 if ($this->debug == TRUE AND $supress_debug == FALSE)
194 {
195 $this->_error('ftp_unable_to_changedir');
196 }
197 return FALSE;
198 }
199
200 return TRUE;
201 }
202
203 // --------------------------------------------------------------------
204
205 /**
206 * Create a directory
207 *
208 * @access public
209 * @param string
210 * @return bool
211 */
Andrey Andreev0a75d6e2011-12-22 19:45:33 +0200212 public function mkdir($path = '', $permissions = NULL)
Derek Allard2067d1a2008-11-13 22:59:24 +0000213 {
214 if ($path == '' OR ! $this->_is_conn())
215 {
216 return FALSE;
217 }
218
219 $result = @ftp_mkdir($this->conn_id, $path);
220
221 if ($result === FALSE)
222 {
223 if ($this->debug == TRUE)
224 {
225 $this->_error('ftp_unable_to_makdir');
226 }
227 return FALSE;
228 }
229
230 // Set file permissions if needed
231 if ( ! is_null($permissions))
232 {
233 $this->chmod($path, (int)$permissions);
234 }
235
236 return TRUE;
237 }
238
239 // --------------------------------------------------------------------
240
241 /**
242 * Upload a file to the server
243 *
244 * @access public
245 * @param string
246 * @param string
247 * @param string
248 * @return bool
249 */
Andrey Andreev0a75d6e2011-12-22 19:45:33 +0200250 public function upload($locpath, $rempath, $mode = 'auto', $permissions = NULL)
Derek Allard2067d1a2008-11-13 22:59:24 +0000251 {
252 if ( ! $this->_is_conn())
253 {
254 return FALSE;
255 }
256
257 if ( ! file_exists($locpath))
258 {
259 $this->_error('ftp_no_source_file');
260 return FALSE;
261 }
262
263 // Set the mode if not specified
Andrey Andreev0a75d6e2011-12-22 19:45:33 +0200264 if ($mode === 'auto')
Derek Allard2067d1a2008-11-13 22:59:24 +0000265 {
266 // Get the file extension so we can set the upload type
267 $ext = $this->_getext($locpath);
268 $mode = $this->_settype($ext);
269 }
270
Andrey Andreev0a75d6e2011-12-22 19:45:33 +0200271 $mode = ($mode === 'ascii') ? FTP_ASCII : FTP_BINARY;
Derek Allard2067d1a2008-11-13 22:59:24 +0000272
273 $result = @ftp_put($this->conn_id, $rempath, $locpath, $mode);
274
275 if ($result === FALSE)
276 {
277 if ($this->debug == TRUE)
278 {
279 $this->_error('ftp_unable_to_upload');
280 }
281 return FALSE;
282 }
283
284 // Set file permissions if needed
285 if ( ! is_null($permissions))
286 {
287 $this->chmod($rempath, (int)$permissions);
288 }
289
290 return TRUE;
291 }
292
293 // --------------------------------------------------------------------
294
295 /**
Phil Sturgeon28b29372010-03-12 00:43:28 +0000296 * Download a file from a remote server to the local server
297 *
298 * @access public
299 * @param string
300 * @param string
301 * @param string
302 * @return bool
303 */
Andrey Andreev0a75d6e2011-12-22 19:45:33 +0200304 public function download($rempath, $locpath, $mode = 'auto')
Phil Sturgeon28b29372010-03-12 00:43:28 +0000305 {
306 if ( ! $this->_is_conn())
307 {
308 return FALSE;
309 }
Barry Mienydd671972010-10-04 16:33:58 +0200310
Phil Sturgeon28b29372010-03-12 00:43:28 +0000311 // Set the mode if not specified
Andrey Andreev0a75d6e2011-12-22 19:45:33 +0200312 if ($mode === 'auto')
Phil Sturgeon28b29372010-03-12 00:43:28 +0000313 {
314 // Get the file extension so we can set the upload type
315 $ext = $this->_getext($rempath);
316 $mode = $this->_settype($ext);
317 }
Barry Mienydd671972010-10-04 16:33:58 +0200318
Andrey Andreev0a75d6e2011-12-22 19:45:33 +0200319 $mode = ($mode === 'ascii') ? FTP_ASCII : FTP_BINARY;
Barry Mienydd671972010-10-04 16:33:58 +0200320
Phil Sturgeon28b29372010-03-12 00:43:28 +0000321 $result = @ftp_get($this->conn_id, $locpath, $rempath, $mode);
322
323 if ($result === FALSE)
324 {
325 if ($this->debug == TRUE)
326 {
327 $this->_error('ftp_unable_to_download');
328 }
Barry Mienydd671972010-10-04 16:33:58 +0200329 return FALSE;
Phil Sturgeon28b29372010-03-12 00:43:28 +0000330 }
Barry Mienydd671972010-10-04 16:33:58 +0200331
Phil Sturgeon28b29372010-03-12 00:43:28 +0000332 return TRUE;
Barry Mienydd671972010-10-04 16:33:58 +0200333 }
Phil Sturgeon28b29372010-03-12 00:43:28 +0000334
335 // --------------------------------------------------------------------
336
337 /**
Derek Allard2067d1a2008-11-13 22:59:24 +0000338 * Rename (or move) a file
339 *
340 * @access public
341 * @param string
342 * @param string
343 * @param bool
344 * @return bool
345 */
Andrey Andreev0a75d6e2011-12-22 19:45:33 +0200346 public function rename($old_file, $new_file, $move = FALSE)
Derek Allard2067d1a2008-11-13 22:59:24 +0000347 {
348 if ( ! $this->_is_conn())
349 {
350 return FALSE;
351 }
352
353 $result = @ftp_rename($this->conn_id, $old_file, $new_file);
354
355 if ($result === FALSE)
356 {
357 if ($this->debug == TRUE)
358 {
Andrey Andreev0a75d6e2011-12-22 19:45:33 +0200359 $this->_error('ftp_unable_to_' . ($move == FALSE ? 'rename' : 'move'));
Derek Allard2067d1a2008-11-13 22:59:24 +0000360 }
361 return FALSE;
362 }
363
364 return TRUE;
365 }
366
367 // --------------------------------------------------------------------
368
369 /**
370 * Move a file
371 *
372 * @access public
373 * @param string
374 * @param string
375 * @return bool
376 */
Andrey Andreev0a75d6e2011-12-22 19:45:33 +0200377 public function move($old_file, $new_file)
Derek Allard2067d1a2008-11-13 22:59:24 +0000378 {
379 return $this->rename($old_file, $new_file, TRUE);
380 }
381
382 // --------------------------------------------------------------------
383
384 /**
385 * Rename (or move) a file
386 *
387 * @access public
388 * @param string
389 * @return bool
390 */
Andrey Andreev0a75d6e2011-12-22 19:45:33 +0200391 public function delete_file($filepath)
Derek Allard2067d1a2008-11-13 22:59:24 +0000392 {
393 if ( ! $this->_is_conn())
394 {
395 return FALSE;
396 }
397
398 $result = @ftp_delete($this->conn_id, $filepath);
399
400 if ($result === FALSE)
401 {
402 if ($this->debug == TRUE)
403 {
404 $this->_error('ftp_unable_to_delete');
405 }
406 return FALSE;
407 }
408
409 return TRUE;
410 }
411
412 // --------------------------------------------------------------------
413
414 /**
415 * Delete a folder and recursively delete everything (including sub-folders)
416 * containted within it.
417 *
418 * @access public
419 * @param string
420 * @return bool
421 */
Andrey Andreev0a75d6e2011-12-22 19:45:33 +0200422 public function delete_dir($filepath)
Derek Allard2067d1a2008-11-13 22:59:24 +0000423 {
424 if ( ! $this->_is_conn())
425 {
426 return FALSE;
427 }
428
429 // Add a trailing slash to the file path if needed
Derek Jones37f4b9c2011-07-01 17:56:50 -0500430 $filepath = preg_replace("/(.+?)\/*$/", "\\1/", $filepath);
Derek Allard2067d1a2008-11-13 22:59:24 +0000431
432 $list = $this->list_files($filepath);
433
434 if ($list !== FALSE AND count($list) > 0)
435 {
436 foreach ($list as $item)
437 {
438 // If we can't delete the item it's probaly a folder so
439 // we'll recursively call delete_dir()
440 if ( ! @ftp_delete($this->conn_id, $item))
441 {
442 $this->delete_dir($item);
443 }
444 }
445 }
446
447 $result = @ftp_rmdir($this->conn_id, $filepath);
448
449 if ($result === FALSE)
450 {
451 if ($this->debug == TRUE)
452 {
453 $this->_error('ftp_unable_to_delete');
454 }
455 return FALSE;
456 }
457
458 return TRUE;
459 }
460
461 // --------------------------------------------------------------------
462
463 /**
464 * Set file permissions
465 *
466 * @access public
Barry Mienydd671972010-10-04 16:33:58 +0200467 * @param string the file path
Derek Allard2067d1a2008-11-13 22:59:24 +0000468 * @param string the permissions
469 * @return bool
470 */
Andrey Andreev0a75d6e2011-12-22 19:45:33 +0200471 public function chmod($path, $perm)
Derek Allard2067d1a2008-11-13 22:59:24 +0000472 {
473 if ( ! $this->_is_conn())
474 {
475 return FALSE;
476 }
477
Derek Allard2067d1a2008-11-13 22:59:24 +0000478 $result = @ftp_chmod($this->conn_id, $perm, $path);
479
480 if ($result === FALSE)
481 {
482 if ($this->debug == TRUE)
483 {
484 $this->_error('ftp_unable_to_chmod');
485 }
486 return FALSE;
487 }
488
489 return TRUE;
490 }
491
492 // --------------------------------------------------------------------
493
494 /**
495 * FTP List files in the specified directory
496 *
497 * @access public
498 * @return array
499 */
Andrey Andreev0a75d6e2011-12-22 19:45:33 +0200500 public function list_files($path = '.')
Derek Allard2067d1a2008-11-13 22:59:24 +0000501 {
502 if ( ! $this->_is_conn())
503 {
504 return FALSE;
505 }
506
507 return ftp_nlist($this->conn_id, $path);
508 }
509
510 // ------------------------------------------------------------------------
511
512 /**
513 * Read a directory and recreate it remotely
514 *
515 * This function recursively reads a folder and everything it contains (including
Derek Jones37f4b9c2011-07-01 17:56:50 -0500516 * sub-folders) and creates a mirror via FTP based on it. Whatever the directory structure
Derek Allard2067d1a2008-11-13 22:59:24 +0000517 * of the original file path will be recreated on the server.
518 *
519 * @access public
520 * @param string path to source with trailing slash
521 * @param string path to destination - include the base folder with trailing slash
522 * @return bool
523 */
Andrey Andreev0a75d6e2011-12-22 19:45:33 +0200524 public function mirror($locpath, $rempath)
Derek Allard2067d1a2008-11-13 22:59:24 +0000525 {
526 if ( ! $this->_is_conn())
527 {
528 return FALSE;
529 }
530
531 // Open the local file path
532 if ($fp = @opendir($locpath))
533 {
Andrey Andreev0a75d6e2011-12-22 19:45:33 +0200534 // Attempt to open the remote file path and try to create it, if it doesn't exist
535 if ( ! $this->changedir($rempath, TRUE) AND ( ! $this->mkdir($rempath) OR ! $this->changedir($rempath)))
Derek Allard2067d1a2008-11-13 22:59:24 +0000536 {
Andrey Andreev0a75d6e2011-12-22 19:45:33 +0200537 return FALSE;
Derek Allard2067d1a2008-11-13 22:59:24 +0000538 }
539
540 // Recursively read the local directory
541 while (FALSE !== ($file = readdir($fp)))
542 {
Andrey Andreev0a75d6e2011-12-22 19:45:33 +0200543 if (@is_dir($locpath.$file) && $file[0] !== '.')
Derek Allard2067d1a2008-11-13 22:59:24 +0000544 {
545 $this->mirror($locpath.$file."/", $rempath.$file."/");
546 }
Andrey Andreev0a75d6e2011-12-22 19:45:33 +0200547 elseif ($file[0] !== ".")
Derek Allard2067d1a2008-11-13 22:59:24 +0000548 {
549 // Get the file extension so we can se the upload type
550 $ext = $this->_getext($file);
551 $mode = $this->_settype($ext);
552
553 $this->upload($locpath.$file, $rempath.$file, $mode);
554 }
555 }
556 return TRUE;
557 }
558
559 return FALSE;
560 }
561
562
563 // --------------------------------------------------------------------
564
565 /**
566 * Extract the file extension
567 *
568 * @access private
569 * @param string
570 * @return string
571 */
Andrey Andreev0a75d6e2011-12-22 19:45:33 +0200572 private function _getext($filename)
Derek Allard2067d1a2008-11-13 22:59:24 +0000573 {
574 if (FALSE === strpos($filename, '.'))
575 {
576 return 'txt';
577 }
578
579 $x = explode('.', $filename);
580 return end($x);
581 }
582
583
584 // --------------------------------------------------------------------
585
586 /**
587 * Set the upload type
588 *
589 * @access private
590 * @param string
591 * @return string
592 */
Andrey Andreev0a75d6e2011-12-22 19:45:33 +0200593 private function _settype($ext)
Derek Allard2067d1a2008-11-13 22:59:24 +0000594 {
595 $text_types = array(
596 'txt',
597 'text',
598 'php',
599 'phps',
600 'php4',
601 'js',
602 'css',
603 'htm',
604 'html',
605 'phtml',
606 'shtml',
607 'log',
608 'xml'
609 );
610
611
612 return (in_array($ext, $text_types)) ? 'ascii' : 'binary';
613 }
614
615 // ------------------------------------------------------------------------
616
617 /**
618 * Close the connection
619 *
620 * @access public
Derek Allard2067d1a2008-11-13 22:59:24 +0000621 * @return bool
622 */
Andrey Andreev0a75d6e2011-12-22 19:45:33 +0200623 public function close()
Derek Allard2067d1a2008-11-13 22:59:24 +0000624 {
625 if ( ! $this->_is_conn())
626 {
627 return FALSE;
628 }
629
Andrey Andreev0a75d6e2011-12-22 19:45:33 +0200630 return @ftp_close($this->conn_id);
Derek Allard2067d1a2008-11-13 22:59:24 +0000631 }
632
633 // ------------------------------------------------------------------------
634
635 /**
636 * Display error message
637 *
638 * @access private
639 * @param string
Andrey Andreev0a75d6e2011-12-22 19:45:33 +0200640 * @return void
Derek Allard2067d1a2008-11-13 22:59:24 +0000641 */
Andrey Andreev0a75d6e2011-12-22 19:45:33 +0200642 private function _error($line)
Derek Allard2067d1a2008-11-13 22:59:24 +0000643 {
644 $CI =& get_instance();
645 $CI->lang->load('ftp');
646 show_error($CI->lang->line($line));
647 }
648
649
650}
651// END FTP Class
652
653/* End of file Ftp.php */
Andrey Andreev0a75d6e2011-12-22 19:45:33 +0200654/* Location: ./system/libraries/Ftp.php */