[securemail] Update Composer dependency ahead of release
- Updating phpseclib/phpseclib (3.0.19 => 3.0.37)pull/1487/head
parent
7bff983d21
commit
0a69c66d09
|
@ -1,26 +1,26 @@
|
||||||
{
|
{
|
||||||
"name": "friendica-addons/securemail",
|
"name": "friendica-addons/securemail",
|
||||||
"description": "Send notification mail encrypted with user-defined public GPG key.",
|
"description": "Send notification mail encrypted with user-defined public GPG key.",
|
||||||
"type": "friendica-addon",
|
"type": "friendica-addon",
|
||||||
"authors": [
|
"authors": [
|
||||||
{
|
{
|
||||||
"name": "Fabio Comuni",
|
"name": "Fabio Comuni",
|
||||||
"homepage": "https://kirgroup.com/profile/fabrixxm",
|
"homepage": "https://kirgroup.com/profile/fabrixxm",
|
||||||
"role": "Developer"
|
"role": "Developer"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"require": {
|
||||||
|
"singpolyma/openpgp-php": "0.6.0"
|
||||||
|
},
|
||||||
|
"replace": {
|
||||||
|
"paragonie/random_compat": "9.99.99"
|
||||||
|
},
|
||||||
|
"license": "AGPL-3.0+",
|
||||||
|
"minimum-stability": "stable",
|
||||||
|
"config": {
|
||||||
|
"autoloader-suffix": "SecuremailAddon",
|
||||||
|
"platform": {
|
||||||
|
"php": "7.3"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
],
|
|
||||||
"require": {
|
|
||||||
"singpolyma/openpgp-php": "0.6.0"
|
|
||||||
},
|
|
||||||
"replace": {
|
|
||||||
"paragonie/random_compat": "9.99.99"
|
|
||||||
},
|
|
||||||
"license": "AGPL-3.0+",
|
|
||||||
"minimum-stability": "stable",
|
|
||||||
"config": {
|
|
||||||
"autoloader-suffix": "SecuremailAddon",
|
|
||||||
"platform": {
|
|
||||||
"php": "7.3"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -70,16 +70,16 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "phpseclib/phpseclib",
|
"name": "phpseclib/phpseclib",
|
||||||
"version": "3.0.19",
|
"version": "3.0.37",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/phpseclib/phpseclib.git",
|
"url": "https://github.com/phpseclib/phpseclib.git",
|
||||||
"reference": "cc181005cf548bfd8a4896383bb825d859259f95"
|
"reference": "cfa2013d0f68c062055180dd4328cc8b9d1f30b8"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/cc181005cf548bfd8a4896383bb825d859259f95",
|
"url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/cfa2013d0f68c062055180dd4328cc8b9d1f30b8",
|
||||||
"reference": "cc181005cf548bfd8a4896383bb825d859259f95",
|
"reference": "cfa2013d0f68c062055180dd4328cc8b9d1f30b8",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
|
@ -172,7 +172,7 @@
|
||||||
"type": "tidelift"
|
"type": "tidelift"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2023-03-05T17:13:09+00:00"
|
"time": "2024-03-03T02:14:58+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "singpolyma/openpgp-php",
|
"name": "singpolyma/openpgp-php",
|
||||||
|
|
|
@ -65,17 +65,17 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "phpseclib/phpseclib",
|
"name": "phpseclib/phpseclib",
|
||||||
"version": "3.0.19",
|
"version": "3.0.37",
|
||||||
"version_normalized": "3.0.19.0",
|
"version_normalized": "3.0.37.0",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/phpseclib/phpseclib.git",
|
"url": "https://github.com/phpseclib/phpseclib.git",
|
||||||
"reference": "cc181005cf548bfd8a4896383bb825d859259f95"
|
"reference": "cfa2013d0f68c062055180dd4328cc8b9d1f30b8"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/cc181005cf548bfd8a4896383bb825d859259f95",
|
"url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/cfa2013d0f68c062055180dd4328cc8b9d1f30b8",
|
||||||
"reference": "cc181005cf548bfd8a4896383bb825d859259f95",
|
"reference": "cfa2013d0f68c062055180dd4328cc8b9d1f30b8",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
|
@ -93,7 +93,7 @@
|
||||||
"ext-mcrypt": "Install the Mcrypt extension in order to speed up a few other cryptographic operations.",
|
"ext-mcrypt": "Install the Mcrypt extension in order to speed up a few other cryptographic operations.",
|
||||||
"ext-openssl": "Install the OpenSSL extension in order to speed up a wide variety of cryptographic operations."
|
"ext-openssl": "Install the OpenSSL extension in order to speed up a wide variety of cryptographic operations."
|
||||||
},
|
},
|
||||||
"time": "2023-03-05T17:13:09+00:00",
|
"time": "2024-03-03T02:14:58+00:00",
|
||||||
"type": "library",
|
"type": "library",
|
||||||
"installation-source": "dist",
|
"installation-source": "dist",
|
||||||
"autoload": {
|
"autoload": {
|
||||||
|
|
|
@ -12,4 +12,6 @@ phpseclib ongoing development is made possible by [Tidelift](https://tidelift.co
|
||||||
- [Charles Severance](https://github.com/csev)
|
- [Charles Severance](https://github.com/csev)
|
||||||
- [Rachel Fish](https://github.com/itsrachelfish)
|
- [Rachel Fish](https://github.com/itsrachelfish)
|
||||||
- Tharyrok
|
- Tharyrok
|
||||||
- [cjhaas](https://github.com/cjhaas)
|
- [cjhaas](https://github.com/cjhaas)
|
||||||
|
- [istiak-tridip](https://github.com/istiak-tridip)
|
||||||
|
- [Anna Filina](https://github.com/afilina)
|
|
@ -51,8 +51,7 @@ SSH-2, SFTP, X.509, an arbitrary-precision integer arithmetic library, Ed25519 /
|
||||||
* PHP4 compatible
|
* PHP4 compatible
|
||||||
* Composer compatible (PSR-0 autoloading)
|
* Composer compatible (PSR-0 autoloading)
|
||||||
* Install using Composer: `composer require phpseclib/phpseclib:~1.0`
|
* Install using Composer: `composer require phpseclib/phpseclib:~1.0`
|
||||||
* Install using PEAR: See [phpseclib PEAR Channel Documentation](http://phpseclib.sourceforge.net/pear.htm)
|
* [Download 1.0.23 as ZIP](http://sourceforge.net/projects/phpseclib/files/phpseclib1.0.23.zip/download)
|
||||||
* [Download 1.0.20 as ZIP](http://sourceforge.net/projects/phpseclib/files/phpseclib1.0.20.zip/download)
|
|
||||||
|
|
||||||
## Security contact information
|
## Security contact information
|
||||||
|
|
||||||
|
|
|
@ -94,7 +94,7 @@ abstract class AsymmetricKey
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $type
|
* @param string $type
|
||||||
* @return string
|
* @return array|string
|
||||||
*/
|
*/
|
||||||
abstract public function toString($type, array $options = []);
|
abstract public function toString($type, array $options = []);
|
||||||
|
|
||||||
|
@ -130,7 +130,7 @@ abstract class AsymmetricKey
|
||||||
*
|
*
|
||||||
* @param string $key
|
* @param string $key
|
||||||
* @param string $password optional
|
* @param string $password optional
|
||||||
* @return AsymmetricKey
|
* @return \phpseclib3\Crypt\Common\PublicKey|\phpseclib3\Crypt\Common\PrivateKey
|
||||||
*/
|
*/
|
||||||
public static function load($key, $password = false)
|
public static function load($key, $password = false)
|
||||||
{
|
{
|
||||||
|
@ -382,7 +382,7 @@ abstract class AsymmetricKey
|
||||||
$shortname = $meta->getShortName();
|
$shortname = $meta->getShortName();
|
||||||
self::$plugins[static::ALGORITHM]['Keys'][strtolower($shortname)] = $fullname;
|
self::$plugins[static::ALGORITHM]['Keys'][strtolower($shortname)] = $fullname;
|
||||||
if ($meta->hasConstant('IS_INVISIBLE')) {
|
if ($meta->hasConstant('IS_INVISIBLE')) {
|
||||||
self::$invisiblePlugins[static::ALGORITHM] = strtolower($name);
|
self::$invisiblePlugins[static::ALGORITHM][] = strtolower($shortname);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -141,6 +141,7 @@ abstract class PKCS8 extends PKCS
|
||||||
break;
|
break;
|
||||||
case 'RC2':
|
case 'RC2':
|
||||||
$cipher = new RC2('cbc');
|
$cipher = new RC2('cbc');
|
||||||
|
$cipher->setKeyLength(64);
|
||||||
break;
|
break;
|
||||||
case '3-KeyTripleDES':
|
case '3-KeyTripleDES':
|
||||||
$cipher = new TripleDES('cbc');
|
$cipher = new TripleDES('cbc');
|
||||||
|
@ -218,7 +219,7 @@ abstract class PKCS8 extends PKCS
|
||||||
{
|
{
|
||||||
switch ($algo) {
|
switch ($algo) {
|
||||||
case 'desCBC':
|
case 'desCBC':
|
||||||
$cipher = new TripleDES('cbc');
|
$cipher = new DES('cbc');
|
||||||
break;
|
break;
|
||||||
case 'des-EDE3-CBC':
|
case 'des-EDE3-CBC':
|
||||||
$cipher = new TripleDES('cbc');
|
$cipher = new TripleDES('cbc');
|
||||||
|
|
|
@ -668,6 +668,8 @@ abstract class SymmetricKey
|
||||||
switch (true) {
|
switch (true) {
|
||||||
// PHP_OS & "\xDF\xDF\xDF" == strtoupper(substr(PHP_OS, 0, 3)), but a lot faster
|
// PHP_OS & "\xDF\xDF\xDF" == strtoupper(substr(PHP_OS, 0, 3)), but a lot faster
|
||||||
case (PHP_OS & "\xDF\xDF\xDF") === 'WIN':
|
case (PHP_OS & "\xDF\xDF\xDF") === 'WIN':
|
||||||
|
case !function_exists('php_uname'):
|
||||||
|
case !is_string(php_uname('m')):
|
||||||
case (php_uname('m') & "\xDF\xDF\xDF") != 'ARM':
|
case (php_uname('m') & "\xDF\xDF\xDF") != 'ARM':
|
||||||
case defined('PHP_INT_SIZE') && PHP_INT_SIZE == 8:
|
case defined('PHP_INT_SIZE') && PHP_INT_SIZE == 8:
|
||||||
self::$use_reg_intval = true;
|
self::$use_reg_intval = true;
|
||||||
|
@ -917,7 +919,7 @@ abstract class SymmetricKey
|
||||||
* @see Crypt/Hash.php
|
* @see Crypt/Hash.php
|
||||||
* @param string $password
|
* @param string $password
|
||||||
* @param string $method
|
* @param string $method
|
||||||
* @param string[] ...$func_args
|
* @param int|string ...$func_args
|
||||||
* @throws \LengthException if pbkdf1 is being used and the derived key length exceeds the hash length
|
* @throws \LengthException if pbkdf1 is being used and the derived key length exceeds the hash length
|
||||||
* @throws \RuntimeException if bcrypt is being used and a salt isn't provided
|
* @throws \RuntimeException if bcrypt is being used and a salt isn't provided
|
||||||
* @return bool
|
* @return bool
|
||||||
|
|
66
securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Formats/Signature/IEEE.php
vendored
Normal file
66
securemail/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Formats/Signature/IEEE.php
vendored
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* IEEE P1363 Signature Handler
|
||||||
|
*
|
||||||
|
* PHP version 5
|
||||||
|
*
|
||||||
|
* Handles signatures in the format described in
|
||||||
|
* https://standards.ieee.org/ieee/1363/2049/ and
|
||||||
|
* https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/sign#ecdsa
|
||||||
|
*
|
||||||
|
* @author Jim Wigginton <terrafrost@php.net>
|
||||||
|
* @copyright 2016 Jim Wigginton
|
||||||
|
* @license http://www.opensource.org/licenses/mit-license.html MIT License
|
||||||
|
* @link http://phpseclib.sourceforge.net
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace phpseclib3\Crypt\EC\Formats\Signature;
|
||||||
|
|
||||||
|
use phpseclib3\Math\BigInteger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ASN1 Signature Handler
|
||||||
|
*
|
||||||
|
* @author Jim Wigginton <terrafrost@php.net>
|
||||||
|
*/
|
||||||
|
abstract class IEEE
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Loads a signature
|
||||||
|
*
|
||||||
|
* @param string $sig
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public static function load($sig)
|
||||||
|
{
|
||||||
|
if (!is_string($sig)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$len = strlen($sig);
|
||||||
|
if ($len & 1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$r = new BigInteger(substr($sig, 0, $len >> 1), 256);
|
||||||
|
$s = new BigInteger(substr($sig, $len >> 1), 256);
|
||||||
|
|
||||||
|
return compact('r', 's');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a signature in the appropriate format
|
||||||
|
*
|
||||||
|
* @param \phpseclib3\Math\BigInteger $r
|
||||||
|
* @param \phpseclib3\Math\BigInteger $s
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public static function save(BigInteger $r, BigInteger $s)
|
||||||
|
{
|
||||||
|
$r = $r->toBytes();
|
||||||
|
$s = $s->toBytes();
|
||||||
|
$len = max(strlen($r), strlen($s));
|
||||||
|
return str_pad($r, $len, "\0", STR_PAD_LEFT) . str_pad($s, $len, "\0", STR_PAD_LEFT);
|
||||||
|
}
|
||||||
|
}
|
|
@ -150,7 +150,7 @@ final class PrivateKey extends EC implements Common\PrivateKey
|
||||||
// we use specified curves to avoid issues with OpenSSL possibly not supporting a given named curve;
|
// we use specified curves to avoid issues with OpenSSL possibly not supporting a given named curve;
|
||||||
// doing this may mean some curve-specific optimizations can't be used but idk if OpenSSL even
|
// doing this may mean some curve-specific optimizations can't be used but idk if OpenSSL even
|
||||||
// has curve-specific optimizations
|
// has curve-specific optimizations
|
||||||
$result = openssl_sign($message, $signature, $this->toString('PKCS8', ['namedCurve' => false]), $this->hash->getHash());
|
$result = openssl_sign($message, $signature, $this->withPassword()->toString('PKCS8', ['namedCurve' => false]), $this->hash->getHash());
|
||||||
|
|
||||||
if ($result) {
|
if ($result) {
|
||||||
if ($shortFormat == 'ASN1') {
|
if ($shortFormat == 'ASN1') {
|
||||||
|
|
|
@ -332,6 +332,7 @@ abstract class RSA extends AsymmetricKey
|
||||||
openssl_pkey_export($rsa, $privatekeystr, null, $config);
|
openssl_pkey_export($rsa, $privatekeystr, null, $config);
|
||||||
|
|
||||||
// clear the buffer of error strings stemming from a minimalistic openssl.cnf
|
// clear the buffer of error strings stemming from a minimalistic openssl.cnf
|
||||||
|
// https://github.com/php/php-src/issues/11054 talks about other errors this'll pick up
|
||||||
while (openssl_error_string() !== false) {
|
while (openssl_error_string() !== false) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -841,15 +842,15 @@ abstract class RSA extends AsymmetricKey
|
||||||
self::ENCRYPTION_PKCS1,
|
self::ENCRYPTION_PKCS1,
|
||||||
self::ENCRYPTION_NONE
|
self::ENCRYPTION_NONE
|
||||||
];
|
];
|
||||||
$numSelected = 0;
|
$encryptedCount = 0;
|
||||||
$selected = 0;
|
$selected = 0;
|
||||||
foreach ($masks as $mask) {
|
foreach ($masks as $mask) {
|
||||||
if ($padding & $mask) {
|
if ($padding & $mask) {
|
||||||
$selected = $mask;
|
$selected = $mask;
|
||||||
$numSelected++;
|
$encryptedCount++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ($numSelected > 1) {
|
if ($encryptedCount > 1) {
|
||||||
throw new InconsistentSetupException('Multiple encryption padding modes have been selected; at most only one should be selected');
|
throw new InconsistentSetupException('Multiple encryption padding modes have been selected; at most only one should be selected');
|
||||||
}
|
}
|
||||||
$encryptionPadding = $selected;
|
$encryptionPadding = $selected;
|
||||||
|
@ -859,22 +860,26 @@ abstract class RSA extends AsymmetricKey
|
||||||
self::SIGNATURE_RELAXED_PKCS1,
|
self::SIGNATURE_RELAXED_PKCS1,
|
||||||
self::SIGNATURE_PKCS1
|
self::SIGNATURE_PKCS1
|
||||||
];
|
];
|
||||||
$numSelected = 0;
|
$signatureCount = 0;
|
||||||
$selected = 0;
|
$selected = 0;
|
||||||
foreach ($masks as $mask) {
|
foreach ($masks as $mask) {
|
||||||
if ($padding & $mask) {
|
if ($padding & $mask) {
|
||||||
$selected = $mask;
|
$selected = $mask;
|
||||||
$numSelected++;
|
$signatureCount++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ($numSelected > 1) {
|
if ($signatureCount > 1) {
|
||||||
throw new InconsistentSetupException('Multiple signature padding modes have been selected; at most only one should be selected');
|
throw new InconsistentSetupException('Multiple signature padding modes have been selected; at most only one should be selected');
|
||||||
}
|
}
|
||||||
$signaturePadding = $selected;
|
$signaturePadding = $selected;
|
||||||
|
|
||||||
$new = clone $this;
|
$new = clone $this;
|
||||||
$new->encryptionPadding = $encryptionPadding;
|
if ($encryptedCount) {
|
||||||
$new->signaturePadding = $signaturePadding;
|
$new->encryptionPadding = $encryptionPadding;
|
||||||
|
}
|
||||||
|
if ($signatureCount) {
|
||||||
|
$new->signaturePadding = $signaturePadding;
|
||||||
|
}
|
||||||
return $new;
|
return $new;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -833,7 +833,6 @@ class Rijndael extends BlockCipher
|
||||||
|
|
||||||
// Generating encrypt code:
|
// Generating encrypt code:
|
||||||
$init_encrypt .= '
|
$init_encrypt .= '
|
||||||
static $tables;
|
|
||||||
if (empty($tables)) {
|
if (empty($tables)) {
|
||||||
$tables = &$this->getTables();
|
$tables = &$this->getTables();
|
||||||
}
|
}
|
||||||
|
@ -890,7 +889,6 @@ class Rijndael extends BlockCipher
|
||||||
|
|
||||||
// Generating decrypt code:
|
// Generating decrypt code:
|
||||||
$init_decrypt .= '
|
$init_decrypt .= '
|
||||||
static $invtables;
|
|
||||||
if (empty($invtables)) {
|
if (empty($invtables)) {
|
||||||
$invtables = &$this->getInvTables();
|
$invtables = &$this->getInvTables();
|
||||||
}
|
}
|
||||||
|
@ -947,7 +945,7 @@ class Rijndael extends BlockCipher
|
||||||
|
|
||||||
$this->inline_crypt = $this->createInlineCryptFunction(
|
$this->inline_crypt = $this->createInlineCryptFunction(
|
||||||
[
|
[
|
||||||
'init_crypt' => '',
|
'init_crypt' => 'static $tables; static $invtables;',
|
||||||
'init_encrypt' => $init_encrypt,
|
'init_encrypt' => $init_encrypt,
|
||||||
'init_decrypt' => $init_decrypt,
|
'init_decrypt' => $init_decrypt,
|
||||||
'encrypt_block' => $encrypt_block,
|
'encrypt_block' => $encrypt_block,
|
||||||
|
|
|
@ -21,7 +21,6 @@
|
||||||
|
|
||||||
namespace phpseclib3\File;
|
namespace phpseclib3\File;
|
||||||
|
|
||||||
use DateTime;
|
|
||||||
use phpseclib3\Common\Functions\Strings;
|
use phpseclib3\Common\Functions\Strings;
|
||||||
use phpseclib3\File\ASN1\Element;
|
use phpseclib3\File\ASN1\Element;
|
||||||
use phpseclib3\Math\BigInteger;
|
use phpseclib3\Math\BigInteger;
|
||||||
|
@ -205,7 +204,7 @@ abstract class ASN1
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return [self::decode_ber($encoded)];
|
return [$decoded];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1149,6 +1148,11 @@ abstract class ASN1
|
||||||
$oid = [];
|
$oid = [];
|
||||||
$pos = 0;
|
$pos = 0;
|
||||||
$len = strlen($content);
|
$len = strlen($content);
|
||||||
|
// see https://github.com/openjdk/jdk/blob/2deb318c9f047ec5a4b160d66a4b52f93688ec42/src/java.base/share/classes/sun/security/util/ObjectIdentifier.java#L55
|
||||||
|
if ($len > 4096) {
|
||||||
|
//throw new \RuntimeException("Object identifier size is limited to 4096 bytes ($len bytes present)");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (ord($content[$len - 1]) & 0x80) {
|
if (ord($content[$len - 1]) & 0x80) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -1403,7 +1407,7 @@ abstract class ASN1
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ($c & 0x80000000) != 0:
|
case ($c & (PHP_INT_SIZE == 8 ? 0x80000000 : (1 << 31))) != 0:
|
||||||
return false;
|
return false;
|
||||||
case $c >= 0x04000000:
|
case $c >= 0x04000000:
|
||||||
$v .= chr(0x80 | ($c & 0x3F));
|
$v .= chr(0x80 | ($c & 0x3F));
|
||||||
|
|
|
@ -164,7 +164,7 @@ class X509
|
||||||
*
|
*
|
||||||
* @var array
|
* @var array
|
||||||
*/
|
*/
|
||||||
private $CAs;
|
private $CAs = [];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The currently loaded certificate
|
* The currently loaded certificate
|
||||||
|
@ -315,6 +315,10 @@ class X509
|
||||||
'id-at-uniqueIdentifier' => '2.5.4.45',
|
'id-at-uniqueIdentifier' => '2.5.4.45',
|
||||||
'id-at-role' => '2.5.4.72',
|
'id-at-role' => '2.5.4.72',
|
||||||
'id-at-postalAddress' => '2.5.4.16',
|
'id-at-postalAddress' => '2.5.4.16',
|
||||||
|
'jurisdictionOfIncorporationCountryName' => '1.3.6.1.4.1.311.60.2.1.3',
|
||||||
|
'jurisdictionOfIncorporationStateOrProvinceName' => '1.3.6.1.4.1.311.60.2.1.2',
|
||||||
|
'jurisdictionLocalityName' => '1.3.6.1.4.1.311.60.2.1.1',
|
||||||
|
'id-at-businessCategory' => '2.5.4.15',
|
||||||
|
|
||||||
//'id-domainComponent' => '0.9.2342.19200300.100.1.25',
|
//'id-domainComponent' => '0.9.2342.19200300.100.1.25',
|
||||||
//'pkcs-9' => '1.2.840.113549.1.9',
|
//'pkcs-9' => '1.2.840.113549.1.9',
|
||||||
|
@ -1038,7 +1042,8 @@ class X509
|
||||||
if ($names = $this->getExtension('id-ce-subjectAltName')) {
|
if ($names = $this->getExtension('id-ce-subjectAltName')) {
|
||||||
foreach ($names as $name) {
|
foreach ($names as $name) {
|
||||||
foreach ($name as $key => $value) {
|
foreach ($name as $key => $value) {
|
||||||
$value = str_replace(['.', '*'], ['\.', '[^.]*'], $value);
|
$value = preg_quote($value);
|
||||||
|
$value = str_replace('\*', '[^.]*', $value);
|
||||||
switch ($key) {
|
switch ($key) {
|
||||||
case 'dNSName':
|
case 'dNSName':
|
||||||
/* From RFC2818 "HTTP over TLS":
|
/* From RFC2818 "HTTP over TLS":
|
||||||
|
@ -1538,6 +1543,20 @@ class X509
|
||||||
private function translateDNProp($propName)
|
private function translateDNProp($propName)
|
||||||
{
|
{
|
||||||
switch (strtolower($propName)) {
|
switch (strtolower($propName)) {
|
||||||
|
case 'jurisdictionofincorporationcountryname':
|
||||||
|
case 'jurisdictioncountryname':
|
||||||
|
case 'jurisdictionc':
|
||||||
|
return 'jurisdictionOfIncorporationCountryName';
|
||||||
|
case 'jurisdictionofincorporationstateorprovincename':
|
||||||
|
case 'jurisdictionstateorprovincename':
|
||||||
|
case 'jurisdictionst':
|
||||||
|
return 'jurisdictionOfIncorporationStateOrProvinceName';
|
||||||
|
case 'jurisdictionlocalityname':
|
||||||
|
case 'jurisdictionl':
|
||||||
|
return 'jurisdictionLocalityName';
|
||||||
|
case 'id-at-businesscategory':
|
||||||
|
case 'businesscategory':
|
||||||
|
return 'id-at-businessCategory';
|
||||||
case 'id-at-countryname':
|
case 'id-at-countryname':
|
||||||
case 'countryname':
|
case 'countryname':
|
||||||
case 'c':
|
case 'c':
|
||||||
|
@ -2030,9 +2049,6 @@ class X509
|
||||||
if (!is_array($this->currentCert) || !isset($this->currentCert['tbsCertificate'])) {
|
if (!is_array($this->currentCert) || !isset($this->currentCert['tbsCertificate'])) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (empty($this->CAs)) {
|
|
||||||
return $chain;
|
|
||||||
}
|
|
||||||
while (true) {
|
while (true) {
|
||||||
$currentCert = $chain[count($chain) - 1];
|
$currentCert = $chain[count($chain) - 1];
|
||||||
for ($i = 0; $i < count($this->CAs); $i++) {
|
for ($i = 0; $i < count($this->CAs); $i++) {
|
||||||
|
|
|
@ -100,10 +100,6 @@ class BigInteger implements \JsonSerializable
|
||||||
/** @var class-string<Engine> $fqmain */
|
/** @var class-string<Engine> $fqmain */
|
||||||
self::$mainEngine = $fqmain;
|
self::$mainEngine = $fqmain;
|
||||||
|
|
||||||
if (!in_array('Default', $modexps)) {
|
|
||||||
$modexps[] = 'DefaultEngine';
|
|
||||||
}
|
|
||||||
|
|
||||||
$found = false;
|
$found = false;
|
||||||
foreach ($modexps as $modexp) {
|
foreach ($modexps as $modexp) {
|
||||||
try {
|
try {
|
||||||
|
@ -140,18 +136,23 @@ class BigInteger implements \JsonSerializable
|
||||||
{
|
{
|
||||||
if (!isset(self::$mainEngine)) {
|
if (!isset(self::$mainEngine)) {
|
||||||
$engines = [
|
$engines = [
|
||||||
['GMP'],
|
['GMP', ['DefaultEngine']],
|
||||||
['PHP64', ['OpenSSL']],
|
['PHP64', ['OpenSSL']],
|
||||||
['BCMath', ['OpenSSL']],
|
['BCMath', ['OpenSSL']],
|
||||||
['PHP32', ['OpenSSL']]
|
['PHP32', ['OpenSSL']],
|
||||||
|
['PHP64', ['DefaultEngine']],
|
||||||
|
['PHP32', ['DefaultEngine']]
|
||||||
];
|
];
|
||||||
|
|
||||||
foreach ($engines as $engine) {
|
foreach ($engines as $engine) {
|
||||||
try {
|
try {
|
||||||
self::setEngine($engine[0], isset($engine[1]) ? $engine[1] : []);
|
self::setEngine($engine[0], $engine[1]);
|
||||||
break;
|
return;
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
throw new \UnexpectedValueException('No valid BigInteger found. This is only possible when JIT is enabled on Windows and neither the GMP or BCMath extensions are available so either disable JIT or install GMP / BCMath');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -619,7 +619,7 @@ abstract class Engine implements \JsonSerializable
|
||||||
*/
|
*/
|
||||||
public function getLengthInBytes()
|
public function getLengthInBytes()
|
||||||
{
|
{
|
||||||
return strlen($this->toBytes());
|
return (int) ceil($this->getLength() / 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -644,6 +644,11 @@ abstract class Engine implements \JsonSerializable
|
||||||
return $this->normalize($temp->powModInner($e, $n));
|
return $this->normalize($temp->powModInner($e, $n));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($this->compare($n) > 0) {
|
||||||
|
list(, $temp) = $this->divide($n);
|
||||||
|
return $temp->powModInner($e, $n);
|
||||||
|
}
|
||||||
|
|
||||||
return $this->powModInner($e, $n);
|
return $this->powModInner($e, $n);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -781,6 +786,11 @@ abstract class Engine implements \JsonSerializable
|
||||||
$min = $temp;
|
$min = $temp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$length = $max->getLength();
|
||||||
|
if ($length > 8196) {
|
||||||
|
throw new \RuntimeException("Generation of random prime numbers larger than 8196 has been disabled ($length)");
|
||||||
|
}
|
||||||
|
|
||||||
$x = static::randomRange($min, $max);
|
$x = static::randomRange($min, $max);
|
||||||
|
|
||||||
return static::randomRangePrimeInner($x, $min, $max);
|
return static::randomRangePrimeInner($x, $min, $max);
|
||||||
|
@ -985,6 +995,15 @@ abstract class Engine implements \JsonSerializable
|
||||||
*/
|
*/
|
||||||
public function isPrime($t = false)
|
public function isPrime($t = false)
|
||||||
{
|
{
|
||||||
|
// OpenSSL limits RSA keys to 16384 bits. The length of an RSA key is equal to the length of the modulo, which is
|
||||||
|
// produced by multiplying the primes p and q by one another. The largest number two 8196 bit primes can produce is
|
||||||
|
// a 16384 bit number so, basically, 8196 bit primes are the largest OpenSSL will generate and if that's the largest
|
||||||
|
// that it'll generate it also stands to reason that that's the largest you'll be able to test primality on
|
||||||
|
$length = $this->getLength();
|
||||||
|
if ($length > 8196) {
|
||||||
|
throw new \RuntimeException("Primality testing is not supported for numbers larger than 8196 bits ($length)");
|
||||||
|
}
|
||||||
|
|
||||||
if (!$t) {
|
if (!$t) {
|
||||||
$t = $this->setupIsPrime();
|
$t = $this->setupIsPrime();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1326,4 +1326,32 @@ abstract class PHP extends Engine
|
||||||
|
|
||||||
return array_reverse($vals);
|
return array_reverse($vals);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
protected static function testJITOnWindows()
|
||||||
|
{
|
||||||
|
// see https://github.com/php/php-src/issues/11917
|
||||||
|
if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN' && function_exists('opcache_get_status') && PHP_VERSION_ID < 80213 && !defined('PHPSECLIB_ALLOW_JIT')) {
|
||||||
|
$status = opcache_get_status();
|
||||||
|
if ($status && isset($status['jit']) && $status['jit']['enabled'] && $status['jit']['on']) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the size of a BigInteger in bits
|
||||||
|
*
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public function getLength()
|
||||||
|
{
|
||||||
|
$max = count($this->value) - 1;
|
||||||
|
return $max != -1 ?
|
||||||
|
$max * static::BASE + intval(ceil(log($this->value[$max] + 1, 2))) :
|
||||||
|
0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -80,10 +80,10 @@ class PHP32 extends PHP
|
||||||
}
|
}
|
||||||
$step = count($vals) & 3;
|
$step = count($vals) & 3;
|
||||||
if ($step) {
|
if ($step) {
|
||||||
$digit = floor($digit / pow(2, 2 * $step));
|
$digit = (int) floor($digit / pow(2, 2 * $step));
|
||||||
}
|
}
|
||||||
if ($step != 3) {
|
if ($step != 3) {
|
||||||
$digit &= static::MAX_DIGIT;
|
$digit = (int) fmod($digit, static::BASE_FULL);
|
||||||
$i++;
|
$i++;
|
||||||
}
|
}
|
||||||
$vals[] = $digit;
|
$vals[] = $digit;
|
||||||
|
@ -102,7 +102,7 @@ class PHP32 extends PHP
|
||||||
*/
|
*/
|
||||||
public static function isValidEngine()
|
public static function isValidEngine()
|
||||||
{
|
{
|
||||||
return PHP_INT_SIZE >= 4;
|
return PHP_INT_SIZE >= 4 && !self::testJITOnWindows();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -103,7 +103,7 @@ class PHP64 extends PHP
|
||||||
*/
|
*/
|
||||||
public static function isValidEngine()
|
public static function isValidEngine()
|
||||||
{
|
{
|
||||||
return PHP_INT_SIZE >= 8;
|
return PHP_INT_SIZE >= 8 && !self::testJITOnWindows();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -48,6 +48,15 @@ class BinaryField extends FiniteField
|
||||||
public function __construct(...$indices)
|
public function __construct(...$indices)
|
||||||
{
|
{
|
||||||
$m = array_shift($indices);
|
$m = array_shift($indices);
|
||||||
|
if ($m > 571) {
|
||||||
|
/* sect571r1 and sect571k1 are the largest binary curves that https://www.secg.org/sec2-v2.pdf defines
|
||||||
|
altho theoretically there may be legit reasons to use binary finite fields with larger degrees
|
||||||
|
imposing a limit on the maximum size is both reasonable and precedented. in particular,
|
||||||
|
http://tools.ietf.org/html/rfc4253#section-6.1 (The Secure Shell (SSH) Transport Layer Protocol) says
|
||||||
|
"implementations SHOULD check that the packet length is reasonable in order for the implementation to
|
||||||
|
avoid denial of service and/or buffer overflow attacks" */
|
||||||
|
throw new \OutOfBoundsException('Degrees larger than 571 are not supported');
|
||||||
|
}
|
||||||
$val = str_repeat('0', $m) . '1';
|
$val = str_repeat('0', $m) . '1';
|
||||||
foreach ($indices as $index) {
|
foreach ($indices as $index) {
|
||||||
$val[$index] = '1';
|
$val[$index] = '1';
|
||||||
|
|
|
@ -263,7 +263,7 @@ class Integer extends Base
|
||||||
$r = $this->value->powMod($temp, static::$modulo[$this->instanceID]);
|
$r = $this->value->powMod($temp, static::$modulo[$this->instanceID]);
|
||||||
|
|
||||||
while (!$t->equals($one)) {
|
while (!$t->equals($one)) {
|
||||||
for ($i == clone $one; $i->compare($m) < 0; $i = $i->add($one)) {
|
for ($i = clone $one; $i->compare($m) < 0; $i = $i->add($one)) {
|
||||||
if ($t->powMod($two->pow($i), static::$modulo[$this->instanceID])->equals($one)) {
|
if ($t->powMod($two->pow($i), static::$modulo[$this->instanceID])->equals($one)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -312,8 +312,11 @@ class Integer extends Base
|
||||||
*/
|
*/
|
||||||
public function toBytes()
|
public function toBytes()
|
||||||
{
|
{
|
||||||
$length = static::$modulo[$this->instanceID]->getLengthInBytes();
|
if (isset(static::$modulo[$this->instanceID])) {
|
||||||
return str_pad($this->value->toBytes(), $length, "\0", STR_PAD_LEFT);
|
$length = static::$modulo[$this->instanceID]->getLengthInBytes();
|
||||||
|
return str_pad($this->value->toBytes(), $length, "\0", STR_PAD_LEFT);
|
||||||
|
}
|
||||||
|
return $this->value->toBytes();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -93,7 +93,7 @@ class SFTP extends SSH2
|
||||||
* @var array
|
* @var array
|
||||||
* @access private
|
* @access private
|
||||||
*/
|
*/
|
||||||
private $packet_types = [];
|
private static $packet_types = [];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Status Codes
|
* Status Codes
|
||||||
|
@ -102,19 +102,19 @@ class SFTP extends SSH2
|
||||||
* @var array
|
* @var array
|
||||||
* @access private
|
* @access private
|
||||||
*/
|
*/
|
||||||
private $status_codes = [];
|
private static $status_codes = [];
|
||||||
|
|
||||||
/** @var array<int, string> */
|
/** @var array<int, string> */
|
||||||
private $attributes;
|
private static $attributes;
|
||||||
|
|
||||||
/** @var array<int, string> */
|
/** @var array<int, string> */
|
||||||
private $open_flags;
|
private static $open_flags;
|
||||||
|
|
||||||
/** @var array<int, string> */
|
/** @var array<int, string> */
|
||||||
private $open_flags5;
|
private static $open_flags5;
|
||||||
|
|
||||||
/** @var array<int, string> */
|
/** @var array<int, string> */
|
||||||
private $file_types;
|
private static $file_types;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The Request ID
|
* The Request ID
|
||||||
|
@ -350,7 +350,9 @@ class SFTP extends SSH2
|
||||||
*
|
*
|
||||||
* Connects to an SFTP server
|
* Connects to an SFTP server
|
||||||
*
|
*
|
||||||
* @param string $host
|
* $host can either be a string, representing the host, or a stream resource.
|
||||||
|
*
|
||||||
|
* @param mixed $host
|
||||||
* @param int $port
|
* @param int $port
|
||||||
* @param int $timeout
|
* @param int $timeout
|
||||||
*/
|
*/
|
||||||
|
@ -360,154 +362,156 @@ class SFTP extends SSH2
|
||||||
|
|
||||||
$this->max_sftp_packet = 1 << 15;
|
$this->max_sftp_packet = 1 << 15;
|
||||||
|
|
||||||
$this->packet_types = [
|
if (empty(self::$packet_types)) {
|
||||||
1 => 'NET_SFTP_INIT',
|
self::$packet_types = [
|
||||||
2 => 'NET_SFTP_VERSION',
|
1 => 'NET_SFTP_INIT',
|
||||||
3 => 'NET_SFTP_OPEN',
|
2 => 'NET_SFTP_VERSION',
|
||||||
4 => 'NET_SFTP_CLOSE',
|
3 => 'NET_SFTP_OPEN',
|
||||||
5 => 'NET_SFTP_READ',
|
4 => 'NET_SFTP_CLOSE',
|
||||||
6 => 'NET_SFTP_WRITE',
|
5 => 'NET_SFTP_READ',
|
||||||
7 => 'NET_SFTP_LSTAT',
|
6 => 'NET_SFTP_WRITE',
|
||||||
9 => 'NET_SFTP_SETSTAT',
|
7 => 'NET_SFTP_LSTAT',
|
||||||
10 => 'NET_SFTP_FSETSTAT',
|
9 => 'NET_SFTP_SETSTAT',
|
||||||
11 => 'NET_SFTP_OPENDIR',
|
10 => 'NET_SFTP_FSETSTAT',
|
||||||
12 => 'NET_SFTP_READDIR',
|
11 => 'NET_SFTP_OPENDIR',
|
||||||
13 => 'NET_SFTP_REMOVE',
|
12 => 'NET_SFTP_READDIR',
|
||||||
14 => 'NET_SFTP_MKDIR',
|
13 => 'NET_SFTP_REMOVE',
|
||||||
15 => 'NET_SFTP_RMDIR',
|
14 => 'NET_SFTP_MKDIR',
|
||||||
16 => 'NET_SFTP_REALPATH',
|
15 => 'NET_SFTP_RMDIR',
|
||||||
17 => 'NET_SFTP_STAT',
|
16 => 'NET_SFTP_REALPATH',
|
||||||
18 => 'NET_SFTP_RENAME',
|
17 => 'NET_SFTP_STAT',
|
||||||
19 => 'NET_SFTP_READLINK',
|
18 => 'NET_SFTP_RENAME',
|
||||||
20 => 'NET_SFTP_SYMLINK',
|
19 => 'NET_SFTP_READLINK',
|
||||||
21 => 'NET_SFTP_LINK',
|
20 => 'NET_SFTP_SYMLINK',
|
||||||
|
21 => 'NET_SFTP_LINK',
|
||||||
|
|
||||||
101 => 'NET_SFTP_STATUS',
|
101 => 'NET_SFTP_STATUS',
|
||||||
102 => 'NET_SFTP_HANDLE',
|
102 => 'NET_SFTP_HANDLE',
|
||||||
103 => 'NET_SFTP_DATA',
|
103 => 'NET_SFTP_DATA',
|
||||||
104 => 'NET_SFTP_NAME',
|
104 => 'NET_SFTP_NAME',
|
||||||
105 => 'NET_SFTP_ATTRS',
|
105 => 'NET_SFTP_ATTRS',
|
||||||
|
|
||||||
200 => 'NET_SFTP_EXTENDED'
|
200 => 'NET_SFTP_EXTENDED'
|
||||||
];
|
];
|
||||||
$this->status_codes = [
|
self::$status_codes = [
|
||||||
0 => 'NET_SFTP_STATUS_OK',
|
0 => 'NET_SFTP_STATUS_OK',
|
||||||
1 => 'NET_SFTP_STATUS_EOF',
|
1 => 'NET_SFTP_STATUS_EOF',
|
||||||
2 => 'NET_SFTP_STATUS_NO_SUCH_FILE',
|
2 => 'NET_SFTP_STATUS_NO_SUCH_FILE',
|
||||||
3 => 'NET_SFTP_STATUS_PERMISSION_DENIED',
|
3 => 'NET_SFTP_STATUS_PERMISSION_DENIED',
|
||||||
4 => 'NET_SFTP_STATUS_FAILURE',
|
4 => 'NET_SFTP_STATUS_FAILURE',
|
||||||
5 => 'NET_SFTP_STATUS_BAD_MESSAGE',
|
5 => 'NET_SFTP_STATUS_BAD_MESSAGE',
|
||||||
6 => 'NET_SFTP_STATUS_NO_CONNECTION',
|
6 => 'NET_SFTP_STATUS_NO_CONNECTION',
|
||||||
7 => 'NET_SFTP_STATUS_CONNECTION_LOST',
|
7 => 'NET_SFTP_STATUS_CONNECTION_LOST',
|
||||||
8 => 'NET_SFTP_STATUS_OP_UNSUPPORTED',
|
8 => 'NET_SFTP_STATUS_OP_UNSUPPORTED',
|
||||||
9 => 'NET_SFTP_STATUS_INVALID_HANDLE',
|
9 => 'NET_SFTP_STATUS_INVALID_HANDLE',
|
||||||
10 => 'NET_SFTP_STATUS_NO_SUCH_PATH',
|
10 => 'NET_SFTP_STATUS_NO_SUCH_PATH',
|
||||||
11 => 'NET_SFTP_STATUS_FILE_ALREADY_EXISTS',
|
11 => 'NET_SFTP_STATUS_FILE_ALREADY_EXISTS',
|
||||||
12 => 'NET_SFTP_STATUS_WRITE_PROTECT',
|
12 => 'NET_SFTP_STATUS_WRITE_PROTECT',
|
||||||
13 => 'NET_SFTP_STATUS_NO_MEDIA',
|
13 => 'NET_SFTP_STATUS_NO_MEDIA',
|
||||||
14 => 'NET_SFTP_STATUS_NO_SPACE_ON_FILESYSTEM',
|
14 => 'NET_SFTP_STATUS_NO_SPACE_ON_FILESYSTEM',
|
||||||
15 => 'NET_SFTP_STATUS_QUOTA_EXCEEDED',
|
15 => 'NET_SFTP_STATUS_QUOTA_EXCEEDED',
|
||||||
16 => 'NET_SFTP_STATUS_UNKNOWN_PRINCIPAL',
|
16 => 'NET_SFTP_STATUS_UNKNOWN_PRINCIPAL',
|
||||||
17 => 'NET_SFTP_STATUS_LOCK_CONFLICT',
|
17 => 'NET_SFTP_STATUS_LOCK_CONFLICT',
|
||||||
18 => 'NET_SFTP_STATUS_DIR_NOT_EMPTY',
|
18 => 'NET_SFTP_STATUS_DIR_NOT_EMPTY',
|
||||||
19 => 'NET_SFTP_STATUS_NOT_A_DIRECTORY',
|
19 => 'NET_SFTP_STATUS_NOT_A_DIRECTORY',
|
||||||
20 => 'NET_SFTP_STATUS_INVALID_FILENAME',
|
20 => 'NET_SFTP_STATUS_INVALID_FILENAME',
|
||||||
21 => 'NET_SFTP_STATUS_LINK_LOOP',
|
21 => 'NET_SFTP_STATUS_LINK_LOOP',
|
||||||
22 => 'NET_SFTP_STATUS_CANNOT_DELETE',
|
22 => 'NET_SFTP_STATUS_CANNOT_DELETE',
|
||||||
23 => 'NET_SFTP_STATUS_INVALID_PARAMETER',
|
23 => 'NET_SFTP_STATUS_INVALID_PARAMETER',
|
||||||
24 => 'NET_SFTP_STATUS_FILE_IS_A_DIRECTORY',
|
24 => 'NET_SFTP_STATUS_FILE_IS_A_DIRECTORY',
|
||||||
25 => 'NET_SFTP_STATUS_BYTE_RANGE_LOCK_CONFLICT',
|
25 => 'NET_SFTP_STATUS_BYTE_RANGE_LOCK_CONFLICT',
|
||||||
26 => 'NET_SFTP_STATUS_BYTE_RANGE_LOCK_REFUSED',
|
26 => 'NET_SFTP_STATUS_BYTE_RANGE_LOCK_REFUSED',
|
||||||
27 => 'NET_SFTP_STATUS_DELETE_PENDING',
|
27 => 'NET_SFTP_STATUS_DELETE_PENDING',
|
||||||
28 => 'NET_SFTP_STATUS_FILE_CORRUPT',
|
28 => 'NET_SFTP_STATUS_FILE_CORRUPT',
|
||||||
29 => 'NET_SFTP_STATUS_OWNER_INVALID',
|
29 => 'NET_SFTP_STATUS_OWNER_INVALID',
|
||||||
30 => 'NET_SFTP_STATUS_GROUP_INVALID',
|
30 => 'NET_SFTP_STATUS_GROUP_INVALID',
|
||||||
31 => 'NET_SFTP_STATUS_NO_MATCHING_BYTE_RANGE_LOCK'
|
31 => 'NET_SFTP_STATUS_NO_MATCHING_BYTE_RANGE_LOCK'
|
||||||
];
|
];
|
||||||
// http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-7.1
|
// http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-7.1
|
||||||
// the order, in this case, matters quite a lot - see \phpseclib3\Net\SFTP::_parseAttributes() to understand why
|
// the order, in this case, matters quite a lot - see \phpseclib3\Net\SFTP::_parseAttributes() to understand why
|
||||||
$this->attributes = [
|
self::$attributes = [
|
||||||
0x00000001 => 'NET_SFTP_ATTR_SIZE',
|
0x00000001 => 'NET_SFTP_ATTR_SIZE',
|
||||||
0x00000002 => 'NET_SFTP_ATTR_UIDGID', // defined in SFTPv3, removed in SFTPv4+
|
0x00000002 => 'NET_SFTP_ATTR_UIDGID', // defined in SFTPv3, removed in SFTPv4+
|
||||||
0x00000080 => 'NET_SFTP_ATTR_OWNERGROUP', // defined in SFTPv4+
|
0x00000080 => 'NET_SFTP_ATTR_OWNERGROUP', // defined in SFTPv4+
|
||||||
0x00000004 => 'NET_SFTP_ATTR_PERMISSIONS',
|
0x00000004 => 'NET_SFTP_ATTR_PERMISSIONS',
|
||||||
0x00000008 => 'NET_SFTP_ATTR_ACCESSTIME',
|
0x00000008 => 'NET_SFTP_ATTR_ACCESSTIME',
|
||||||
0x00000010 => 'NET_SFTP_ATTR_CREATETIME', // SFTPv4+
|
0x00000010 => 'NET_SFTP_ATTR_CREATETIME', // SFTPv4+
|
||||||
0x00000020 => 'NET_SFTP_ATTR_MODIFYTIME',
|
0x00000020 => 'NET_SFTP_ATTR_MODIFYTIME',
|
||||||
0x00000040 => 'NET_SFTP_ATTR_ACL',
|
0x00000040 => 'NET_SFTP_ATTR_ACL',
|
||||||
0x00000100 => 'NET_SFTP_ATTR_SUBSECOND_TIMES',
|
0x00000100 => 'NET_SFTP_ATTR_SUBSECOND_TIMES',
|
||||||
0x00000200 => 'NET_SFTP_ATTR_BITS', // SFTPv5+
|
0x00000200 => 'NET_SFTP_ATTR_BITS', // SFTPv5+
|
||||||
0x00000400 => 'NET_SFTP_ATTR_ALLOCATION_SIZE', // SFTPv6+
|
0x00000400 => 'NET_SFTP_ATTR_ALLOCATION_SIZE', // SFTPv6+
|
||||||
0x00000800 => 'NET_SFTP_ATTR_TEXT_HINT',
|
0x00000800 => 'NET_SFTP_ATTR_TEXT_HINT',
|
||||||
0x00001000 => 'NET_SFTP_ATTR_MIME_TYPE',
|
0x00001000 => 'NET_SFTP_ATTR_MIME_TYPE',
|
||||||
0x00002000 => 'NET_SFTP_ATTR_LINK_COUNT',
|
0x00002000 => 'NET_SFTP_ATTR_LINK_COUNT',
|
||||||
0x00004000 => 'NET_SFTP_ATTR_UNTRANSLATED_NAME',
|
0x00004000 => 'NET_SFTP_ATTR_UNTRANSLATED_NAME',
|
||||||
0x00008000 => 'NET_SFTP_ATTR_CTIME',
|
0x00008000 => 'NET_SFTP_ATTR_CTIME',
|
||||||
// 0x80000000 will yield a floating point on 32-bit systems and converting floating points to integers
|
// 0x80000000 will yield a floating point on 32-bit systems and converting floating points to integers
|
||||||
// yields inconsistent behavior depending on how php is compiled. so we left shift -1 (which, in
|
// yields inconsistent behavior depending on how php is compiled. so we left shift -1 (which, in
|
||||||
// two's compliment, consists of all 1 bits) by 31. on 64-bit systems this'll yield 0xFFFFFFFF80000000.
|
// two's compliment, consists of all 1 bits) by 31. on 64-bit systems this'll yield 0xFFFFFFFF80000000.
|
||||||
// that's not a problem, however, and 'anded' and a 32-bit number, as all the leading 1 bits are ignored.
|
// that's not a problem, however, and 'anded' and a 32-bit number, as all the leading 1 bits are ignored.
|
||||||
(PHP_INT_SIZE == 4 ? -1 : 0xFFFFFFFF) => 'NET_SFTP_ATTR_EXTENDED'
|
(PHP_INT_SIZE == 4 ? (-1 << 31) : 0x80000000) => 'NET_SFTP_ATTR_EXTENDED'
|
||||||
];
|
];
|
||||||
// http://tools.ietf.org/html/draft-ietf-secsh-filexfer-04#section-6.3
|
// http://tools.ietf.org/html/draft-ietf-secsh-filexfer-04#section-6.3
|
||||||
// the flag definitions change somewhat in SFTPv5+. if SFTPv5+ support is added to this library, maybe name
|
// the flag definitions change somewhat in SFTPv5+. if SFTPv5+ support is added to this library, maybe name
|
||||||
// the array for that $this->open5_flags and similarly alter the constant names.
|
// the array for that $this->open5_flags and similarly alter the constant names.
|
||||||
$this->open_flags = [
|
self::$open_flags = [
|
||||||
0x00000001 => 'NET_SFTP_OPEN_READ',
|
0x00000001 => 'NET_SFTP_OPEN_READ',
|
||||||
0x00000002 => 'NET_SFTP_OPEN_WRITE',
|
0x00000002 => 'NET_SFTP_OPEN_WRITE',
|
||||||
0x00000004 => 'NET_SFTP_OPEN_APPEND',
|
0x00000004 => 'NET_SFTP_OPEN_APPEND',
|
||||||
0x00000008 => 'NET_SFTP_OPEN_CREATE',
|
0x00000008 => 'NET_SFTP_OPEN_CREATE',
|
||||||
0x00000010 => 'NET_SFTP_OPEN_TRUNCATE',
|
0x00000010 => 'NET_SFTP_OPEN_TRUNCATE',
|
||||||
0x00000020 => 'NET_SFTP_OPEN_EXCL',
|
0x00000020 => 'NET_SFTP_OPEN_EXCL',
|
||||||
0x00000040 => 'NET_SFTP_OPEN_TEXT' // defined in SFTPv4
|
0x00000040 => 'NET_SFTP_OPEN_TEXT' // defined in SFTPv4
|
||||||
];
|
];
|
||||||
// SFTPv5+ changed the flags up:
|
// SFTPv5+ changed the flags up:
|
||||||
// https://datatracker.ietf.org/doc/html/draft-ietf-secsh-filexfer-13#section-8.1.1.3
|
// https://datatracker.ietf.org/doc/html/draft-ietf-secsh-filexfer-13#section-8.1.1.3
|
||||||
$this->open_flags5 = [
|
self::$open_flags5 = [
|
||||||
// when SSH_FXF_ACCESS_DISPOSITION is a 3 bit field that controls how the file is opened
|
// when SSH_FXF_ACCESS_DISPOSITION is a 3 bit field that controls how the file is opened
|
||||||
0x00000000 => 'NET_SFTP_OPEN_CREATE_NEW',
|
0x00000000 => 'NET_SFTP_OPEN_CREATE_NEW',
|
||||||
0x00000001 => 'NET_SFTP_OPEN_CREATE_TRUNCATE',
|
0x00000001 => 'NET_SFTP_OPEN_CREATE_TRUNCATE',
|
||||||
0x00000002 => 'NET_SFTP_OPEN_OPEN_EXISTING',
|
0x00000002 => 'NET_SFTP_OPEN_OPEN_EXISTING',
|
||||||
0x00000003 => 'NET_SFTP_OPEN_OPEN_OR_CREATE',
|
0x00000003 => 'NET_SFTP_OPEN_OPEN_OR_CREATE',
|
||||||
0x00000004 => 'NET_SFTP_OPEN_TRUNCATE_EXISTING',
|
0x00000004 => 'NET_SFTP_OPEN_TRUNCATE_EXISTING',
|
||||||
// the rest of the flags are not supported
|
// the rest of the flags are not supported
|
||||||
0x00000008 => 'NET_SFTP_OPEN_APPEND_DATA', // "the offset field of SS_FXP_WRITE requests is ignored"
|
0x00000008 => 'NET_SFTP_OPEN_APPEND_DATA', // "the offset field of SS_FXP_WRITE requests is ignored"
|
||||||
0x00000010 => 'NET_SFTP_OPEN_APPEND_DATA_ATOMIC',
|
0x00000010 => 'NET_SFTP_OPEN_APPEND_DATA_ATOMIC',
|
||||||
0x00000020 => 'NET_SFTP_OPEN_TEXT_MODE',
|
0x00000020 => 'NET_SFTP_OPEN_TEXT_MODE',
|
||||||
0x00000040 => 'NET_SFTP_OPEN_BLOCK_READ',
|
0x00000040 => 'NET_SFTP_OPEN_BLOCK_READ',
|
||||||
0x00000080 => 'NET_SFTP_OPEN_BLOCK_WRITE',
|
0x00000080 => 'NET_SFTP_OPEN_BLOCK_WRITE',
|
||||||
0x00000100 => 'NET_SFTP_OPEN_BLOCK_DELETE',
|
0x00000100 => 'NET_SFTP_OPEN_BLOCK_DELETE',
|
||||||
0x00000200 => 'NET_SFTP_OPEN_BLOCK_ADVISORY',
|
0x00000200 => 'NET_SFTP_OPEN_BLOCK_ADVISORY',
|
||||||
0x00000400 => 'NET_SFTP_OPEN_NOFOLLOW',
|
0x00000400 => 'NET_SFTP_OPEN_NOFOLLOW',
|
||||||
0x00000800 => 'NET_SFTP_OPEN_DELETE_ON_CLOSE',
|
0x00000800 => 'NET_SFTP_OPEN_DELETE_ON_CLOSE',
|
||||||
0x00001000 => 'NET_SFTP_OPEN_ACCESS_AUDIT_ALARM_INFO',
|
0x00001000 => 'NET_SFTP_OPEN_ACCESS_AUDIT_ALARM_INFO',
|
||||||
0x00002000 => 'NET_SFTP_OPEN_ACCESS_BACKUP',
|
0x00002000 => 'NET_SFTP_OPEN_ACCESS_BACKUP',
|
||||||
0x00004000 => 'NET_SFTP_OPEN_BACKUP_STREAM',
|
0x00004000 => 'NET_SFTP_OPEN_BACKUP_STREAM',
|
||||||
0x00008000 => 'NET_SFTP_OPEN_OVERRIDE_OWNER',
|
0x00008000 => 'NET_SFTP_OPEN_OVERRIDE_OWNER',
|
||||||
];
|
];
|
||||||
// http://tools.ietf.org/html/draft-ietf-secsh-filexfer-04#section-5.2
|
// http://tools.ietf.org/html/draft-ietf-secsh-filexfer-04#section-5.2
|
||||||
// see \phpseclib3\Net\SFTP::_parseLongname() for an explanation
|
// see \phpseclib3\Net\SFTP::_parseLongname() for an explanation
|
||||||
$this->file_types = [
|
self::$file_types = [
|
||||||
1 => 'NET_SFTP_TYPE_REGULAR',
|
1 => 'NET_SFTP_TYPE_REGULAR',
|
||||||
2 => 'NET_SFTP_TYPE_DIRECTORY',
|
2 => 'NET_SFTP_TYPE_DIRECTORY',
|
||||||
3 => 'NET_SFTP_TYPE_SYMLINK',
|
3 => 'NET_SFTP_TYPE_SYMLINK',
|
||||||
4 => 'NET_SFTP_TYPE_SPECIAL',
|
4 => 'NET_SFTP_TYPE_SPECIAL',
|
||||||
5 => 'NET_SFTP_TYPE_UNKNOWN',
|
5 => 'NET_SFTP_TYPE_UNKNOWN',
|
||||||
// the following types were first defined for use in SFTPv5+
|
// the following types were first defined for use in SFTPv5+
|
||||||
// http://tools.ietf.org/html/draft-ietf-secsh-filexfer-05#section-5.2
|
// http://tools.ietf.org/html/draft-ietf-secsh-filexfer-05#section-5.2
|
||||||
6 => 'NET_SFTP_TYPE_SOCKET',
|
6 => 'NET_SFTP_TYPE_SOCKET',
|
||||||
7 => 'NET_SFTP_TYPE_CHAR_DEVICE',
|
7 => 'NET_SFTP_TYPE_CHAR_DEVICE',
|
||||||
8 => 'NET_SFTP_TYPE_BLOCK_DEVICE',
|
8 => 'NET_SFTP_TYPE_BLOCK_DEVICE',
|
||||||
9 => 'NET_SFTP_TYPE_FIFO'
|
9 => 'NET_SFTP_TYPE_FIFO'
|
||||||
];
|
];
|
||||||
$this->define_array(
|
self::define_array(
|
||||||
$this->packet_types,
|
self::$packet_types,
|
||||||
$this->status_codes,
|
self::$status_codes,
|
||||||
$this->attributes,
|
self::$attributes,
|
||||||
$this->open_flags,
|
self::$open_flags,
|
||||||
$this->open_flags5,
|
self::$open_flags5,
|
||||||
$this->file_types
|
self::$file_types
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
|
||||||
if (!defined('NET_SFTP_QUEUE_SIZE')) {
|
if (!defined('NET_SFTP_QUEUE_SIZE')) {
|
||||||
define('NET_SFTP_QUEUE_SIZE', 32);
|
define('NET_SFTP_QUEUE_SIZE', 32);
|
||||||
|
@ -543,22 +547,7 @@ class SFTP extends SSH2
|
||||||
*/
|
*/
|
||||||
private function partial_init_sftp_connection()
|
private function partial_init_sftp_connection()
|
||||||
{
|
{
|
||||||
$this->window_size_server_to_client[self::CHANNEL] = $this->window_size;
|
$response = $this->open_channel(self::CHANNEL, true);
|
||||||
|
|
||||||
$packet = Strings::packSSH2(
|
|
||||||
'CsN3',
|
|
||||||
NET_SSH2_MSG_CHANNEL_OPEN,
|
|
||||||
'session',
|
|
||||||
self::CHANNEL,
|
|
||||||
$this->window_size,
|
|
||||||
0x4000
|
|
||||||
);
|
|
||||||
|
|
||||||
$this->send_binary_packet($packet);
|
|
||||||
|
|
||||||
$this->channel_status[self::CHANNEL] = NET_SSH2_MSG_CHANNEL_OPEN;
|
|
||||||
|
|
||||||
$response = $this->get_channel_packet(self::CHANNEL, true);
|
|
||||||
if ($response === true && $this->isTimeout()) {
|
if ($response === true && $this->isTimeout()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -815,7 +804,7 @@ class SFTP extends SSH2
|
||||||
list($status) = Strings::unpackSSH2('N', $response);
|
list($status) = Strings::unpackSSH2('N', $response);
|
||||||
}
|
}
|
||||||
|
|
||||||
$error = $this->status_codes[$status];
|
$error = self::$status_codes[$status];
|
||||||
|
|
||||||
if ($this->version > 2) {
|
if ($this->version > 2) {
|
||||||
list($message) = Strings::unpackSSH2('s', $response);
|
list($message) = Strings::unpackSSH2('s', $response);
|
||||||
|
@ -2138,10 +2127,10 @@ class SFTP extends SSH2
|
||||||
|
|
||||||
if ($start >= 0) {
|
if ($start >= 0) {
|
||||||
$offset = $start;
|
$offset = $start;
|
||||||
} elseif ($mode & self::RESUME) {
|
} elseif ($mode & (self::RESUME | self::RESUME_START)) {
|
||||||
// if NET_SFTP_OPEN_APPEND worked as it should _size() wouldn't need to be called
|
// if NET_SFTP_OPEN_APPEND worked as it should _size() wouldn't need to be called
|
||||||
$size = $this->stat($remote_file)['size'];
|
$stat = $this->stat($remote_file);
|
||||||
$offset = $size !== false ? $size : 0;
|
$offset = $stat !== false && $stat['size'] ? $stat['size'] : 0;
|
||||||
} else {
|
} else {
|
||||||
$offset = 0;
|
$offset = 0;
|
||||||
if ($this->version >= 5) {
|
if ($this->version >= 5) {
|
||||||
|
@ -2210,6 +2199,9 @@ class SFTP extends SSH2
|
||||||
if ($local_start >= 0) {
|
if ($local_start >= 0) {
|
||||||
fseek($fp, $local_start);
|
fseek($fp, $local_start);
|
||||||
$size -= $local_start;
|
$size -= $local_start;
|
||||||
|
} elseif ($mode & self::RESUME) {
|
||||||
|
fseek($fp, $offset);
|
||||||
|
$size -= $offset;
|
||||||
}
|
}
|
||||||
} elseif ($dataCallback) {
|
} elseif ($dataCallback) {
|
||||||
$size = 0;
|
$size = 0;
|
||||||
|
@ -2497,14 +2489,6 @@ class SFTP extends SSH2
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($length > 0 && $length <= $offset - $start) {
|
|
||||||
if ($local_file === false) {
|
|
||||||
$content = substr($content, 0, $length);
|
|
||||||
} else {
|
|
||||||
ftruncate($fp, $length + $res_offset);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($fclose_check) {
|
if ($fclose_check) {
|
||||||
fclose($fp);
|
fclose($fp);
|
||||||
|
|
||||||
|
@ -2840,15 +2824,37 @@ class SFTP extends SSH2
|
||||||
return $this->get_stat_cache_prop($path, 'gid');
|
return $this->get_stat_cache_prop($path, 'gid');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Recursively go through rawlist() output to get the total filesize
|
||||||
|
*
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
private static function recursiveFilesize(array $files)
|
||||||
|
{
|
||||||
|
$size = 0;
|
||||||
|
foreach ($files as $name => $file) {
|
||||||
|
if ($name == '.' || $name == '..') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$size += is_array($file) ?
|
||||||
|
self::recursiveFilesize($file) :
|
||||||
|
$file->size;
|
||||||
|
}
|
||||||
|
return $size;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets file size
|
* Gets file size
|
||||||
*
|
*
|
||||||
* @param string $path
|
* @param string $path
|
||||||
|
* @param bool $recursive
|
||||||
* @return mixed
|
* @return mixed
|
||||||
*/
|
*/
|
||||||
public function filesize($path)
|
public function filesize($path, $recursive = false)
|
||||||
{
|
{
|
||||||
return $this->get_stat_cache_prop($path, 'size');
|
return !$recursive || $this->filetype($path) != 'dir' ?
|
||||||
|
$this->get_stat_cache_prop($path, 'size') :
|
||||||
|
self::recursiveFilesize($this->rawlist($path, true));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -3041,7 +3047,7 @@ class SFTP extends SSH2
|
||||||
list($flags) = Strings::unpackSSH2('N', $response);
|
list($flags) = Strings::unpackSSH2('N', $response);
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach ($this->attributes as $key => $value) {
|
foreach (self::$attributes as $key => $value) {
|
||||||
switch ($flags & $key) {
|
switch ($flags & $key) {
|
||||||
case NET_SFTP_ATTR_UIDGID:
|
case NET_SFTP_ATTR_UIDGID:
|
||||||
if ($this->version > 3) {
|
if ($this->version > 3) {
|
||||||
|
@ -3272,7 +3278,7 @@ class SFTP extends SSH2
|
||||||
$stop = microtime(true);
|
$stop = microtime(true);
|
||||||
|
|
||||||
if (defined('NET_SFTP_LOGGING')) {
|
if (defined('NET_SFTP_LOGGING')) {
|
||||||
$packet_type = '-> ' . $this->packet_types[$type] .
|
$packet_type = '-> ' . self::$packet_types[$type] .
|
||||||
' (' . round($stop - $start, 4) . 's)';
|
' (' . round($stop - $start, 4) . 's)';
|
||||||
$this->append_log($packet_type, $data);
|
$this->append_log($packet_type, $data);
|
||||||
}
|
}
|
||||||
|
@ -3289,6 +3295,7 @@ class SFTP extends SSH2
|
||||||
$this->use_request_id = false;
|
$this->use_request_id = false;
|
||||||
$this->pwd = false;
|
$this->pwd = false;
|
||||||
$this->requestBuffer = [];
|
$this->requestBuffer = [];
|
||||||
|
$this->partial_init = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -3376,7 +3383,7 @@ class SFTP extends SSH2
|
||||||
$packet = Strings::shift($this->packet_buffer, $length);
|
$packet = Strings::shift($this->packet_buffer, $length);
|
||||||
|
|
||||||
if (defined('NET_SFTP_LOGGING')) {
|
if (defined('NET_SFTP_LOGGING')) {
|
||||||
$packet_type = '<- ' . $this->packet_types[$this->packet_type] .
|
$packet_type = '<- ' . self::$packet_types[$this->packet_type] .
|
||||||
' (' . round($stop - $start, 4) . 's)';
|
' (' . round($stop - $start, 4) . 's)';
|
||||||
$this->append_log($packet_type, $packet);
|
$this->append_log($packet_type, $packet);
|
||||||
}
|
}
|
||||||
|
@ -3420,7 +3427,7 @@ class SFTP extends SSH2
|
||||||
*
|
*
|
||||||
* Returns a string if NET_SFTP_LOGGING == self::LOG_COMPLEX, an array if NET_SFTP_LOGGING == self::LOG_SIMPLE and false if !defined('NET_SFTP_LOGGING')
|
* Returns a string if NET_SFTP_LOGGING == self::LOG_COMPLEX, an array if NET_SFTP_LOGGING == self::LOG_SIMPLE and false if !defined('NET_SFTP_LOGGING')
|
||||||
*
|
*
|
||||||
* @return array|string
|
* @return array|string|false
|
||||||
*/
|
*/
|
||||||
public function getSFTPLog()
|
public function getSFTPLog()
|
||||||
{
|
{
|
||||||
|
@ -3439,7 +3446,7 @@ class SFTP extends SSH2
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns all errors
|
* Returns all errors on the SFTP layer
|
||||||
*
|
*
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
|
@ -3449,7 +3456,7 @@ class SFTP extends SSH2
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the last error
|
* Returns the last error on the SFTP layer
|
||||||
*
|
*
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue