Subversion Repositories oidplus

Rev

Rev 846 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

  1. <?php
  2.  
  3. /**
  4.  * SFTP Stream Wrapper
  5.  *
  6.  * Creates an sftp:// protocol handler that can be used with, for example, fopen(), dir(), etc.
  7.  *
  8.  * PHP version 5
  9.  *
  10.  * @category  Net
  11.  * @package   SFTP
  12.  * @author    Jim Wigginton <terrafrost@php.net>
  13.  * @copyright 2013 Jim Wigginton
  14.  * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
  15.  * @link      http://phpseclib.sourceforge.net
  16.  */
  17.  
  18. namespace phpseclib3\Net\SFTP;
  19.  
  20. use phpseclib3\Crypt\Common\PrivateKey;
  21. use phpseclib3\Net\SFTP;
  22. use phpseclib3\Net\SSH2;
  23.  
  24. /**
  25.  * SFTP Stream Wrapper
  26.  *
  27.  * @package SFTP
  28.  * @author  Jim Wigginton <terrafrost@php.net>
  29.  * @access  public
  30.  */
  31. class Stream
  32. {
  33.     /**
  34.      * SFTP instances
  35.      *
  36.      * Rather than re-create the connection we re-use instances if possible
  37.      *
  38.      * @var array
  39.      */
  40.     public static $instances;
  41.  
  42.     /**
  43.      * SFTP instance
  44.      *
  45.      * @var object
  46.      * @access private
  47.      */
  48.     private $sftp;
  49.  
  50.     /**
  51.      * Path
  52.      *
  53.      * @var string
  54.      * @access private
  55.      */
  56.     private $path;
  57.  
  58.     /**
  59.      * Mode
  60.      *
  61.      * @var string
  62.      * @access private
  63.      */
  64.     private $mode;
  65.  
  66.     /**
  67.      * Position
  68.      *
  69.      * @var int
  70.      * @access private
  71.      */
  72.     private $pos;
  73.  
  74.     /**
  75.      * Size
  76.      *
  77.      * @var int
  78.      * @access private
  79.      */
  80.     private $size;
  81.  
  82.     /**
  83.      * Directory entries
  84.      *
  85.      * @var array
  86.      * @access private
  87.      */
  88.     private $entries;
  89.  
  90.     /**
  91.      * EOF flag
  92.      *
  93.      * @var bool
  94.      * @access private
  95.      */
  96.     private $eof;
  97.  
  98.     /**
  99.      * Context resource
  100.      *
  101.      * Technically this needs to be publicly accessible so PHP can set it directly
  102.      *
  103.      * @var resource
  104.      * @access public
  105.      */
  106.     public $context;
  107.  
  108.     /**
  109.      * Notification callback function
  110.      *
  111.      * @var callable
  112.      * @access public
  113.      */
  114.     private $notification;
  115.  
  116.     /**
  117.      * Registers this class as a URL wrapper.
  118.      *
  119.      * @param string $protocol The wrapper name to be registered.
  120.      * @return bool True on success, false otherwise.
  121.      * @access public
  122.      */
  123.     public static function register($protocol = 'sftp')
  124.     {
  125.         if (in_array($protocol, stream_get_wrappers(), true)) {
  126.             return false;
  127.         }
  128.         return stream_wrapper_register($protocol, get_called_class());
  129.     }
  130.  
  131.     /**
  132.      * The Constructor
  133.      *
  134.      * @access public
  135.      */
  136.     public function __construct()
  137.     {
  138.         if (defined('NET_SFTP_STREAM_LOGGING')) {
  139.             echo "__construct()\r\n";
  140.         }
  141.     }
  142.  
  143.     /**
  144.      * Path Parser
  145.      *
  146.      * Extract a path from a URI and actually connect to an SSH server if appropriate
  147.      *
  148.      * If "notification" is set as a context parameter the message code for successful login is
  149.      * NET_SSH2_MSG_USERAUTH_SUCCESS. For a failed login it's NET_SSH2_MSG_USERAUTH_FAILURE.
  150.      *
  151.      * @param string $path
  152.      * @return string
  153.      * @access private
  154.      */
  155.     protected function parse_path($path)
  156.     {
  157.         $orig = $path;
  158.         extract(parse_url($path) + ['port' => 22]);
  159.         if (isset($query)) {
  160.             $path .= '?' . $query;
  161.         } elseif (preg_match('/(\?|\?#)$/', $orig)) {
  162.             $path .= '?';
  163.         }
  164.         if (isset($fragment)) {
  165.             $path .= '#' . $fragment;
  166.         } elseif ($orig[strlen($orig) - 1] == '#') {
  167.             $path .= '#';
  168.         }
  169.  
  170.         if (!isset($host)) {
  171.             return false;
  172.         }
  173.  
  174.         if (isset($this->context)) {
  175.             $context = stream_context_get_params($this->context);
  176.             if (isset($context['notification'])) {
  177.                 $this->notification = $context['notification'];
  178.             }
  179.         }
  180.  
  181.         if (preg_match('/^{[a-z0-9]+}$/i', $host)) {
  182.             $host = SSH2::getConnectionByResourceId($host);
  183.             if ($host === false) {
  184.                 return false;
  185.             }
  186.             $this->sftp = $host;
  187.         } else {
  188.             if (isset($this->context)) {
  189.                 $context = stream_context_get_options($this->context);
  190.             }
  191.             if (isset($context[$scheme]['session'])) {
  192.                 $sftp = $context[$scheme]['session'];
  193.             }
  194.             if (isset($context[$scheme]['sftp'])) {
  195.                 $sftp = $context[$scheme]['sftp'];
  196.             }
  197.             if (isset($sftp) && $sftp instanceof SFTP) {
  198.                 $this->sftp = $sftp;
  199.                 return $path;
  200.             }
  201.             if (isset($context[$scheme]['username'])) {
  202.                 $user = $context[$scheme]['username'];
  203.             }
  204.             if (isset($context[$scheme]['password'])) {
  205.                 $pass = $context[$scheme]['password'];
  206.             }
  207.             if (isset($context[$scheme]['privkey']) && $context[$scheme]['privkey'] instanceof PrivateKey) {
  208.                 $pass = $context[$scheme]['privkey'];
  209.             }
  210.  
  211.             if (!isset($user) || !isset($pass)) {
  212.                 return false;
  213.             }
  214.  
  215.             // casting $pass to a string is necessary in the event that it's a \phpseclib3\Crypt\RSA object
  216.             if (isset(self::$instances[$host][$port][$user][(string) $pass])) {
  217.                 $this->sftp = self::$instances[$host][$port][$user][(string) $pass];
  218.             } else {
  219.                 $this->sftp = new SFTP($host, $port);
  220.                 $this->sftp->disableStatCache();
  221.                 if (isset($this->notification) && is_callable($this->notification)) {
  222.                     /* if !is_callable($this->notification) we could do this:
  223.  
  224.                        user_error('fopen(): failed to call user notifier', E_USER_WARNING);
  225.  
  226.                        the ftp wrapper gives errors like that when the notifier isn't callable.
  227.                        i've opted not to do that, however, since the ftp wrapper gives the line
  228.                        on which the fopen occurred as the line number - not the line that the
  229.                        user_error is on.
  230.                     */
  231.                     call_user_func($this->notification, STREAM_NOTIFY_CONNECT, STREAM_NOTIFY_SEVERITY_INFO, '', 0, 0, 0);
  232.                     call_user_func($this->notification, STREAM_NOTIFY_AUTH_REQUIRED, STREAM_NOTIFY_SEVERITY_INFO, '', 0, 0, 0);
  233.                     if (!$this->sftp->login($user, $pass)) {
  234.                         call_user_func($this->notification, STREAM_NOTIFY_AUTH_RESULT, STREAM_NOTIFY_SEVERITY_ERR, 'Login Failure', NET_SSH2_MSG_USERAUTH_FAILURE, 0, 0);
  235.                         return false;
  236.                     }
  237.                     call_user_func($this->notification, STREAM_NOTIFY_AUTH_RESULT, STREAM_NOTIFY_SEVERITY_INFO, 'Login Success', NET_SSH2_MSG_USERAUTH_SUCCESS, 0, 0);
  238.                 } else {
  239.                     if (!$this->sftp->login($user, $pass)) {
  240.                         return false;
  241.                     }
  242.                 }
  243.                 self::$instances[$host][$port][$user][(string) $pass] = $this->sftp;
  244.             }
  245.         }
  246.  
  247.         return $path;
  248.     }
  249.  
  250.     /**
  251.      * Opens file or URL
  252.      *
  253.      * @param string $path
  254.      * @param string $mode
  255.      * @param int $options
  256.      * @param string $opened_path
  257.      * @return bool
  258.      * @access public
  259.      */
  260.     private function _stream_open($path, $mode, $options, &$opened_path)
  261.     {
  262.         $path = $this->parse_path($path);
  263.  
  264.         if ($path === false) {
  265.             return false;
  266.         }
  267.         $this->path = $path;
  268.  
  269.         $this->size = $this->sftp->filesize($path);
  270.         $this->mode = preg_replace('#[bt]$#', '', $mode);
  271.         $this->eof = false;
  272.  
  273.         if ($this->size === false) {
  274.             if ($this->mode[0] == 'r') {
  275.                 return false;
  276.             } else {
  277.                 $this->sftp->touch($path);
  278.                 $this->size = 0;
  279.             }
  280.         } else {
  281.             switch ($this->mode[0]) {
  282.                 case 'x':
  283.                     return false;
  284.                 case 'w':
  285.                     $this->sftp->truncate($path, 0);
  286.                     $this->size = 0;
  287.             }
  288.         }
  289.  
  290.         $this->pos = $this->mode[0] != 'a' ? 0 : $this->size;
  291.  
  292.         return true;
  293.     }
  294.  
  295.     /**
  296.      * Read from stream
  297.      *
  298.      * @param int $count
  299.      * @return mixed
  300.      * @access public
  301.      */
  302.     private function _stream_read($count)
  303.     {
  304.         switch ($this->mode) {
  305.             case 'w':
  306.             case 'a':
  307.             case 'x':
  308.             case 'c':
  309.                 return false;
  310.         }
  311.  
  312.         // commented out because some files - eg. /dev/urandom - will say their size is 0 when in fact it's kinda infinite
  313.         //if ($this->pos >= $this->size) {
  314.         //    $this->eof = true;
  315.         //    return false;
  316.         //}
  317.  
  318.         $result = $this->sftp->get($this->path, false, $this->pos, $count);
  319.         if (isset($this->notification) && is_callable($this->notification)) {
  320.             if ($result === false) {
  321.                 call_user_func($this->notification, STREAM_NOTIFY_FAILURE, STREAM_NOTIFY_SEVERITY_ERR, $this->sftp->getLastSFTPError(), NET_SFTP_OPEN, 0, 0);
  322.                 return 0;
  323.             }
  324.             // seems that PHP calls stream_read in 8k chunks
  325.             call_user_func($this->notification, STREAM_NOTIFY_PROGRESS, STREAM_NOTIFY_SEVERITY_INFO, '', 0, strlen($result), $this->size);
  326.         }
  327.  
  328.         if (empty($result)) { // ie. false or empty string
  329.             $this->eof = true;
  330.             return false;
  331.         }
  332.         $this->pos += strlen($result);
  333.  
  334.         return $result;
  335.     }
  336.  
  337.     /**
  338.      * Write to stream
  339.      *
  340.      * @param string $data
  341.      * @return int|false
  342.      * @access public
  343.      */
  344.     private function _stream_write($data)
  345.     {
  346.         switch ($this->mode) {
  347.             case 'r':
  348.                 return false;
  349.         }
  350.  
  351.         $result = $this->sftp->put($this->path, $data, SFTP::SOURCE_STRING, $this->pos);
  352.         if (isset($this->notification) && is_callable($this->notification)) {
  353.             if (!$result) {
  354.                 call_user_func($this->notification, STREAM_NOTIFY_FAILURE, STREAM_NOTIFY_SEVERITY_ERR, $this->sftp->getLastSFTPError(), NET_SFTP_OPEN, 0, 0);
  355.                 return 0;
  356.             }
  357.             // seems that PHP splits up strings into 8k blocks before calling stream_write
  358.             call_user_func($this->notification, STREAM_NOTIFY_PROGRESS, STREAM_NOTIFY_SEVERITY_INFO, '', 0, strlen($data), strlen($data));
  359.         }
  360.  
  361.         if ($result === false) {
  362.             return false;
  363.         }
  364.         $this->pos += strlen($data);
  365.         if ($this->pos > $this->size) {
  366.             $this->size = $this->pos;
  367.         }
  368.         $this->eof = false;
  369.         return strlen($data);
  370.     }
  371.  
  372.     /**
  373.      * Retrieve the current position of a stream
  374.      *
  375.      * @return int
  376.      * @access public
  377.      */
  378.     private function _stream_tell()
  379.     {
  380.         return $this->pos;
  381.     }
  382.  
  383.     /**
  384.      * Tests for end-of-file on a file pointer
  385.      *
  386.      * In my testing there are four classes functions that normally effect the pointer:
  387.      * fseek, fputs  / fwrite, fgets / fread and ftruncate.
  388.      *
  389.      * Only fgets / fread, however, results in feof() returning true. do fputs($fp, 'aaa') on a blank file and feof()
  390.      * will return false. do fread($fp, 1) and feof() will then return true. do fseek($fp, 10) on ablank file and feof()
  391.      * will return false. do fread($fp, 1) and feof() will then return true.
  392.      *
  393.      * @return bool
  394.      * @access public
  395.      */
  396.     private function _stream_eof()
  397.     {
  398.         return $this->eof;
  399.     }
  400.  
  401.     /**
  402.      * Seeks to specific location in a stream
  403.      *
  404.      * @param int $offset
  405.      * @param int $whence
  406.      * @return bool
  407.      * @access public
  408.      */
  409.     private function _stream_seek($offset, $whence)
  410.     {
  411.         switch ($whence) {
  412.             case SEEK_SET:
  413.                 if ($offset < 0) {
  414.                     return false;
  415.                 }
  416.                 break;
  417.             case SEEK_CUR:
  418.                 $offset += $this->pos;
  419.                 break;
  420.             case SEEK_END:
  421.                 $offset += $this->size;
  422.         }
  423.  
  424.         $this->pos = $offset;
  425.         $this->eof = false;
  426.         return true;
  427.     }
  428.  
  429.     /**
  430.      * Change stream options
  431.      *
  432.      * @param string $path
  433.      * @param int $option
  434.      * @param mixed $var
  435.      * @return bool
  436.      * @access public
  437.      */
  438.     private function _stream_metadata($path, $option, $var)
  439.     {
  440.         $path = $this->parse_path($path);
  441.         if ($path === false) {
  442.             return false;
  443.         }
  444.  
  445.         // stream_metadata was introduced in PHP 5.4.0 but as of 5.4.11 the constants haven't been defined
  446.         // see http://www.php.net/streamwrapper.stream-metadata and https://bugs.php.net/64246
  447.         //     and https://github.com/php/php-src/blob/master/main/php_streams.h#L592
  448.         switch ($option) {
  449.             case 1: // PHP_STREAM_META_TOUCH
  450.                 $time = isset($var[0]) ? $var[0] : null;
  451.                 $atime = isset($var[1]) ? $var[1] : null;
  452.                 return $this->sftp->touch($path, $time, $atime);
  453.             case 2: // PHP_STREAM_OWNER_NAME
  454.             case 3: // PHP_STREAM_GROUP_NAME
  455.                 return false;
  456.             case 4: // PHP_STREAM_META_OWNER
  457.                 return $this->sftp->chown($path, $var);
  458.             case 5: // PHP_STREAM_META_GROUP
  459.                 return $this->sftp->chgrp($path, $var);
  460.             case 6: // PHP_STREAM_META_ACCESS
  461.                 return $this->sftp->chmod($path, $var) !== false;
  462.         }
  463.     }
  464.  
  465.     /**
  466.      * Retrieve the underlaying resource
  467.      *
  468.      * @param int $cast_as
  469.      * @return resource
  470.      * @access public
  471.      */
  472.     private function _stream_cast($cast_as)
  473.     {
  474.         return $this->sftp->fsock;
  475.     }
  476.  
  477.     /**
  478.      * Advisory file locking
  479.      *
  480.      * @param int $operation
  481.      * @return bool
  482.      * @access public
  483.      */
  484.     private function _stream_lock($operation)
  485.     {
  486.         return false;
  487.     }
  488.  
  489.     /**
  490.      * Renames a file or directory
  491.      *
  492.      * Attempts to rename oldname to newname, moving it between directories if necessary.
  493.      * If newname exists, it will be overwritten.  This is a departure from what \phpseclib3\Net\SFTP
  494.      * does.
  495.      *
  496.      * @param string $path_from
  497.      * @param string $path_to
  498.      * @return bool
  499.      * @access public
  500.      */
  501.     private function _rename($path_from, $path_to)
  502.     {
  503.         $path1 = parse_url($path_from);
  504.         $path2 = parse_url($path_to);
  505.         unset($path1['path'], $path2['path']);
  506.         if ($path1 != $path2) {
  507.             return false;
  508.         }
  509.  
  510.         $path_from = $this->parse_path($path_from);
  511.         $path_to = parse_url($path_to);
  512.         if ($path_from === false) {
  513.             return false;
  514.         }
  515.  
  516.         $path_to = $path_to['path']; // the $component part of parse_url() was added in PHP 5.1.2
  517.         // "It is an error if there already exists a file with the name specified by newpath."
  518.         //  -- http://tools.ietf.org/html/draft-ietf-secsh-filexfer-02#section-6.5
  519.         if (!$this->sftp->rename($path_from, $path_to)) {
  520.             if ($this->sftp->stat($path_to)) {
  521.                 return $this->sftp->delete($path_to, true) && $this->sftp->rename($path_from, $path_to);
  522.             }
  523.             return false;
  524.         }
  525.  
  526.         return true;
  527.     }
  528.  
  529.     /**
  530.      * Open directory handle
  531.      *
  532.      * The only $options is "whether or not to enforce safe_mode (0x04)". Since safe mode was deprecated in 5.3 and
  533.      * removed in 5.4 I'm just going to ignore it.
  534.      *
  535.      * Also, nlist() is the best that this function is realistically going to be able to do. When an SFTP client
  536.      * sends a SSH_FXP_READDIR packet you don't generally get info on just one file but on multiple files. Quoting
  537.      * the SFTP specs:
  538.      *
  539.      *    The SSH_FXP_NAME response has the following format:
  540.      *
  541.      *        uint32     id
  542.      *        uint32     count
  543.      *        repeats count times:
  544.      *                string     filename
  545.      *                string     longname
  546.      *                ATTRS      attrs
  547.      *
  548.      * @param string $path
  549.      * @param int $options
  550.      * @return bool
  551.      * @access public
  552.      */
  553.     private function _dir_opendir($path, $options)
  554.     {
  555.         $path = $this->parse_path($path);
  556.         if ($path === false) {
  557.             return false;
  558.         }
  559.         $this->pos = 0;
  560.         $this->entries = $this->sftp->nlist($path);
  561.         return $this->entries !== false;
  562.     }
  563.  
  564.     /**
  565.      * Read entry from directory handle
  566.      *
  567.      * @return mixed
  568.      * @access public
  569.      */
  570.     private function _dir_readdir()
  571.     {
  572.         if (isset($this->entries[$this->pos])) {
  573.             return $this->entries[$this->pos++];
  574.         }
  575.         return false;
  576.     }
  577.  
  578.     /**
  579.      * Rewind directory handle
  580.      *
  581.      * @return bool
  582.      * @access public
  583.      */
  584.     private function _dir_rewinddir()
  585.     {
  586.         $this->pos = 0;
  587.         return true;
  588.     }
  589.  
  590.     /**
  591.      * Close directory handle
  592.      *
  593.      * @return bool
  594.      * @access public
  595.      */
  596.     private function _dir_closedir()
  597.     {
  598.         return true;
  599.     }
  600.  
  601.     /**
  602.      * Create a directory
  603.      *
  604.      * Only valid $options is STREAM_MKDIR_RECURSIVE
  605.      *
  606.      * @param string $path
  607.      * @param int $mode
  608.      * @param int $options
  609.      * @return bool
  610.      * @access public
  611.      */
  612.     private function _mkdir($path, $mode, $options)
  613.     {
  614.         $path = $this->parse_path($path);
  615.         if ($path === false) {
  616.             return false;
  617.         }
  618.  
  619.         return $this->sftp->mkdir($path, $mode, $options & STREAM_MKDIR_RECURSIVE);
  620.     }
  621.  
  622.     /**
  623.      * Removes a directory
  624.      *
  625.      * Only valid $options is STREAM_MKDIR_RECURSIVE per <http://php.net/streamwrapper.rmdir>, however,
  626.      * <http://php.net/rmdir>  does not have a $recursive parameter as mkdir() does so I don't know how
  627.      * STREAM_MKDIR_RECURSIVE is supposed to be set. Also, when I try it out with rmdir() I get 8 as
  628.      * $options. What does 8 correspond to?
  629.      *
  630.      * @param string $path
  631.      * @param int $options
  632.      * @return bool
  633.      * @access public
  634.      */
  635.     private function _rmdir($path, $options)
  636.     {
  637.         $path = $this->parse_path($path);
  638.         if ($path === false) {
  639.             return false;
  640.         }
  641.  
  642.         return $this->sftp->rmdir($path);
  643.     }
  644.  
  645.     /**
  646.      * Flushes the output
  647.      *
  648.      * See <http://php.net/fflush>. Always returns true because \phpseclib3\Net\SFTP doesn't cache stuff before writing
  649.      *
  650.      * @return bool
  651.      * @access public
  652.      */
  653.     private function _stream_flush()
  654.     {
  655.         return true;
  656.     }
  657.  
  658.     /**
  659.      * Retrieve information about a file resource
  660.      *
  661.      * @return mixed
  662.      * @access public
  663.      */
  664.     private function _stream_stat()
  665.     {
  666.         $results = $this->sftp->stat($this->path);
  667.         if ($results === false) {
  668.             return false;
  669.         }
  670.         return $results;
  671.     }
  672.  
  673.     /**
  674.      * Delete a file
  675.      *
  676.      * @param string $path
  677.      * @return bool
  678.      * @access public
  679.      */
  680.     private function _unlink($path)
  681.     {
  682.         $path = $this->parse_path($path);
  683.         if ($path === false) {
  684.             return false;
  685.         }
  686.  
  687.         return $this->sftp->delete($path, false);
  688.     }
  689.  
  690.     /**
  691.      * Retrieve information about a file
  692.      *
  693.      * Ignores the STREAM_URL_STAT_QUIET flag because the entirety of \phpseclib3\Net\SFTP\Stream is quiet by default
  694.      * might be worthwhile to reconstruct bits 12-16 (ie. the file type) if mode doesn't have them but we'll
  695.      * cross that bridge when and if it's reached
  696.      *
  697.      * @param string $path
  698.      * @param int $flags
  699.      * @return mixed
  700.      * @access public
  701.      */
  702.     private function _url_stat($path, $flags)
  703.     {
  704.         $path = $this->parse_path($path);
  705.         if ($path === false) {
  706.             return false;
  707.         }
  708.  
  709.         $results = $flags & STREAM_URL_STAT_LINK ? $this->sftp->lstat($path) : $this->sftp->stat($path);
  710.         if ($results === false) {
  711.             return false;
  712.         }
  713.  
  714.         return $results;
  715.     }
  716.  
  717.     /**
  718.      * Truncate stream
  719.      *
  720.      * @param int $new_size
  721.      * @return bool
  722.      * @access public
  723.      */
  724.     private function _stream_truncate($new_size)
  725.     {
  726.         if (!$this->sftp->truncate($this->path, $new_size)) {
  727.             return false;
  728.         }
  729.  
  730.         $this->eof = false;
  731.         $this->size = $new_size;
  732.  
  733.         return true;
  734.     }
  735.  
  736.     /**
  737.      * Change stream options
  738.      *
  739.      * STREAM_OPTION_WRITE_BUFFER isn't supported for the same reason stream_flush isn't.
  740.      * The other two aren't supported because of limitations in \phpseclib3\Net\SFTP.
  741.      *
  742.      * @param int $option
  743.      * @param int $arg1
  744.      * @param int $arg2
  745.      * @return bool
  746.      * @access public
  747.      */
  748.     private function _stream_set_option($option, $arg1, $arg2)
  749.     {
  750.         return false;
  751.     }
  752.  
  753.     /**
  754.      * Close an resource
  755.      *
  756.      * @access public
  757.      */
  758.     private function _stream_close()
  759.     {
  760.     }
  761.  
  762.     /**
  763.      * __call Magic Method
  764.      *
  765.      * When you're utilizing an SFTP stream you're not calling the methods in this class directly - PHP is calling them for you.
  766.      * Which kinda begs the question... what methods is PHP calling and what parameters is it passing to them? This function
  767.      * lets you figure that out.
  768.      *
  769.      * If NET_SFTP_STREAM_LOGGING is defined all calls will be output on the screen and then (regardless of whether or not
  770.      * NET_SFTP_STREAM_LOGGING is enabled) the parameters will be passed through to the appropriate method.
  771.      *
  772.      * @param string $name
  773.      * @param array $arguments
  774.      * @return mixed
  775.      * @access public
  776.      */
  777.     public function __call($name, $arguments)
  778.     {
  779.         if (defined('NET_SFTP_STREAM_LOGGING')) {
  780.             echo $name . '(';
  781.             $last = count($arguments) - 1;
  782.             foreach ($arguments as $i => $argument) {
  783.                 var_export($argument);
  784.                 if ($i != $last) {
  785.                     echo ',';
  786.                 }
  787.             }
  788.             echo ")\r\n";
  789.         }
  790.         $name = '_' . $name;
  791.         if (!method_exists($this, $name)) {
  792.             return false;
  793.         }
  794.         return $this->$name(...$arguments);
  795.     }
  796. }
  797.