[securemail] Update Composer dependency ahead of release

- Updating phpseclib/phpseclib (3.0.19 => 3.0.37)
pull/1487/head
Hypolite Petovan 2024-03-19 22:08:59 -04:00
parent 7bff983d21
commit 0a69c66d09
23 changed files with 922 additions and 492 deletions

View File

@ -1,26 +1,26 @@
{
"name": "friendica-addons/securemail",
"description": "Send notification mail encrypted with user-defined public GPG key.",
"type": "friendica-addon",
"authors": [
{
"name": "Fabio Comuni",
"homepage": "https://kirgroup.com/profile/fabrixxm",
"role": "Developer"
"name": "friendica-addons/securemail",
"description": "Send notification mail encrypted with user-defined public GPG key.",
"type": "friendica-addon",
"authors": [
{
"name": "Fabio Comuni",
"homepage": "https://kirgroup.com/profile/fabrixxm",
"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"
}
}
}

View File

@ -70,16 +70,16 @@
},
{
"name": "phpseclib/phpseclib",
"version": "3.0.19",
"version": "3.0.37",
"source": {
"type": "git",
"url": "https://github.com/phpseclib/phpseclib.git",
"reference": "cc181005cf548bfd8a4896383bb825d859259f95"
"reference": "cfa2013d0f68c062055180dd4328cc8b9d1f30b8"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/cc181005cf548bfd8a4896383bb825d859259f95",
"reference": "cc181005cf548bfd8a4896383bb825d859259f95",
"url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/cfa2013d0f68c062055180dd4328cc8b9d1f30b8",
"reference": "cfa2013d0f68c062055180dd4328cc8b9d1f30b8",
"shasum": ""
},
"require": {
@ -172,7 +172,7 @@
"type": "tidelift"
}
],
"time": "2023-03-05T17:13:09+00:00"
"time": "2024-03-03T02:14:58+00:00"
},
{
"name": "singpolyma/openpgp-php",

View File

@ -65,17 +65,17 @@
},
{
"name": "phpseclib/phpseclib",
"version": "3.0.19",
"version_normalized": "3.0.19.0",
"version": "3.0.37",
"version_normalized": "3.0.37.0",
"source": {
"type": "git",
"url": "https://github.com/phpseclib/phpseclib.git",
"reference": "cc181005cf548bfd8a4896383bb825d859259f95"
"reference": "cfa2013d0f68c062055180dd4328cc8b9d1f30b8"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/cc181005cf548bfd8a4896383bb825d859259f95",
"reference": "cc181005cf548bfd8a4896383bb825d859259f95",
"url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/cfa2013d0f68c062055180dd4328cc8b9d1f30b8",
"reference": "cfa2013d0f68c062055180dd4328cc8b9d1f30b8",
"shasum": ""
},
"require": {
@ -93,7 +93,7 @@
"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."
},
"time": "2023-03-05T17:13:09+00:00",
"time": "2024-03-03T02:14:58+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {

View File

@ -12,4 +12,6 @@ phpseclib ongoing development is made possible by [Tidelift](https://tidelift.co
- [Charles Severance](https://github.com/csev)
- [Rachel Fish](https://github.com/itsrachelfish)
- Tharyrok
- [cjhaas](https://github.com/cjhaas)
- [cjhaas](https://github.com/cjhaas)
- [istiak-tridip](https://github.com/istiak-tridip)
- [Anna Filina](https://github.com/afilina)

View File

@ -51,8 +51,7 @@ SSH-2, SFTP, X.509, an arbitrary-precision integer arithmetic library, Ed25519 /
* PHP4 compatible
* Composer compatible (PSR-0 autoloading)
* 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.20 as ZIP](http://sourceforge.net/projects/phpseclib/files/phpseclib1.0.20.zip/download)
* [Download 1.0.23 as ZIP](http://sourceforge.net/projects/phpseclib/files/phpseclib1.0.23.zip/download)
## Security contact information

View File

@ -94,7 +94,7 @@ abstract class AsymmetricKey
/**
* @param string $type
* @return string
* @return array|string
*/
abstract public function toString($type, array $options = []);
@ -130,7 +130,7 @@ abstract class AsymmetricKey
*
* @param string $key
* @param string $password optional
* @return AsymmetricKey
* @return \phpseclib3\Crypt\Common\PublicKey|\phpseclib3\Crypt\Common\PrivateKey
*/
public static function load($key, $password = false)
{
@ -382,7 +382,7 @@ abstract class AsymmetricKey
$shortname = $meta->getShortName();
self::$plugins[static::ALGORITHM]['Keys'][strtolower($shortname)] = $fullname;
if ($meta->hasConstant('IS_INVISIBLE')) {
self::$invisiblePlugins[static::ALGORITHM] = strtolower($name);
self::$invisiblePlugins[static::ALGORITHM][] = strtolower($shortname);
}
}
}

View File

@ -141,6 +141,7 @@ abstract class PKCS8 extends PKCS
break;
case 'RC2':
$cipher = new RC2('cbc');
$cipher->setKeyLength(64);
break;
case '3-KeyTripleDES':
$cipher = new TripleDES('cbc');
@ -218,7 +219,7 @@ abstract class PKCS8 extends PKCS
{
switch ($algo) {
case 'desCBC':
$cipher = new TripleDES('cbc');
$cipher = new DES('cbc');
break;
case 'des-EDE3-CBC':
$cipher = new TripleDES('cbc');

View File

@ -668,6 +668,8 @@ abstract class SymmetricKey
switch (true) {
// PHP_OS & "\xDF\xDF\xDF" == strtoupper(substr(PHP_OS, 0, 3)), but a lot faster
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 defined('PHP_INT_SIZE') && PHP_INT_SIZE == 8:
self::$use_reg_intval = true;
@ -917,7 +919,7 @@ abstract class SymmetricKey
* @see Crypt/Hash.php
* @param string $password
* @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 \RuntimeException if bcrypt is being used and a salt isn't provided
* @return bool

View 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);
}
}

View File

@ -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;
// doing this may mean some curve-specific optimizations can't be used but idk if OpenSSL even
// 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 ($shortFormat == 'ASN1') {

View File

@ -332,6 +332,7 @@ abstract class RSA extends AsymmetricKey
openssl_pkey_export($rsa, $privatekeystr, null, $config);
// 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) {
}
@ -841,15 +842,15 @@ abstract class RSA extends AsymmetricKey
self::ENCRYPTION_PKCS1,
self::ENCRYPTION_NONE
];
$numSelected = 0;
$encryptedCount = 0;
$selected = 0;
foreach ($masks as $mask) {
if ($padding & $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');
}
$encryptionPadding = $selected;
@ -859,22 +860,26 @@ abstract class RSA extends AsymmetricKey
self::SIGNATURE_RELAXED_PKCS1,
self::SIGNATURE_PKCS1
];
$numSelected = 0;
$signatureCount = 0;
$selected = 0;
foreach ($masks as $mask) {
if ($padding & $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');
}
$signaturePadding = $selected;
$new = clone $this;
$new->encryptionPadding = $encryptionPadding;
$new->signaturePadding = $signaturePadding;
if ($encryptedCount) {
$new->encryptionPadding = $encryptionPadding;
}
if ($signatureCount) {
$new->signaturePadding = $signaturePadding;
}
return $new;
}

View File

@ -833,7 +833,6 @@ class Rijndael extends BlockCipher
// Generating encrypt code:
$init_encrypt .= '
static $tables;
if (empty($tables)) {
$tables = &$this->getTables();
}
@ -890,7 +889,6 @@ class Rijndael extends BlockCipher
// Generating decrypt code:
$init_decrypt .= '
static $invtables;
if (empty($invtables)) {
$invtables = &$this->getInvTables();
}
@ -947,7 +945,7 @@ class Rijndael extends BlockCipher
$this->inline_crypt = $this->createInlineCryptFunction(
[
'init_crypt' => '',
'init_crypt' => 'static $tables; static $invtables;',
'init_encrypt' => $init_encrypt,
'init_decrypt' => $init_decrypt,
'encrypt_block' => $encrypt_block,

View File

@ -21,7 +21,6 @@
namespace phpseclib3\File;
use DateTime;
use phpseclib3\Common\Functions\Strings;
use phpseclib3\File\ASN1\Element;
use phpseclib3\Math\BigInteger;
@ -205,7 +204,7 @@ abstract class ASN1
return null;
}
return [self::decode_ber($encoded)];
return [$decoded];
}
/**
@ -1149,6 +1148,11 @@ abstract class ASN1
$oid = [];
$pos = 0;
$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) {
return false;
@ -1403,7 +1407,7 @@ abstract class ASN1
return false;
}
break;
case ($c & 0x80000000) != 0:
case ($c & (PHP_INT_SIZE == 8 ? 0x80000000 : (1 << 31))) != 0:
return false;
case $c >= 0x04000000:
$v .= chr(0x80 | ($c & 0x3F));

View File

@ -164,7 +164,7 @@ class X509
*
* @var array
*/
private $CAs;
private $CAs = [];
/**
* The currently loaded certificate
@ -315,6 +315,10 @@ class X509
'id-at-uniqueIdentifier' => '2.5.4.45',
'id-at-role' => '2.5.4.72',
'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',
//'pkcs-9' => '1.2.840.113549.1.9',
@ -1038,7 +1042,8 @@ class X509
if ($names = $this->getExtension('id-ce-subjectAltName')) {
foreach ($names as $name) {
foreach ($name as $key => $value) {
$value = str_replace(['.', '*'], ['\.', '[^.]*'], $value);
$value = preg_quote($value);
$value = str_replace('\*', '[^.]*', $value);
switch ($key) {
case 'dNSName':
/* From RFC2818 "HTTP over TLS":
@ -1538,6 +1543,20 @@ class X509
private function translateDNProp($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 'countryname':
case 'c':
@ -2030,9 +2049,6 @@ class X509
if (!is_array($this->currentCert) || !isset($this->currentCert['tbsCertificate'])) {
return false;
}
if (empty($this->CAs)) {
return $chain;
}
while (true) {
$currentCert = $chain[count($chain) - 1];
for ($i = 0; $i < count($this->CAs); $i++) {

View File

@ -100,10 +100,6 @@ class BigInteger implements \JsonSerializable
/** @var class-string<Engine> $fqmain */
self::$mainEngine = $fqmain;
if (!in_array('Default', $modexps)) {
$modexps[] = 'DefaultEngine';
}
$found = false;
foreach ($modexps as $modexp) {
try {
@ -140,18 +136,23 @@ class BigInteger implements \JsonSerializable
{
if (!isset(self::$mainEngine)) {
$engines = [
['GMP'],
['GMP', ['DefaultEngine']],
['PHP64', ['OpenSSL']],
['BCMath', ['OpenSSL']],
['PHP32', ['OpenSSL']]
['PHP32', ['OpenSSL']],
['PHP64', ['DefaultEngine']],
['PHP32', ['DefaultEngine']]
];
foreach ($engines as $engine) {
try {
self::setEngine($engine[0], isset($engine[1]) ? $engine[1] : []);
break;
self::setEngine($engine[0], $engine[1]);
return;
} 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');
}
}

View File

@ -619,7 +619,7 @@ abstract class Engine implements \JsonSerializable
*/
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));
}
if ($this->compare($n) > 0) {
list(, $temp) = $this->divide($n);
return $temp->powModInner($e, $n);
}
return $this->powModInner($e, $n);
}
@ -781,6 +786,11 @@ abstract class Engine implements \JsonSerializable
$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);
return static::randomRangePrimeInner($x, $min, $max);
@ -985,6 +995,15 @@ abstract class Engine implements \JsonSerializable
*/
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) {
$t = $this->setupIsPrime();
}

View File

@ -1326,4 +1326,32 @@ abstract class PHP extends Engine
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;
}
}

View File

@ -80,10 +80,10 @@ class PHP32 extends PHP
}
$step = count($vals) & 3;
if ($step) {
$digit = floor($digit / pow(2, 2 * $step));
$digit = (int) floor($digit / pow(2, 2 * $step));
}
if ($step != 3) {
$digit &= static::MAX_DIGIT;
$digit = (int) fmod($digit, static::BASE_FULL);
$i++;
}
$vals[] = $digit;
@ -102,7 +102,7 @@ class PHP32 extends PHP
*/
public static function isValidEngine()
{
return PHP_INT_SIZE >= 4;
return PHP_INT_SIZE >= 4 && !self::testJITOnWindows();
}
/**

View File

@ -103,7 +103,7 @@ class PHP64 extends PHP
*/
public static function isValidEngine()
{
return PHP_INT_SIZE >= 8;
return PHP_INT_SIZE >= 8 && !self::testJITOnWindows();
}
/**

View File

@ -48,6 +48,15 @@ class BinaryField extends FiniteField
public function __construct(...$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';
foreach ($indices as $index) {
$val[$index] = '1';

View File

@ -263,7 +263,7 @@ class Integer extends Base
$r = $this->value->powMod($temp, static::$modulo[$this->instanceID]);
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)) {
break;
}
@ -312,8 +312,11 @@ class Integer extends Base
*/
public function toBytes()
{
$length = static::$modulo[$this->instanceID]->getLengthInBytes();
return str_pad($this->value->toBytes(), $length, "\0", STR_PAD_LEFT);
if (isset(static::$modulo[$this->instanceID])) {
$length = static::$modulo[$this->instanceID]->getLengthInBytes();
return str_pad($this->value->toBytes(), $length, "\0", STR_PAD_LEFT);
}
return $this->value->toBytes();
}
/**

View File

@ -93,7 +93,7 @@ class SFTP extends SSH2
* @var array
* @access private
*/
private $packet_types = [];
private static $packet_types = [];
/**
* Status Codes
@ -102,19 +102,19 @@ class SFTP extends SSH2
* @var array
* @access private
*/
private $status_codes = [];
private static $status_codes = [];
/** @var array<int, string> */
private $attributes;
private static $attributes;
/** @var array<int, string> */
private $open_flags;
private static $open_flags;
/** @var array<int, string> */
private $open_flags5;
private static $open_flags5;
/** @var array<int, string> */
private $file_types;
private static $file_types;
/**
* The Request ID
@ -350,7 +350,9 @@ class SFTP extends SSH2
*
* 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 $timeout
*/
@ -360,154 +362,156 @@ class SFTP extends SSH2
$this->max_sftp_packet = 1 << 15;
$this->packet_types = [
1 => 'NET_SFTP_INIT',
2 => 'NET_SFTP_VERSION',
3 => 'NET_SFTP_OPEN',
4 => 'NET_SFTP_CLOSE',
5 => 'NET_SFTP_READ',
6 => 'NET_SFTP_WRITE',
7 => 'NET_SFTP_LSTAT',
9 => 'NET_SFTP_SETSTAT',
10 => 'NET_SFTP_FSETSTAT',
11 => 'NET_SFTP_OPENDIR',
12 => 'NET_SFTP_READDIR',
13 => 'NET_SFTP_REMOVE',
14 => 'NET_SFTP_MKDIR',
15 => 'NET_SFTP_RMDIR',
16 => 'NET_SFTP_REALPATH',
17 => 'NET_SFTP_STAT',
18 => 'NET_SFTP_RENAME',
19 => 'NET_SFTP_READLINK',
20 => 'NET_SFTP_SYMLINK',
21 => 'NET_SFTP_LINK',
if (empty(self::$packet_types)) {
self::$packet_types = [
1 => 'NET_SFTP_INIT',
2 => 'NET_SFTP_VERSION',
3 => 'NET_SFTP_OPEN',
4 => 'NET_SFTP_CLOSE',
5 => 'NET_SFTP_READ',
6 => 'NET_SFTP_WRITE',
7 => 'NET_SFTP_LSTAT',
9 => 'NET_SFTP_SETSTAT',
10 => 'NET_SFTP_FSETSTAT',
11 => 'NET_SFTP_OPENDIR',
12 => 'NET_SFTP_READDIR',
13 => 'NET_SFTP_REMOVE',
14 => 'NET_SFTP_MKDIR',
15 => 'NET_SFTP_RMDIR',
16 => 'NET_SFTP_REALPATH',
17 => 'NET_SFTP_STAT',
18 => 'NET_SFTP_RENAME',
19 => 'NET_SFTP_READLINK',
20 => 'NET_SFTP_SYMLINK',
21 => 'NET_SFTP_LINK',
101 => 'NET_SFTP_STATUS',
102 => 'NET_SFTP_HANDLE',
103 => 'NET_SFTP_DATA',
104 => 'NET_SFTP_NAME',
105 => 'NET_SFTP_ATTRS',
101 => 'NET_SFTP_STATUS',
102 => 'NET_SFTP_HANDLE',
103 => 'NET_SFTP_DATA',
104 => 'NET_SFTP_NAME',
105 => 'NET_SFTP_ATTRS',
200 => 'NET_SFTP_EXTENDED'
];
$this->status_codes = [
0 => 'NET_SFTP_STATUS_OK',
1 => 'NET_SFTP_STATUS_EOF',
2 => 'NET_SFTP_STATUS_NO_SUCH_FILE',
3 => 'NET_SFTP_STATUS_PERMISSION_DENIED',
4 => 'NET_SFTP_STATUS_FAILURE',
5 => 'NET_SFTP_STATUS_BAD_MESSAGE',
6 => 'NET_SFTP_STATUS_NO_CONNECTION',
7 => 'NET_SFTP_STATUS_CONNECTION_LOST',
8 => 'NET_SFTP_STATUS_OP_UNSUPPORTED',
9 => 'NET_SFTP_STATUS_INVALID_HANDLE',
10 => 'NET_SFTP_STATUS_NO_SUCH_PATH',
11 => 'NET_SFTP_STATUS_FILE_ALREADY_EXISTS',
12 => 'NET_SFTP_STATUS_WRITE_PROTECT',
13 => 'NET_SFTP_STATUS_NO_MEDIA',
14 => 'NET_SFTP_STATUS_NO_SPACE_ON_FILESYSTEM',
15 => 'NET_SFTP_STATUS_QUOTA_EXCEEDED',
16 => 'NET_SFTP_STATUS_UNKNOWN_PRINCIPAL',
17 => 'NET_SFTP_STATUS_LOCK_CONFLICT',
18 => 'NET_SFTP_STATUS_DIR_NOT_EMPTY',
19 => 'NET_SFTP_STATUS_NOT_A_DIRECTORY',
20 => 'NET_SFTP_STATUS_INVALID_FILENAME',
21 => 'NET_SFTP_STATUS_LINK_LOOP',
22 => 'NET_SFTP_STATUS_CANNOT_DELETE',
23 => 'NET_SFTP_STATUS_INVALID_PARAMETER',
24 => 'NET_SFTP_STATUS_FILE_IS_A_DIRECTORY',
25 => 'NET_SFTP_STATUS_BYTE_RANGE_LOCK_CONFLICT',
26 => 'NET_SFTP_STATUS_BYTE_RANGE_LOCK_REFUSED',
27 => 'NET_SFTP_STATUS_DELETE_PENDING',
28 => 'NET_SFTP_STATUS_FILE_CORRUPT',
29 => 'NET_SFTP_STATUS_OWNER_INVALID',
30 => 'NET_SFTP_STATUS_GROUP_INVALID',
31 => 'NET_SFTP_STATUS_NO_MATCHING_BYTE_RANGE_LOCK'
];
// 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
$this->attributes = [
0x00000001 => 'NET_SFTP_ATTR_SIZE',
0x00000002 => 'NET_SFTP_ATTR_UIDGID', // defined in SFTPv3, removed in SFTPv4+
0x00000080 => 'NET_SFTP_ATTR_OWNERGROUP', // defined in SFTPv4+
0x00000004 => 'NET_SFTP_ATTR_PERMISSIONS',
0x00000008 => 'NET_SFTP_ATTR_ACCESSTIME',
0x00000010 => 'NET_SFTP_ATTR_CREATETIME', // SFTPv4+
0x00000020 => 'NET_SFTP_ATTR_MODIFYTIME',
0x00000040 => 'NET_SFTP_ATTR_ACL',
0x00000100 => 'NET_SFTP_ATTR_SUBSECOND_TIMES',
0x00000200 => 'NET_SFTP_ATTR_BITS', // SFTPv5+
0x00000400 => 'NET_SFTP_ATTR_ALLOCATION_SIZE', // SFTPv6+
0x00000800 => 'NET_SFTP_ATTR_TEXT_HINT',
0x00001000 => 'NET_SFTP_ATTR_MIME_TYPE',
0x00002000 => 'NET_SFTP_ATTR_LINK_COUNT',
0x00004000 => 'NET_SFTP_ATTR_UNTRANSLATED_NAME',
0x00008000 => 'NET_SFTP_ATTR_CTIME',
// 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
// 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.
(PHP_INT_SIZE == 4 ? -1 : 0xFFFFFFFF) => 'NET_SFTP_ATTR_EXTENDED'
];
// 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 array for that $this->open5_flags and similarly alter the constant names.
$this->open_flags = [
0x00000001 => 'NET_SFTP_OPEN_READ',
0x00000002 => 'NET_SFTP_OPEN_WRITE',
0x00000004 => 'NET_SFTP_OPEN_APPEND',
0x00000008 => 'NET_SFTP_OPEN_CREATE',
0x00000010 => 'NET_SFTP_OPEN_TRUNCATE',
0x00000020 => 'NET_SFTP_OPEN_EXCL',
0x00000040 => 'NET_SFTP_OPEN_TEXT' // defined in SFTPv4
];
// SFTPv5+ changed the flags up:
// https://datatracker.ietf.org/doc/html/draft-ietf-secsh-filexfer-13#section-8.1.1.3
$this->open_flags5 = [
// when SSH_FXF_ACCESS_DISPOSITION is a 3 bit field that controls how the file is opened
0x00000000 => 'NET_SFTP_OPEN_CREATE_NEW',
0x00000001 => 'NET_SFTP_OPEN_CREATE_TRUNCATE',
0x00000002 => 'NET_SFTP_OPEN_OPEN_EXISTING',
0x00000003 => 'NET_SFTP_OPEN_OPEN_OR_CREATE',
0x00000004 => 'NET_SFTP_OPEN_TRUNCATE_EXISTING',
// the rest of the flags are not supported
0x00000008 => 'NET_SFTP_OPEN_APPEND_DATA', // "the offset field of SS_FXP_WRITE requests is ignored"
0x00000010 => 'NET_SFTP_OPEN_APPEND_DATA_ATOMIC',
0x00000020 => 'NET_SFTP_OPEN_TEXT_MODE',
0x00000040 => 'NET_SFTP_OPEN_BLOCK_READ',
0x00000080 => 'NET_SFTP_OPEN_BLOCK_WRITE',
0x00000100 => 'NET_SFTP_OPEN_BLOCK_DELETE',
0x00000200 => 'NET_SFTP_OPEN_BLOCK_ADVISORY',
0x00000400 => 'NET_SFTP_OPEN_NOFOLLOW',
0x00000800 => 'NET_SFTP_OPEN_DELETE_ON_CLOSE',
0x00001000 => 'NET_SFTP_OPEN_ACCESS_AUDIT_ALARM_INFO',
0x00002000 => 'NET_SFTP_OPEN_ACCESS_BACKUP',
0x00004000 => 'NET_SFTP_OPEN_BACKUP_STREAM',
0x00008000 => 'NET_SFTP_OPEN_OVERRIDE_OWNER',
];
// http://tools.ietf.org/html/draft-ietf-secsh-filexfer-04#section-5.2
// see \phpseclib3\Net\SFTP::_parseLongname() for an explanation
$this->file_types = [
1 => 'NET_SFTP_TYPE_REGULAR',
2 => 'NET_SFTP_TYPE_DIRECTORY',
3 => 'NET_SFTP_TYPE_SYMLINK',
4 => 'NET_SFTP_TYPE_SPECIAL',
5 => 'NET_SFTP_TYPE_UNKNOWN',
// the following types were first defined for use in SFTPv5+
// http://tools.ietf.org/html/draft-ietf-secsh-filexfer-05#section-5.2
6 => 'NET_SFTP_TYPE_SOCKET',
7 => 'NET_SFTP_TYPE_CHAR_DEVICE',
8 => 'NET_SFTP_TYPE_BLOCK_DEVICE',
9 => 'NET_SFTP_TYPE_FIFO'
];
$this->define_array(
$this->packet_types,
$this->status_codes,
$this->attributes,
$this->open_flags,
$this->open_flags5,
$this->file_types
);
200 => 'NET_SFTP_EXTENDED'
];
self::$status_codes = [
0 => 'NET_SFTP_STATUS_OK',
1 => 'NET_SFTP_STATUS_EOF',
2 => 'NET_SFTP_STATUS_NO_SUCH_FILE',
3 => 'NET_SFTP_STATUS_PERMISSION_DENIED',
4 => 'NET_SFTP_STATUS_FAILURE',
5 => 'NET_SFTP_STATUS_BAD_MESSAGE',
6 => 'NET_SFTP_STATUS_NO_CONNECTION',
7 => 'NET_SFTP_STATUS_CONNECTION_LOST',
8 => 'NET_SFTP_STATUS_OP_UNSUPPORTED',
9 => 'NET_SFTP_STATUS_INVALID_HANDLE',
10 => 'NET_SFTP_STATUS_NO_SUCH_PATH',
11 => 'NET_SFTP_STATUS_FILE_ALREADY_EXISTS',
12 => 'NET_SFTP_STATUS_WRITE_PROTECT',
13 => 'NET_SFTP_STATUS_NO_MEDIA',
14 => 'NET_SFTP_STATUS_NO_SPACE_ON_FILESYSTEM',
15 => 'NET_SFTP_STATUS_QUOTA_EXCEEDED',
16 => 'NET_SFTP_STATUS_UNKNOWN_PRINCIPAL',
17 => 'NET_SFTP_STATUS_LOCK_CONFLICT',
18 => 'NET_SFTP_STATUS_DIR_NOT_EMPTY',
19 => 'NET_SFTP_STATUS_NOT_A_DIRECTORY',
20 => 'NET_SFTP_STATUS_INVALID_FILENAME',
21 => 'NET_SFTP_STATUS_LINK_LOOP',
22 => 'NET_SFTP_STATUS_CANNOT_DELETE',
23 => 'NET_SFTP_STATUS_INVALID_PARAMETER',
24 => 'NET_SFTP_STATUS_FILE_IS_A_DIRECTORY',
25 => 'NET_SFTP_STATUS_BYTE_RANGE_LOCK_CONFLICT',
26 => 'NET_SFTP_STATUS_BYTE_RANGE_LOCK_REFUSED',
27 => 'NET_SFTP_STATUS_DELETE_PENDING',
28 => 'NET_SFTP_STATUS_FILE_CORRUPT',
29 => 'NET_SFTP_STATUS_OWNER_INVALID',
30 => 'NET_SFTP_STATUS_GROUP_INVALID',
31 => 'NET_SFTP_STATUS_NO_MATCHING_BYTE_RANGE_LOCK'
];
// 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
self::$attributes = [
0x00000001 => 'NET_SFTP_ATTR_SIZE',
0x00000002 => 'NET_SFTP_ATTR_UIDGID', // defined in SFTPv3, removed in SFTPv4+
0x00000080 => 'NET_SFTP_ATTR_OWNERGROUP', // defined in SFTPv4+
0x00000004 => 'NET_SFTP_ATTR_PERMISSIONS',
0x00000008 => 'NET_SFTP_ATTR_ACCESSTIME',
0x00000010 => 'NET_SFTP_ATTR_CREATETIME', // SFTPv4+
0x00000020 => 'NET_SFTP_ATTR_MODIFYTIME',
0x00000040 => 'NET_SFTP_ATTR_ACL',
0x00000100 => 'NET_SFTP_ATTR_SUBSECOND_TIMES',
0x00000200 => 'NET_SFTP_ATTR_BITS', // SFTPv5+
0x00000400 => 'NET_SFTP_ATTR_ALLOCATION_SIZE', // SFTPv6+
0x00000800 => 'NET_SFTP_ATTR_TEXT_HINT',
0x00001000 => 'NET_SFTP_ATTR_MIME_TYPE',
0x00002000 => 'NET_SFTP_ATTR_LINK_COUNT',
0x00004000 => 'NET_SFTP_ATTR_UNTRANSLATED_NAME',
0x00008000 => 'NET_SFTP_ATTR_CTIME',
// 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
// 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.
(PHP_INT_SIZE == 4 ? (-1 << 31) : 0x80000000) => 'NET_SFTP_ATTR_EXTENDED'
];
// 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 array for that $this->open5_flags and similarly alter the constant names.
self::$open_flags = [
0x00000001 => 'NET_SFTP_OPEN_READ',
0x00000002 => 'NET_SFTP_OPEN_WRITE',
0x00000004 => 'NET_SFTP_OPEN_APPEND',
0x00000008 => 'NET_SFTP_OPEN_CREATE',
0x00000010 => 'NET_SFTP_OPEN_TRUNCATE',
0x00000020 => 'NET_SFTP_OPEN_EXCL',
0x00000040 => 'NET_SFTP_OPEN_TEXT' // defined in SFTPv4
];
// SFTPv5+ changed the flags up:
// https://datatracker.ietf.org/doc/html/draft-ietf-secsh-filexfer-13#section-8.1.1.3
self::$open_flags5 = [
// when SSH_FXF_ACCESS_DISPOSITION is a 3 bit field that controls how the file is opened
0x00000000 => 'NET_SFTP_OPEN_CREATE_NEW',
0x00000001 => 'NET_SFTP_OPEN_CREATE_TRUNCATE',
0x00000002 => 'NET_SFTP_OPEN_OPEN_EXISTING',
0x00000003 => 'NET_SFTP_OPEN_OPEN_OR_CREATE',
0x00000004 => 'NET_SFTP_OPEN_TRUNCATE_EXISTING',
// the rest of the flags are not supported
0x00000008 => 'NET_SFTP_OPEN_APPEND_DATA', // "the offset field of SS_FXP_WRITE requests is ignored"
0x00000010 => 'NET_SFTP_OPEN_APPEND_DATA_ATOMIC',
0x00000020 => 'NET_SFTP_OPEN_TEXT_MODE',
0x00000040 => 'NET_SFTP_OPEN_BLOCK_READ',
0x00000080 => 'NET_SFTP_OPEN_BLOCK_WRITE',
0x00000100 => 'NET_SFTP_OPEN_BLOCK_DELETE',
0x00000200 => 'NET_SFTP_OPEN_BLOCK_ADVISORY',
0x00000400 => 'NET_SFTP_OPEN_NOFOLLOW',
0x00000800 => 'NET_SFTP_OPEN_DELETE_ON_CLOSE',
0x00001000 => 'NET_SFTP_OPEN_ACCESS_AUDIT_ALARM_INFO',
0x00002000 => 'NET_SFTP_OPEN_ACCESS_BACKUP',
0x00004000 => 'NET_SFTP_OPEN_BACKUP_STREAM',
0x00008000 => 'NET_SFTP_OPEN_OVERRIDE_OWNER',
];
// http://tools.ietf.org/html/draft-ietf-secsh-filexfer-04#section-5.2
// see \phpseclib3\Net\SFTP::_parseLongname() for an explanation
self::$file_types = [
1 => 'NET_SFTP_TYPE_REGULAR',
2 => 'NET_SFTP_TYPE_DIRECTORY',
3 => 'NET_SFTP_TYPE_SYMLINK',
4 => 'NET_SFTP_TYPE_SPECIAL',
5 => 'NET_SFTP_TYPE_UNKNOWN',
// the following types were first defined for use in SFTPv5+
// http://tools.ietf.org/html/draft-ietf-secsh-filexfer-05#section-5.2
6 => 'NET_SFTP_TYPE_SOCKET',
7 => 'NET_SFTP_TYPE_CHAR_DEVICE',
8 => 'NET_SFTP_TYPE_BLOCK_DEVICE',
9 => 'NET_SFTP_TYPE_FIFO'
];
self::define_array(
self::$packet_types,
self::$status_codes,
self::$attributes,
self::$open_flags,
self::$open_flags5,
self::$file_types
);
}
if (!defined('NET_SFTP_QUEUE_SIZE')) {
define('NET_SFTP_QUEUE_SIZE', 32);
@ -543,22 +547,7 @@ class SFTP extends SSH2
*/
private function partial_init_sftp_connection()
{
$this->window_size_server_to_client[self::CHANNEL] = $this->window_size;
$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);
$response = $this->open_channel(self::CHANNEL, true);
if ($response === true && $this->isTimeout()) {
return false;
}
@ -815,7 +804,7 @@ class SFTP extends SSH2
list($status) = Strings::unpackSSH2('N', $response);
}
$error = $this->status_codes[$status];
$error = self::$status_codes[$status];
if ($this->version > 2) {
list($message) = Strings::unpackSSH2('s', $response);
@ -2138,10 +2127,10 @@ class SFTP extends SSH2
if ($start >= 0) {
$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
$size = $this->stat($remote_file)['size'];
$offset = $size !== false ? $size : 0;
$stat = $this->stat($remote_file);
$offset = $stat !== false && $stat['size'] ? $stat['size'] : 0;
} else {
$offset = 0;
if ($this->version >= 5) {
@ -2210,6 +2199,9 @@ class SFTP extends SSH2
if ($local_start >= 0) {
fseek($fp, $local_start);
$size -= $local_start;
} elseif ($mode & self::RESUME) {
fseek($fp, $offset);
$size -= $offset;
}
} elseif ($dataCallback) {
$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) {
fclose($fp);
@ -2840,15 +2824,37 @@ class SFTP extends SSH2
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
*
* @param string $path
* @param bool $recursive
* @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);
}
foreach ($this->attributes as $key => $value) {
foreach (self::$attributes as $key => $value) {
switch ($flags & $key) {
case NET_SFTP_ATTR_UIDGID:
if ($this->version > 3) {
@ -3272,7 +3278,7 @@ class SFTP extends SSH2
$stop = microtime(true);
if (defined('NET_SFTP_LOGGING')) {
$packet_type = '-> ' . $this->packet_types[$type] .
$packet_type = '-> ' . self::$packet_types[$type] .
' (' . round($stop - $start, 4) . 's)';
$this->append_log($packet_type, $data);
}
@ -3289,6 +3295,7 @@ class SFTP extends SSH2
$this->use_request_id = false;
$this->pwd = false;
$this->requestBuffer = [];
$this->partial_init = false;
}
/**
@ -3376,7 +3383,7 @@ class SFTP extends SSH2
$packet = Strings::shift($this->packet_buffer, $length);
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)';
$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')
*
* @return array|string
* @return array|string|false
*/
public function getSFTPLog()
{
@ -3439,7 +3446,7 @@ class SFTP extends SSH2
}
/**
* Returns all errors
* Returns all errors on the SFTP layer
*
* @return array
*/
@ -3449,7 +3456,7 @@ class SFTP extends SSH2
}
/**
* Returns the last error
* Returns the last error on the SFTP layer
*
* @return string
*/

File diff suppressed because it is too large Load Diff