Verzeichnisstruktur phpBB-3.1.0


Veröffentlicht
27.10.2014

So funktioniert es


Auf das letzte Element klicken. Dies geht jeweils ein Schritt zurück

Auf das Icon klicken, dies öffnet das Verzeichnis. Nochmal klicken schließt das Verzeichnis.
Auf den Verzeichnisnamen klicken, dies zeigt nur das Verzeichnis mit Inhalt an

(Beispiel Datei-Icons)

Auf das Icon klicken um den Quellcode anzuzeigen

functions_transfer.php

Zuletzt modifiziert: 09.10.2024, 12:51 - Dateigröße: 17.53 KiB


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