Subversion-Projekte lars-tiefland.ci

Revision

Revision 2254 | Zur aktuellen Revision | Details | Vergleich mit vorheriger | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
68 lars 1
<?php
2
/**
3
 * CodeIgniter
4
 *
5
 * An open source application development framework for PHP
6
 *
7
 * This content is released under the MIT License (MIT)
8
 *
2257 lars 9
 * Copyright (c) 2014 - 2018, British Columbia Institute of Technology
68 lars 10
 *
11
 * Permission is hereby granted, free of charge, to any person obtaining a copy
12
 * of this software and associated documentation files (the "Software"), to deal
13
 * in the Software without restriction, including without limitation the rights
14
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15
 * copies of the Software, and to permit persons to whom the Software is
16
 * furnished to do so, subject to the following conditions:
17
 *
18
 * The above copyright notice and this permission notice shall be included in
19
 * all copies or substantial portions of the Software.
20
 *
21
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
27
 * THE SOFTWARE.
28
 *
29
 * @package	CodeIgniter
30
 * @author	EllisLab Dev Team
31
 * @copyright	Copyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)
2257 lars 32
 * @copyright	Copyright (c) 2014 - 2018, British Columbia Institute of Technology (http://bcit.ca/)
68 lars 33
 * @license	http://opensource.org/licenses/MIT	MIT License
34
 * @link	https://codeigniter.com
35
 * @since	Version 1.0.0
36
 * @filesource
37
 */
38
defined('BASEPATH') OR exit('No direct script access allowed');
39
 
40
/**
41
 * FTP Class
42
 *
43
 * @package		CodeIgniter
44
 * @subpackage	Libraries
45
 * @category	Libraries
46
 * @author		EllisLab Dev Team
47
 * @link		https://codeigniter.com/user_guide/libraries/ftp.html
48
 */
49
class CI_FTP {
50
 
51
	/**
52
	 * FTP Server hostname
53
	 *
54
	 * @var	string
55
	 */
56
	public $hostname = '';
57
 
58
	/**
59
	 * FTP Username
60
	 *
61
	 * @var	string
62
	 */
63
	public $username = '';
64
 
65
	/**
66
	 * FTP Password
67
	 *
68
	 * @var	string
69
	 */
70
	public $password = '';
71
 
72
	/**
73
	 * FTP Server port
74
	 *
75
	 * @var	int
76
	 */
77
	public $port = 21;
78
 
79
	/**
80
	 * Passive mode flag
81
	 *
82
	 * @var	bool
83
	 */
84
	public $passive = TRUE;
85
 
86
	/**
87
	 * Debug flag
88
	 *
89
	 * Specifies whether to display error messages.
90
	 *
91
	 * @var	bool
92
	 */
93
	public $debug = FALSE;
94
 
95
	// --------------------------------------------------------------------
96
 
97
	/**
98
	 * Connection ID
99
	 *
100
	 * @var	resource
101
	 */
102
	protected $conn_id;
103
 
104
	// --------------------------------------------------------------------
105
 
106
	/**
107
	 * Constructor
108
	 *
109
	 * @param	array	$config
110
	 * @return	void
111
	 */
112
	public function __construct($config = array())
113
	{
114
		empty($config) OR $this->initialize($config);
115
		log_message('info', 'FTP Class Initialized');
116
	}
117
 
118
	// --------------------------------------------------------------------
119
 
120
	/**
121
	 * Initialize preferences
122
	 *
123
	 * @param	array	$config
124
	 * @return	void
125
	 */
126
	public function initialize($config = array())
127
	{
128
		foreach ($config as $key => $val)
129
		{
130
			if (isset($this->$key))
131
			{
132
				$this->$key = $val;
133
			}
134
		}
135
 
136
		// Prep the hostname
137
		$this->hostname = preg_replace('|.+?://|', '', $this->hostname);
138
	}
139
 
140
	// --------------------------------------------------------------------
141
 
142
	/**
143
	 * FTP Connect
144
	 *
145
	 * @param	array	 $config	Connection values
146
	 * @return	bool
147
	 */
148
	public function connect($config = array())
149
	{
150
		if (count($config) > 0)
151
		{
152
			$this->initialize($config);
153
		}
154
 
155
		if (FALSE === ($this->conn_id = @ftp_connect($this->hostname, $this->port)))
156
		{
157
			if ($this->debug === TRUE)
158
			{
159
				$this->_error('ftp_unable_to_connect');
160
			}
161
 
162
			return FALSE;
163
		}
164
 
165
		if ( ! $this->_login())
166
		{
167
			if ($this->debug === TRUE)
168
			{
169
				$this->_error('ftp_unable_to_login');
170
			}
171
 
172
			return FALSE;
173
		}
174
 
175
		// Set passive mode if needed
176
		if ($this->passive === TRUE)
177
		{
178
			ftp_pasv($this->conn_id, TRUE);
179
		}
180
 
181
		return TRUE;
182
	}
183
 
184
	// --------------------------------------------------------------------
185
 
186
	/**
187
	 * FTP Login
188
	 *
189
	 * @return	bool
190
	 */
191
	protected function _login()
192
	{
193
		return @ftp_login($this->conn_id, $this->username, $this->password);
194
	}
195
 
196
	// --------------------------------------------------------------------
197
 
198
	/**
199
	 * Validates the connection ID
200
	 *
201
	 * @return	bool
202
	 */
203
	protected function _is_conn()
204
	{
205
		if ( ! is_resource($this->conn_id))
206
		{
207
			if ($this->debug === TRUE)
208
			{
209
				$this->_error('ftp_no_connection');
210
			}
211
 
212
			return FALSE;
213
		}
214
 
215
		return TRUE;
216
	}
217
 
218
	// --------------------------------------------------------------------
219
 
220
	/**
221
	 * Change directory
222
	 *
223
	 * The second parameter lets us momentarily turn off debugging so that
224
	 * this function can be used to test for the existence of a folder
225
	 * without throwing an error. There's no FTP equivalent to is_dir()
226
	 * so we do it by trying to change to a particular directory.
227
	 * Internally, this parameter is only used by the "mirror" function below.
228
	 *
229
	 * @param	string	$path
230
	 * @param	bool	$suppress_debug
231
	 * @return	bool
232
	 */
233
	public function changedir($path, $suppress_debug = FALSE)
234
	{
235
		if ( ! $this->_is_conn())
236
		{
237
			return FALSE;
238
		}
239
 
240
		$result = @ftp_chdir($this->conn_id, $path);
241
 
242
		if ($result === FALSE)
243
		{
244
			if ($this->debug === TRUE && $suppress_debug === FALSE)
245
			{
246
				$this->_error('ftp_unable_to_changedir');
247
			}
248
 
249
			return FALSE;
250
		}
251
 
252
		return TRUE;
253
	}
254
 
255
	// --------------------------------------------------------------------
256
 
257
	/**
258
	 * Create a directory
259
	 *
260
	 * @param	string	$path
261
	 * @param	int	$permissions
262
	 * @return	bool
263
	 */
264
	public function mkdir($path, $permissions = NULL)
265
	{
266
		if ($path === '' OR ! $this->_is_conn())
267
		{
268
			return FALSE;
269
		}
270
 
271
		$result = @ftp_mkdir($this->conn_id, $path);
272
 
273
		if ($result === FALSE)
274
		{
275
			if ($this->debug === TRUE)
276
			{
277
				$this->_error('ftp_unable_to_mkdir');
278
			}
279
 
280
			return FALSE;
281
		}
282
 
283
		// Set file permissions if needed
284
		if ($permissions !== NULL)
285
		{
286
			$this->chmod($path, (int) $permissions);
287
		}
288
 
289
		return TRUE;
290
	}
291
 
292
	// --------------------------------------------------------------------
293
 
294
	/**
295
	 * Upload a file to the server
296
	 *
297
	 * @param	string	$locpath
298
	 * @param	string	$rempath
299
	 * @param	string	$mode
300
	 * @param	int	$permissions
301
	 * @return	bool
302
	 */
303
	public function upload($locpath, $rempath, $mode = 'auto', $permissions = NULL)
304
	{
305
		if ( ! $this->_is_conn())
306
		{
307
			return FALSE;
308
		}
309
 
310
		if ( ! file_exists($locpath))
311
		{
312
			$this->_error('ftp_no_source_file');
313
			return FALSE;
314
		}
315
 
316
		// Set the mode if not specified
317
		if ($mode === 'auto')
318
		{
319
			// Get the file extension so we can set the upload type
320
			$ext = $this->_getext($locpath);
321
			$mode = $this->_settype($ext);
322
		}
323
 
324
		$mode = ($mode === 'ascii') ? FTP_ASCII : FTP_BINARY;
325
 
326
		$result = @ftp_put($this->conn_id, $rempath, $locpath, $mode);
327
 
328
		if ($result === FALSE)
329
		{
330
			if ($this->debug === TRUE)
331
			{
332
				$this->_error('ftp_unable_to_upload');
333
			}
334
 
335
			return FALSE;
336
		}
337
 
338
		// Set file permissions if needed
339
		if ($permissions !== NULL)
340
		{
341
			$this->chmod($rempath, (int) $permissions);
342
		}
343
 
344
		return TRUE;
345
	}
346
 
347
	// --------------------------------------------------------------------
348
 
349
	/**
350
	 * Download a file from a remote server to the local server
351
	 *
352
	 * @param	string	$rempath
353
	 * @param	string	$locpath
354
	 * @param	string	$mode
355
	 * @return	bool
356
	 */
357
	public function download($rempath, $locpath, $mode = 'auto')
358
	{
359
		if ( ! $this->_is_conn())
360
		{
361
			return FALSE;
362
		}
363
 
364
		// Set the mode if not specified
365
		if ($mode === 'auto')
366
		{
367
			// Get the file extension so we can set the upload type
368
			$ext = $this->_getext($rempath);
369
			$mode = $this->_settype($ext);
370
		}
371
 
372
		$mode = ($mode === 'ascii') ? FTP_ASCII : FTP_BINARY;
373
 
374
		$result = @ftp_get($this->conn_id, $locpath, $rempath, $mode);
375
 
376
		if ($result === FALSE)
377
		{
378
			if ($this->debug === TRUE)
379
			{
380
				$this->_error('ftp_unable_to_download');
381
			}
382
 
383
			return FALSE;
384
		}
385
 
386
		return TRUE;
387
	}
388
 
389
	// --------------------------------------------------------------------
390
 
391
	/**
392
	 * Rename (or move) a file
393
	 *
394
	 * @param	string	$old_file
395
	 * @param	string	$new_file
396
	 * @param	bool	$move
397
	 * @return	bool
398
	 */
399
	public function rename($old_file, $new_file, $move = FALSE)
400
	{
401
		if ( ! $this->_is_conn())
402
		{
403
			return FALSE;
404
		}
405
 
406
		$result = @ftp_rename($this->conn_id, $old_file, $new_file);
407
 
408
		if ($result === FALSE)
409
		{
410
			if ($this->debug === TRUE)
411
			{
412
				$this->_error('ftp_unable_to_'.($move === FALSE ? 'rename' : 'move'));
413
			}
414
 
415
			return FALSE;
416
		}
417
 
418
		return TRUE;
419
	}
420
 
421
	// --------------------------------------------------------------------
422
 
423
	/**
424
	 * Move a file
425
	 *
426
	 * @param	string	$old_file
427
	 * @param	string	$new_file
428
	 * @return	bool
429
	 */
430
	public function move($old_file, $new_file)
431
	{
432
		return $this->rename($old_file, $new_file, TRUE);
433
	}
434
 
435
	// --------------------------------------------------------------------
436
 
437
	/**
438
	 * Rename (or move) a file
439
	 *
440
	 * @param	string	$filepath
441
	 * @return	bool
442
	 */
443
	public function delete_file($filepath)
444
	{
445
		if ( ! $this->_is_conn())
446
		{
447
			return FALSE;
448
		}
449
 
450
		$result = @ftp_delete($this->conn_id, $filepath);
451
 
452
		if ($result === FALSE)
453
		{
454
			if ($this->debug === TRUE)
455
			{
456
				$this->_error('ftp_unable_to_delete');
457
			}
458
 
459
			return FALSE;
460
		}
461
 
462
		return TRUE;
463
	}
464
 
465
	// --------------------------------------------------------------------
466
 
467
	/**
468
	 * Delete a folder and recursively delete everything (including sub-folders)
469
	 * contained within it.
470
	 *
471
	 * @param	string	$filepath
472
	 * @return	bool
473
	 */
474
	public function delete_dir($filepath)
475
	{
476
		if ( ! $this->_is_conn())
477
		{
478
			return FALSE;
479
		}
480
 
481
		// Add a trailing slash to the file path if needed
482
		$filepath = preg_replace('/(.+?)\/*$/', '\\1/', $filepath);
483
 
484
		$list = $this->list_files($filepath);
485
		if ( ! empty($list))
486
		{
487
			for ($i = 0, $c = count($list); $i < $c; $i++)
488
			{
2107 lars 489
				// If we can't delete the item it's probably a directory,
68 lars 490
				// so we'll recursively call delete_dir()
491
				if ( ! preg_match('#/\.\.?$#', $list[$i]) && ! @ftp_delete($this->conn_id, $list[$i]))
492
				{
493
					$this->delete_dir($filepath.$list[$i]);
494
				}
495
			}
496
		}
497
 
498
		if (@ftp_rmdir($this->conn_id, $filepath) === FALSE)
499
		{
500
			if ($this->debug === TRUE)
501
			{
502
				$this->_error('ftp_unable_to_delete');
503
			}
504
 
505
			return FALSE;
506
		}
507
 
508
		return TRUE;
509
	}
510
 
511
	// --------------------------------------------------------------------
512
 
513
	/**
514
	 * Set file permissions
515
	 *
516
	 * @param	string	$path	File path
517
	 * @param	int	$perm	Permissions
518
	 * @return	bool
519
	 */
520
	public function chmod($path, $perm)
521
	{
522
		if ( ! $this->_is_conn())
523
		{
524
			return FALSE;
525
		}
526
 
527
		if (@ftp_chmod($this->conn_id, $perm, $path) === FALSE)
528
		{
529
			if ($this->debug === TRUE)
530
			{
531
				$this->_error('ftp_unable_to_chmod');
532
			}
533
 
534
			return FALSE;
535
		}
536
 
537
		return TRUE;
538
	}
539
 
540
	// --------------------------------------------------------------------
541
 
542
	/**
543
	 * FTP List files in the specified directory
544
	 *
545
	 * @param	string	$path
546
	 * @return	array
547
	 */
548
	public function list_files($path = '.')
549
	{
550
		return $this->_is_conn()
551
			? ftp_nlist($this->conn_id, $path)
552
			: FALSE;
553
	}
554
 
555
	// ------------------------------------------------------------------------
556
 
557
	/**
558
	 * Read a directory and recreate it remotely
559
	 *
560
	 * This function recursively reads a folder and everything it contains
561
	 * (including sub-folders) and creates a mirror via FTP based on it.
562
	 * Whatever the directory structure of the original file path will be
563
	 * recreated on the server.
564
	 *
565
	 * @param	string	$locpath	Path to source with trailing slash
566
	 * @param	string	$rempath	Path to destination - include the base folder with trailing slash
567
	 * @return	bool
568
	 */
569
	public function mirror($locpath, $rempath)
570
	{
571
		if ( ! $this->_is_conn())
572
		{
573
			return FALSE;
574
		}
575
 
576
		// Open the local file path
577
		if ($fp = @opendir($locpath))
578
		{
579
			// Attempt to open the remote file path and try to create it, if it doesn't exist
580
			if ( ! $this->changedir($rempath, TRUE) && ( ! $this->mkdir($rempath) OR ! $this->changedir($rempath)))
581
			{
582
				return FALSE;
583
			}
584
 
585
			// Recursively read the local directory
586
			while (FALSE !== ($file = readdir($fp)))
587
			{
588
				if (is_dir($locpath.$file) && $file[0] !== '.')
589
				{
590
					$this->mirror($locpath.$file.'/', $rempath.$file.'/');
591
				}
592
				elseif ($file[0] !== '.')
593
				{
594
					// Get the file extension so we can se the upload type
595
					$ext = $this->_getext($file);
596
					$mode = $this->_settype($ext);
597
 
598
					$this->upload($locpath.$file, $rempath.$file, $mode);
599
				}
600
			}
601
 
602
			return TRUE;
603
		}
604
 
605
		return FALSE;
606
	}
607
 
608
	// --------------------------------------------------------------------
609
 
610
	/**
611
	 * Extract the file extension
612
	 *
613
	 * @param	string	$filename
614
	 * @return	string
615
	 */
616
	protected function _getext($filename)
617
	{
618
		return (($dot = strrpos($filename, '.')) === FALSE)
619
			? 'txt'
620
			: substr($filename, $dot + 1);
621
	}
622
 
623
	// --------------------------------------------------------------------
624
 
625
	/**
626
	 * Set the upload type
627
	 *
628
	 * @param	string	$ext	Filename extension
629
	 * @return	string
630
	 */
631
	protected function _settype($ext)
632
	{
633
		return in_array($ext, array('txt', 'text', 'php', 'phps', 'php4', 'js', 'css', 'htm', 'html', 'phtml', 'shtml', 'log', 'xml'), TRUE)
634
			? 'ascii'
635
			: 'binary';
636
	}
637
 
638
	// ------------------------------------------------------------------------
639
 
640
	/**
641
	 * Close the connection
642
	 *
643
	 * @return	bool
644
	 */
645
	public function close()
646
	{
647
		return $this->_is_conn()
648
			? @ftp_close($this->conn_id)
649
			: FALSE;
650
	}
651
 
652
	// ------------------------------------------------------------------------
653
 
654
	/**
655
	 * Display error message
656
	 *
657
	 * @param	string	$line
658
	 * @return	void
659
	 */
660
	protected function _error($line)
661
	{
662
		$CI =& get_instance();
663
		$CI->lang->load('ftp');
664
		show_error($CI->lang->line($line));
665
	}
666
 
667
}