blob: 70d7fc897194b3fd8f6c3feed851723efb2de014 [file] [log] [blame]
Derek Jones37f4b9c2011-07-01 17:56:50 -05001<?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
8 *
9 * Licensed under the Open Software License version 3.0
10 *
11 * 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
41 var $hostname = '';
42 var $username = '';
43 var $password = '';
44 var $port = 21;
45 var $passive = TRUE;
46 var $debug = FALSE;
47 var $conn_id = FALSE;
48
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 */
74 function initialize($config = array())
75 {
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 */
97 function connect($config = array())
98 {
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 */
139 function _login()
140 {
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 */
152 function _is_conn()
153 {
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 */
182 function changedir($path = '', $supress_debug = FALSE)
183 {
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 */
212 function mkdir($path = '', $permissions = NULL)
213 {
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 */
250 function upload($locpath, $rempath, $mode = 'auto', $permissions = NULL)
251 {
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
264 if ($mode == 'auto')
265 {
266 // Get the file extension so we can set the upload type
267 $ext = $this->_getext($locpath);
268 $mode = $this->_settype($ext);
269 }
270
271 $mode = ($mode == 'ascii') ? FTP_ASCII : FTP_BINARY;
272
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 */
304 function download($rempath, $locpath, $mode = 'auto')
305 {
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
312 if ($mode == 'auto')
313 {
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
Phil Sturgeon28b29372010-03-12 00:43:28 +0000319 $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 */
346 function rename($old_file, $new_file, $move = FALSE)
347 {
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 {
359 $msg = ($move == FALSE) ? 'ftp_unable_to_rename' : 'ftp_unable_to_move';
360
361 $this->_error($msg);
362 }
363 return FALSE;
364 }
365
366 return TRUE;
367 }
368
369 // --------------------------------------------------------------------
370
371 /**
372 * Move a file
373 *
374 * @access public
375 * @param string
376 * @param string
377 * @return bool
378 */
379 function move($old_file, $new_file)
380 {
381 return $this->rename($old_file, $new_file, TRUE);
382 }
383
384 // --------------------------------------------------------------------
385
386 /**
387 * Rename (or move) a file
388 *
389 * @access public
390 * @param string
391 * @return bool
392 */
393 function delete_file($filepath)
394 {
395 if ( ! $this->_is_conn())
396 {
397 return FALSE;
398 }
399
400 $result = @ftp_delete($this->conn_id, $filepath);
401
402 if ($result === FALSE)
403 {
404 if ($this->debug == TRUE)
405 {
406 $this->_error('ftp_unable_to_delete');
407 }
408 return FALSE;
409 }
410
411 return TRUE;
412 }
413
414 // --------------------------------------------------------------------
415
416 /**
417 * Delete a folder and recursively delete everything (including sub-folders)
418 * containted within it.
419 *
420 * @access public
421 * @param string
422 * @return bool
423 */
424 function delete_dir($filepath)
425 {
426 if ( ! $this->_is_conn())
427 {
428 return FALSE;
429 }
430
431 // Add a trailing slash to the file path if needed
Derek Jones37f4b9c2011-07-01 17:56:50 -0500432 $filepath = preg_replace("/(.+?)\/*$/", "\\1/", $filepath);
Derek Allard2067d1a2008-11-13 22:59:24 +0000433
434 $list = $this->list_files($filepath);
435
436 if ($list !== FALSE AND count($list) > 0)
437 {
438 foreach ($list as $item)
439 {
440 // If we can't delete the item it's probaly a folder so
441 // we'll recursively call delete_dir()
442 if ( ! @ftp_delete($this->conn_id, $item))
443 {
444 $this->delete_dir($item);
445 }
446 }
447 }
448
449 $result = @ftp_rmdir($this->conn_id, $filepath);
450
451 if ($result === FALSE)
452 {
453 if ($this->debug == TRUE)
454 {
455 $this->_error('ftp_unable_to_delete');
456 }
457 return FALSE;
458 }
459
460 return TRUE;
461 }
462
463 // --------------------------------------------------------------------
464
465 /**
466 * Set file permissions
467 *
468 * @access public
Barry Mienydd671972010-10-04 16:33:58 +0200469 * @param string the file path
Derek Allard2067d1a2008-11-13 22:59:24 +0000470 * @param string the permissions
471 * @return bool
472 */
473 function chmod($path, $perm)
474 {
475 if ( ! $this->_is_conn())
476 {
477 return FALSE;
478 }
479
480 // Permissions can only be set when running PHP 5
481 if ( ! function_exists('ftp_chmod'))
482 {
483 if ($this->debug == TRUE)
484 {
485 $this->_error('ftp_unable_to_chmod');
486 }
487 return FALSE;
488 }
489
490 $result = @ftp_chmod($this->conn_id, $perm, $path);
491
492 if ($result === FALSE)
493 {
494 if ($this->debug == TRUE)
495 {
496 $this->_error('ftp_unable_to_chmod');
497 }
498 return FALSE;
499 }
500
501 return TRUE;
502 }
503
504 // --------------------------------------------------------------------
505
506 /**
507 * FTP List files in the specified directory
508 *
509 * @access public
510 * @return array
511 */
512 function list_files($path = '.')
513 {
514 if ( ! $this->_is_conn())
515 {
516 return FALSE;
517 }
518
519 return ftp_nlist($this->conn_id, $path);
520 }
521
522 // ------------------------------------------------------------------------
523
524 /**
525 * Read a directory and recreate it remotely
526 *
527 * This function recursively reads a folder and everything it contains (including
Derek Jones37f4b9c2011-07-01 17:56:50 -0500528 * sub-folders) and creates a mirror via FTP based on it. Whatever the directory structure
Derek Allard2067d1a2008-11-13 22:59:24 +0000529 * of the original file path will be recreated on the server.
530 *
531 * @access public
532 * @param string path to source with trailing slash
533 * @param string path to destination - include the base folder with trailing slash
534 * @return bool
535 */
536 function mirror($locpath, $rempath)
537 {
538 if ( ! $this->_is_conn())
539 {
540 return FALSE;
541 }
542
543 // Open the local file path
544 if ($fp = @opendir($locpath))
545 {
546 // Attempt to open the remote file path.
547 if ( ! $this->changedir($rempath, TRUE))
548 {
549 // If it doesn't exist we'll attempt to create the direcotory
550 if ( ! $this->mkdir($rempath) OR ! $this->changedir($rempath))
551 {
552 return FALSE;
553 }
554 }
555
556 // Recursively read the local directory
557 while (FALSE !== ($file = readdir($fp)))
558 {
559 if (@is_dir($locpath.$file) && substr($file, 0, 1) != '.')
560 {
561 $this->mirror($locpath.$file."/", $rempath.$file."/");
562 }
563 elseif (substr($file, 0, 1) != ".")
564 {
565 // Get the file extension so we can se the upload type
566 $ext = $this->_getext($file);
567 $mode = $this->_settype($ext);
568
569 $this->upload($locpath.$file, $rempath.$file, $mode);
570 }
571 }
572 return TRUE;
573 }
574
575 return FALSE;
576 }
577
578
579 // --------------------------------------------------------------------
580
581 /**
582 * Extract the file extension
583 *
584 * @access private
585 * @param string
586 * @return string
587 */
588 function _getext($filename)
589 {
590 if (FALSE === strpos($filename, '.'))
591 {
592 return 'txt';
593 }
594
595 $x = explode('.', $filename);
596 return end($x);
597 }
598
599
600 // --------------------------------------------------------------------
601
602 /**
603 * Set the upload type
604 *
605 * @access private
606 * @param string
607 * @return string
608 */
609 function _settype($ext)
610 {
611 $text_types = array(
612 'txt',
613 'text',
614 'php',
615 'phps',
616 'php4',
617 'js',
618 'css',
619 'htm',
620 'html',
621 'phtml',
622 'shtml',
623 'log',
624 'xml'
625 );
626
627
628 return (in_array($ext, $text_types)) ? 'ascii' : 'binary';
629 }
630
631 // ------------------------------------------------------------------------
632
633 /**
634 * Close the connection
635 *
636 * @access public
637 * @param string path to source
638 * @param string path to destination
639 * @return bool
640 */
641 function close()
642 {
643 if ( ! $this->_is_conn())
644 {
645 return FALSE;
646 }
647
648 @ftp_close($this->conn_id);
649 }
650
651 // ------------------------------------------------------------------------
652
653 /**
654 * Display error message
655 *
656 * @access private
657 * @param string
658 * @return bool
659 */
660 function _error($line)
661 {
662 $CI =& get_instance();
663 $CI->lang->load('ftp');
664 show_error($CI->lang->line($line));
665 }
666
667
668}
669// END FTP Class
670
671/* End of file Ftp.php */
Derek Jonesa3ffbbb2008-05-11 18:18:29 +0000672/* Location: ./system/libraries/Ftp.php */