diff --git a/phpseclib/Crypt/AES.php b/phpseclib/Crypt/AES.php index de60dee2..bc05adf6 100644 --- a/phpseclib/Crypt/AES.php +++ b/phpseclib/Crypt/AES.php @@ -868,7 +868,8 @@ class Crypt_AES extends Crypt_Rijndael { $s0 = $dt0[($e0 >> 24) & 0xff] ^ $dt1[($e3 >> 16) & 0xff] ^ $dt2[($e2 >> 8) & 0xff] ^ $dt3[$e1 & 0xff] ^ $dw[52]; $s1 = $dt0[($e1 >> 24) & 0xff] ^ $dt1[($e0 >> 16) & 0xff] ^ $dt2[($e3 >> 8) & 0xff] ^ $dt3[$e2 & 0xff] ^ $dw[53]; $s2 = $dt0[($e2 >> 24) & 0xff] ^ $dt1[($e1 >> 16) & 0xff] ^ $dt2[($e0 >> 8) & 0xff] ^ $dt3[$e3 & 0xff] ^ $dw[54]; - $e3= $dt0[($e3 >> 24) & 0xff] ^ $dt1[($e2 >> 16) & 0xff] ^ $dt2[($e1 >> 8) & 0xff] ^ $dt3[$e0 & 0xff] ^ $dw[55]; + $e3 = $dt0[($e3 >> 24) & 0xff] ^ $dt1[($e2 >> 16) & 0xff] ^ $dt2[($e1 >> 8) & 0xff] ^ $dt3[$e0 & 0xff] ^ $dw[55]; + // Note: Here we skip $s3 but using $e3 $e0 = $s0; $e1 = $s1; @@ -880,7 +881,8 @@ class Crypt_AES extends Crypt_Rijndael { $s0 = $dt0[($e0 >> 24) & 0xff] ^ $dt1[($e3 >> 16) & 0xff] ^ $dt2[($e2 >> 8) & 0xff] ^ $dt3[$e1 & 0xff] ^ $dw[44]; $s1 = $dt0[($e1 >> 24) & 0xff] ^ $dt1[($e0 >> 16) & 0xff] ^ $dt2[($e3 >> 8) & 0xff] ^ $dt3[$e2 & 0xff] ^ $dw[45]; $s2 = $dt0[($e2 >> 24) & 0xff] ^ $dt1[($e1 >> 16) & 0xff] ^ $dt2[($e0 >> 8) & 0xff] ^ $dt3[$e3 & 0xff] ^ $dw[46]; - $e3= $dt0[($e3 >> 24) & 0xff] ^ $dt1[($e2 >> 16) & 0xff] ^ $dt2[($e1 >> 8) & 0xff] ^ $dt3[$e0 & 0xff] ^ $dw[47]; + $e3 = $dt0[($e3 >> 24) & 0xff] ^ $dt1[($e2 >> 16) & 0xff] ^ $dt2[($e1 >> 8) & 0xff] ^ $dt3[$e0 & 0xff] ^ $dw[47]; + // Note: Here we skip $s3 but using $e3 $e0 = $s0; $e1 = $s1; diff --git a/phpseclib/File/X509.php b/phpseclib/File/X509.php index 8a2acb20..278da62e 100644 --- a/phpseclib/File/X509.php +++ b/phpseclib/File/X509.php @@ -3156,8 +3156,8 @@ class File_X509 { return false; } - $startDate = !empty($this->startDate) ? $this->startDate : @date('M j H:i:s Y T'); - $endDate = !empty($this->endDate) ? $this->endDate : @date('M j H:i:s Y T', strtotime('+1 year')); + $startDate = !empty($this->startDate) ? $this->startDate : @date('D, d M y H:i:s O'); + $endDate = !empty($this->endDate) ? $this->endDate : @date('D, d M y H:i:s O', strtotime('+1 year')); $serialNumber = !empty($this->serialNumber) ? $this->serialNumber : new Math_BigInteger(); $this->currentCert = array( @@ -3329,7 +3329,7 @@ class File_X509 { $currentCert = isset($this->currentCert) ? $this->currentCert : NULL; $signatureSubject = isset($this->signatureSubject) ? $this->signatureSubject : NULL; - $thisUpdate = !empty($this->startDate) ? $this->startDate : @date('M j H:i:s Y T'); + $thisUpdate = !empty($this->startDate) ? $this->startDate : @date('D, d M y H:i:s O'); if (isset($crl->currentCert) && is_array($crl->currentCert) && isset($crl->currentCert['tbsCertList'])) { $this->currentCert = $crl->currentCert; @@ -3479,7 +3479,7 @@ class File_X509 { */ function setStartDate($date) { - $this->startDate = @date('M j H:i:s Y T', @strtotime($date)); + $this->startDate = @date('D, d M y H:i:s O', @strtotime($date)); } /** @@ -3503,7 +3503,7 @@ class File_X509 { $temp = chr(FILE_ASN1_TYPE_GENERALIZED_TIME) . $asn1->_encodeLength(strlen($temp)) . $temp; $this->endDate = new File_ASN1_Element($temp); } else { - $this->endDate = @date('M j H:i:s Y T', @strtotime($date)); + $this->endDate = @date('D, d M y H:i:s O', @strtotime($date)); } } @@ -4131,7 +4131,7 @@ class File_X509 { $i = count($rclist); $rclist[] = array('userCertificate' => $serial, - 'revocationDate' => array('generalTime' => @date('M j H:i:s Y T'))); + 'revocationDate' => array('generalTime' => @date('D, d M y H:i:s O'))); return $i; } diff --git a/phpseclib/Net/SFTP.php b/phpseclib/Net/SFTP.php index 8db087d3..0a40ad76 100644 --- a/phpseclib/Net/SFTP.php +++ b/phpseclib/Net/SFTP.php @@ -329,7 +329,8 @@ class Net_SFTP extends Net_SSH2 { 0x00000002 => 'NET_SFTP_OPEN_WRITE', 0x00000004 => 'NET_SFTP_OPEN_APPEND', 0x00000008 => 'NET_SFTP_OPEN_CREATE', - 0x00000010 => 'NET_SFTP_OPEN_TRUNCATE' + 0x00000010 => 'NET_SFTP_OPEN_TRUNCATE', + 0x00000020 => 'NET_SFTP_OPEN_EXCL' ); // http://tools.ietf.org/html/draft-ietf-secsh-filexfer-04#section-5.2 // see Net_SFTP::_parseLongname() for an explanation @@ -1050,6 +1051,92 @@ class Net_SFTP extends Net_SSH2 { return isset($result['size']) ? $result['size'] : -1; } + /** + * Sets access and modification time of file. + * + * If the file does not exist, it will be created. + * + * @param String $filename + * @param optional Integer $time + * @param optional Integer $atime + * @return Boolean + * @access public + */ + function touch($filename, $time = NULL, $atime = NULL) + { + if (!($this->bitmap & NET_SSH2_MASK_LOGIN)) { + return false; + } + + $filename = $this->_realpath($filename); + if ($filename === false) { + return false; + } + + if (!isset($time)) { + $time = time(); + } + if (!isset($atime)) { + $atime = $time; + } + + $flags = NET_SFTP_OPEN_CREATE | NET_SFTP_OPEN_EXCL; + $attr = pack('N3', NET_SFTP_ATTR_ACCESSTIME, $time, $atime); + $packet = pack('Na*N2', strlen($filename), $filename, $flags, $attr); + if (!$this->_send_sftp_packet(NET_SFTP_OPEN, $packet)) { + return false; + } + + $response = $this->_get_sftp_packet(); + switch ($this->packet_type) { + case NET_SFTP_HANDLE: + $handle = substr($response, 4); + + if (!$this->_send_sftp_packet(NET_SFTP_CLOSE, pack('Na*', strlen($handle), $handle))) { + return false; + } + + $response = $this->_get_sftp_packet(); + if ($this->packet_type != NET_SFTP_STATUS) { + user_error('Expected SSH_FXP_STATUS'); + return false; + } + + extract(unpack('Nstatus', $this->_string_shift($response, 4))); + if ($status != NET_SFTP_STATUS_OK) { + $this->_logError($response, $status); + return false; + } + + return true; + case NET_SFTP_STATUS: + $this->_logError($response); + break; + default: + user_error('Expected SSH_FXP_HANDLE or SSH_FXP_STATUS'); + return false; + } + + $attr = pack('N3', NET_SFTP_ATTR_ACCESSTIME, $time, $atime); + if (!$this->_send_sftp_packet(NET_SFTP_SETSTAT, pack('Na*a*', strlen($filename), $filename, $attr))) { + return false; + } + + $response = $this->_get_sftp_packet(); + if ($this->packet_type != NET_SFTP_STATUS) { + user_error('Expected SSH_FXP_STATUS'); + return false; + } + + extract(unpack('Nstatus', $this->_string_shift($response, 4))); + if ($status != NET_SFTP_STATUS_OK) { + $this->_logError($response, $status); + return false; + } + + return true; + } + /** * Set permissions on a file. * @@ -1057,6 +1144,7 @@ class Net_SFTP extends Net_SSH2 { * * @param Integer $mode * @param String $filename + * @param optional Boolean $recursive * @return Mixed * @access public */ @@ -1066,6 +1154,12 @@ class Net_SFTP extends Net_SSH2 { return false; } + if (is_string($mode) && is_int($filename)) { + $temp = $mode; + $mode = $filename; + $filename = $temp; + } + $filename = $this->_realpath($filename); if ($filename === false) { return false; @@ -1323,14 +1417,19 @@ class Net_SFTP extends Net_SSH2 { * Currently, only binary mode is supported. As such, if the line endings need to be adjusted, you will need to take * care of that, yourself. * + * As for $start... if it's negative (which it is by default) a new file will be created or an existing + * file truncated depending on $mode | NET_SFTP_RESUME. If it's zero or positive it'll be updated at that + * spot. + * * @param String $remote_file * @param String $data * @param optional Integer $mode + * @param optional Integer $start * @return Boolean * @access public * @internal ASCII mode for SFTPv4/5/6 can be supported by adding a new function - Net_SFTP::setMode(). */ - function put($remote_file, $data, $mode = NET_SFTP_STRING) + function put($remote_file, $data, $mode = NET_SFTP_STRING, $start = -1) { if (!($this->bitmap & NET_SSH2_MASK_LOGIN)) { return false; @@ -1348,9 +1447,13 @@ class Net_SFTP extends Net_SSH2 { // if NET_SFTP_OPEN_APPEND worked as it should the following (up until the -----------) wouldn't be necessary $offset = 0; - if ($mode & NET_SFTP_RESUME) { - $size = $this->_size($remote_file); - $offset = $size !== false ? $size : 0; + if (($mode & NET_SFTP_RESUME) || $start >= 0) { + if ($start >= 0) { + $offset = $start; + } else { + $size = $this->_size($remote_file); + $offset = $size !== false ? $size : 0; + } } else { $flags|= NET_SFTP_OPEN_TRUNCATE; } @@ -1477,10 +1580,14 @@ class Net_SFTP extends Net_SSH2 { * * Returns a string containing the contents of $remote_file if $local_file is left undefined or a boolean false if * the operation was unsuccessful. If $local_file is defined, returns true or false depending on the success of the - * operation + * operation. + * + * $offset and $length can be used to download files in chunks. * * @param String $remote_file * @param optional String $local_file + * @param optional Integer $offset + * @param optional Integer $length * @return Mixed * @access public */ diff --git a/phpseclib/Net/SSH2.php b/phpseclib/Net/SSH2.php index 43bfbca2..932af869 100644 --- a/phpseclib/Net/SSH2.php +++ b/phpseclib/Net/SSH2.php @@ -717,6 +717,21 @@ class Net_SSH2 { */ var $exit_status; + /** + * Flag to request a PTY when using exec() + * + * @see Net_SSH2::enablePTY() + * @access private + */ + var $request_pty = false; + + /** + * Flag set while exec() is running when using enablePTY() + * + * @access private + */ + var $in_request_pty_exec = false; + /** * Default Constructor. * @@ -1816,6 +1831,34 @@ class Net_SSH2 { return false; } + if ($this->request_pty === true) { + $terminal_modes = pack('C', NET_SSH2_TTY_OP_END); + $packet = pack('CNNa*CNa*N5a*', + NET_SSH2_MSG_CHANNEL_REQUEST, $this->server_channels[NET_SSH2_CHANNEL_EXEC], strlen('pty-req'), 'pty-req', 1, strlen('vt100'), 'vt100', + 80, 24, 0, 0, strlen($terminal_modes), $terminal_modes); + + if (!$this->_send_binary_packet($packet)) { + return false; + } + $response = $this->_get_binary_packet(); + if ($response === false) { + user_error('Connection closed by server'); + return false; + } + + list(, $type) = unpack('C', $this->_string_shift($response, 1)); + + switch ($type) { + case NET_SSH2_MSG_CHANNEL_SUCCESS: + break; + case NET_SSH2_MSG_CHANNEL_FAILURE: + default: + user_error('Unable to request pseudo-terminal'); + return $this->_disconnect(NET_SSH2_DISCONNECT_BY_APPLICATION); + } + $this->in_request_pty_exec = true; + } + // sending a pty-req SSH_MSG_CHANNEL_REQUEST message is unnecessary and, in fact, in most cases, slows things // down. the one place where it might be desirable is if you're doing something like Net_SSH2::exec('ping localhost &'). // with a pty-req SSH_MSG_CHANNEL_REQUEST, exec() will return immediately and the ping process will then @@ -1840,7 +1883,7 @@ class Net_SSH2 { $this->channel_status[NET_SSH2_CHANNEL_EXEC] = NET_SSH2_MSG_CHANNEL_DATA; - if (!$block) { + if (!$block || $this->in_request_pty_exec) { return true; } @@ -1868,6 +1911,10 @@ class Net_SSH2 { */ function _initShell() { + if ($this->in_request_pty_exec === true) { + return true; + } + $this->window_size_client_to_server[NET_SSH2_CHANNEL_SHELL] = 0x7FFFFFFF; $packet_size = 0x4000; @@ -1957,6 +2004,8 @@ class Net_SSH2 { return false; } + $channel = $this->in_request_pty_exec ? NET_SSH2_CHANNEL_EXEC : NET_SSH2_CHANNEL_SHELL; + $match = $expect; while (true) { if ($mode == NET_SSH2_READ_REGEX) { @@ -1967,8 +2016,9 @@ class Net_SSH2 { if ($pos !== false) { return $this->_string_shift($this->interactiveBuffer, $pos + strlen($match)); } - $response = $this->_get_channel_packet(NET_SSH2_CHANNEL_SHELL); + $response = $this->_get_channel_packet($channel); if (is_bool($response)) { + $this->in_request_pty_exec = false; return $response ? $this->_string_shift($this->interactiveBuffer, strlen($this->interactiveBuffer)) : false; } @@ -1996,7 +2046,8 @@ class Net_SSH2 { return false; } - return $this->_send_channel_packet(NET_SSH2_CHANNEL_SHELL, $cmd); + $channel = $this->in_request_pty_exec ? NET_SSH2_CHANNEL_EXEC : NET_SSH2_CHANNEL_SHELL; + return $this->_send_channel_packet($channel, $cmd); } /** @@ -2219,6 +2270,26 @@ class Net_SSH2 { $this->quiet_mode = false; } + /** + * Enable request-pty when using exec() + * + * @access public + */ + function enablePTY() + { + $this->request_pty = true; + } + + /** + * Disable request-pty when using exec() + * + * @access public + */ + function disablePTY() + { + $this->request_pty = false; + } + /** * Gets channel data *