Verzeichnisstruktur phpBB-3.2.0


Veröffentlicht
06.01.2017

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.43 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          // We only use the BINARY file mode to cicumvent rewrite actions from ftp server (mostly linefeeds being replaced)
410          $mode = FTP_BINARY;
411   
412          $to_dir = dirname($to_file);
413          $to_file = basename($to_file);
414          $this->_chdir($to_dir);
415   
416          $result = @ftp_put($this->connection, $to_file, $from_file, $mode);
417          $this->_chdir($this->root_path);
418   
419          return $result;
420      }
421   
422      /**
423      * Delete file (DELETE)
424      * @access private
425      */
426      function _delete($file)
427      {
428          return @ftp_delete($this->connection, $file);
429      }
430   
431      /**
432      * Close ftp session (CLOSE)
433      * @access private
434      */
435      function _close()
436      {
437          if (!$this->connection)
438          {
439              return false;
440          }
441   
442          return @ftp_quit($this->connection);
443      }
444   
445      /**
446      * Return current working directory (CWD)
447      * At the moment not used by parent class
448      * @access private
449      */
450      function _cwd()
451      {
452          return @ftp_pwd($this->connection);
453      }
454   
455      /**
456      * Return list of files in a given directory (LS)
457      * @access private
458      */
459      function _ls($dir = './')
460      {
461          $list = @ftp_nlist($this->connection, $dir);
462   
463          // See bug #46295 - Some FTP daemons don't like './'
464          if ($dir === './')
465          {
466              // Let's try some alternatives
467              $list = (empty($list)) ? @ftp_nlist($this->connection, '.') : $list;
468              $list = (empty($list)) ? @ftp_nlist($this->connection, '') : $list;
469          }
470   
471          // Return on error
472          if ($list === false)
473          {
474              return false;
475          }
476   
477          // Remove path if prepended
478          foreach ($list as $key => $item)
479          {
480              // Use same separator for item and dir
481              $item = str_replace('\\', '/', $item);
482              $dir = str_replace('\\', '/', $dir);
483   
484              if (!empty($dir) && strpos($item, $dir) === 0)
485              {
486                  $item = substr($item, strlen($dir));
487              }
488   
489              $list[$key] = $item;
490          }
491   
492          return $list;
493      }
494   
495      /**
496      * FTP SITE command (ftp-only function)
497      * @access private
498      */
499      function _site($command)
500      {
501          return @ftp_site($this->connection, $command);
502      }
503  }
504   
505  /**
506  * FTP fsock transfer class
507  */
508  class ftp_fsock extends transfer
509  {
510      var $data_connection;
511   
512      /**
513      * Standard parameters for FTP session
514      */
515      function ftp_fsock($host, $username, $password, $root_path, $port = 21, $timeout = 10)
516      {
517          $this->host            = $host;
518          $this->port            = $port;
519          $this->username        = $username;
520          $this->password        = $password;
521          $this->timeout        = $timeout;
522   
523          // Make sure $this->root_path is layed out the same way as the $user->page['root_script_path'] value (/ at the end)
524          $this->root_path    = str_replace('\\', '/', $this->root_path);
525   
526          if (!empty($root_path))
527          {
528              $this->root_path = (($root_path[0] != '/' ) ? '/' : '') . $root_path . ((substr($root_path, -1, 1) == '/') ? '' : '/');
529          }
530   
531          // Init some needed values
532          $this->transfer();
533   
534          return;
535      }
536   
537      /**
538      * Requests data
539      */
540      static public function data()
541      {
542          global $user;
543   
544          return array(
545              'host'        => 'localhost',
546              'username'    => 'anonymous',
547              'password'    => '',
548              'root_path'    => $user->page['root_script_path'],
549              'port'        => 21,
550              'timeout'    => 10
551          );
552      }
553   
554      /**
555      * Init FTP Session
556      * @access private
557      */
558      function _init()
559      {
560          $errno = 0;
561          $errstr = '';
562   
563          // connect to the server
564          $this->connection = @fsockopen($this->host, $this->port, $errno, $errstr, $this->timeout);
565   
566          if (!$this->connection || !$this->_check_command())
567          {
568              return 'ERR_CONNECTING_SERVER';
569          }
570   
571          @stream_set_timeout($this->connection, $this->timeout);
572   
573          // login
574          if (!$this->_send_command('USER', $this->username))
575          {
576              return 'ERR_UNABLE_TO_LOGIN';
577          }
578   
579          if (!$this->_send_command('PASS', $this->password))
580          {
581              return 'ERR_UNABLE_TO_LOGIN';
582          }
583   
584          // change to the root directory
585          if (!$this->_chdir($this->root_path))
586          {
587              return 'ERR_CHANGING_DIRECTORY';
588          }
589   
590          return true;
591      }
592   
593      /**
594      * Create Directory (MKDIR)
595      * @access private
596      */
597      function _mkdir($dir)
598      {
599          return $this->_send_command('MKD', $dir);
600      }
601   
602      /**
603      * Remove directory (RMDIR)
604      * @access private
605      */
606      function _rmdir($dir)
607      {
608          return $this->_send_command('RMD', $dir);
609      }
610   
611      /**
612      * Rename File
613      * @access private
614      */
615      function _rename($old_handle, $new_handle)
616      {
617          $this->_send_command('RNFR', $old_handle);
618          return $this->_send_command('RNTO', $new_handle);
619      }
620   
621      /**
622      * Change current working directory (CHDIR)
623      * @access private
624      */
625      function _chdir($dir = '')
626      {
627          if ($dir && $dir !== '/')
628          {
629              if (substr($dir, -1, 1) == '/')
630              {
631                  $dir = substr($dir, 0, -1);
632              }
633          }
634   
635          return $this->_send_command('CWD', $dir);
636      }
637   
638      /**
639      * change file permissions (CHMOD)
640      * @access private
641      */
642      function _chmod($file, $perms)
643      {
644          // Unfortunatly CHMOD is not expecting an octal value...
645          // We need to transform the integer (which was an octal) to an octal representation (to get the int) and then pass as is. ;)
646          return $this->_send_command('SITE CHMOD', base_convert($perms, 10, 8) . ' ' . $file);
647      }
648   
649      /**
650      * Upload file to location (PUT)
651      * @access private
652      */
653      function _put($from_file, $to_file)
654      {
655          // We only use the BINARY file mode to cicumvent rewrite actions from ftp server (mostly linefeeds being replaced)
656          // 'I' == BINARY
657          // 'A' == ASCII
658          if (!$this->_send_command('TYPE', 'I'))
659          {
660              return false;
661          }
662   
663          // open the connection to send file over
664          if (!$this->_open_data_connection())
665          {
666              return false;
667          }
668   
669          $this->_send_command('STOR', $to_file, false);
670   
671          // send the file
672          $fp = @fopen($from_file, 'rb');
673          while (!@feof($fp))
674          {
675              @fwrite($this->data_connection, @fread($fp, 4096));
676          }
677          @fclose($fp);
678   
679          // close connection
680          $this->_close_data_connection();
681   
682          return $this->_check_command();
683      }
684   
685      /**
686      * Delete file (DELETE)
687      * @access private
688      */
689      function _delete($file)
690      {
691          return $this->_send_command('DELE', $file);
692      }
693   
694      /**
695      * Close ftp session (CLOSE)
696      * @access private
697      */
698      function _close()
699      {
700          if (!$this->connection)
701          {
702              return false;
703          }
704   
705          return $this->_send_command('QUIT');
706      }
707   
708      /**
709      * Return current working directory (CWD)
710      * At the moment not used by parent class
711      * @access private
712      */
713      function _cwd()
714      {
715          $this->_send_command('PWD', '', false);
716          return preg_replace('#^[0-9]{3} "(.+)" .+\r\n#', '\\1', $this->_check_command(true));
717      }
718   
719      /**
720      * Return list of files in a given directory (LS)
721      * @access private
722      */
723      function _ls($dir = './')
724      {
725          if (!$this->_open_data_connection())
726          {
727              return false;
728          }
729   
730          $this->_send_command('NLST', $dir);
731   
732          $list = array();
733          while (!@feof($this->data_connection))
734          {
735              $filename = preg_replace('#[\r\n]#', '', @fgets($this->data_connection, 512));
736   
737              if ($filename !== '')
738              {
739                  $list[] = $filename;
740              }
741          }
742          $this->_close_data_connection();
743   
744          // Clear buffer
745          $this->_check_command();
746   
747          // See bug #46295 - Some FTP daemons don't like './'
748          if ($dir === './' && empty($list))
749          {
750              // Let's try some alternatives
751              $list = $this->_ls('.');
752   
753              if (empty($list))
754              {
755                  $list = $this->_ls('');
756              }
757   
758              return $list;
759          }
760   
761          // Remove path if prepended
762          foreach ($list as $key => $item)
763          {
764              // Use same separator for item and dir
765              $item = str_replace('\\', '/', $item);
766              $dir = str_replace('\\', '/', $dir);
767   
768              if (!empty($dir) && strpos($item, $dir) === 0)
769              {
770                  $item = substr($item, strlen($dir));
771              }
772   
773              $list[$key] = $item;
774          }
775   
776          return $list;
777      }
778   
779      /**
780      * Send a command to server (FTP fsock only function)
781      * @access private
782      */
783      function _send_command($command, $args = '', $check = true)
784      {
785          if (!empty($args))
786          {
787              $command = "$command $args";
788          }
789   
790          fwrite($this->connection, $command . "\r\n");
791   
792          if ($check === true && !$this->_check_command())
793          {
794              return false;
795          }
796   
797          return true;
798      }
799   
800      /**
801      * Opens a connection to send data (FTP fosck only function)
802      * @access private
803      */
804      function _open_data_connection()
805      {
806          // Try to find out whether we have a IPv4 or IPv6 (control) connection
807          if (function_exists('stream_socket_get_name'))
808          {
809              $socket_name = stream_socket_get_name($this->connection, true);
810              $server_ip = substr($socket_name, 0, strrpos($socket_name, ':'));
811          }
812   
813          if (!isset($server_ip) || preg_match(get_preg_expression('ipv4'), $server_ip))
814          {
815              // Passive mode
816              $this->_send_command('PASV', '', false);
817   
818              if (!$ip_port = $this->_check_command(true))
819              {
820                  return false;
821              }
822   
823              // open the connection to start sending the file
824              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))
825              {
826                  // bad ip and port
827                  return false;
828              }
829   
830              $temp = explode(',', $temp[0]);
831              $server_ip = $temp[0] . '.' . $temp[1] . '.' . $temp[2] . '.' . $temp[3];
832              $server_port = $temp[4] * 256 + $temp[5];
833          }
834          else
835          {
836              // Extended Passive Mode - RFC2428
837              $this->_send_command('EPSV', '', false);
838   
839              if (!$epsv_response = $this->_check_command(true))
840              {
841                  return false;
842              }
843   
844              // Response looks like "229 Entering Extended Passive Mode (|||12345|)"
845              // where 12345 is the tcp port for the data connection
846              if (!preg_match('#\(\|\|\|([0-9]+)\|\)#', $epsv_response, $match))
847              {
848                  return false;
849              }
850              $server_port = (int) $match[1];
851   
852              // fsockopen expects IPv6 address in square brackets
853              $server_ip = "[$server_ip]";
854          }
855   
856          $errno = 0;
857          $errstr = '';
858   
859          if (!$this->data_connection = @fsockopen($server_ip, $server_port, $errno, $errstr, $this->timeout))
860          {
861              return false;
862          }
863          @stream_set_timeout($this->data_connection, $this->timeout);
864   
865          return true;
866      }
867   
868      /**
869      * Closes a connection used to send data
870      * @access private
871      */
872      function _close_data_connection()
873      {
874          return @fclose($this->data_connection);
875      }
876   
877      /**
878      * Check to make sure command was successful (FTP fsock only function)
879      * @access private
880      */
881      function _check_command($return = false)
882      {
883          $response = '';
884   
885          do
886          {
887              $result = @fgets($this->connection, 512);
888              $response .= $result;
889          }
890          while (substr($result, 3, 1) !== ' ');
891   
892          if (!preg_match('#^[123]#', $response))
893          {
894              return false;
895          }
896   
897          return ($return) ? $response : true;
898      }
899  }
900