phpBB
Statistics
| Revision:

root / branches / phpBB-3_0_0 / phpBB / includes / functions_transfer.php

History | View | Annotate | Download (17.5 kB)

1 5375 acydburn
<?php
2 5375 acydburn
/**
3 5375 acydburn
*
4 5375 acydburn
* @package phpBB3
5 5375 acydburn
* @version $Id$
6 5375 acydburn
* @copyright (c) 2005 phpBB Group
7 5375 acydburn
* @license http://opensource.org/licenses/gpl-license.php GNU Public License
8 5375 acydburn
*
9 5375 acydburn
*/
10 5375 acydburn
11 5375 acydburn
/**
12 8146 acydburn
* @ignore
13 8146 acydburn
*/
14 8146 acydburn
if (!defined('IN_PHPBB'))
15 8146 acydburn
{
16 8146 acydburn
        exit;
17 8146 acydburn
}
18 8146 acydburn
19 8146 acydburn
/**
20 6058 acydburn
* Transfer class, wrapper for ftp/sftp/ssh
21 5375 acydburn
* @package phpBB3
22 5375 acydburn
*/
23 5375 acydburn
class transfer
24 5375 acydburn
{
25 5375 acydburn
        var $connection;
26 5375 acydburn
        var $host;
27 5375 acydburn
        var $port;
28 5375 acydburn
        var $username;
29 5375 acydburn
        var $password;
30 5375 acydburn
        var $timeout;
31 5375 acydburn
        var $root_path;
32 5375 acydburn
        var $tmp_path;
33 5375 acydburn
        var $file_perms;
34 5375 acydburn
        var $dir_perms;
35 5375 acydburn
36 5375 acydburn
        /**
37 5375 acydburn
        * Constructor - init some basic values
38 5375 acydburn
        */
39 5375 acydburn
        function transfer()
40 5375 acydburn
        {
41 5375 acydburn
                global $phpbb_root_path;
42 5375 acydburn
43 7241 acydburn
                $this->file_perms        = 0644;
44 7241 acydburn
                $this->dir_perms        = 0777;
45 5375 acydburn
46 5375 acydburn
                // We use the store directory as temporary path to circumvent open basedir restrictions
47 5416 acydburn
                $this->tmp_path = $phpbb_root_path . 'store/';
48 5375 acydburn
        }
49 6048 acydburn
50 5375 acydburn
        /**
51 5375 acydburn
        * Write file to location
52 5375 acydburn
        */
53 5375 acydburn
        function write_file($destination_file = '', $contents = '')
54 5375 acydburn
        {
55 5375 acydburn
                global $phpbb_root_path;
56 5375 acydburn
57 6015 acydburn
                $destination_file = $this->root_path . str_replace($phpbb_root_path, '', $destination_file);
58 5375 acydburn
59 5375 acydburn
                // need to create a temp file and then move that temp file.
60 5375 acydburn
                // ftp functions can only move files around and can't create.
61 5375 acydburn
                // This means that the users will need to have access to write
62 5375 acydburn
                // temporary files or have write access on a folder within phpBB
63 6930 acydburn
                // like the cache folder. If the user can't do either, then
64 5375 acydburn
                // he/she needs to use the fsock ftp method
65 5388 acydburn
                $temp_name = tempnam($this->tmp_path, 'transfer_');
66 5375 acydburn
                @unlink($temp_name);
67 5375 acydburn
68 5375 acydburn
                $fp = @fopen($temp_name, 'w');
69 5375 acydburn
70 5375 acydburn
                if (!$fp)
71 5375 acydburn
                {
72 6048 acydburn
                        trigger_error('Unable to create temporary file ' . $temp_name, E_USER_ERROR);
73 5375 acydburn
                }
74 6048 acydburn
75 5375 acydburn
                @fwrite($fp, $contents);
76 5375 acydburn
                @fclose($fp);
77 5375 acydburn
78 5375 acydburn
                $result = $this->overwrite_file($temp_name, $destination_file);
79 5375 acydburn
80 5375 acydburn
                // remove temporary file now
81 5375 acydburn
                @unlink($temp_name);
82 5375 acydburn
83 5375 acydburn
                return $result;
84 5375 acydburn
        }
85 5375 acydburn
86 5375 acydburn
        /**
87 5375 acydburn
        * Moving file into location. If the destination file already exists it gets overwritten
88 5375 acydburn
        */
89 5375 acydburn
        function overwrite_file($source_file, $destination_file)
90 5375 acydburn
        {
91 5375 acydburn
                /**
92 5375 acydburn
                * @todo generally think about overwriting files in another way, by creating a temporary file and then renaming it
93 5375 acydburn
                * @todo check for the destination file existance too
94 5375 acydburn
                */
95 5375 acydburn
                $this->_delete($destination_file);
96 5375 acydburn
                $result = $this->_put($source_file, $destination_file);
97 5375 acydburn
                $this->_chmod($destination_file, $this->file_perms);
98 6048 acydburn
99 5375 acydburn
                return $result;
100 5375 acydburn
        }
101 5375 acydburn
102 5375 acydburn
        /**
103 5375 acydburn
        * Create directory structure
104 5375 acydburn
        */
105 5375 acydburn
        function make_dir($dir)
106 5375 acydburn
        {
107 5375 acydburn
                global $phpbb_root_path;
108 5375 acydburn
109 5416 acydburn
                $dir = str_replace($phpbb_root_path, '', $dir);
110 5375 acydburn
                $dir = explode('/', $dir);
111 5375 acydburn
                $dirs = '';
112 5375 acydburn
113 5375 acydburn
                for ($i = 0, $total = sizeof($dir); $i < $total; $i++)
114 5375 acydburn
                {
115 5375 acydburn
                        $result = true;
116 5375 acydburn
117 6048 acydburn
                        if (strpos($dir[$i], '.') === 0)
118 5375 acydburn
                        {
119 5375 acydburn
                                continue;
120 5375 acydburn
                        }
121 5375 acydburn
                        $cur_dir = $dir[$i] . '/';
122 5375 acydburn
123 5375 acydburn
                        if (!file_exists($phpbb_root_path . $dirs . $cur_dir))
124 5375 acydburn
                        {
125 6048 acydburn
                                // create the directory
126 5375 acydburn
                                $result = $this->_mkdir($dir[$i]);
127 5375 acydburn
                                $this->_chmod($dir[$i], $this->dir_perms);
128 5375 acydburn
                        }
129 5375 acydburn
130 6015 acydburn
                        $this->_chdir($this->root_path . $dirs . $dir[$i]);
131 5375 acydburn
                        $dirs .= $cur_dir;
132 5375 acydburn
                }
133 5375 acydburn
134 5375 acydburn
                $this->_chdir($this->root_path);
135 5375 acydburn
136 5375 acydburn
                /**
137 5375 acydburn
                * @todo stack result into array to make sure every path creation has been taken care of
138 5375 acydburn
                */
139 5375 acydburn
                return $result;
140 5375 acydburn
        }
141 5375 acydburn
142 5375 acydburn
        /**
143 5375 acydburn
        * Copy file from source location to destination location
144 5375 acydburn
        */
145 5375 acydburn
        function copy_file($from_loc, $to_loc)
146 5375 acydburn
        {
147 5375 acydburn
                global $phpbb_root_path;
148 5375 acydburn
149 5375 acydburn
                $from_loc = ((strpos($from_loc, $phpbb_root_path) !== 0) ? $phpbb_root_path : '') . $from_loc;
150 6015 acydburn
                $to_loc = $this->root_path . str_replace($phpbb_root_path, '', $to_loc);
151 5375 acydburn
152 5375 acydburn
                if (!file_exists($from_loc))
153 5375 acydburn
                {
154 5375 acydburn
                        return false;
155 5375 acydburn
                }
156 6048 acydburn
157 5375 acydburn
                $result = $this->overwrite_file($from_loc, $to_loc);
158 5375 acydburn
159 5375 acydburn
                return $result;
160 5375 acydburn
        }
161 5375 acydburn
162 5375 acydburn
        /**
163 5375 acydburn
        * Remove file
164 5375 acydburn
        */
165 5375 acydburn
        function delete_file($file)
166 5375 acydburn
        {
167 5375 acydburn
                global $phpbb_root_path;
168 6048 acydburn
169 6015 acydburn
                $file = $this->root_path . str_replace($phpbb_root_path, '', $file);
170 5375 acydburn
171 5375 acydburn
                return $this->_delete($file);
172 5375 acydburn
        }
173 6048 acydburn
174 5375 acydburn
        /**
175 5375 acydburn
        * Remove directory
176 5375 acydburn
        * @todo remove child directories?
177 5375 acydburn
        */
178 5375 acydburn
        function remove_dir($dir)
179 5375 acydburn
        {
180 5375 acydburn
                global $phpbb_root_path;
181 6048 acydburn
182 6015 acydburn
                $dir = $this->root_path . str_replace($phpbb_root_path, '', $dir);
183 6048 acydburn
184 5375 acydburn
                return $this->_rmdir($dir);
185 5375 acydburn
        }
186 5375 acydburn
187 5375 acydburn
        /**
188 5562 davidmj
        * Rename a file or folder
189 5562 davidmj
        */
190 5562 davidmj
        function rename($old_handle, $new_handle)
191 5562 davidmj
        {
192 5562 davidmj
                global $phpbb_root_path;
193 5562 davidmj
194 6015 acydburn
                $old_handle = $this->root_path . str_replace($phpbb_root_path, '', $old_handle);
195 6048 acydburn
196 5562 davidmj
                return $this->_rename($old_handle, $new_handle);
197 5562 davidmj
        }
198 5562 davidmj
199 5562 davidmj
        /**
200 6312 acydburn
        * Check if a specified file exist...
201 6312 acydburn
        */
202 6312 acydburn
        function file_exists($directory, $filename)
203 6312 acydburn
        {
204 6312 acydburn
                global $phpbb_root_path;
205 6312 acydburn
206 6312 acydburn
                $directory = $this->root_path . str_replace($phpbb_root_path, '', $directory);
207 6312 acydburn
208 6689 acydburn
                $this->_chdir($directory);
209 9433 acydburn
                $result = $this->_ls();
210 6689 acydburn
211 6312 acydburn
                if ($result !== false && is_array($result))
212 6312 acydburn
                {
213 6312 acydburn
                        return (in_array($filename, $result)) ? true : false;
214 6312 acydburn
                }
215 6312 acydburn
216 6312 acydburn
                return false;
217 6312 acydburn
        }
218 6312 acydburn
219 6312 acydburn
        /**
220 5416 acydburn
        * Open session
221 5416 acydburn
        */
222 5416 acydburn
        function open_session()
223 5416 acydburn
        {
224 5416 acydburn
                return $this->_init();
225 5416 acydburn
        }
226 5416 acydburn
227 5416 acydburn
        /**
228 5375 acydburn
        * Close current session
229 5375 acydburn
        */
230 5375 acydburn
        function close_session()
231 5375 acydburn
        {
232 5375 acydburn
                return $this->_close();
233 5375 acydburn
        }
234 5388 acydburn
235 5388 acydburn
        /**
236 5388 acydburn
        * Determine methods able to be used
237 5388 acydburn
        */
238 5388 acydburn
        function methods()
239 5388 acydburn
        {
240 5388 acydburn
                $methods = array();
241 5870 acydburn
                $disabled_functions = explode(',', @ini_get('disable_functions'));
242 5388 acydburn
243 5388 acydburn
                if (@extension_loaded('ftp'))
244 5388 acydburn
                {
245 5388 acydburn
                        $methods[] = 'ftp';
246 5388 acydburn
                }
247 5388 acydburn
248 5870 acydburn
                if (!in_array('fsockopen', $disabled_functions))
249 5870 acydburn
                {
250 5870 acydburn
                        $methods[] = 'ftp_fsock';
251 5870 acydburn
                }
252 5870 acydburn
253 5388 acydburn
                return $methods;
254 5388 acydburn
        }
255 5375 acydburn
}
256 5375 acydburn
257 5375 acydburn
/**
258 6058 acydburn
* FTP transfer class
259 5375 acydburn
* @package phpBB3
260 5375 acydburn
*/
261 5375 acydburn
class ftp extends transfer
262 5375 acydburn
{
263 5375 acydburn
        /**
264 5375 acydburn
        * Standard parameters for FTP session
265 5375 acydburn
        */
266 5375 acydburn
        function ftp($host, $username, $password, $root_path, $port = 21, $timeout = 10)
267 5375 acydburn
        {
268 5375 acydburn
                $this->host                        = $host;
269 5375 acydburn
                $this->port                        = $port;
270 5375 acydburn
                $this->username                = $username;
271 5375 acydburn
                $this->password                = $password;
272 5375 acydburn
                $this->timeout                = $timeout;
273 5595 acydburn
274 6015 acydburn
                // Make sure $this->root_path is layed out the same way as the $user->page['root_script_path'] value (/ at the end)
275 5595 acydburn
                $this->root_path        = str_replace('\\', '/', $this->root_path);
276 5375 acydburn
277 6698 acydburn
                if (!empty($root_path))
278 6698 acydburn
                {
279 6698 acydburn
                        $this->root_path = (($root_path[0] != '/' ) ? '/' : '') . $root_path . ((substr($root_path, -1, 1) == '/') ? '' : '/');
280 6698 acydburn
                }
281 6698 acydburn
282 5562 davidmj
                // Init some needed values
283 5562 davidmj
                transfer::transfer();
284 5562 davidmj
285 5375 acydburn
                return;
286 5375 acydburn
        }
287 5375 acydburn
288 5375 acydburn
        /**
289 5562 davidmj
        * Requests data
290 5562 davidmj
        */
291 5562 davidmj
        function data()
292 5562 davidmj
        {
293 5595 acydburn
                global $user;
294 5595 acydburn
295 6048 acydburn
                return array(
296 6048 acydburn
                        'host'                => 'localhost',
297 6048 acydburn
                        'username'        => 'anonymous',
298 6048 acydburn
                        'password'        => '',
299 6048 acydburn
                        'root_path'        => $user->page['root_script_path'],
300 6048 acydburn
                        'port'                => 21,
301 6048 acydburn
                        'timeout'        => 10
302 6048 acydburn
                );
303 5562 davidmj
        }
304 5562 davidmj
305 5562 davidmj
        /**
306 5375 acydburn
        * Init FTP Session
307 6312 acydburn
        * @access private
308 5375 acydburn
        */
309 5416 acydburn
        function _init()
310 5375 acydburn
        {
311 5375 acydburn
                // connect to the server
312 5375 acydburn
                $this->connection = @ftp_connect($this->host, $this->port, $this->timeout);
313 5375 acydburn
314 5375 acydburn
                if (!$this->connection)
315 5375 acydburn
                {
316 6048 acydburn
                        return 'ERR_CONNECTING_SERVER';
317 5375 acydburn
                }
318 5375 acydburn
319 5375 acydburn
                // login to the server
320 5375 acydburn
                if (!@ftp_login($this->connection, $this->username, $this->password))
321 5375 acydburn
                {
322 6048 acydburn
                        return 'ERR_UNABLE_TO_LOGIN';
323 5375 acydburn
                }
324 5375 acydburn
325 9819 bantu
                // attempt to turn pasv mode on
326 9819 bantu
                @ftp_pasv($this->connection, true);
327 9819 bantu
328 5375 acydburn
                // change to the root directory
329 5375 acydburn
                if (!$this->_chdir($this->root_path))
330 5375 acydburn
                {
331 6048 acydburn
                        return 'ERR_CHANGING_DIRECTORY';
332 5375 acydburn
                }
333 5375 acydburn
334 5375 acydburn
                return true;
335 5375 acydburn
        }
336 5375 acydburn
337 5375 acydburn
        /**
338 5375 acydburn
        * Create Directory (MKDIR)
339 6312 acydburn
        * @access private
340 5375 acydburn
        */
341 5375 acydburn
        function _mkdir($dir)
342 5375 acydburn
        {
343 5375 acydburn
                return @ftp_mkdir($this->connection, $dir);
344 5375 acydburn
        }
345 5375 acydburn
346 5375 acydburn
        /**
347 5375 acydburn
        * Remove directory (RMDIR)
348 6312 acydburn
        * @access private
349 5375 acydburn
        */
350 5375 acydburn
        function _rmdir($dir)
351 5375 acydburn
        {
352 5375 acydburn
                return @ftp_rmdir($this->connection, $dir);
353 5375 acydburn
        }
354 5375 acydburn
355 5375 acydburn
        /**
356 6139 acydburn
        * Rename file
357 6312 acydburn
        * @access private
358 5562 davidmj
        */
359 5562 davidmj
        function _rename($old_handle, $new_handle)
360 5562 davidmj
        {
361 5562 davidmj
                return @ftp_rename($this->connection, $old_handle, $new_handle);
362 5562 davidmj
        }
363 5562 davidmj
364 5562 davidmj
        /**
365 5375 acydburn
        * Change current working directory (CHDIR)
366 6312 acydburn
        * @access private
367 5375 acydburn
        */
368 5375 acydburn
        function _chdir($dir = '')
369 5375 acydburn
        {
370 6730 acydburn
                if ($dir && $dir !== '/')
371 5375 acydburn
                {
372 6730 acydburn
                        if (substr($dir, -1, 1) == '/')
373 6730 acydburn
                        {
374 6730 acydburn
                                $dir = substr($dir, 0, -1);
375 6730 acydburn
                        }
376 5375 acydburn
                }
377 5375 acydburn
378 5375 acydburn
                return @ftp_chdir($this->connection, $dir);
379 5375 acydburn
        }
380 5375 acydburn
381 5375 acydburn
        /**
382 5375 acydburn
        * change file permissions (CHMOD)
383 6312 acydburn
        * @access private
384 5375 acydburn
        */
385 5375 acydburn
        function _chmod($file, $perms)
386 5375 acydburn
        {
387 5562 davidmj
                if (function_exists('ftp_chmod'))
388 5562 davidmj
                {
389 5562 davidmj
                        $err = @ftp_chmod($this->connection, $perms, $file);
390 5562 davidmj
                }
391 5562 davidmj
                else
392 5562 davidmj
                {
393 7782 acydburn
                        // Unfortunatly CHMOD is not expecting an octal value...
394 7782 acydburn
                        // We need to transform the integer (which was an octal) to an octal representation (to get the int) and then pass as is. ;)
395 7782 acydburn
                        $chmod_cmd = 'CHMOD ' . base_convert($perms, 10, 8) . ' ' . $file;
396 5562 davidmj
                        $err = $this->_site($chmod_cmd);
397 5562 davidmj
                }
398 6048 acydburn
399 5375 acydburn
                return $err;
400 5375 acydburn
        }
401 5375 acydburn
402 5375 acydburn
        /**
403 5375 acydburn
        * Upload file to location (PUT)
404 6312 acydburn
        * @access private
405 5375 acydburn
        */
406 5375 acydburn
        function _put($from_file, $to_file)
407 5375 acydburn
        {
408 5375 acydburn
                // get the file extension
409 5375 acydburn
                $file_extension = strtolower(substr(strrchr($to_file, '.'), 1));
410 5375 acydburn
411 5416 acydburn
                // We only use the BINARY file mode to cicumvent rewrite actions from ftp server (mostly linefeeds being replaced)
412 5416 acydburn
                $mode = FTP_BINARY;
413 5416 acydburn
414 5375 acydburn
                $to_dir = dirname($to_file);
415 5375 acydburn
                $to_file = basename($to_file);
416 5375 acydburn
                $this->_chdir($to_dir);
417 5375 acydburn
418 5375 acydburn
                $result = @ftp_put($this->connection, $to_file, $from_file, $mode);
419 5375 acydburn
                $this->_chdir($this->root_path);
420 5375 acydburn
421 5375 acydburn
                return $result;
422 5375 acydburn
        }
423 5375 acydburn
424 5375 acydburn
        /**
425 5375 acydburn
        * Delete file (DELETE)
426 6312 acydburn
        * @access private
427 5375 acydburn
        */
428 5375 acydburn
        function _delete($file)
429 5375 acydburn
        {
430 5375 acydburn
                return @ftp_delete($this->connection, $file);
431 5375 acydburn
        }
432 6048 acydburn
433 5375 acydburn
        /**
434 5375 acydburn
        * Close ftp session (CLOSE)
435 6312 acydburn
        * @access private
436 5375 acydburn
        */
437 5375 acydburn
        function _close()
438 5375 acydburn
        {
439 5416 acydburn
                if (!$this->connection)
440 5416 acydburn
                {
441 5416 acydburn
                        return false;
442 5416 acydburn
                }
443 5416 acydburn
444 5375 acydburn
                return @ftp_quit($this->connection);
445 5375 acydburn
        }
446 5375 acydburn
447 5375 acydburn
        /**
448 5375 acydburn
        * Return current working directory (CWD)
449 5375 acydburn
        * At the moment not used by parent class
450 6312 acydburn
        * @access private
451 5375 acydburn
        */
452 5375 acydburn
        function _cwd()
453 5375 acydburn
        {
454 5375 acydburn
                return @ftp_pwd($this->connection);
455 5375 acydburn
        }
456 5375 acydburn
457 5375 acydburn
        /**
458 5375 acydburn
        * Return list of files in a given directory (LS)
459 6312 acydburn
        * @access private
460 5375 acydburn
        */
461 5375 acydburn
        function _ls($dir = './')
462 5375 acydburn
        {
463 9433 acydburn
                $list = @ftp_nlist($this->connection, $dir);
464 9433 acydburn
465 9820 bantu
                // See bug #46295 - Some FTP daemons don't like './'
466 9820 bantu
                if ($dir === './')
467 9820 bantu
                {
468 9820 bantu
                        // Let's try some alternatives
469 9820 bantu
                        $list = (empty($list)) ? @ftp_nlist($this->connection, '.') : $list;
470 9820 bantu
                        $list = (empty($list)) ? @ftp_nlist($this->connection, '') : $list;
471 9820 bantu
                }
472 9820 bantu
473 9819 bantu
                // Return on error
474 9819 bantu
                if ($list === false)
475 9819 bantu
                {
476 9819 bantu
                        return false;
477 9819 bantu
                }
478 9819 bantu
479 9433 acydburn
                // Remove path if prepended
480 9433 acydburn
                foreach ($list as $key => $item)
481 9433 acydburn
                {
482 9433 acydburn
                        // Use same separator for item and dir
483 9433 acydburn
                        $item = str_replace('\\', '/', $item);
484 9433 acydburn
                        $dir = str_replace('\\', '/', $dir);
485 9433 acydburn
486 9822 bantu
                        if (!empty($dir) && strpos($item, $dir) === 0)
487 9433 acydburn
                        {
488 9433 acydburn
                                $item = substr($item, strlen($dir));
489 9433 acydburn
                        }
490 9433 acydburn
491 9433 acydburn
                        $list[$key] = $item;
492 9433 acydburn
                }
493 9433 acydburn
494 9433 acydburn
                return $list;
495 5375 acydburn
        }
496 5375 acydburn
497 5375 acydburn
        /**
498 5375 acydburn
        * FTP SITE command (ftp-only function)
499 6312 acydburn
        * @access private
500 5375 acydburn
        */
501 5375 acydburn
        function _site($command)
502 5375 acydburn
        {
503 5375 acydburn
                return @ftp_site($this->connection, $command);
504 5375 acydburn
        }
505 5375 acydburn
}
506 5375 acydburn
507 5870 acydburn
/**
508 5870 acydburn
* FTP fsock transfer class
509 6058 acydburn
*
510 5870 acydburn
* @author wGEric
511 6058 acydburn
* @package phpBB3
512 5870 acydburn
*/
513 5870 acydburn
class ftp_fsock extends transfer
514 5870 acydburn
{
515 5870 acydburn
        var $data_connection;
516 5870 acydburn
517 5870 acydburn
        /**
518 5870 acydburn
        * Standard parameters for FTP session
519 5870 acydburn
        */
520 5870 acydburn
        function ftp_fsock($host, $username, $password, $root_path, $port = 21, $timeout = 10)
521 5870 acydburn
        {
522 5870 acydburn
                $this->host                        = $host;
523 5870 acydburn
                $this->port                        = $port;
524 5870 acydburn
                $this->username                = $username;
525 5870 acydburn
                $this->password                = $password;
526 5870 acydburn
                $this->timeout                = $timeout;
527 5870 acydburn
528 6459 acydburn
                // Make sure $this->root_path is layed out the same way as the $user->page['root_script_path'] value (/ at the end)
529 5870 acydburn
                $this->root_path        = str_replace('\\', '/', $this->root_path);
530 5870 acydburn
531 6698 acydburn
                if (!empty($root_path))
532 6698 acydburn
                {
533 6698 acydburn
                        $this->root_path = (($root_path[0] != '/' ) ? '/' : '') . $root_path . ((substr($root_path, -1, 1) == '/') ? '' : '/');
534 6698 acydburn
                }
535 6698 acydburn
536 5870 acydburn
                // Init some needed values
537 5870 acydburn
                transfer::transfer();
538 5870 acydburn
539 5870 acydburn
                return;
540 5870 acydburn
        }
541 5870 acydburn
542 5870 acydburn
        /**
543 5870 acydburn
        * Requests data
544 5870 acydburn
        */
545 5870 acydburn
        function data()
546 5870 acydburn
        {
547 5870 acydburn
                global $user;
548 5870 acydburn
549 6048 acydburn
                return array(
550 6048 acydburn
                        'host'                => 'localhost',
551 6048 acydburn
                        'username'        => 'anonymous',
552 6048 acydburn
                        'password'        => '',
553 6048 acydburn
                        'root_path'        => $user->page['root_script_path'],
554 6048 acydburn
                        'port'                => 21,
555 6048 acydburn
                        'timeout'        => 10
556 6048 acydburn
                );
557 5870 acydburn
        }
558 5870 acydburn
559 5870 acydburn
        /**
560 5870 acydburn
        * Init FTP Session
561 6312 acydburn
        * @access private
562 5870 acydburn
        */
563 5870 acydburn
        function _init()
564 5870 acydburn
        {
565 5870 acydburn
                $errno = 0;
566 5870 acydburn
                $errstr = '';
567 5870 acydburn
568 5870 acydburn
                // connect to the server
569 5870 acydburn
                $this->connection = @fsockopen($this->host, $this->port, $errno, $errstr, $this->timeout);
570 5870 acydburn
571 5870 acydburn
                if (!$this->connection || !$this->_check_command())
572 5870 acydburn
                {
573 6048 acydburn
                        return 'ERR_CONNECTING_SERVER';
574 5870 acydburn
                }
575 5870 acydburn
576 5870 acydburn
                @stream_set_timeout($this->connection, $this->timeout);
577 5870 acydburn
578 5870 acydburn
                // login
579 5870 acydburn
                if (!$this->_send_command('USER', $this->username))
580 5870 acydburn
                {
581 6048 acydburn
                        return 'ERR_UNABLE_TO_LOGIN';
582 5870 acydburn
                }
583 5870 acydburn
584 5870 acydburn
                if (!$this->_send_command('PASS', $this->password))
585 5870 acydburn
                {
586 6048 acydburn
                        return 'ERR_UNABLE_TO_LOGIN';
587 5870 acydburn
                }
588 5870 acydburn
589 5870 acydburn
                // change to the root directory
590 5870 acydburn
                if (!$this->_chdir($this->root_path))
591 5870 acydburn
                {
592 6048 acydburn
                        return 'ERR_CHANGING_DIRECTORY';
593 5870 acydburn
                }
594 5870 acydburn
595 5870 acydburn
                return true;
596 5870 acydburn
        }
597 5870 acydburn
598 5870 acydburn
        /**
599 5870 acydburn
        * Create Directory (MKDIR)
600 6312 acydburn
        * @access private
601 5870 acydburn
        */
602 5870 acydburn
        function _mkdir($dir)
603 5870 acydburn
        {
604 5870 acydburn
                return $this->_send_command('MKD', $dir);
605 5870 acydburn
        }
606 5870 acydburn
607 5870 acydburn
        /**
608 5870 acydburn
        * Remove directory (RMDIR)
609 6312 acydburn
        * @access private
610 5870 acydburn
        */
611 5870 acydburn
        function _rmdir($dir)
612 5870 acydburn
        {
613 5870 acydburn
                return $this->_send_command('RMD', $dir);
614 5870 acydburn
        }
615 5870 acydburn
616 5870 acydburn
        /**
617 6139 acydburn
        * Rename File
618 6312 acydburn
        * @access private
619 6139 acydburn
        */
620 6139 acydburn
        function _rename($old_handle, $new_handle)
621 6139 acydburn
        {
622 6139 acydburn
                $this->_send_command('RNFR', $old_handle);
623 6139 acydburn
                return $this->_send_command('RNTO', $new_handle);
624 6139 acydburn
        }
625 6139 acydburn
626 6139 acydburn
        /**
627 5870 acydburn
        * Change current working directory (CHDIR)
628 6312 acydburn
        * @access private
629 5870 acydburn
        */
630 5870 acydburn
        function _chdir($dir = '')
631 5870 acydburn
        {
632 6730 acydburn
                if ($dir && $dir !== '/')
633 5870 acydburn
                {
634 6730 acydburn
                        if (substr($dir, -1, 1) == '/')
635 6730 acydburn
                        {
636 6730 acydburn
                                $dir = substr($dir, 0, -1);
637 6730 acydburn
                        }
638 5870 acydburn
                }
639 5870 acydburn
640 5870 acydburn
                return $this->_send_command('CWD', $dir);
641 5870 acydburn
        }
642 5870 acydburn
643 5870 acydburn
        /**
644 5870 acydburn
        * change file permissions (CHMOD)
645 6312 acydburn
        * @access private
646 5870 acydburn
        */
647 5870 acydburn
        function _chmod($file, $perms)
648 5870 acydburn
        {
649 7782 acydburn
                // Unfortunatly CHMOD is not expecting an octal value...
650 7782 acydburn
                // We need to transform the integer (which was an octal) to an octal representation (to get the int) and then pass as is. ;)
651 7782 acydburn
                return $this->_send_command('SITE CHMOD', base_convert($perms, 10, 8) . ' ' . $file);
652 5870 acydburn
        }
653 5870 acydburn
654 5870 acydburn
        /**
655 5870 acydburn
        * Upload file to location (PUT)
656 6312 acydburn
        * @access private
657 5870 acydburn
        */
658 5870 acydburn
        function _put($from_file, $to_file)
659 5870 acydburn
        {
660 5870 acydburn
                // We only use the BINARY file mode to cicumvent rewrite actions from ftp server (mostly linefeeds being replaced)
661 5870 acydburn
                // 'I' == BINARY
662 5870 acydburn
                // 'A' == ASCII
663 5870 acydburn
                if (!$this->_send_command('TYPE', 'I'))
664 5870 acydburn
                {
665 5870 acydburn
                        return false;
666 5870 acydburn
                }
667 5870 acydburn
668 5870 acydburn
                // open the connection to send file over
669 5870 acydburn
                if (!$this->_open_data_connection())
670 5870 acydburn
                {
671 5870 acydburn
                        return false;
672 5870 acydburn
                }
673 5870 acydburn
674 6139 acydburn
                $this->_send_command('STOR', $to_file, false);
675 6139 acydburn
676 5870 acydburn
                // send the file
677 5870 acydburn
                $fp = @fopen($from_file, 'rb');
678 5870 acydburn
                while (!@feof($fp))
679 5870 acydburn
                {
680 6139 acydburn
                        @fwrite($this->data_connection, @fread($fp, 4096));
681 5870 acydburn
                }
682 5870 acydburn
                @fclose($fp);
683 5870 acydburn
684 5870 acydburn
                // close connection
685 5870 acydburn
                $this->_close_data_connection();
686 5870 acydburn
687 5870 acydburn
                return $this->_check_command();
688 5870 acydburn
        }
689 5870 acydburn
690 5870 acydburn
        /**
691 5870 acydburn
        * Delete file (DELETE)
692 6312 acydburn
        * @access private
693 5870 acydburn
        */
694 5870 acydburn
        function _delete($file)
695 5870 acydburn
        {
696 5870 acydburn
                return $this->_send_command('DELE', $file);
697 5870 acydburn
        }
698 5870 acydburn
699 5870 acydburn
        /**
700 5870 acydburn
        * Close ftp session (CLOSE)
701 6312 acydburn
        * @access private
702 5870 acydburn
        */
703 5870 acydburn
        function _close()
704 5870 acydburn
        {
705 5870 acydburn
                if (!$this->connection)
706 5870 acydburn
                {
707 5870 acydburn
                        return false;
708 5870 acydburn
                }
709 5870 acydburn
710 5870 acydburn
                return $this->_send_command('QUIT');
711 5870 acydburn
        }
712 5870 acydburn
713 5870 acydburn
        /**
714 5870 acydburn
        * Return current working directory (CWD)
715 5870 acydburn
        * At the moment not used by parent class
716 6312 acydburn
        * @access private
717 5870 acydburn
        */
718 5870 acydburn
        function _cwd()
719 5870 acydburn
        {
720 5870 acydburn
                $this->_send_command('PWD', '', false);
721 5870 acydburn
                return preg_replace('#^[0-9]{3} "(.+)" .+\r\n#', '\\1', $this->_check_command(true));
722 5870 acydburn
        }
723 5870 acydburn
724 5870 acydburn
        /**
725 5870 acydburn
        * Return list of files in a given directory (LS)
726 6312 acydburn
        * @access private
727 5870 acydburn
        */
728 5870 acydburn
        function _ls($dir = './')
729 5870 acydburn
        {
730 5870 acydburn
                if (!$this->_open_data_connection())
731 5870 acydburn
                {
732 5870 acydburn
                        return false;
733 5870 acydburn
                }
734 5870 acydburn
735 5870 acydburn
                $this->_send_command('NLST', $dir);
736 5870 acydburn
737 5870 acydburn
                $list = array();
738 5870 acydburn
                while (!@feof($this->data_connection))
739 5870 acydburn
                {
740 9821 bantu
                        $filename = preg_replace('#[\r\n]#', '', @fgets($this->data_connection, 512));
741 9821 bantu
742 9821 bantu
                        if ($filename !== '')
743 9821 bantu
                        {
744 9821 bantu
                                $list[] = $filename;
745 9821 bantu
                        }
746 5870 acydburn
                }
747 5870 acydburn
                $this->_close_data_connection();
748 5870 acydburn
749 9433 acydburn
                // Clear buffer
750 9433 acydburn
                $this->_check_command();
751 9433 acydburn
752 9822 bantu
                // See bug #46295 - Some FTP daemons don't like './'
753 9822 bantu
                if ($dir === './' && empty($list))
754 9822 bantu
                {
755 9822 bantu
                        // Let's try some alternatives
756 9822 bantu
                        $list = $this->_ls('.');
757 9822 bantu
758 9822 bantu
                        if (empty($list))
759 9822 bantu
                        {
760 9822 bantu
                                $list = $this->_ls('');
761 9822 bantu
                        }
762 9822 bantu
763 9822 bantu
                        return $list;
764 9822 bantu
                }
765 9822 bantu
766 9433 acydburn
                // Remove path if prepended
767 9433 acydburn
                foreach ($list as $key => $item)
768 9433 acydburn
                {
769 9433 acydburn
                        // Use same separator for item and dir
770 9433 acydburn
                        $item = str_replace('\\', '/', $item);
771 9433 acydburn
                        $dir = str_replace('\\', '/', $dir);
772 9433 acydburn
773 9822 bantu
                        if (!empty($dir) && strpos($item, $dir) === 0)
774 9433 acydburn
                        {
775 9433 acydburn
                                $item = substr($item, strlen($dir));
776 9433 acydburn
                        }
777 9433 acydburn
778 9433 acydburn
                        $list[$key] = $item;
779 9433 acydburn
                }
780 9433 acydburn
781 5870 acydburn
                return $list;
782 5870 acydburn
        }
783 5870 acydburn
784 5870 acydburn
        /**
785 5870 acydburn
        * Send a command to server (FTP fsock only function)
786 6312 acydburn
        * @access private
787 5870 acydburn
        */
788 5870 acydburn
        function _send_command($command, $args = '', $check = true)
789 5870 acydburn
        {
790 5870 acydburn
                if (!empty($args))
791 5870 acydburn
                {
792 5870 acydburn
                        $command = "$command $args";
793 5870 acydburn
                }
794 5870 acydburn
795 5870 acydburn
                fwrite($this->connection, $command . "\r\n");
796 5870 acydburn
797 5870 acydburn
                if ($check === true && !$this->_check_command())
798 5870 acydburn
                {
799 5870 acydburn
                        return false;
800 5870 acydburn
                }
801 5870 acydburn
802 5870 acydburn
                return true;
803 5870 acydburn
        }
804 5870 acydburn
805 5870 acydburn
        /**
806 5870 acydburn
        * Opens a connection to send data (FTP fosck only function)
807 6312 acydburn
        * @access private
808 5870 acydburn
        */
809 5870 acydburn
        function _open_data_connection()
810 5870 acydburn
        {
811 11360 git-gate
                // Try to find out whether we have a IPv4 or IPv6 (control) connection
812 11360 git-gate
                if (function_exists('stream_socket_get_name'))
813 5870 acydburn
                {
814 11360 git-gate
                        $socket_name = stream_socket_get_name($this->connection, true);
815 11360 git-gate
                        $server_ip = substr($socket_name, 0, strrpos($socket_name, ':'));
816 5870 acydburn
                }
817 5870 acydburn
818 11360 git-gate
                if (!isset($server_ip) || preg_match(get_preg_expression('ipv4'), $server_ip))
819 5870 acydburn
                {
820 11360 git-gate
                        // Passive mode
821 11360 git-gate
                        $this->_send_command('PASV', '', false);
822 11360 git-gate
823 11360 git-gate
                        if (!$ip_port = $this->_check_command(true))
824 11360 git-gate
                        {
825 11360 git-gate
                                return false;
826 11360 git-gate
                        }
827 11360 git-gate
828 11360 git-gate
                        // open the connection to start sending the file
829 11360 git-gate
                        if (!preg_match('#[0-9]{1,3},[0-9]{1,3},[0-9]{1,3},[0-9]{1,3},[0-9]+,[0-9]+#', $ip_port, $temp))
830 11360 git-gate
                        {
831 11360 git-gate
                                // bad ip and port
832 11360 git-gate
                                return false;
833 11360 git-gate
                        }
834 11360 git-gate
835 11360 git-gate
                        $temp = explode(',', $temp[0]);
836 11360 git-gate
                        $server_ip = $temp[0] . '.' . $temp[1] . '.' . $temp[2] . '.' . $temp[3];
837 11360 git-gate
                        $server_port = $temp[4] * 256 + $temp[5];
838 5870 acydburn
                }
839 11360 git-gate
                else
840 11360 git-gate
                {
841 11360 git-gate
                        // Extended Passive Mode - RFC2428
842 11360 git-gate
                        $this->_send_command('EPSV', '', false);
843 5870 acydburn
844 11360 git-gate
                        if (!$epsv_response = $this->_check_command(true))
845 11360 git-gate
                        {
846 11360 git-gate
                                return false;
847 11360 git-gate
                        }
848 11360 git-gate
849 11360 git-gate
                        // Response looks like "229 Entering Extended Passive Mode (|||12345|)"
850 11360 git-gate
                        // where 12345 is the tcp port for the data connection
851 11360 git-gate
                        if (!preg_match('#\(\|\|\|([0-9]+)\|\)#', $epsv_response, $match))
852 11360 git-gate
                        {
853 11360 git-gate
                                return false;
854 11360 git-gate
                        }
855 11360 git-gate
                        $server_port = (int) $match[1];
856 11360 git-gate
857 11360 git-gate
                        // fsockopen expects IPv6 address in square brackets
858 11360 git-gate
                        $server_ip = "[$server_ip]";
859 11360 git-gate
                }
860 11360 git-gate
861 5870 acydburn
                $errno = 0;
862 5870 acydburn
                $errstr = '';
863 5870 acydburn
864 5870 acydburn
                if (!$this->data_connection = @fsockopen($server_ip, $server_port, $errno, $errstr, $this->timeout))
865 5870 acydburn
                {
866 5870 acydburn
                        return false;
867 5870 acydburn
                }
868 6139 acydburn
                @stream_set_timeout($this->data_connection, $this->timeout);
869 5870 acydburn
870 5870 acydburn
                return true;
871 5870 acydburn
        }
872 5870 acydburn
873 5870 acydburn
        /**
874 5870 acydburn
        * Closes a connection used to send data
875 6312 acydburn
        * @access private
876 5870 acydburn
        */
877 5870 acydburn
        function _close_data_connection()
878 5870 acydburn
        {
879 6139 acydburn
                return @fclose($this->data_connection);
880 5870 acydburn
        }
881 5870 acydburn
882 5870 acydburn
        /**
883 5870 acydburn
        * Check to make sure command was successful (FTP fsock only function)
884 6312 acydburn
        * @access private
885 5870 acydburn
        */
886 5870 acydburn
        function _check_command($return = false)
887 5870 acydburn
        {
888 5870 acydburn
                $response = '';
889 5870 acydburn
890 5870 acydburn
                do
891 5870 acydburn
                {
892 5870 acydburn
                        $result = @fgets($this->connection, 512);
893 5870 acydburn
                        $response .= $result;
894 5870 acydburn
                }
895 9821 bantu
                while (substr($result, 3, 1) !== ' ');
896 5870 acydburn
897 5870 acydburn
                if (!preg_match('#^[123]#', $response))
898 5870 acydburn
                {
899 5870 acydburn
                        return false;
900 5870 acydburn
                }
901 5870 acydburn
902 5870 acydburn
                return ($return) ? $response : true;
903 5870 acydburn
        }
904 5870 acydburn
}
905 5870 acydburn
906 5375 acydburn
?>