WordPress.org

Make WordPress Core

Ticket #8210: 8210.2.diff

File 8210.2.diff, 21.2 KB (added by DD32, 9 years ago)
  • wp-admin/includes/class-wp-filesystem-ssh2.php

     
    4141 */
    4242class WP_Filesystem_SSH2 extends WP_Filesystem_Base {
    4343
    44         var $debugtest = false; //      set this to true only if your a debuging your connection
    45 
    46         var $link = null;
    47         var $sftp_link = null;
     44        var $link = false;
     45        var $sftp_link = false;
    4846        var $keys = false;
    4947        /*
    5048         * This is the timeout value for ssh results to comeback.
     
    6866                        $this->errors->add('no_ssh2_ext', __('The ssh2 PHP extension is not available'));
    6967                        return false;
    7068                }
     69                if ( ! version_compare(phpversion(), '5', '>=') ) {
     70                        $this->errors->add('ssh2_php_requirement', __('The ssh2 PHP extension is available, however requires PHP 5+'));
     71                        return false;
     72                }
    7173
    7274                // Set defaults:
    7375                if ( empty($opt['port']) )
     
    8486                        $this->wp_base = $opt['base'];
    8587
    8688                // Check if the options provided are OK.
    87                 if ( empty ($opt['username']) )
    88                         $this->errors->add('empty_username', __('SSH2 username is required'));
    89                 else
    90                         $this->options['username'] = $opt['username'];
    91 
    92                 if ( ( !empty ($opt['public_key']) ) && ( !empty ($opt['private_key']) ) ) {
     89                if ( !empty ($opt['public_key']) && !empty ($opt['private_key']) ) {
    9390                        $this->options['public_key'] = $opt['public_key'];
    9491                        $this->options['private_key'] = $opt['private_key'];
    9592
    96                         $this->options['hostkey'] = array("hostkey" => "ssh-rsa");
     93                        $this->options['hostkey'] = array('hostkey' => 'ssh-rsa');
    9794
    9895                        $this->keys = true;
     96                } elseif ( empty ($opt['username']) ) {
     97                        $this->errors->add('empty_username', __('SSH2 username is required'));
    9998                }
    10099
     100                if ( !empty($opt['username']) )
     101                        $this->options['username'] = $opt['username'];
    101102
    102103                if ( empty ($opt['password']) ) {
    103104                        if ( !$this->keys )     //       password can be blank if we are using keys
     
    109110        }
    110111
    111112        function connect() {
    112                 $this->debug("connect();");
    113 
    114113                if ( ! $this->keys ) {
    115114                        $this->link = @ssh2_connect($this->options['hostname'], $this->options['port']);
    116115                } else {
     
    139138                return true;
    140139        }
    141140
    142         function run_command($link, $command, $returnbool = false) {
    143                 $this->debug("run_command();");
    144                 if(!($stream = @ssh2_exec( $link, $command . "; echo \"__COMMAND_FINISHED__\";"))) {
     141        function run_command( $command, $returnbool = false) {
     142
     143                if ( ! $this->link )
     144                        return false;
     145
     146                if ( ! ($stream = ssh2_exec($this->link, $command)) ) {
    145147                        $this->errors->add('command', sprintf(__('Unable to perform command: %s'), $command));
    146148                } else {
    147149                        stream_set_blocking( $stream, true );
    148                         $time_start = time();
    149                         $data = null;
    150                         while( true ) {
    151                                 if (strpos($data,"__COMMAND_FINISHED__") !== false){
    152                                         break;  //      the command has finshed!
    153                                 }
    154                                 if( (time()-$time_start) > $this->timeout ){
    155                                         $this->errors->add('command', sprintf(__('Connection to the server has timeout after %s seconds.'), $this->timeout));
    156                                         unset($this->link);
    157                                         unset($this->sftp_link); //     close connections
    158                                         return false;
    159                                 }
    160                                 while( $buf = fread( $stream, strlen($stream) ) )
    161                                         $data .= $buf;
    162                         }
    163                         fclose($stream);
    164                         $data = trim(str_replace("__COMMAND_FINISHED__", "", $data));
    165                         if (($returnbool) && ( (int) $data )) {
    166                                 return true;
    167                         } elseif (($returnbool) && (! (int) $data )) {
    168                                 return false;
    169                         } else {
     150                        stream_set_timeout( $stream, $this->timeout );
     151                        $data = stream_get_contents($stream);
     152
     153                        if ( $returnbool )
     154                                return '' != trim($data);
     155                        else
    170156                                return $data;
    171                         }
    172157                }
    173158                return false;
    174159        }
    175160
    176         function debug($text)
    177         {
    178                 if ($this->debugtest)
    179                 {
    180                         echo "<br/>" . $text . "<br/>";
    181                 }
    182         }
    183 
    184161        function setDefaultPermissions($perm) {
    185162                $this->debug("setDefaultPermissions();");
    186163                if ( $perm )
     
    188165        }
    189166
    190167        function get_contents($file, $type = '', $resumepos = 0 ) {
    191                 $this->debug("get_contents();");
    192                 $tempfile = wp_tempnam( $file );
    193                 if ( ! $tempfile )
    194                         return false;
    195                 if( ! ssh2_scp_recv($this->link, $file, $tempfile) )
    196                         return false;
    197                 $contents = file_get_contents($tempfile);
    198                 unlink($tempfile);
    199                 return $contents;
     168                $file = ltrim($file, '/');
     169                return file_get_contents('ssh2.sftp://' . $this->sftp_link .'/' . $file);
    200170        }
    201171
    202172        function get_contents_array($file) {
    203                 $this->debug("get_contents_array();");
    204                 return explode("\n", $this->get_contents($file));
     173                $file = ltrim($file, '/');
     174                return file('ssh2.sftp://' . $this->sftp_link .'/' . $file);
    205175        }
    206176
    207177        function put_contents($file, $contents, $type = '' ) {
    208                 $this->debug("put_contents($file);");
    209                 $tempfile = wp_tempnam( $file );
    210                 $temp = fopen($tempfile, 'w');
    211                 if ( ! $temp )
    212                         return false;
    213                 fwrite($temp, $contents);
    214                 fclose($temp);
    215                 $ret = ssh2_scp_send($this->link, $tempfile, $file, $this->permission);
    216                 unlink($tempfile);
    217                 return $ret;
     178                $file = ltrim($file, '/');
     179                return file_put_contents('ssh2.sftp://' . $this->sftp_link .'/' . $file, $contents);
    218180        }
    219181
    220182        function cwd() {
    221                 $this->debug("cwd();");
    222                 $cwd = $this->run_command($this->link, 'pwd');
     183                $cwd = $this->run_command('pwd');
    223184                if( $cwd )
    224185                        $cwd = trailingslashit($cwd);
    225186                return $cwd;
    226187        }
    227188
    228189        function chdir($dir) {
    229                 $this->debug("chdir();");
    230                 return $this->run_command($this->link, 'cd ' . $dir, true);
     190                return $this->run_command('cd ' . $dir, true);
    231191        }
    232192
    233193        function chgrp($file, $group, $recursive = false ) {
    234                 $this->debug("chgrp();");
    235194                if ( ! $this->exists($file) )
    236195                        return false;
    237196                if ( ! $recursive || ! $this->is_dir($file) )
    238                         return $this->run_command($this->link, sprintf('chgrp %o %s', $mode, $file), true);
    239                 return $this->run_command($this->link, sprintf('chgrp -R %o %s', $mode, $file), true);
     197                        return $this->run_command(sprintf('chgrp %o %s', $mode, escapeshellarg($file)), true);
     198                return $this->run_command(sprintf('chgrp -R %o %s', $mode, escapeshellarg($file)), true);
    240199        }
    241200
    242201        function chmod($file, $mode = false, $recursive = false) {
    243                 $this->debug("chmod();");
    244202                if( ! $mode )
    245203                        $mode = $this->permission;
    246204                if( ! $mode )
     
    248206                if ( ! $this->exists($file) )
    249207                        return false;
    250208                if ( ! $recursive || ! $this->is_dir($file) )
    251                         return $this->run_command($this->link, sprintf('chmod %o %s', $mode, $file), true);
    252                 return $this->run_command($this->link, sprintf('chmod -R %o %s', $mode, $file), true);
     209                        return $this->run_command(sprintf('chmod %o %s', $mode, escapeshellarg($file)), true);
     210                return $this->run_command(sprintf('chmod -R %o %s', $mode, escapeshellarg($file)), true);
    253211        }
    254212
    255213        function chown($file, $owner, $recursive = false ) {
    256                 $this->debug("chown();");
    257214                if ( ! $this->exists($file) )
    258215                        return false;
    259216                if ( ! $recursive || ! $this->is_dir($file) )
    260                         return $this->run_command($this->link, sprintf('chown %o %s', $mode, $file), true);
    261                 return $this->run_command($this->link, sprintf('chown -R %o %s', $mode, $file), true);
     217                        return $this->run_command(sprintf('chown %o %s', $mode, escapeshellarg($file)), true);
     218                return $this->run_command(sprintf('chown -R %o %s', $mode, escapeshellarg($file)), true);
    262219        }
    263220
    264221        function owner($file) {
    265                 $this->debug("owner();");
    266                 $dir = $this->dirlist($file);
    267                 return $dir[$file]['owner'];
     222                $owneruid = @fileowner('ssh2.sftp://' . $this->sftp_link . '/' . ltrim($file, '/'));
     223                if ( ! $owneruid )
     224                        return false;
     225                if ( ! function_exists('posix_getpwuid') )
     226                        return $owneruid;
     227                $ownerarray = posix_getpwuid($owneruid);
     228                return $ownerarray['name'];
    268229        }
    269230
    270231        function getchmod($file) {
    271                 $this->debug("getchmod();");
    272                 $dir = $this->dirlist($file);
    273                 return $dir[$file]['permsn'];
     232                return substr(decoct(@fileperms( 'ssh2.sftp://' . $this->sftp_link . '/' . ltrim($file, '/') )),3);
    274233        }
    275234
    276235        function group($file) {
    277                 $this->debug("group();");
    278                 $dir = $this->dirlist($file);
    279                 return $dir[$file]['group'];
     236                $gid = @filegroup('ssh2.sftp://' . $this->sftp_link . '/' . ltrim($file, '/'));
     237                if ( ! $gid )
     238                        return false;
     239                if ( ! function_exists('posix_getgrgid') )
     240                        return $gid;
     241                $grouparray = posix_getgrgid($gid);
     242                return $grouparray['name'];
    280243        }
    281244
    282245        function copy($source, $destination, $overwrite = false ) {
    283                 $this->debug("copy();");
    284246                if( ! $overwrite && $this->exists($destination) )
    285247                        return false;
    286248                $content = $this->get_contents($source);
     
    290252        }
    291253
    292254        function move($source, $destination, $overwrite = false) {
    293                 $this->debug("move();");
    294255                return @ssh2_sftp_rename($this->link, $source, $destination);
    295256        }
    296257
    297258        function delete($file, $recursive = false) {
    298                 $this->debug("delete();");
    299259                if ( $this->is_file($file) )
    300260                        return ssh2_sftp_unlink($this->sftp_link, $file);
    301261                if ( ! $recursive )
     
    310270        }
    311271
    312272        function exists($file) {
    313                 $this->debug("exists();");
    314                 return $this->run_command($this->link, sprintf('ls -lad %s', $file), true);
     273                //return $this->run_command(sprintf('ls -lad %s', escapeshellarg($file)), true);
     274                $file = ltrim($file, '/');
     275                return file_exists('ssh2.sftp://' . $this->sftp_link .'/' . $file);
    315276        }
    316277
    317278        function is_file($file) {
    318                 $this->debug("is_file();");
    319                 //DO NOT RELY ON dirlist()!
    320                 $list = $this->run_command($this->link, sprintf('ls -lad %s', $file));
    321                 $list = $this->parselisting($list);
    322                 if ( ! $list )
    323                         return false;
    324                 else
    325                         return ( !$list['isdir'] && !$list['islink'] ); //ie. not a file or link, yet exists, must be file.
     279                $file = ltrim($file, '/');
     280                return is_file('ssh2.sftp://' . $this->sftp_link .'/' . $file);
    326281        }
    327282
    328283        function is_dir($path) {
    329                 $this->debug("is_dir();");
    330                 //DO NOT RELY ON dirlist()!
    331                 $list = $this->parselisting($this->run_command($this->link, sprintf('ls -lad %s', untrailingslashit($path))));
    332                 if ( ! $list )
    333                         return false;
    334                 else
    335                         return $list['isdir'];
     284                $path = ltrim($path, '/');
     285                return is_dir('ssh2.sftp://' . $this->sftp_link .'/' . $path);
    336286        }
    337287
    338288        function is_readable($file) {
    339                 //Not implmented.
     289                $file = ltrim($file, '/');
     290                return is_readable('ssh2.sftp://' . $this->sftp_link .'/' . $file);
    340291        }
    341292
    342293        function is_writable($file) {
    343                 //Not implmented.
     294                $file = ltrim($file, '/');
     295                return is_writable('ssh2.sftp://' . $this->sftp_link .'/' . $file);
    344296        }
    345297
    346298        function atime($file) {
    347                 //Not implmented.
     299                $file = ltrim($file, '/');
     300                return fileatime('ssh2.sftp://' . $this->sftp_link .'/' . $file);
    348301        }
    349302
    350303        function mtime($file) {
    351                 //Not implmented.
     304                $file = ltrim($file, '/');
     305                return filemtime('ssh2.sftp://' . $this->sftp_link .'/' . $file);
    352306        }
    353307
    354308        function size($file) {
    355                 //Not implmented.
     309                $file = ltrim($file, '/');
     310                return filesize('ssh2.sftp://' . $this->sftp_link .'/' . $file);
    356311        }
    357312
    358313        function touch($file, $time = 0, $atime = 0) {
     
    360315        }
    361316
    362317        function mkdir($path, $chmod = null, $chown = false, $chgrp = false) {
    363                 $this->debug("mkdir();");
    364318                $path = untrailingslashit($path);
    365                 if( ! ssh2_sftp_mkdir($this->sftp_link, $path, $chmod, true) )
     319                $chmod = !empty($chmod) ? $chmod : $this->permission;
     320                if ( ! ssh2_sftp_mkdir($this->sftp_link, $path, $chmod, true) )
    366321                        return false;
    367                 if( $chown )
     322                if ( $chown )
    368323                        $this->chown($path, $chown);
    369                 if( $chgrp )
     324                if ( $chgrp )
    370325                        $this->chgrp($path, $chgrp);
    371326                return true;
    372327        }
    373328
    374329        function rmdir($path, $recursive = false) {
    375                 $this->debug("rmdir();");
    376330                return $this->delete($path, $recursive);
    377331        }
    378332
    379         function parselisting($line) {
    380         $this->debug("parselisting();");
    381                 $is_windows = ($this->OS_remote == FTP_OS_Windows);
    382                 if ($is_windows && preg_match("/([0-9]{2})-([0-9]{2})-([0-9]{2}) +([0-9]{2}):([0-9]{2})(AM|PM) +([0-9]+|<DIR>) +(.+)/", $line, $lucifer)) {
    383                         $b = array();
    384                         if ($lucifer[3]<70) { $lucifer[3] +=2000; } else { $lucifer[3]+=1900; } // 4digit year fix
    385                         $b['isdir'] = ($lucifer[7]=="<DIR>");
    386                         if ( $b['isdir'] )
    387                                 $b['type'] = 'd';
    388                         else
    389                                 $b['type'] = 'f';
    390                         $b['size'] = $lucifer[7];
    391                         $b['month'] = $lucifer[1];
    392                         $b['day'] = $lucifer[2];
    393                         $b['year'] = $lucifer[3];
    394                         $b['hour'] = $lucifer[4];
    395                         $b['minute'] = $lucifer[5];
    396                         $b['time'] = @mktime($lucifer[4]+(strcasecmp($lucifer[6],"PM")==0?12:0),$lucifer[5],0,$lucifer[1],$lucifer[2],$lucifer[3]);
    397                         $b['am/pm'] = $lucifer[6];
    398                         $b['name'] = $lucifer[8];
    399                 } else if (!$is_windows && $lucifer=preg_split("/[ ]/",$line,9,PREG_SPLIT_NO_EMPTY)) {
    400                         //echo $line."\n";
    401                         $lcount=count($lucifer);
    402                         if ($lcount<8) return '';
    403                         $b = array();
    404                         $b['isdir'] = $lucifer[0]{0} === "d";
    405                         $b['islink'] = $lucifer[0]{0} === "l";
    406                         if ( $b['isdir'] )
    407                                 $b['type'] = 'd';
    408                         elseif ( $b['islink'] )
    409                                 $b['type'] = 'l';
    410                         else
    411                                 $b['type'] = 'f';
    412                         $b['perms'] = $lucifer[0];
    413                         $b['number'] = $lucifer[1];
    414                         $b['owner'] = $lucifer[2];
    415                         $b['group'] = $lucifer[3];
    416                         $b['size'] = $lucifer[4];
    417                         if ($lcount==8) {
    418                                 sscanf($lucifer[5],"%d-%d-%d",$b['year'],$b['month'],$b['day']);
    419                                 sscanf($lucifer[6],"%d:%d",$b['hour'],$b['minute']);
    420                                 $b['time'] = @mktime($b['hour'],$b['minute'],0,$b['month'],$b['day'],$b['year']);
    421                                 $b['name'] = $lucifer[7];
    422                         } else {
    423                                 $b['month'] = $lucifer[5];
    424                                 $b['day'] = $lucifer[6];
    425                                 if (preg_match("/([0-9]{2}):([0-9]{2})/",$lucifer[7],$l2)) {
    426                                         $b['year'] = date("Y");
    427                                         $b['hour'] = $l2[1];
    428                                         $b['minute'] = $l2[2];
    429                                 } else {
    430                                         $b['year'] = $lucifer[7];
    431                                         $b['hour'] = 0;
    432                                         $b['minute'] = 0;
    433                                 }
    434                                 $b['time'] = strtotime(sprintf("%d %s %d %02d:%02d",$b['day'],$b['month'],$b['year'],$b['hour'],$b['minute']));
    435                                 $b['name'] = $lucifer[8];
    436                         }
    437                 }
    438 
    439                 return $b;
    440         }
    441 
    442         function dirlist($path = '.', $incdot = false, $recursive = false) {
    443                 $this->debug("dirlist();");
    444                 if( $this->is_file($path) ) {
     333        function dirlist($path, $incdot = false, $recursive = false) {
     334                if ( $this->is_file($path) ) {
    445335                        $limitFile = basename($path);
    446                         $path = trailingslashit(dirname($path));
     336                        $path = dirname($path);
    447337                } else {
    448338                        $limitFile = false;
    449339                }
     340                if ( ! $this->is_dir($path) )
     341                        return false;
    450342
    451                 $list = $this->run_command($this->link, sprintf('ls -la %s', $path));
    452 
    453                 if ( $list === false )
     343                $ret = array();
     344                $dir = @dir('ssh2.sftp://' . $this->sftp_link .'/' . ltrim($path, '/') );
     345                if ( ! $dir )
    454346                        return false;
     347                while (false !== ($entry = $dir->read()) ) {
     348                        $struc = array();
     349                        $struc['name'] = $entry;
    455350
    456                 $list = explode("\n", $list);
    457 
    458                 $dirlist = array();
    459                 foreach ( (array)$list as $k => $v ) {
    460                         $entry = $this->parselisting($v);
    461                         if ( empty($entry) )
     351                        if ( '.' == $struc['name'] || '..' == $struc['name'] )
     352                                continue; //Do not care about these folders.
     353                        if ( '.' == $struc['name'][0] && !$incdot)
    462354                                continue;
    463 
    464                         if ( '.' == $entry['name'] || '..' == $entry['name'] )
     355                        if ( $limitFile && $struc['name'] != $limitFile)
    465356                                continue;
    466357
    467                         $dirlist[ $entry['name'] ] = $entry;
    468                 }
     358                        $struc['perms']         = $this->gethchmod($path.'/'.$entry);
     359                        $struc['permsn']        = $this->getnumchmodfromh($struc['perms']);
     360                        $struc['number']        = false;
     361                        $struc['owner']         = $this->owner($path.'/'.$entry);
     362                        $struc['group']         = $this->group($path.'/'.$entry);
     363                        $struc['size']          = $this->size($path.'/'.$entry);
     364                        $struc['lastmodunix']= $this->mtime($path.'/'.$entry);
     365                        $struc['lastmod']   = date('M j',$struc['lastmodunix']);
     366                        $struc['time']          = date('h:i:s',$struc['lastmodunix']);
     367                        $struc['type']          = $this->is_dir($path.'/'.$entry) ? 'd' : 'f';
    469368
    470                 if ( ! $dirlist )
    471                         return false;
    472 
    473                 if ( empty($dirlist) )
    474                         return array();
    475 
    476                 $ret = array();
    477                 foreach ( $dirlist as $struc ) {
    478 
    479369                        if ( 'd' == $struc['type'] ) {
    480                                 $struc['files'] = array();
    481 
    482                                 if ( $incdot ){
    483                                         //We're including the doted starts
    484                                         if( '.' != $struc['name'] && '..' != $struc['name'] ){ //Ok, It isnt a special folder
    485                                                 if ($recursive)
    486                                                         $struc['files'] = $this->dirlist($path . '/' . $struc['name'], $incdot, $recursive);
    487                                         }
    488                                 } else { //No dots
    489                                         if ( $recursive )
    490                                                 $struc['files'] = $this->dirlist($path . '/' . $struc['name'], $incdot, $recursive);
    491                                 }
     370                                if ( $recursive )
     371                                        $struc['files'] = $this->dirlist($path . '/' . $struc['name'], $incdot, $recursive);
     372                                else
     373                                        $struc['files'] = array();
    492374                        }
    493                         //File
    494                         $ret[$struc['name']] = $struc;
     375
     376                        $ret[ $struc['name'] ] = $struc;
    495377                }
     378                $dir->close();
     379                unset($dir);
    496380                return $ret;
    497381        }
    498         function __destruct() {
    499                 $this->debug("__destruct();");
    500                 if ( $this->link )
    501                         unset($this->link);
    502                 if ( $this->sftp_link )
    503                         unset($this->sftp_link);
    504         }
    505 }
    506 
    507 ?>
     382}
     383 No newline at end of file
  • wp-admin/includes/file.php

     
    630630                unlink($temp_file);
    631631        }
    632632
    633         if ( ! $method && isset($args['connection_type']) && 'ssh' == $args['connection_type'] && extension_loaded('ssh2') ) $method = 'ssh2';
     633        if ( ! $method && isset($args['connection_type']) && 'ssh' == $args['connection_type'] && extension_loaded('ssh2') && extension_loaded('sockets') ) $method = 'ssh2';
    634634        if ( ! $method && extension_loaded('ftp') ) $method = 'ftpext';
    635635        if ( ! $method && ( extension_loaded('sockets') || function_exists('fsockopen') ) ) $method = 'ftpsockets'; //Sockets: Socket extension; PHP Mode: FSockopen / fwrite / fread
    636636        return apply_filters('filesystem_method', $method);
     
    657657        if ( 'direct' == $type )
    658658                return true;
    659659
    660         $credentials = get_option('ftp_credentials', array());
     660        $credentials = get_option('ftp_credentials', array( 'hostname' => '', 'username' => ''));
     661
    661662        // If defined, set it to that, Else, If POST'd, set it to that, If not, Set it to whatever it previously was(saved details in option)
    662663        $credentials['hostname'] = defined('FTP_HOST') ? FTP_HOST : (!empty($_POST['hostname']) ? $_POST['hostname'] : $credentials['hostname']);
    663664        $credentials['username'] = defined('FTP_USER') ? FTP_USER : (!empty($_POST['username']) ? $_POST['username'] : $credentials['username']);
    664         $credentials['password'] = defined('FTP_PASS') ? FTP_PASS : (!empty($_POST['password']) ? $_POST['password'] : $credentials['password']);
     665        $credentials['password'] = defined('FTP_PASS') ? FTP_PASS : (!empty($_POST['password']) ? $_POST['password'] : '');
    665666
    666667        // Check to see if we are setting the public/private keys for ssh
    667         $credentials['public_key'] = defined('FTP_PUBKEY') ? FTP_PUBKEY : (!empty($_POST['public_key']) ? $_POST['public_key'] : $credentials['public_key']);
    668         $credentials['private_key'] = defined('FTP_PRIKEY') ? FTP_PRIKEY : (!empty($_POST['private_key']) ? $_POST['private_key'] : $credentials['private_key']);
     668        $credentials['public_key'] = defined('FTP_PUBKEY') ? FTP_PUBKEY : (!empty($_POST['public_key']) ? $_POST['public_key'] : '');
     669        $credentials['private_key'] = defined('FTP_PRIKEY') ? FTP_PRIKEY : (!empty($_POST['private_key']) ? $_POST['private_key'] : '');
    669670
    670671        //sanitize the hostname, Some people might pass in odd-data:
    671672        $credentials['hostname'] = preg_replace('|\w+://|', '', $credentials['hostname']); //Strip any schemes off
     
    682683        else if ( !isset($credentials['connection_type']) || (isset($_POST['connection_type']) && 'ftp' == $_POST['connection_type']) )
    683684                $credentials['connection_type'] = 'ftp';
    684685
    685         if ( ! $error && !empty($credentials['password']) && !empty($credentials['username']) && !empty($credentials['hostname']) ) {
     686        if ( ! $error &&
     687                        (
     688                                ( !empty($credentials['password']) && !empty($credentials['username']) && !empty($credentials['hostname']) ) ||
     689                                ( 'ssh' == $credentials['connection_type'] && !empty($credentials['public_key']) && !empty($credentials['private_key']) )
     690                        ) ) {
    686691                $stored_credentials = $credentials;
    687692                if ( !empty($stored_credentials['port']) ) //save port as part of hostname to simplify above code.
    688693                        $stored_credentials['hostname'] .= ':' . $stored_credentials['port'];
     
    745750<label for="public_key"><?php _e('Public Key:') ?></label ><br />
    746751<label for="private_key"><?php _e('Private Key:') ?></label>
    747752</div></th>
    748 <td><br /><input name="public_key" type="text" id="public_key" value=""<?php if( defined('FTP_PUBKEY') ) echo ' disabled="disabled"' ?> size="40" /><br /><input name="private_key" type="text" id="private_key" value=""<?php if( defined('FTP_PRIKEY') ) echo ' disabled="disabled"' ?> size="40" />
     753<td><br /><input name="public_key" type="text" id="public_key" value="<?php echo attribute_escape($public_key) ?>"<?php if( defined('FTP_PUBKEY') ) echo ' disabled="disabled"' ?> size="40" /><br /><input name="private_key" type="text" id="private_key" value="<?php echo attribute_escape($private_key) ?>"<?php if( defined('FTP_PRIKEY') ) echo ' disabled="disabled"' ?> size="40" />
    749754<div><?php _e('Enter the location on the server where the keys are located. If a passphrase is needed, enter that in the password field above.') ?></div></td>
    750755</tr>
    751756