phpBB
Statistics
| Revision:

root / trunk / phpBB / includes / functions_transfer.php

History | View | Annotate | Download (17.4 kB)

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