Remove file execution permission.
[living-lab-site.git] / system / libraries / Ftp.php
1 <?php  if ( ! defined('BASEPATH')) exit('No direct script access allowed');
2 /**
3  * CodeIgniter
4  *
5  * An open source application development framework for PHP 5.1.6 or newer
6  *
7  * @package             CodeIgniter
8  * @author              ExpressionEngine Dev Team
9  * @copyright   Copyright (c) 2008 - 2011, EllisLab, Inc.
10  * @license             http://codeigniter.com/user_guide/license.html
11  * @link                http://codeigniter.com
12  * @since               Version 1.0
13  * @filesource
14  */
15
16 // ------------------------------------------------------------------------
17
18 /**
19  * FTP Class
20  *
21  * @package             CodeIgniter
22  * @subpackage  Libraries
23  * @category    Libraries
24  * @author              ExpressionEngine Dev Team
25  * @link                http://codeigniter.com/user_guide/libraries/ftp.html
26  */
27 class CI_FTP {
28
29         var $hostname   = '';
30         var $username   = '';
31         var $password   = '';
32         var $port               = 21;
33         var $passive    = TRUE;
34         var $debug              = FALSE;
35         var $conn_id    = FALSE;
36
37
38         /**
39          * Constructor - Sets Preferences
40          *
41          * The constructor can be passed an array of config values
42          */
43         public function __construct($config = array())
44         {
45                 if (count($config) > 0)
46                 {
47                         $this->initialize($config);
48                 }
49
50                 log_message('debug', "FTP Class Initialized");
51         }
52
53         // --------------------------------------------------------------------
54
55         /**
56          * Initialize preferences
57          *
58          * @access      public
59          * @param       array
60          * @return      void
61          */
62         function initialize($config = array())
63         {
64                 foreach ($config as $key => $val)
65                 {
66                         if (isset($this->$key))
67                         {
68                                 $this->$key = $val;
69                         }
70                 }
71
72                 // Prep the hostname
73                 $this->hostname = preg_replace('|.+?://|', '', $this->hostname);
74         }
75
76         // --------------------------------------------------------------------
77
78         /**
79          * FTP Connect
80          *
81          * @access      public
82          * @param       array    the connection values
83          * @return      bool
84          */
85         function connect($config = array())
86         {
87                 if (count($config) > 0)
88                 {
89                         $this->initialize($config);
90                 }
91
92                 if (FALSE === ($this->conn_id = @ftp_connect($this->hostname, $this->port)))
93                 {
94                         if ($this->debug == TRUE)
95                         {
96                                 $this->_error('ftp_unable_to_connect');
97                         }
98                         return FALSE;
99                 }
100
101                 if ( ! $this->_login())
102                 {
103                         if ($this->debug == TRUE)
104                         {
105                                 $this->_error('ftp_unable_to_login');
106                         }
107                         return FALSE;
108                 }
109
110                 // Set passive mode if needed
111                 if ($this->passive == TRUE)
112                 {
113                         ftp_pasv($this->conn_id, TRUE);
114                 }
115
116                 return TRUE;
117         }
118
119         // --------------------------------------------------------------------
120
121         /**
122          * FTP Login
123          *
124          * @access      private
125          * @return      bool
126          */
127         function _login()
128         {
129                 return @ftp_login($this->conn_id, $this->username, $this->password);
130         }
131
132         // --------------------------------------------------------------------
133
134         /**
135          * Validates the connection ID
136          *
137          * @access      private
138          * @return      bool
139          */
140         function _is_conn()
141         {
142                 if ( ! is_resource($this->conn_id))
143                 {
144                         if ($this->debug == TRUE)
145                         {
146                                 $this->_error('ftp_no_connection');
147                         }
148                         return FALSE;
149                 }
150                 return TRUE;
151         }
152
153         // --------------------------------------------------------------------
154
155
156         /**
157          * Change directory
158          *
159          * The second parameter lets us momentarily turn off debugging so that
160          * this function can be used to test for the existence of a folder
161          * without throwing an error.  There's no FTP equivalent to is_dir()
162          * so we do it by trying to change to a particular directory.
163          * Internally, this parameter is only used by the "mirror" function below.
164          *
165          * @access      public
166          * @param       string
167          * @param       bool
168          * @return      bool
169          */
170         function changedir($path = '', $supress_debug = FALSE)
171         {
172                 if ($path == '' OR ! $this->_is_conn())
173                 {
174                         return FALSE;
175                 }
176
177                 $result = @ftp_chdir($this->conn_id, $path);
178
179                 if ($result === FALSE)
180                 {
181                         if ($this->debug == TRUE AND $supress_debug == FALSE)
182                         {
183                                 $this->_error('ftp_unable_to_changedir');
184                         }
185                         return FALSE;
186                 }
187
188                 return TRUE;
189         }
190
191         // --------------------------------------------------------------------
192
193         /**
194          * Create a directory
195          *
196          * @access      public
197          * @param       string
198          * @return      bool
199          */
200         function mkdir($path = '', $permissions = NULL)
201         {
202                 if ($path == '' OR ! $this->_is_conn())
203                 {
204                         return FALSE;
205                 }
206
207                 $result = @ftp_mkdir($this->conn_id, $path);
208
209                 if ($result === FALSE)
210                 {
211                         if ($this->debug == TRUE)
212                         {
213                                 $this->_error('ftp_unable_to_makdir');
214                         }
215                         return FALSE;
216                 }
217
218                 // Set file permissions if needed
219                 if ( ! is_null($permissions))
220                 {
221                         $this->chmod($path, (int)$permissions);
222                 }
223
224                 return TRUE;
225         }
226
227         // --------------------------------------------------------------------
228
229         /**
230          * Upload a file to the server
231          *
232          * @access      public
233          * @param       string
234          * @param       string
235          * @param       string
236          * @return      bool
237          */
238         function upload($locpath, $rempath, $mode = 'auto', $permissions = NULL)
239         {
240                 if ( ! $this->_is_conn())
241                 {
242                         return FALSE;
243                 }
244
245                 if ( ! file_exists($locpath))
246                 {
247                         $this->_error('ftp_no_source_file');
248                         return FALSE;
249                 }
250
251                 // Set the mode if not specified
252                 if ($mode == 'auto')
253                 {
254                         // Get the file extension so we can set the upload type
255                         $ext = $this->_getext($locpath);
256                         $mode = $this->_settype($ext);
257                 }
258
259                 $mode = ($mode == 'ascii') ? FTP_ASCII : FTP_BINARY;
260
261                 $result = @ftp_put($this->conn_id, $rempath, $locpath, $mode);
262
263                 if ($result === FALSE)
264                 {
265                         if ($this->debug == TRUE)
266                         {
267                                 $this->_error('ftp_unable_to_upload');
268                         }
269                         return FALSE;
270                 }
271
272                 // Set file permissions if needed
273                 if ( ! is_null($permissions))
274                 {
275                         $this->chmod($rempath, (int)$permissions);
276                 }
277
278                 return TRUE;
279         }
280
281         // --------------------------------------------------------------------
282
283         /**
284          * Download a file from a remote server to the local server
285          *
286          * @access      public
287          * @param       string
288          * @param       string
289          * @param       string
290          * @return      bool
291          */
292         function download($rempath, $locpath, $mode = 'auto')
293         {
294                 if ( ! $this->_is_conn())
295                 {
296                         return FALSE;
297                 }
298
299                 // Set the mode if not specified
300                 if ($mode == 'auto')
301                 {
302                         // Get the file extension so we can set the upload type
303                         $ext = $this->_getext($rempath);
304                         $mode = $this->_settype($ext);
305                 }
306
307                 $mode = ($mode == 'ascii') ? FTP_ASCII : FTP_BINARY;
308
309                 $result = @ftp_get($this->conn_id, $locpath, $rempath, $mode);
310
311                 if ($result === FALSE)
312                 {
313                         if ($this->debug == TRUE)
314                         {
315                                 $this->_error('ftp_unable_to_download');
316                         }
317                         return FALSE;
318                 }
319
320                 return TRUE;
321         }
322
323         // --------------------------------------------------------------------
324
325         /**
326          * Rename (or move) a file
327          *
328          * @access      public
329          * @param       string
330          * @param       string
331          * @param       bool
332          * @return      bool
333          */
334         function rename($old_file, $new_file, $move = FALSE)
335         {
336                 if ( ! $this->_is_conn())
337                 {
338                         return FALSE;
339                 }
340
341                 $result = @ftp_rename($this->conn_id, $old_file, $new_file);
342
343                 if ($result === FALSE)
344                 {
345                         if ($this->debug == TRUE)
346                         {
347                                 $msg = ($move == FALSE) ? 'ftp_unable_to_rename' : 'ftp_unable_to_move';
348
349                                 $this->_error($msg);
350                         }
351                         return FALSE;
352                 }
353
354                 return TRUE;
355         }
356
357         // --------------------------------------------------------------------
358
359         /**
360          * Move a file
361          *
362          * @access      public
363          * @param       string
364          * @param       string
365          * @return      bool
366          */
367         function move($old_file, $new_file)
368         {
369                 return $this->rename($old_file, $new_file, TRUE);
370         }
371
372         // --------------------------------------------------------------------
373
374         /**
375          * Rename (or move) a file
376          *
377          * @access      public
378          * @param       string
379          * @return      bool
380          */
381         function delete_file($filepath)
382         {
383                 if ( ! $this->_is_conn())
384                 {
385                         return FALSE;
386                 }
387
388                 $result = @ftp_delete($this->conn_id, $filepath);
389
390                 if ($result === FALSE)
391                 {
392                         if ($this->debug == TRUE)
393                         {
394                                 $this->_error('ftp_unable_to_delete');
395                         }
396                         return FALSE;
397                 }
398
399                 return TRUE;
400         }
401
402         // --------------------------------------------------------------------
403
404         /**
405          * Delete a folder and recursively delete everything (including sub-folders)
406          * containted within it.
407          *
408          * @access      public
409          * @param       string
410          * @return      bool
411          */
412         function delete_dir($filepath)
413         {
414                 if ( ! $this->_is_conn())
415                 {
416                         return FALSE;
417                 }
418
419                 // Add a trailing slash to the file path if needed
420                 $filepath = preg_replace("/(.+?)\/*$/", "\\1/",  $filepath);
421
422                 $list = $this->list_files($filepath);
423
424                 if ($list !== FALSE AND count($list) > 0)
425                 {
426                         foreach ($list as $item)
427                         {
428                                 // If we can't delete the item it's probaly a folder so
429                                 // we'll recursively call delete_dir()
430                                 if ( ! @ftp_delete($this->conn_id, $item))
431                                 {
432                                         $this->delete_dir($item);
433                                 }
434                         }
435                 }
436
437                 $result = @ftp_rmdir($this->conn_id, $filepath);
438
439                 if ($result === FALSE)
440                 {
441                         if ($this->debug == TRUE)
442                         {
443                                 $this->_error('ftp_unable_to_delete');
444                         }
445                         return FALSE;
446                 }
447
448                 return TRUE;
449         }
450
451         // --------------------------------------------------------------------
452
453         /**
454          * Set file permissions
455          *
456          * @access      public
457          * @param       string  the file path
458          * @param       string  the permissions
459          * @return      bool
460          */
461         function chmod($path, $perm)
462         {
463                 if ( ! $this->_is_conn())
464                 {
465                         return FALSE;
466                 }
467
468                 // Permissions can only be set when running PHP 5
469                 if ( ! function_exists('ftp_chmod'))
470                 {
471                         if ($this->debug == TRUE)
472                         {
473                                 $this->_error('ftp_unable_to_chmod');
474                         }
475                         return FALSE;
476                 }
477
478                 $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          */
500         function list_files($path = '.')
501         {
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
516          * sub-folders) and creates a mirror via FTP based on it.  Whatever the directory structure
517          * 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          */
524         function mirror($locpath, $rempath)
525         {
526                 if ( ! $this->_is_conn())
527                 {
528                         return FALSE;
529                 }
530
531                 // Open the local file path
532                 if ($fp = @opendir($locpath))
533                 {
534                         // Attempt to open the remote file path.
535                         if ( ! $this->changedir($rempath, TRUE))
536                         {
537                                 // If it doesn't exist we'll attempt to create the direcotory
538                                 if ( ! $this->mkdir($rempath) OR ! $this->changedir($rempath))
539                                 {
540                                         return FALSE;
541                                 }
542                         }
543
544                         // Recursively read the local directory
545                         while (FALSE !== ($file = readdir($fp)))
546                         {
547                                 if (@is_dir($locpath.$file) && substr($file, 0, 1) != '.')
548                                 {
549                                         $this->mirror($locpath.$file."/", $rempath.$file."/");
550                                 }
551                                 elseif (substr($file, 0, 1) != ".")
552                                 {
553                                         // Get the file extension so we can se the upload type
554                                         $ext = $this->_getext($file);
555                                         $mode = $this->_settype($ext);
556
557                                         $this->upload($locpath.$file, $rempath.$file, $mode);
558                                 }
559                         }
560                         return TRUE;
561                 }
562
563                 return FALSE;
564         }
565
566
567         // --------------------------------------------------------------------
568
569         /**
570          * Extract the file extension
571          *
572          * @access      private
573          * @param       string
574          * @return      string
575          */
576         function _getext($filename)
577         {
578                 if (FALSE === strpos($filename, '.'))
579                 {
580                         return 'txt';
581                 }
582
583                 $x = explode('.', $filename);
584                 return end($x);
585         }
586
587
588         // --------------------------------------------------------------------
589
590         /**
591          * Set the upload type
592          *
593          * @access      private
594          * @param       string
595          * @return      string
596          */
597         function _settype($ext)
598         {
599                 $text_types = array(
600                                                         'txt',
601                                                         'text',
602                                                         'php',
603                                                         'phps',
604                                                         'php4',
605                                                         'js',
606                                                         'css',
607                                                         'htm',
608                                                         'html',
609                                                         'phtml',
610                                                         'shtml',
611                                                         'log',
612                                                         'xml'
613                                                         );
614
615
616                 return (in_array($ext, $text_types)) ? 'ascii' : 'binary';
617         }
618
619         // ------------------------------------------------------------------------
620
621         /**
622          * Close the connection
623          *
624          * @access      public
625          * @param       string  path to source
626          * @param       string  path to destination
627          * @return      bool
628          */
629         function close()
630         {
631                 if ( ! $this->_is_conn())
632                 {
633                         return FALSE;
634                 }
635
636                 @ftp_close($this->conn_id);
637         }
638
639         // ------------------------------------------------------------------------
640
641         /**
642          * Display error message
643          *
644          * @access      private
645          * @param       string
646          * @return      bool
647          */
648         function _error($line)
649         {
650                 $CI =& get_instance();
651                 $CI->lang->load('ftp');
652                 show_error($CI->lang->line($line));
653         }
654
655
656 }
657 // END FTP Class
658
659 /* End of file Ftp.php */
660 /* Location: ./system/libraries/Ftp.php */