updated composer dependencies

This commit is contained in:
Andreas Gohr 2018-04-13 08:37:14 +02:00
parent b2c9cd19ff
commit 43d3f077ff
39 changed files with 900 additions and 2308 deletions

42
composer.lock generated
View File

@ -189,16 +189,16 @@
},
{
"name": "paragonie/random_compat",
"version": "v2.0.10",
"version": "v2.0.12",
"source": {
"type": "git",
"url": "https://github.com/paragonie/random_compat.git",
"reference": "634bae8e911eefa89c1abfbf1b66da679ac8f54d"
"reference": "258c89a6b97de7dfaf5b8c7607d0478e236b04fb"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/paragonie/random_compat/zipball/634bae8e911eefa89c1abfbf1b66da679ac8f54d",
"reference": "634bae8e911eefa89c1abfbf1b66da679ac8f54d",
"url": "https://api.github.com/repos/paragonie/random_compat/zipball/258c89a6b97de7dfaf5b8c7607d0478e236b04fb",
"reference": "258c89a6b97de7dfaf5b8c7607d0478e236b04fb",
"shasum": ""
},
"require": {
@ -233,20 +233,20 @@
"pseudorandom",
"random"
],
"time": "2017-03-13T16:27:32+00:00"
"time": "2018-04-04T21:24:14+00:00"
},
{
"name": "phpseclib/phpseclib",
"version": "2.0.6",
"version": "2.0.10",
"source": {
"type": "git",
"url": "https://github.com/phpseclib/phpseclib.git",
"reference": "34a7699e6f31b1ef4035ee36444407cecf9f56aa"
"reference": "d305b780829ea4252ed9400b3f5937c2c99b51d4"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/34a7699e6f31b1ef4035ee36444407cecf9f56aa",
"reference": "34a7699e6f31b1ef4035ee36444407cecf9f56aa",
"url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/d305b780829ea4252ed9400b3f5937c2c99b51d4",
"reference": "d305b780829ea4252ed9400b3f5937c2c99b51d4",
"shasum": ""
},
"require": {
@ -254,7 +254,7 @@
},
"require-dev": {
"phing/phing": "~2.7",
"phpunit/phpunit": "~4.0",
"phpunit/phpunit": "^4.8.35|^5.7|^6.0",
"sami/sami": "~2.0",
"squizlabs/php_codesniffer": "~2.0"
},
@ -325,20 +325,20 @@
"x.509",
"x509"
],
"time": "2017-06-05T06:31:10+00:00"
"time": "2018-02-19T04:29:13+00:00"
},
{
"name": "simplepie/simplepie",
"version": "1.5",
"version": "1.5.1",
"source": {
"type": "git",
"url": "https://github.com/simplepie/simplepie.git",
"reference": "5de5551953f95feef12cf355a7a26a70f94aa3ab"
"reference": "db9fff27b6d49eed3d4047cd3211ec8dba2f5d6e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/simplepie/simplepie/zipball/5de5551953f95feef12cf355a7a26a70f94aa3ab",
"reference": "5de5551953f95feef12cf355a7a26a70f94aa3ab",
"url": "https://api.github.com/repos/simplepie/simplepie/zipball/db9fff27b6d49eed3d4047cd3211ec8dba2f5d6e",
"reference": "db9fff27b6d49eed3d4047cd3211ec8dba2f5d6e",
"shasum": ""
},
"require": {
@ -385,7 +385,7 @@
"feeds",
"rss"
],
"time": "2017-04-17T07:29:31+00:00"
"time": "2017-11-12T02:03:34+00:00"
},
{
"name": "splitbrain/php-archive",
@ -440,16 +440,16 @@
},
{
"name": "splitbrain/php-cli",
"version": "1.1.1",
"version": "1.1.2",
"source": {
"type": "git",
"url": "https://github.com/splitbrain/php-cli.git",
"reference": "4795af10ff1c3b1ac614ef380d7d810af495e6f1"
"reference": "1d6f0bf9eccbfd79d1f4d185ef27573601185c23"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/splitbrain/php-cli/zipball/4795af10ff1c3b1ac614ef380d7d810af495e6f1",
"reference": "4795af10ff1c3b1ac614ef380d7d810af495e6f1",
"url": "https://api.github.com/repos/splitbrain/php-cli/zipball/1d6f0bf9eccbfd79d1f4d185ef27573601185c23",
"reference": "1d6f0bf9eccbfd79d1f4d185ef27573601185c23",
"shasum": ""
},
"require": {
@ -487,7 +487,7 @@
"optparse",
"terminal"
],
"time": "2017-10-27T16:18:07+00:00"
"time": "2018-02-02T08:46:12+00:00"
}
],
"packages-dev": [],

View File

@ -6,6 +6,6 @@ $vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);
return array(
'5255c38a0faeba867671b61dfda6d864' => $vendorDir . '/paragonie/random_compat/lib/random.php',
'decc78cc4436b1292c6c0d151b19445c' => $vendorDir . '/phpseclib/phpseclib/phpseclib/bootstrap.php',
'5255c38a0faeba867671b61dfda6d864' => $vendorDir . '/paragonie/random_compat/lib/random.php',
);

View File

@ -7,8 +7,8 @@ namespace Composer\Autoload;
class ComposerStaticInita19a915ee98347a0c787119619d2ff9b
{
public static $files = array (
'5255c38a0faeba867671b61dfda6d864' => __DIR__ . '/..' . '/paragonie/random_compat/lib/random.php',
'decc78cc4436b1292c6c0d151b19445c' => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib/bootstrap.php',
'5255c38a0faeba867671b61dfda6d864' => __DIR__ . '/..' . '/paragonie/random_compat/lib/random.php',
);
public static $prefixLengthsPsr4 = array (

View File

@ -1,54 +1,4 @@
[
{
"name": "paragonie/random_compat",
"version": "v2.0.10",
"version_normalized": "2.0.10.0",
"source": {
"type": "git",
"url": "https://github.com/paragonie/random_compat.git",
"reference": "634bae8e911eefa89c1abfbf1b66da679ac8f54d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/paragonie/random_compat/zipball/634bae8e911eefa89c1abfbf1b66da679ac8f54d",
"reference": "634bae8e911eefa89c1abfbf1b66da679ac8f54d",
"shasum": ""
},
"require": {
"php": ">=5.2.0"
},
"require-dev": {
"phpunit/phpunit": "4.*|5.*"
},
"suggest": {
"ext-libsodium": "Provides a modern crypto API that can be used to generate random bytes."
},
"time": "2017-03-13T16:27:32+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
"files": [
"lib/random.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Paragon Initiative Enterprises",
"email": "security@paragonie.com",
"homepage": "https://paragonie.com"
}
],
"description": "PHP 5.x polyfill for random_bytes() and random_int() from PHP 7",
"keywords": [
"csprng",
"pseudorandom",
"random"
]
},
{
"name": "geshi/geshi",
"version": "v1.0.9.0",
@ -293,17 +243,17 @@
},
{
"name": "phpseclib/phpseclib",
"version": "2.0.6",
"version_normalized": "2.0.6.0",
"version": "2.0.10",
"version_normalized": "2.0.10.0",
"source": {
"type": "git",
"url": "https://github.com/phpseclib/phpseclib.git",
"reference": "34a7699e6f31b1ef4035ee36444407cecf9f56aa"
"reference": "d305b780829ea4252ed9400b3f5937c2c99b51d4"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/34a7699e6f31b1ef4035ee36444407cecf9f56aa",
"reference": "34a7699e6f31b1ef4035ee36444407cecf9f56aa",
"url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/d305b780829ea4252ed9400b3f5937c2c99b51d4",
"reference": "d305b780829ea4252ed9400b3f5937c2c99b51d4",
"shasum": ""
},
"require": {
@ -311,7 +261,7 @@
},
"require-dev": {
"phing/phing": "~2.7",
"phpunit/phpunit": "~4.0",
"phpunit/phpunit": "^4.8.35|^5.7|^6.0",
"sami/sami": "~2.0",
"squizlabs/php_codesniffer": "~2.0"
},
@ -321,7 +271,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": "2017-06-05T06:31:10+00:00",
"time": "2018-02-19T04:29:13+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
@ -386,18 +336,68 @@
]
},
{
"name": "simplepie/simplepie",
"version": "1.5",
"version_normalized": "1.5.0.0",
"name": "paragonie/random_compat",
"version": "v2.0.12",
"version_normalized": "2.0.12.0",
"source": {
"type": "git",
"url": "https://github.com/simplepie/simplepie.git",
"reference": "5de5551953f95feef12cf355a7a26a70f94aa3ab"
"url": "https://github.com/paragonie/random_compat.git",
"reference": "258c89a6b97de7dfaf5b8c7607d0478e236b04fb"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/simplepie/simplepie/zipball/5de5551953f95feef12cf355a7a26a70f94aa3ab",
"reference": "5de5551953f95feef12cf355a7a26a70f94aa3ab",
"url": "https://api.github.com/repos/paragonie/random_compat/zipball/258c89a6b97de7dfaf5b8c7607d0478e236b04fb",
"reference": "258c89a6b97de7dfaf5b8c7607d0478e236b04fb",
"shasum": ""
},
"require": {
"php": ">=5.2.0"
},
"require-dev": {
"phpunit/phpunit": "4.*|5.*"
},
"suggest": {
"ext-libsodium": "Provides a modern crypto API that can be used to generate random bytes."
},
"time": "2018-04-04T21:24:14+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
"files": [
"lib/random.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Paragon Initiative Enterprises",
"email": "security@paragonie.com",
"homepage": "https://paragonie.com"
}
],
"description": "PHP 5.x polyfill for random_bytes() and random_int() from PHP 7",
"keywords": [
"csprng",
"pseudorandom",
"random"
]
},
{
"name": "simplepie/simplepie",
"version": "1.5.1",
"version_normalized": "1.5.1.0",
"source": {
"type": "git",
"url": "https://github.com/simplepie/simplepie.git",
"reference": "db9fff27b6d49eed3d4047cd3211ec8dba2f5d6e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/simplepie/simplepie/zipball/db9fff27b6d49eed3d4047cd3211ec8dba2f5d6e",
"reference": "db9fff27b6d49eed3d4047cd3211ec8dba2f5d6e",
"shasum": ""
},
"require": {
@ -409,7 +409,7 @@
"suggest": {
"mf2/mf2": "Microformat module that allows for parsing HTML for microformats"
},
"time": "2017-04-17T07:29:31+00:00",
"time": "2017-11-12T02:03:34+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
@ -449,17 +449,17 @@
},
{
"name": "splitbrain/php-cli",
"version": "1.1.1",
"version_normalized": "1.1.1.0",
"version": "1.1.2",
"version_normalized": "1.1.2.0",
"source": {
"type": "git",
"url": "https://github.com/splitbrain/php-cli.git",
"reference": "4795af10ff1c3b1ac614ef380d7d810af495e6f1"
"reference": "1d6f0bf9eccbfd79d1f4d185ef27573601185c23"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/splitbrain/php-cli/zipball/4795af10ff1c3b1ac614ef380d7d810af495e6f1",
"reference": "4795af10ff1c3b1ac614ef380d7d810af495e6f1",
"url": "https://api.github.com/repos/splitbrain/php-cli/zipball/1d6f0bf9eccbfd79d1f4d185ef27573601185c23",
"reference": "1d6f0bf9eccbfd79d1f4d185ef27573601185c23",
"shasum": ""
},
"require": {
@ -471,7 +471,7 @@
"suggest": {
"psr/log": "Allows you to make the CLI available as PSR-3 logger"
},
"time": "2017-10-27T16:18:07+00:00",
"time": "2018-02-02T08:46:12+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {

View File

@ -38,9 +38,10 @@ if (!is_callable('RandomCompat_intval')) {
* through.
*
* @param int|float $number The number we want to convert to an int
* @param boolean $fail_open Set to true to not throw an exception
* @param bool $fail_open Set to true to not throw an exception
*
* @return float|int
* @psalm-suppress InvalidReturnType
*
* @throws TypeError
*/

View File

@ -203,8 +203,9 @@ if (!is_callable('random_bytes')) {
* and hope the developer won't let it fail silently.
*
* @param mixed $length
* @return void
* @psalm-suppress MissingReturnType
* @throws Exception
* @return string
*/
function random_bytes($length)
{
@ -212,6 +213,7 @@ if (!is_callable('random_bytes')) {
throw new Exception(
'There is no suitable CSPRNG installed on your system'
);
return '';
}
}
}

View File

@ -70,10 +70,10 @@ if (!is_callable('random_bytes')) {
$n = ($bytes - $i) > 1073741824
? 1073741824
: $bytes - $i;
$buf .= Sodium::randombytes_buf($n);
$buf .= Sodium::randombytes_buf((int) $n);
}
} else {
$buf .= Sodium::randombytes_buf($bytes);
$buf .= Sodium::randombytes_buf((int) $bytes);
}
if (is_string($buf)) {

View File

@ -78,7 +78,7 @@ if (!is_callable('random_int')) {
}
if ($max === $min) {
return $min;
return (int) $min;
}
/**
@ -185,6 +185,6 @@ if (!is_callable('random_int')) {
*/
} while (!is_int($val) || $val > $max || $val < $min);
return (int)$val;
return (int) $val;
}
}

View File

@ -8,6 +8,9 @@
<directory name="lib" />
</projectFiles>
<issueHandlers>
<RedundantConditionGivenDocblockType errorLevel="info" />
<UnresolvableInclude errorLevel="info" />
<DuplicateClass errorLevel="info" />
<InvalidOperand errorLevel="info" />
<UndefinedConstant errorLevel="info" />
<MissingReturnType errorLevel="info" />

View File

@ -36,7 +36,7 @@ AES, Blowfish, Twofish, SSH-1, SSH-2, SFTP, and X.509
* 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.7 as ZIP](http://sourceforge.net/projects/phpseclib/files/phpseclib1.0.7.zip/download)
* [Download 1.0.10 as ZIP](http://sourceforge.net/projects/phpseclib/files/phpseclib1.0.10.zip/download)
## Support

View File

@ -55,7 +55,7 @@
},
"require-dev": {
"phing/phing": "~2.7",
"phpunit/phpunit": "~4.0",
"phpunit/phpunit": "^4.8.35|^5.7|^6.0",
"sami/sami": "~2.0",
"squizlabs/php_codesniffer": "~2.0"
},

File diff suppressed because it is too large Load Diff

View File

@ -492,8 +492,8 @@ abstract class Base
$this->_setEngine();
// Determining whether inline crypting can be used by the cipher
if ($this->use_inline_crypt !== false && function_exists('create_function')) {
$this->use_inline_crypt = true;
if ($this->use_inline_crypt !== false) {
$this->use_inline_crypt = version_compare(PHP_VERSION, '5.3.0') >= 0 || function_exists('create_function');
}
}
@ -2492,6 +2492,11 @@ abstract class Base
}
// Create the $inline function and return its name as string. Ready to run!
if (version_compare(PHP_VERSION, '5.3.0') >= 0) {
eval('$func = function ($_action, &$self, $_text) { ' . $init_crypt . 'if ($_action == "encrypt") { ' . $encrypt . ' } else { ' . $decrypt . ' } };');
return $func;
}
return create_function('$_action, &$self, $_text', $init_crypt . 'if ($_action == "encrypt") { ' . $encrypt . ' } else { ' . $decrypt . ' }');
}
@ -2550,4 +2555,44 @@ abstract class Base
return $result . pack('H*', sha1($hash));
}
}
/**
* Convert float to int
*
* On ARM CPUs converting floats to ints doesn't always work
*
* @access private
* @param string $x
* @return int
*/
function safe_intval($x)
{
switch (true) {
case is_int($x):
// PHP 5.3, per http://php.net/releases/5_3_0.php, introduced "more consistent float rounding"
case (php_uname('m') & "\xDF\xDF\xDF") != 'ARM':
return $x;
}
return (fmod($x, 0x80000000) & 0x7FFFFFFF) |
((fmod(floor($x / 0x80000000), 2) & 1) << 31);
}
/**
* eval()'able string for in-line float to int
*
* @access private
* @return string
*/
function safe_intval_inline()
{
switch (true) {
case defined('PHP_INT_SIZE') && PHP_INT_SIZE == 8:
case (php_uname('m') & "\xDF\xDF\xDF") != 'ARM':
return '%s';
break;
default:
$safeint = '(is_int($temp = %s) ? $temp : (fmod($temp, 0x80000000) & 0x7FFFFFFF) | ';
return $safeint . '((fmod(floor($temp / 0x80000000), 2) & 1) << 31))';
}
}
}

View File

@ -294,7 +294,7 @@ class Blowfish extends Base
function setKeyLength($length)
{
if ($length < 32) {
$this->key_length = 7;
$this->key_length = 4;
} elseif ($length > 448) {
$this->key_length = 56;
} else {
@ -408,16 +408,14 @@ class Blowfish extends Base
for ($i = 0; $i < 16; $i+= 2) {
$l^= $p[$i];
$r^= ($sb_0[$l >> 24 & 0xff] +
$sb_1[$l >> 16 & 0xff] ^
$r^= $this->safe_intval(($this->safe_intval($sb_0[$l >> 24 & 0xff] + $sb_1[$l >> 16 & 0xff]) ^
$sb_2[$l >> 8 & 0xff]) +
$sb_3[$l & 0xff];
$sb_3[$l & 0xff]);
$r^= $p[$i + 1];
$l^= ($sb_0[$r >> 24 & 0xff] +
$sb_1[$r >> 16 & 0xff] ^
$l^= $this->safe_intval(($this->safe_intval($sb_0[$r >> 24 & 0xff] + $sb_1[$r >> 16 & 0xff]) ^
$sb_2[$r >> 8 & 0xff]) +
$sb_3[$r & 0xff];
$sb_3[$r & 0xff]);
}
return pack("N*", $r ^ $p[17], $l ^ $p[16]);
}
@ -443,16 +441,14 @@ class Blowfish extends Base
for ($i = 17; $i > 2; $i-= 2) {
$l^= $p[$i];
$r^= ($sb_0[$l >> 24 & 0xff] +
$sb_1[$l >> 16 & 0xff] ^
$r^= $this->safe_intval(($this->safe_intval($sb_0[$l >> 24 & 0xff] + $sb_1[$l >> 16 & 0xff]) ^
$sb_2[$l >> 8 & 0xff]) +
$sb_3[$l & 0xff];
$sb_3[$l & 0xff]);
$r^= $p[$i - 1];
$l^= ($sb_0[$r >> 24 & 0xff] +
$sb_1[$r >> 16 & 0xff] ^
$l^= $this->safe_intval(($this->safe_intval($sb_0[$r >> 24 & 0xff] + $sb_1[$r >> 16 & 0xff]) ^
$sb_2[$r >> 8 & 0xff]) +
$sb_3[$r & 0xff];
$sb_3[$r & 0xff]);
}
return pack("N*", $r ^ $p[0], $l ^ $p[1]);
}
@ -478,6 +474,8 @@ class Blowfish extends Base
$code_hash = str_pad($code_hash, 32) . $this->_hashInlineCryptFunction($this->key);
}
$safeint = $this->safe_intval_inline();
if (!isset($lambda_functions[$code_hash])) {
switch (true) {
case $gen_hi_opt_code:
@ -513,16 +511,14 @@ class Blowfish extends Base
for ($i = 0; $i < 16; $i+= 2) {
$encrypt_block.= '
$l^= ' . $p[$i] . ';
$r^= ($sb_0[$l >> 24 & 0xff] +
$sb_1[$l >> 16 & 0xff] ^
$r^= ' . sprintf($safeint, '(' . sprintf($safeint, '$sb_0[$l >> 24 & 0xff] + $sb_1[$l >> 16 & 0xff]') . ' ^
$sb_2[$l >> 8 & 0xff]) +
$sb_3[$l & 0xff];
$sb_3[$l & 0xff]') . ';
$r^= ' . $p[$i + 1] . ';
$l^= ($sb_0[$r >> 24 & 0xff] +
$sb_1[$r >> 16 & 0xff] ^
$l^= ' . sprintf($safeint, '(' . sprintf($safeint, '$sb_0[$r >> 24 & 0xff] + $sb_1[$r >> 16 & 0xff]') . ' ^
$sb_2[$r >> 8 & 0xff]) +
$sb_3[$r & 0xff];
$sb_3[$r & 0xff]') . ';
';
}
$encrypt_block.= '
@ -542,16 +538,14 @@ class Blowfish extends Base
for ($i = 17; $i > 2; $i-= 2) {
$decrypt_block.= '
$l^= ' . $p[$i] . ';
$r^= ($sb_0[$l >> 24 & 0xff] +
$sb_1[$l >> 16 & 0xff] ^
$r^= ' . sprintf($safeint, '(' . sprintf($safeint, '$sb_0[$l >> 24 & 0xff] + $sb_1[$l >> 16 & 0xff]') . ' ^
$sb_2[$l >> 8 & 0xff]) +
$sb_3[$l & 0xff];
$sb_3[$l & 0xff]') . ';
$r^= ' . $p[$i - 1] . ';
$l^= ($sb_0[$r >> 24 & 0xff] +
$sb_1[$r >> 16 & 0xff] ^
$l^= ' . sprintf($safeint, '(' . sprintf($safeint, '$sb_0[$r >> 24 & 0xff] + $sb_1[$r >> 16 & 0xff]') . ' ^
$sb_2[$r >> 8 & 0xff]) +
$sb_3[$r & 0xff];
$sb_3[$r & 0xff]') . ';
';
}

View File

@ -1357,8 +1357,8 @@ class DES extends Base
$k[self::ENCRYPT][$i] = '$ke[' . $i . ']';
$k[self::DECRYPT][$i] = '$kd[' . $i . ']';
}
$init_encrypt = '$ke = $self->keys[self::ENCRYPT];';
$init_decrypt = '$kd = $self->keys[self::DECRYPT];';
$init_encrypt = '$ke = $self->keys[$self::ENCRYPT];';
$init_decrypt = '$kd = $self->keys[$self::DECRYPT];';
break;
}

View File

@ -802,7 +802,12 @@ class Hash
$result+= $argument < 0 ? ($argument & 0x7FFFFFFF) + 0x80000000 : $argument;
}
return fmod($result, $mod);
if ((php_uname('m') & "\xDF\xDF\xDF") != 'ARM') {
return fmod($result, $mod);
}
return (fmod($result, 0x80000000) & 0x7FFFFFFF) |
((fmod(floor($result / 0x80000000), 2) & 1) << 31);
}
/**

View File

@ -296,7 +296,7 @@ class RC2 extends Base
function setKeyLength($length)
{
if ($length < 8) {
$this->default_key_length = 8;
$this->default_key_length = 1;
} elseif ($length > 1024) {
$this->default_key_length = 128;
} else {

View File

@ -107,7 +107,7 @@ class RC4 extends Base
* @var string
* @access private
*/
var $key = "\0";
var $key;
/**
* The Key Stream for decryption and encryption

View File

@ -2423,7 +2423,7 @@ class RSA
$db = $maskedDB ^ $dbMask;
$lHash2 = substr($db, 0, $this->hLen);
$m = substr($db, $this->hLen);
if ($lHash != $lHash2) {
if (!$this->_equals($lHash, $lHash2)) {
user_error('Decryption error');
return false;
}

View File

@ -45,6 +45,10 @@ class Random
*/
static function string($length)
{
if (!$length) {
return '';
}
if (version_compare(PHP_VERSION, '7.0.0', '>=')) {
try {
return \random_bytes($length);

View File

@ -432,8 +432,10 @@ class Twofish extends Base
$m2[$q1[$q0[$j] ^ $key[15]] ^ $key[7]] ^
$m3[$q1[$q1[$j] ^ $key[16]] ^ $key[8]];
$B = ($B << 8) | ($B >> 24 & 0xff);
$K[] = $A+= $B;
$K[] = (($A+= $B) << 9 | $A >> 23 & 0x1ff);
$A = $this->safe_intval($A + $B);
$K[] = $A;
$A = $this->safe_intval($A + $B);
$K[] = ($A << 9 | $A >> 23 & 0x1ff);
}
for ($i = 0; $i < 256; ++$i) {
$S0[$i] = $m0[$q0[$q0[$i] ^ $s4] ^ $s0];
@ -456,8 +458,10 @@ class Twofish extends Base
$m2[$q1[$q0[$q0[$j] ^ $key[23]] ^ $key[15]] ^ $key[7]] ^
$m3[$q1[$q1[$q0[$j] ^ $key[24]] ^ $key[16]] ^ $key[8]];
$B = ($B << 8) | ($B >> 24 & 0xff);
$K[] = $A+= $B;
$K[] = (($A+= $B) << 9 | $A >> 23 & 0x1ff);
$A = $this->safe_intval($A + $B);
$K[] = $A;
$A = $this->safe_intval($A + $B);
$K[] = ($A << 9 | $A >> 23 & 0x1ff);
}
for ($i = 0; $i < 256; ++$i) {
$S0[$i] = $m0[$q0[$q0[$q1[$i] ^ $s8] ^ $s4] ^ $s0];
@ -481,8 +485,10 @@ class Twofish extends Base
$m2[$q1[$q0[$q0[$q0[$j] ^ $key[31]] ^ $key[23]] ^ $key[15]] ^ $key[7]] ^
$m3[$q1[$q1[$q0[$q1[$j] ^ $key[32]] ^ $key[24]] ^ $key[16]] ^ $key[8]];
$B = ($B << 8) | ($B >> 24 & 0xff);
$K[] = $A+= $B;
$K[] = (($A+= $B) << 9 | $A >> 23 & 0x1ff);
$A = $this->safe_intval($A + $B);
$K[] = $A;
$A = $this->safe_intval($A + $B);
$K[] = ($A << 9 | $A >> 23 & 0x1ff);
}
for ($i = 0; $i < 256; ++$i) {
$S0[$i] = $m0[$q0[$q0[$q1[$q1[$i] ^ $sc] ^ $s8] ^ $s4] ^ $s0];
@ -578,9 +584,9 @@ class Twofish extends Base
$S1[ $R1 & 0xff] ^
$S2[($R1 >> 8) & 0xff] ^
$S3[($R1 >> 16) & 0xff];
$R2^= $t0 + $t1 + $K[++$ki];
$R2^= $this->safe_intval($t0 + $t1 + $K[++$ki]);
$R2 = ($R2 >> 1 & 0x7fffffff) | ($R2 << 31);
$R3 = ((($R3 >> 31) & 1) | ($R3 << 1)) ^ ($t0 + ($t1 << 1) + $K[++$ki]);
$R3 = ((($R3 >> 31) & 1) | ($R3 << 1)) ^ $this->safe_intval($t0 + ($t1 << 1) + $K[++$ki]);
$t0 = $S0[ $R2 & 0xff] ^
$S1[($R2 >> 8) & 0xff] ^
@ -590,9 +596,9 @@ class Twofish extends Base
$S1[ $R3 & 0xff] ^
$S2[($R3 >> 8) & 0xff] ^
$S3[($R3 >> 16) & 0xff];
$R0^= ($t0 + $t1 + $K[++$ki]);
$R0^= $this->safe_intval($t0 + $t1 + $K[++$ki]);
$R0 = ($R0 >> 1 & 0x7fffffff) | ($R0 << 31);
$R1 = ((($R1 >> 31) & 1) | ($R1 << 1)) ^ ($t0 + ($t1 << 1) + $K[++$ki]);
$R1 = ((($R1 >> 31) & 1) | ($R1 << 1)) ^ $this->safe_intval($t0 + ($t1 << 1) + $K[++$ki]);
}
// @codingStandardsIgnoreStart
@ -634,9 +640,9 @@ class Twofish extends Base
$S1[$R1 & 0xff] ^
$S2[$R1 >> 8 & 0xff] ^
$S3[$R1 >> 16 & 0xff];
$R3^= $t0 + ($t1 << 1) + $K[--$ki];
$R3^= $this->safe_intval($t0 + ($t1 << 1) + $K[--$ki]);
$R3 = $R3 >> 1 & 0x7fffffff | $R3 << 31;
$R2 = ($R2 >> 31 & 0x1 | $R2 << 1) ^ ($t0 + $t1 + $K[--$ki]);
$R2 = ($R2 >> 31 & 0x1 | $R2 << 1) ^ $this->safe_intval($t0 + $t1 + $K[--$ki]);
$t0 = $S0[$R2 & 0xff] ^
$S1[$R2 >> 8 & 0xff] ^
@ -646,9 +652,9 @@ class Twofish extends Base
$S1[$R3 & 0xff] ^
$S2[$R3 >> 8 & 0xff] ^
$S3[$R3 >> 16 & 0xff];
$R1^= $t0 + ($t1 << 1) + $K[--$ki];
$R1^= $this->safe_intval($t0 + ($t1 << 1) + $K[--$ki]);
$R1 = $R1 >> 1 & 0x7fffffff | $R1 << 31;
$R0 = ($R0 >> 31 & 0x1 | $R0 << 1) ^ ($t0 + $t1 + $K[--$ki]);
$R0 = ($R0 >> 31 & 0x1 | $R0 << 1) ^ $this->safe_intval($t0 + $t1 + $K[--$ki]);
}
// @codingStandardsIgnoreStart
@ -679,6 +685,8 @@ class Twofish extends Base
$code_hash = str_pad($code_hash, 32) . $this->_hashInlineCryptFunction($this->key);
}
$safeint = $this->safe_intval_inline();
if (!isset($lambda_functions[$code_hash])) {
switch (true) {
case $gen_hi_opt_code:
@ -727,9 +735,9 @@ class Twofish extends Base
$S1[ $R1 & 0xff] ^
$S2[($R1 >> 8) & 0xff] ^
$S3[($R1 >> 16) & 0xff];
$R2^= ($t0 + $t1 + '.$K[++$ki].');
$R2^= ' . sprintf($safeint, '$t0 + $t1 + ' . $K[++$ki]) . ';
$R2 = ($R2 >> 1 & 0x7fffffff) | ($R2 << 31);
$R3 = ((($R3 >> 31) & 1) | ($R3 << 1)) ^ ($t0 + ($t1 << 1) + '.$K[++$ki].');
$R3 = ((($R3 >> 31) & 1) | ($R3 << 1)) ^ ' . sprintf($safeint, '($t0 + ($t1 << 1) + ' . $K[++$ki] . ')') . ';
$t0 = $S0[ $R2 & 0xff] ^
$S1[($R2 >> 8) & 0xff] ^
@ -739,16 +747,16 @@ class Twofish extends Base
$S1[ $R3 & 0xff] ^
$S2[($R3 >> 8) & 0xff] ^
$S3[($R3 >> 16) & 0xff];
$R0^= ($t0 + $t1 + '.$K[++$ki].');
$R0^= ' . sprintf($safeint, '($t0 + $t1 + ' . $K[++$ki] . ')') . ';
$R0 = ($R0 >> 1 & 0x7fffffff) | ($R0 << 31);
$R1 = ((($R1 >> 31) & 1) | ($R1 << 1)) ^ ($t0 + ($t1 << 1) + '.$K[++$ki].');
$R1 = ((($R1 >> 31) & 1) | ($R1 << 1)) ^ ' . sprintf($safeint, '($t0 + ($t1 << 1) + ' . $K[++$ki] . ')') . ';
';
}
$encrypt_block.= '
$in = pack("V4", '.$K[4].' ^ $R2,
'.$K[5].' ^ $R3,
'.$K[6].' ^ $R0,
'.$K[7].' ^ $R1);
$in = pack("V4", ' . $K[4] . ' ^ $R2,
' . $K[5] . ' ^ $R3,
' . $K[6] . ' ^ $R0,
' . $K[7] . ' ^ $R1);
';
// Generating decrypt code:
@ -769,9 +777,9 @@ class Twofish extends Base
$S1[$R1 & 0xff] ^
$S2[$R1 >> 8 & 0xff] ^
$S3[$R1 >> 16 & 0xff];
$R3^= $t0 + ($t1 << 1) + '.$K[--$ki].';
$R3^= ' . sprintf($safeint, '$t0 + ($t1 << 1) + ' . $K[--$ki]) . ';
$R3 = $R3 >> 1 & 0x7fffffff | $R3 << 31;
$R2 = ($R2 >> 31 & 0x1 | $R2 << 1) ^ ($t0 + $t1 + '.$K[--$ki].');
$R2 = ($R2 >> 31 & 0x1 | $R2 << 1) ^ ' . sprintf($safeint, '($t0 + $t1 + '.$K[--$ki] . ')') . ';
$t0 = $S0[$R2 & 0xff] ^
$S1[$R2 >> 8 & 0xff] ^
@ -781,16 +789,16 @@ class Twofish extends Base
$S1[$R3 & 0xff] ^
$S2[$R3 >> 8 & 0xff] ^
$S3[$R3 >> 16 & 0xff];
$R1^= $t0 + ($t1 << 1) + '.$K[--$ki].';
$R1^= ' . sprintf($safeint, '$t0 + ($t1 << 1) + ' . $K[--$ki]) . ';
$R1 = $R1 >> 1 & 0x7fffffff | $R1 << 31;
$R0 = ($R0 >> 31 & 0x1 | $R0 << 1) ^ ($t0 + $t1 + '.$K[--$ki].');
$R0 = ($R0 >> 31 & 0x1 | $R0 << 1) ^ ' . sprintf($safeint, '($t0 + $t1 + '.$K[--$ki] . ')') . ';
';
}
$decrypt_block.= '
$in = pack("V4", '.$K[0].' ^ $R2,
'.$K[1].' ^ $R3,
'.$K[2].' ^ $R0,
'.$K[3].' ^ $R1);
$in = pack("V4", ' . $K[0] . ' ^ $R2,
' . $K[1] . ' ^ $R3,
' . $K[2] . ' ^ $R0,
' . $K[3] . ' ^ $R1);
';
$lambda_functions[$code_hash] = $this->_createInlineCryptFunction(

View File

@ -305,6 +305,9 @@ class ANSI
case preg_match('#\x1B\[(\d+)D#', $this->ansi, $match): // Move cursor left n lines
$this->old_x = $this->x;
$this->x-= $match[1];
if ($this->x < 0) {
$this->x = 0;
}
break;
case preg_match('#\x1B\[(\d+);(\d+)r#', $this->ansi, $match): // Set top and bottom lines of a window
break;
@ -416,7 +419,7 @@ class ANSI
if ($this->x > $this->max_x) {
$this->x = 0;
$this->y++;
$this->_newLine();
} else {
$this->x++;
}

View File

@ -25,6 +25,8 @@ namespace phpseclib\File;
use phpseclib\File\ASN1\Element;
use phpseclib\Math\BigInteger;
use DateTime;
use DateTimeZone;
/**
* Pure-PHP ASN.1 Parser
@ -707,7 +709,7 @@ class ASN1
if (isset($mapping['implicit'])) {
$decoded['content'] = $this->_decodeTime($decoded['content'], $decoded['type']);
}
return @date($this->format, $decoded['content']);
return $decoded['content'] ? $decoded['content']->format($this->format) : false;
case self::TYPE_BIT_STRING:
if (isset($mapping['mapping'])) {
$offset = ord($decoded['content'][0]);
@ -956,7 +958,8 @@ class ASN1
case self::TYPE_GENERALIZED_TIME:
$format = $mapping['type'] == self::TYPE_UTC_TIME ? 'y' : 'Y';
$format.= 'mdHis';
$value = @gmdate($format, strtotime($source)) . 'Z';
$date = new DateTime($source, new DateTimeZone('GMT'));
$value = $date->format($format) . 'Z';
break;
case self::TYPE_BIT_STRING:
if (isset($mapping['mapping'])) {
@ -1137,33 +1140,32 @@ class ASN1
http://tools.ietf.org/html/rfc5280#section-4.1.2.5.2
http://www.obj-sys.com/asn1tutorial/node14.html */
$pattern = $tag == self::TYPE_UTC_TIME ?
'#^(..)(..)(..)(..)(..)(..)?(.*)$#' :
'#(....)(..)(..)(..)(..)(..).*([Z+-].*)$#';
preg_match($pattern, $content, $matches);
list(, $year, $month, $day, $hour, $minute, $second, $timezone) = $matches;
$format = 'YmdHis';
if ($tag == self::TYPE_UTC_TIME) {
$year = $year >= 50 ? "19$year" : "20$year";
}
if ($timezone == 'Z') {
$mktime = 'gmmktime';
$timezone = 0;
} elseif (preg_match('#([+-])(\d\d)(\d\d)#', $timezone, $matches)) {
$mktime = 'gmmktime';
$timezone = 60 * $matches[3] + 3600 * $matches[2];
if ($matches[1] == '-') {
$timezone = -$timezone;
// https://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf#page=28 says "the seconds
// element shall always be present" but none-the-less I've seen X509 certs where it isn't and if the
// browsers parse it phpseclib ought to too
if (preg_match('#^(\d{10})(Z|[+-]\d{4})$#', $content, $matches)) {
$content = $matches[1] . '00' . $matches[2];
}
} else {
$mktime = 'mktime';
$timezone = 0;
$prefix = substr($content, 0, 2) >= 50 ? '19' : '20';
$content = $prefix . $content;
} elseif (strpos($content, '.') !== false) {
$format.= '.u';
}
return @$mktime((int)$hour, (int)$minute, (int)$second, (int)$month, (int)$day, (int)$year) + $timezone;
if ($content[strlen($content) - 1] == 'Z') {
$content = substr($content, 0, -1) . '+0000';
}
if (strpos($content, '-') !== false || strpos($content, '+') !== false) {
$format.= 'O';
}
// error supression isn't necessary as of PHP 7.0:
// http://php.net/manual/en/migration70.other-changes.php
return @DateTime::createFromFormat($format, $content);
}
/**

View File

@ -31,6 +31,8 @@ use phpseclib\Crypt\Random;
use phpseclib\Crypt\RSA;
use phpseclib\File\ASN1\Element;
use phpseclib\Math\BigInteger;
use DateTime;
use DateTimeZone;
/**
* Pure-PHP X.509 Parser
@ -2030,30 +2032,32 @@ class X509
}
if ($names = $this->getExtension('id-ce-subjectAltName')) {
foreach ($names as $key => $value) {
$value = str_replace(array('.', '*'), array('\.', '[^.]*'), $value);
switch ($key) {
case 'dNSName':
/* From RFC2818 "HTTP over TLS":
foreach ($names as $name) {
foreach ($name as $key => $value) {
$value = str_replace(array('.', '*'), array('\.', '[^.]*'), $value);
switch ($key) {
case 'dNSName':
/* From RFC2818 "HTTP over TLS":
If a subjectAltName extension of type dNSName is present, that MUST
be used as the identity. Otherwise, the (most specific) Common Name
field in the Subject field of the certificate MUST be used. Although
the use of the Common Name is existing practice, it is deprecated and
Certification Authorities are encouraged to use the dNSName instead. */
if (preg_match('#^' . $value . '$#', $components['host'])) {
return true;
}
break;
case 'iPAddress':
/* From RFC2818 "HTTP over TLS":
If a subjectAltName extension of type dNSName is present, that MUST
be used as the identity. Otherwise, the (most specific) Common Name
field in the Subject field of the certificate MUST be used. Although
the use of the Common Name is existing practice, it is deprecated and
Certification Authorities are encouraged to use the dNSName instead. */
if (preg_match('#^' . $value . '$#', $components['host'])) {
return true;
}
break;
case 'iPAddress':
/* From RFC2818 "HTTP over TLS":
In some cases, the URI is specified as an IP address rather than a
hostname. In this case, the iPAddress subjectAltName must be present
in the certificate and must exactly match the IP in the URI. */
if (preg_match('#(?:\d{1-3}\.){4}#', $components['host'] . '.') && preg_match('#^' . $value . '$#', $components['host'])) {
return true;
}
In some cases, the URI is specified as an IP address rather than a
hostname. In this case, the iPAddress subjectAltName must be present
in the certificate and must exactly match the IP in the URI. */
if (preg_match('#(?:\d{1-3}\.){4}#', $components['host'] . '.') && preg_match('#^' . $value . '$#', $components['host'])) {
return true;
}
}
}
}
return false;
@ -2082,7 +2086,7 @@ class X509
}
if (!isset($date)) {
$date = time();
$date = new DateTime($date, new DateTimeZone(@date_default_timezone_get()));
}
$notBefore = $this->currentCert['tbsCertificate']['validity']['notBefore'];
@ -2092,8 +2096,8 @@ class X509
$notAfter = isset($notAfter['generalTime']) ? $notAfter['generalTime'] : $notAfter['utcTime'];
switch (true) {
case $date < @strtotime($notBefore):
case $date > @strtotime($notAfter):
case $date < new DateTime($notBefore, new DateTimeZone(@date_default_timezone_get())):
case $date > new DateTime($notAfter, new DateTimeZone(@date_default_timezone_get())):
return false;
}
@ -2137,7 +2141,8 @@ class X509
$subjectKeyID = $this->getExtension('id-ce-subjectKeyIdentifier');
switch (true) {
case !is_array($authorityKey):
case is_array($authorityKey) && isset($authorityKey['keyIdentifier']) && $authorityKey['keyIdentifier'] === $subjectKeyID:
case !$subjectKeyID:
case isset($authorityKey['keyIdentifier']) && $authorityKey['keyIdentifier'] === $subjectKeyID:
$signingCert = $this->currentCert; // working cert
}
}
@ -2154,7 +2159,11 @@ class X509
$subjectKeyID = $this->getExtension('id-ce-subjectKeyIdentifier', $ca);
switch (true) {
case !is_array($authorityKey):
case is_array($authorityKey) && isset($authorityKey['keyIdentifier']) && $authorityKey['keyIdentifier'] === $subjectKeyID:
case !$subjectKeyID:
case isset($authorityKey['keyIdentifier']) && $authorityKey['keyIdentifier'] === $subjectKeyID:
if (is_array($authorityKey) && isset($authorityKey['authorityCertSerialNumber']) && !$authorityKey['authorityCertSerialNumber']->equals($ca['tbsCertificate']['serialNumber'])) {
break 2; // serial mismatch - check other ca
}
$signingCert = $ca; // working cert
break 3;
}
@ -2200,7 +2209,11 @@ class X509
$subjectKeyID = $this->getExtension('id-ce-subjectKeyIdentifier', $ca);
switch (true) {
case !is_array($authorityKey):
case is_array($authorityKey) && isset($authorityKey['keyIdentifier']) && $authorityKey['keyIdentifier'] === $subjectKeyID:
case !$subjectKeyID:
case isset($authorityKey['keyIdentifier']) && $authorityKey['keyIdentifier'] === $subjectKeyID:
if (is_array($authorityKey) && isset($authorityKey['authorityCertSerialNumber']) && !$authorityKey['authorityCertSerialNumber']->equals($ca['tbsCertificate']['serialNumber'])) {
break 2; // serial mismatch - check other ca
}
$signingCert = $ca; // working cert
break 3;
}
@ -2472,6 +2485,10 @@ class X509
}
$dn = array_values($dn);
// fix for https://bugs.php.net/75433 affecting PHP 7.2
if (!isset($dn[0])) {
$dn = array_splice($dn, 0, 0);
}
}
/**
@ -2715,7 +2732,9 @@ class X509
$value = array_pop($value); // Always strip data type.
}
} elseif (is_object($value) && $value instanceof Element) {
$callback = create_function('$x', 'return "\x" . bin2hex($x[0]);');
$callback = function ($x) {
return "\x" . bin2hex($x[0]);
};
$value = strtoupper(preg_replace_callback('#[^\x20-\x7E]#', $callback, $value->element));
}
$output.= $desc . '=' . $value;
@ -3338,7 +3357,11 @@ class X509
*/
function _timeField($date)
{
$year = @gmdate("Y", @strtotime($date)); // the same way ASN1.php parses this
if ($date instanceof Element) {
return $date;
}
$dateObj = new DateTime($date, new DateTimeZone('GMT'));
$year = $dateObj->format('Y'); // the same way ASN1.php parses this
if ($year < 2050) {
return array('utcTime' => $date);
} else {
@ -3403,8 +3426,12 @@ class X509
return false;
}
$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'));
$startDate = new DateTime('now', new DateTimeZone(@date_default_timezone_get()));
$startDate = !empty($this->startDate) ? $this->startDate : $startDate->format('D, d M Y H:i:s O');
$endDate = new DateTime('+1 year', new DateTimeZone(@date_default_timezone_get()));
$endDate = !empty($this->endDate) ? $this->endDate : $endDate->format('D, d M Y H:i:s O');
/* "The serial number MUST be a positive integer"
"Conforming CAs MUST NOT use serialNumber values longer than 20 octets."
-- https://tools.ietf.org/html/rfc5280#section-4.1.2.2
@ -3672,7 +3699,9 @@ class X509
$currentCert = isset($this->currentCert) ? $this->currentCert : null;
$signatureSubject = isset($this->signatureSubject) ? $this->signatureSubject : null;
$thisUpdate = !empty($this->startDate) ? $this->startDate : @date('D, d M Y H:i:s O');
$thisUpdate = new DateTime('now', new DateTimeZone(@date_default_timezone_get()));
$thisUpdate = !empty($this->startDate) ? $this->startDate : $thisUpdate->format('D, d M Y H:i:s O');
if (isset($crl->currentCert) && is_array($crl->currentCert) && isset($crl->currentCert['tbsCertList'])) {
$this->currentCert = $crl->currentCert;
@ -3823,7 +3852,11 @@ class X509
*/
function setStartDate($date)
{
$this->startDate = @date('D, d M Y H:i:s O', @strtotime($date));
if (!is_object($date) || !is_a($date, 'DateTime')) {
$date = new DateTime($date, new DateTimeZone(@date_default_timezone_get()));
}
$this->startDate = $date->format('D, d M Y H:i:s O');
}
/**
@ -3847,7 +3880,11 @@ class X509
$temp = chr(ASN1::TYPE_GENERALIZED_TIME) . $asn1->_encodeLength(strlen($temp)) . $temp;
$this->endDate = new Element($temp);
} else {
$this->endDate = @date('D, d M Y H:i:s O', @strtotime($date));
if (!is_object($date) || !is_a($date, 'DateTime')) {
$date = new DateTime($date, new DateTimeZone(@date_default_timezone_get()));
}
$this->endDate = $date->format('D, d M Y H:i:s O');
}
}
@ -4057,6 +4094,10 @@ class X509
}
$extensions = array_values($extensions);
// fix for https://bugs.php.net/75433 affecting PHP 7.2
if (!isset($extensions[0])) {
$extensions = array_splice($extensions, 0, 0);
}
return $result;
}
@ -4577,8 +4618,9 @@ class X509
}
$i = count($rclist);
$revocationDate = new DateTime('now', new DateTimeZone(@date_default_timezone_get()));
$rclist[] = array('userCertificate' => $serial,
'revocationDate' => $this->_timeField(@date('D, d M Y H:i:s O')));
'revocationDate' => $this->_timeField($revocationDate->format('D, d M Y H:i:s O')));
return $i;
}

View File

@ -360,8 +360,12 @@ class BigInteger
case 256:
switch (MATH_BIGINTEGER_MODE) {
case self::MODE_GMP:
$sign = $this->is_negative ? '-' : '';
$this->value = gmp_init($sign . '0x' . bin2hex($x));
$this->value = function_exists('gmp_import') ?
gmp_import($x) :
gmp_init('0x' . bin2hex($x));
if ($this->is_negative) {
$this->value = gmp_neg($this->value);
}
break;
case self::MODE_BCMATH:
// round $len to the nearest 4 (thanks, DavidMJ!)
@ -548,9 +552,13 @@ class BigInteger
return $this->precision > 0 ? str_repeat(chr(0), ($this->precision + 1) >> 3) : '';
}
$temp = gmp_strval(gmp_abs($this->value), 16);
$temp = (strlen($temp) & 1) ? '0' . $temp : $temp;
$temp = pack('H*', $temp);
if (function_exists('gmp_export')) {
$temp = gmp_export($this->value);
} else {
$temp = gmp_strval(gmp_abs($this->value), 16);
$temp = (strlen($temp) & 1) ? '0' . $temp : $temp;
$temp = pack('H*', $temp);
}
return $this->precision > 0 ?
substr(str_pad($temp, $this->precision >> 3, chr(0), STR_PAD_LEFT), -($this->precision >> 3)) :
@ -2860,8 +2868,7 @@ class BigInteger
switch (MATH_BIGINTEGER_MODE) {
case self::MODE_GMP:
$temp = new static();
$temp->value = gmp_xor($this->value, $x->value);
$temp->value = gmp_xor(gmp_abs($this->value), gmp_abs($x->value));
return $this->_normalize($temp);
case self::MODE_BCMATH:
$left = $this->toBytes();
@ -2877,6 +2884,7 @@ class BigInteger
$length = max(count($this->value), count($x->value));
$result = $this->copy();
$result->is_negative = false;
$result->value = array_pad($result->value, $length, 0);
$x->value = array_pad($x->value, $length, 0);
@ -2900,7 +2908,7 @@ class BigInteger
// (will always result in a smaller number. ie. ~1 isn't 1111 1110 - it's 0)
$temp = $this->toBytes();
if ($temp == '') {
return '';
return $this->_normalize(new static());
}
$pre_msb = decbin(ord($temp[0]));
$temp = ~$temp;
@ -3435,7 +3443,7 @@ class BigInteger
break;
}
}
$s = 26 * $i + $j - 1;
$s = 26 * $i + $j;
$r->_rshift($s);
}

View File

@ -158,7 +158,7 @@ class SFTP extends SSH2
* Current working directory
*
* @var string
* @see self::_realpath()
* @see self::realpath()
* @see self::chdir()
* @access private
*/
@ -187,7 +187,7 @@ class SFTP extends SSH2
*
* @see self::getSFTPErrors()
* @see self::getLastSFTPError()
* @var string
* @var array
* @access private
*/
var $sftp_errors = array();
@ -236,6 +236,20 @@ class SFTP extends SSH2
*/
var $sortOptions = array();
/**
* Canonicalization Flag
*
* Determines whether or not paths should be canonicalized before being
* passed on to the remote server.
*
* @see self::enablePathCanonicalization()
* @see self::disablePathCanonicalization()
* @see self::realpath()
* @var bool
* @access private
*/
var $canonicalize_paths = true;
/**
* Default Constructor.
*
@ -335,7 +349,7 @@ class SFTP extends SSH2
// 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.
-1 << 31 => 'NET_SFTP_ATTR_EXTENDED'
(-1 << 31) & 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
@ -409,7 +423,7 @@ class SFTP extends SSH2
$this->channel_status[self::CHANNEL] = NET_SSH2_MSG_CHANNEL_OPEN;
$response = $this->_get_channel_packet(self::CHANNEL);
$response = $this->_get_channel_packet(self::CHANNEL, true);
if ($response === false) {
return false;
}
@ -430,7 +444,7 @@ class SFTP extends SSH2
$this->channel_status[self::CHANNEL] = NET_SSH2_MSG_CHANNEL_REQUEST;
$response = $this->_get_channel_packet(self::CHANNEL);
$response = $this->_get_channel_packet(self::CHANNEL, true);
if ($response === false) {
// from PuTTY's psftp.exe
$command = "test -x /usr/lib/sftp-server && exec /usr/lib/sftp-server\n" .
@ -454,7 +468,7 @@ class SFTP extends SSH2
$this->channel_status[self::CHANNEL] = NET_SSH2_MSG_CHANNEL_REQUEST;
$response = $this->_get_channel_packet(self::CHANNEL);
$response = $this->_get_channel_packet(self::CHANNEL, true);
if ($response === false) {
return false;
}
@ -575,6 +589,26 @@ class SFTP extends SSH2
$this->stat_cache = array();
}
/**
* Enable path canonicalization
*
* @access public
*/
function enablePathCanonicalization()
{
$this->canonicalize_paths = true;
}
/**
* Enable path canonicalization
*
* @access public
*/
function disablePathCanonicalization()
{
$this->canonicalize_paths = false;
}
/**
* Returns the current directory name
*
@ -633,13 +667,20 @@ class SFTP extends SSH2
* SFTP doesn't provide a mechanism by which the current working directory can be changed, so we'll emulate it. Returns
* the absolute (canonicalized) path.
*
* If canonicalize_paths has been disabled using disablePathCanonicalization(), $path is returned as-is.
*
* @see self::chdir()
* @see self::disablePathCanonicalization()
* @param string $path
* @return mixed
* @access private
*/
function _realpath($path)
{
if (!$this->canonicalize_paths) {
return $path;
}
if ($this->pwd === false) {
// http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-8.9
if (!$this->_send_sftp_packet(NET_SFTP_REALPATH, pack('Na*', strlen($path), $path))) {
@ -1106,7 +1147,7 @@ class SFTP extends SSH2
$temp[$dir] = array();
}
if ($i === $max) {
if (is_object($temp[$dir])) {
if (is_object($temp[$dir]) && is_object($value)) {
if (!isset($value->stat) && isset($temp[$dir]->stat)) {
$value->stat = $temp[$dir]->stat;
}
@ -1294,7 +1335,7 @@ class SFTP extends SSH2
/**
* Returns general information about a file or symbolic link
*
* Determines information without calling \phpseclib\Net\SFTP::_realpath().
* Determines information without calling \phpseclib\Net\SFTP::realpath().
* The second parameter can be either NET_SFTP_STAT or NET_SFTP_LSTAT.
*
* @param string $filename
@ -1455,7 +1496,7 @@ class SFTP extends SSH2
return true;
}
$filename = $this->_realPath($filename);
$filename = $this->realpath($filename);
// rather than return what the permissions *should* be, we'll return what they actually are. this will also
// tell us if the file actually exists.
// incidentally, SFTPv4+ adds an additional 32-bit integer field - flags - to the following:
@ -1938,7 +1979,7 @@ class SFTP extends SSH2
if (isset($fp)) {
$stat = fstat($fp);
$size = $stat['size'];
$size = !empty($stat) ? $stat['size'] : 0;
if ($local_start >= 0) {
fseek($fp, $local_start);
@ -2929,7 +2970,7 @@ class SFTP extends SSH2
// SFTP packet length
while (strlen($this->packet_buffer) < 4) {
$temp = $this->_get_channel_packet(self::CHANNEL);
$temp = $this->_get_channel_packet(self::CHANNEL, true);
if (is_bool($temp)) {
$this->packet_type = false;
$this->packet_buffer = '';
@ -2946,7 +2987,7 @@ class SFTP extends SSH2
// SFTP packet type and data payload
while ($tempLength > 0) {
$temp = $this->_get_channel_packet(self::CHANNEL);
$temp = $this->_get_channel_packet(self::CHANNEL, true);
if (is_bool($temp)) {
$this->packet_type = false;
$this->packet_buffer = '';
@ -3014,7 +3055,7 @@ class SFTP extends SSH2
/**
* Returns all errors
*
* @return string
* @return array
* @access public
*/
function getSFTPErrors()

View File

@ -179,7 +179,7 @@ class Stream
if ($host[0] == '$') {
$host = substr($host, 1);
global $$host;
global ${$host};
if (($$host instanceof SFTP) === false) {
return false;
}

View File

@ -916,7 +916,7 @@ class SSH1
/**
* Returns the output of an interactive shell when there's a match for $expect
*
* $expect can take the form of a string literal or, if $mode == self::READ__REGEX,
* $expect can take the form of a string literal or, if $mode == self::READ_REGEX,
* a regular expression.
*
* @see self::write()
@ -925,7 +925,7 @@ class SSH1
* @return bool
* @access public
*/
function read($expect, $mode = self::READ__SIMPLE)
function read($expect, $mode = self::READ_SIMPLE)
{
if (!($this->bitmap & self::MASK_LOGIN)) {
user_error('Operation disallowed prior to login()');
@ -939,7 +939,7 @@ class SSH1
$match = $expect;
while (true) {
if ($mode == self::READ__REGEX) {
if ($mode == self::READ_REGEX) {
preg_match($expect, $this->interactiveBuffer, $matches);
$match = isset($matches[0]) ? $matches[0] : '';
}

View File

@ -100,10 +100,10 @@ class SSH2
* @see \phpseclib\Net\SSH2::_get_channel_packet()
* @access private
*/
const CHANNEL_EXEC = 0; // PuTTy uses 0x100
const CHANNEL_SHELL = 1;
const CHANNEL_SUBSYSTEM = 2;
const CHANNEL_AGENT_FORWARD = 3;
const CHANNEL_EXEC = 1; // PuTTy uses 0x100
const CHANNEL_SHELL = 2;
const CHANNEL_SUBSYSTEM = 3;
const CHANNEL_AGENT_FORWARD = 4;
/**#@-*/
/**#@+
@ -126,6 +126,10 @@ class SSH2
* Dumps the content real-time to a file
*/
const LOG_REALTIME_FILE = 4;
/**
* Make sure that the log never gets larger than this
*/
const LOG_MAX_SIZE = 1048576; // 1024 * 1024
/**#@-*/
/**#@+
@ -141,9 +145,9 @@ class SSH2
*/
const READ_REGEX = 2;
/**
* Make sure that the log never gets larger than this
* Returns when a string matching the regular expression $expect is found
*/
const LOG_MAX_SIZE = 1048576; // 1024 * 1024
const READ_NEXT = 3;
/**#@-*/
/**
@ -866,6 +870,54 @@ class SSH2
*/
var $agent;
/**
* Send the identification string first?
*
* @var bool
* @access private
*/
var $send_id_string_first = true;
/**
* Send the key exchange initiation packet first?
*
* @var bool
* @access private
*/
var $send_kex_first = true;
/**
* Some versions of OpenSSH incorrectly calculate the key size
*
* @var bool
* @access private
*/
var $bad_key_size_fix = false;
/**
* The selected decryption algorithm
*
* @var string
* @access private
*/
var $decrypt_algorithm = '';
/**
* Should we try to re-connect to re-establish keys?
*
* @var bool
* @access private
*/
var $retry_connect = false;
/**
* Binary Packet Buffer
*
* @var string|false
* @access private
*/
var $binary_packet_buffer = false;
/**
* Default Constructor.
*
@ -978,13 +1030,69 @@ class SSH2
* CRYPT_MODE_INTERNAL, CRYPT_MODE_MCRYPT
*
* @param int $engine
* @access private
* @access public
*/
function setCryptoEngine($engine)
{
$this->crypto_engine = $engine;
}
/**
* Send Identification String First
*
* https://tools.ietf.org/html/rfc4253#section-4.2 says "when the connection has been established,
* both sides MUST send an identification string". It does not say which side sends it first. In
* theory it shouldn't matter but it is a fact of life that some SSH servers are simply buggy
*
* @access public
*/
function sendIdentificationStringFirst()
{
$this->send_id_string_first = true;
}
/**
* Send Identification String Last
*
* https://tools.ietf.org/html/rfc4253#section-4.2 says "when the connection has been established,
* both sides MUST send an identification string". It does not say which side sends it first. In
* theory it shouldn't matter but it is a fact of life that some SSH servers are simply buggy
*
* @access public
*/
function sendIdentificationStringLast()
{
$this->send_id_string_first = false;
}
/**
* Send SSH_MSG_KEXINIT First
*
* https://tools.ietf.org/html/rfc4253#section-7.1 says "key exchange begins by each sending
* sending the [SSH_MSG_KEXINIT] packet". It does not say which side sends it first. In theory
* it shouldn't matter but it is a fact of life that some SSH servers are simply buggy
*
* @access public
*/
function sendKEXINITFirst()
{
$this->send_kex_first = true;
}
/**
* Send SSH_MSG_KEXINIT Last
*
* https://tools.ietf.org/html/rfc4253#section-7.1 says "key exchange begins by each sending
* sending the [SSH_MSG_KEXINIT] packet". It does not say which side sends it first. In theory
* it shouldn't matter but it is a fact of life that some SSH servers are simply buggy
*
* @access public
*/
function sendKEXINITLast()
{
$this->send_kex_first = false;
}
/**
* Connect to an SSHv2 server
*
@ -1026,7 +1134,9 @@ class SSH2
$this->identifier = $this->_generate_identifier();
fputs($this->fsock, $this->identifier . "\r\n");
if ($this->send_id_string_first) {
fputs($this->fsock, $this->identifier . "\r\n");
}
/* According to the SSH2 specs,
@ -1099,23 +1209,33 @@ class SSH2
$this->errors[] = utf8_decode($data);
}
if ($matches[3] != '1.99' && $matches[3] != '2.0') {
if (version_compare($matches[3], '1.99', '<')) {
user_error("Cannot connect to SSH $matches[3] servers");
return false;
}
$response = $this->_get_binary_packet();
if ($response === false) {
user_error('Connection closed by server');
return false;
if (!$this->send_id_string_first) {
fputs($this->fsock, $this->identifier . "\r\n");
}
if (!strlen($response) || ord($response[0]) != NET_SSH2_MSG_KEXINIT) {
user_error('Expected SSH_MSG_KEXINIT');
return false;
if (!$this->send_kex_first) {
$response = $this->_get_binary_packet();
if ($response === false) {
user_error('Connection closed by server');
return false;
}
if (!strlen($response) || ord($response[0]) != NET_SSH2_MSG_KEXINIT) {
user_error('Expected SSH_MSG_KEXINIT');
return false;
}
if (!$this->_key_exchange($response)) {
return false;
}
}
if (!$this->_key_exchange($response)) {
if ($this->send_kex_first && !$this->_key_exchange()) {
return false;
}
@ -1137,7 +1257,7 @@ class SSH2
$identifier = 'SSH-2.0-phpseclib_2.0';
$ext = array();
if (extension_loaded('libsodium')) {
if (function_exists('\\Sodium\\library_version_major')) {
$ext[] = 'libsodium';
}
@ -1163,10 +1283,10 @@ class SSH2
/**
* Key Exchange
*
* @param string $kexinit_payload_server
* @param string $kexinit_payload_server optional
* @access private
*/
function _key_exchange($kexinit_payload_server)
function _key_exchange($kexinit_payload_server = false)
{
$kex_algorithms = array(
// Elliptic Curve Diffie-Hellman Key Agreement (ECDH) using
@ -1287,8 +1407,9 @@ class SSH2
);
// some SSH servers have buggy implementations of some of the above algorithms
switch ($this->server_identifier) {
case 'SSH-2.0-SSHD':
switch (true) {
case $this->server_identifier == 'SSH-2.0-SSHD':
case substr($this->server_identifier, 0, 13) == 'SSH-2.0-DLINK':
$mac_algorithms = array_values(array_diff(
$mac_algorithms,
array('hmac-sha1-96', 'hmac-md5-96')
@ -1303,6 +1424,51 @@ class SSH2
$client_cookie = Random::string(16);
$kexinit_payload_client = pack(
'Ca*Na*Na*Na*Na*Na*Na*Na*Na*Na*Na*CN',
NET_SSH2_MSG_KEXINIT,
$client_cookie,
strlen($str_kex_algorithms),
$str_kex_algorithms,
strlen($str_server_host_key_algorithms),
$str_server_host_key_algorithms,
strlen($encryption_algorithms_client_to_server),
$encryption_algorithms_client_to_server,
strlen($encryption_algorithms_server_to_client),
$encryption_algorithms_server_to_client,
strlen($mac_algorithms_client_to_server),
$mac_algorithms_client_to_server,
strlen($mac_algorithms_server_to_client),
$mac_algorithms_server_to_client,
strlen($compression_algorithms_client_to_server),
$compression_algorithms_client_to_server,
strlen($compression_algorithms_server_to_client),
$compression_algorithms_server_to_client,
0,
'',
0,
'',
0,
0
);
if ($this->send_kex_first) {
if (!$this->_send_binary_packet($kexinit_payload_client)) {
return false;
}
$kexinit_payload_server = $this->_get_binary_packet();
if ($kexinit_payload_server === false) {
user_error('Connection closed by server');
return false;
}
if (!strlen($kexinit_payload_server) || ord($kexinit_payload_server[0]) != NET_SSH2_MSG_KEXINIT) {
user_error('Expected SSH_MSG_KEXINIT');
return false;
}
}
$response = $kexinit_payload_server;
$this->_string_shift($response, 1); // skip past the message number (it should be SSH_MSG_KEXINIT)
$server_cookie = $this->_string_shift($response, 16);
@ -1373,39 +1539,9 @@ class SSH2
extract(unpack('Cfirst_kex_packet_follows', $this->_string_shift($response, 1)));
$first_kex_packet_follows = $first_kex_packet_follows != 0;
// the sending of SSH2_MSG_KEXINIT could go in one of two places. this is the second place.
$kexinit_payload_client = pack(
'Ca*Na*Na*Na*Na*Na*Na*Na*Na*Na*Na*CN',
NET_SSH2_MSG_KEXINIT,
$client_cookie,
strlen($str_kex_algorithms),
$str_kex_algorithms,
strlen($str_server_host_key_algorithms),
$str_server_host_key_algorithms,
strlen($encryption_algorithms_client_to_server),
$encryption_algorithms_client_to_server,
strlen($encryption_algorithms_server_to_client),
$encryption_algorithms_server_to_client,
strlen($mac_algorithms_client_to_server),
$mac_algorithms_client_to_server,
strlen($mac_algorithms_server_to_client),
$mac_algorithms_server_to_client,
strlen($compression_algorithms_client_to_server),
$compression_algorithms_client_to_server,
strlen($compression_algorithms_server_to_client),
$compression_algorithms_server_to_client,
0,
'',
0,
'',
0,
0
);
if (!$this->_send_binary_packet($kexinit_payload_client)) {
if (!$this->send_kex_first && !$this->_send_binary_packet($kexinit_payload_client)) {
return false;
}
// here ends the second place.
// we need to decide upon the symmetric encryption algorithms before we do the diffie-hellman key exchange
// we don't initialize any crypto-objects, yet - we do that, later. for now, we need the lengths to make the
@ -1677,6 +1813,8 @@ class SSH2
return false;
}
$this->decrypt_algorithm = $decrypt;
$keyBytes = pack('Na*', strlen($keyBytes), $keyBytes);
$this->encrypt = $this->_encryption_algorithm_to_crypt_instance($encrypt);
@ -1843,6 +1981,10 @@ class SSH2
*/
function _encryption_algorithm_to_key_size($algorithm)
{
if ($this->bad_key_size_fix && $this->_bad_algorithm_candidate($algorithm)) {
return 16;
}
switch ($algorithm) {
case 'none':
return 0;
@ -1917,6 +2059,27 @@ class SSH2
return null;
}
/*
* Tests whether or not proposed algorithm has a potential for issues
*
* @link https://www.chiark.greenend.org.uk/~sgtatham/putty/wishlist/ssh2-aesctr-openssh.html
* @link https://bugzilla.mindrot.org/show_bug.cgi?id=1291
* @param string $algorithm Name of the encryption algorithm
* @return bool
* @access private
*/
function _bad_algorithm_candidate($algorithm)
{
switch ($algorithm) {
case 'arcfour256':
case 'aes192-ctr':
case 'aes256-ctr':
return true;
}
return false;
}
/**
* Login
*
@ -1996,6 +2159,13 @@ class SSH2
$response = $this->_get_binary_packet();
if ($response === false) {
if ($this->retry_connect) {
$this->retry_connect = false;
if (!$this->_connect()) {
return false;
}
return $this->_login_helper($username, $password);
}
user_error('Connection closed by server');
return false;
}
@ -2812,6 +2982,10 @@ class SSH2
$channel = $this->_get_interactive_channel();
if ($mode == self::READ_NEXT) {
return $this->_get_channel_packet($channel);
}
$match = $expect;
while (true) {
if ($mode == self::READ_REGEX) {
@ -3010,6 +3184,24 @@ class SSH2
return (bool) ($this->bitmap & self::MASK_LOGIN);
}
/**
* Resets a connection for re-use
*
* @param int $reason
* @access private
*/
function _reset_connection($reason)
{
$this->_disconnect($reason);
$this->decrypt = $this->encrypt = false;
$this->decrypt_block_size = $this->encrypt_block_size = 8;
$this->hmac_check = $this->hmac_create = false;
$this->hmac_size = false;
$this->session_id = false;
$this->retry_connect = true;
$this->get_seq_no = $this->send_seq_no = 0;
}
/**
* Gets Binary Packets
*
@ -3019,7 +3211,7 @@ class SSH2
* @return string
* @access private
*/
function _get_binary_packet()
function _get_binary_packet($skip_channel_filter = false)
{
if (!is_resource($this->fsock) || feof($this->fsock)) {
user_error('Connection closed prematurely');
@ -3053,6 +3245,11 @@ class SSH2
// "implementations SHOULD check that the packet length is reasonable"
// PuTTY uses 0x9000 as the actual max packet size and so to shall we
if ($remaining_length < -$this->decrypt_block_size || $remaining_length > 0x9000 || $remaining_length % $this->decrypt_block_size != 0) {
if (!$this->bad_key_size_fix && $this->_bad_algorithm_candidate($this->decrypt_algorithm) && !($this->bitmap & SSH2::MASK_LOGIN)) {
$this->bad_key_size_fix = true;
$this->_reset_connection(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
return false;
}
user_error('Invalid size');
return false;
}
@ -3068,6 +3265,7 @@ class SSH2
$buffer.= $temp;
$remaining_length-= strlen($temp);
}
$stop = microtime(true);
if (strlen($buffer)) {
$raw.= $this->decrypt !== false ? $this->decrypt->decrypt($buffer) : $buffer;
@ -3103,7 +3301,7 @@ class SSH2
$this->last_packet = $current;
}
return $this->_filter($payload);
return $this->_filter($payload, $skip_channel_filter);
}
/**
@ -3115,7 +3313,7 @@ class SSH2
* @return string
* @access private
*/
function _filter($payload)
function _filter($payload, $skip_channel_filter)
{
switch (ord($payload[0])) {
case NET_SSH2_MSG_DISCONNECT:
@ -3128,7 +3326,7 @@ class SSH2
$this->bitmap = 0;
return false;
case NET_SSH2_MSG_IGNORE:
$payload = $this->_get_binary_packet();
$payload = $this->_get_binary_packet($skip_channel_filter);
break;
case NET_SSH2_MSG_DEBUG:
$this->_string_shift($payload, 2);
@ -3137,17 +3335,18 @@ class SSH2
}
extract(unpack('Nlength', $this->_string_shift($payload, 4)));
$this->errors[] = 'SSH_MSG_DEBUG: ' . utf8_decode($this->_string_shift($payload, $length));
$payload = $this->_get_binary_packet();
$payload = $this->_get_binary_packet($skip_channel_filter);
break;
case NET_SSH2_MSG_UNIMPLEMENTED:
return false;
case NET_SSH2_MSG_KEXINIT:
if ($this->session_id !== false) {
$this->send_kex_first = false;
if (!$this->_key_exchange($payload)) {
$this->bitmap = 0;
return false;
}
$payload = $this->_get_binary_packet();
$payload = $this->_get_binary_packet($skip_channel_filter);
}
}
@ -3165,6 +3364,17 @@ class SSH2
// only called when we've already logged in
if (($this->bitmap & self::MASK_CONNECTED) && $this->isAuthenticated()) {
switch (ord($payload[0])) {
case NET_SSH2_MSG_CHANNEL_DATA:
case NET_SSH2_MSG_CHANNEL_EXTENDED_DATA:
case NET_SSH2_MSG_CHANNEL_REQUEST:
case NET_SSH2_MSG_CHANNEL_CLOSE:
case NET_SSH2_MSG_CHANNEL_EOF:
if (!$skip_channel_filter && !empty($this->server_channels)) {
$this->binary_packet_buffer = $payload;
$this->_get_channel_packet(true);
$payload = $this->_get_binary_packet();
}
break;
case NET_SSH2_MSG_GLOBAL_REQUEST: // see http://tools.ietf.org/html/rfc4254#section-4
if (strlen($payload) < 4) {
return false;
@ -3176,7 +3386,7 @@ class SSH2
return $this->_disconnect(NET_SSH2_DISCONNECT_BY_APPLICATION);
}
$payload = $this->_get_binary_packet();
$payload = $this->_get_binary_packet($skip_channel_filter);
break;
case NET_SSH2_MSG_CHANNEL_OPEN: // see http://tools.ietf.org/html/rfc4254#section-5.1
$this->_string_shift($payload, 1);
@ -3239,7 +3449,7 @@ class SSH2
return $this->_disconnect(NET_SSH2_DISCONNECT_BY_APPLICATION);
}
}
$payload = $this->_get_binary_packet();
$payload = $this->_get_binary_packet($skip_channel_filter);
break;
case NET_SSH2_MSG_CHANNEL_WINDOW_ADJUST:
$this->_string_shift($payload, 1);
@ -3250,7 +3460,7 @@ class SSH2
extract(unpack('Nwindow_size', $this->_string_shift($payload, 4)));
$this->window_size_client_to_server[$channel]+= $window_size;
$payload = ($this->bitmap & self::MASK_WINDOW_ADJUST) ? true : $this->_get_binary_packet();
$payload = ($this->bitmap & self::MASK_WINDOW_ADJUST) ? true : $this->_get_binary_packet($skip_channel_filter);
}
}
@ -3347,32 +3557,38 @@ class SSH2
}
while (true) {
if ($this->curTimeout) {
if ($this->curTimeout < 0) {
$this->is_timeout = true;
return true;
if ($this->binary_packet_buffer !== false) {
$response = $this->binary_packet_buffer;
$this->binary_packet_buffer = false;
} else {
if ($this->curTimeout) {
if ($this->curTimeout < 0) {
$this->is_timeout = true;
return true;
}
$read = array($this->fsock);
$write = $except = null;
$start = microtime(true);
$sec = floor($this->curTimeout);
$usec = 1000000 * ($this->curTimeout - $sec);
// on windows this returns a "Warning: Invalid CRT parameters detected" error
if (!@stream_select($read, $write, $except, $sec, $usec) && !count($read)) {
$this->is_timeout = true;
return true;
}
$elapsed = microtime(true) - $start;
$this->curTimeout-= $elapsed;
}
$read = array($this->fsock);
$write = $except = null;
$start = microtime(true);
$sec = floor($this->curTimeout);
$usec = 1000000 * ($this->curTimeout - $sec);
// on windows this returns a "Warning: Invalid CRT parameters detected" error
if (!@stream_select($read, $write, $except, $sec, $usec) && !count($read)) {
$this->is_timeout = true;
return true;
$response = $this->_get_binary_packet(true);
if ($response === false) {
user_error('Connection closed by server');
return false;
}
$elapsed = microtime(true) - $start;
$this->curTimeout-= $elapsed;
}
$response = $this->_get_binary_packet();
if ($response === false) {
user_error('Connection closed by server');
return false;
}
if ($client_channel == -1 && $response === true) {
return true;
}
@ -3407,6 +3623,82 @@ class SSH2
$this->window_size_server_to_client[$channel]+= $this->window_size;
}
switch ($type) {
case NET_SSH2_MSG_CHANNEL_EXTENDED_DATA:
/*
if ($client_channel == NET_SSH2_CHANNEL_EXEC) {
$this->_send_channel_packet($client_channel, chr(0));
}
*/
// currently, there's only one possible value for $data_type_code: NET_SSH2_EXTENDED_DATA_STDERR
if (strlen($response) < 8) {
return false;
}
extract(unpack('Ndata_type_code/Nlength', $this->_string_shift($response, 8)));
$data = $this->_string_shift($response, $length);
$this->stdErrorLog.= $data;
if ($skip_extended || $this->quiet_mode) {
continue 2;
}
if ($client_channel == $channel && $this->channel_status[$channel] == NET_SSH2_MSG_CHANNEL_DATA) {
return $data;
}
if (!isset($this->channel_buffers[$channel])) {
$this->channel_buffers[$channel] = array();
}
$this->channel_buffers[$channel][] = $data;
continue 2;
case NET_SSH2_MSG_CHANNEL_REQUEST:
if ($this->channel_status[$channel] == NET_SSH2_MSG_CHANNEL_CLOSE) {
continue 2;
}
if (strlen($response) < 4) {
return false;
}
extract(unpack('Nlength', $this->_string_shift($response, 4)));
$value = $this->_string_shift($response, $length);
switch ($value) {
case 'exit-signal':
$this->_string_shift($response, 1);
if (strlen($response) < 4) {
return false;
}
extract(unpack('Nlength', $this->_string_shift($response, 4)));
$this->errors[] = 'SSH_MSG_CHANNEL_REQUEST (exit-signal): ' . $this->_string_shift($response, $length);
$this->_string_shift($response, 1);
if (strlen($response) < 4) {
return false;
}
extract(unpack('Nlength', $this->_string_shift($response, 4)));
if ($length) {
$this->errors[count($this->errors)].= "\r\n" . $this->_string_shift($response, $length);
}
$this->_send_binary_packet(pack('CN', NET_SSH2_MSG_CHANNEL_EOF, $this->server_channels[$client_channel]));
$this->_send_binary_packet(pack('CN', NET_SSH2_MSG_CHANNEL_CLOSE, $this->server_channels[$channel]));
$this->channel_status[$channel] = NET_SSH2_MSG_CHANNEL_EOF;
continue 3;
case 'exit-status':
if (strlen($response) < 5) {
return false;
}
extract(unpack('Cfalse/Nexit_status', $this->_string_shift($response, 5)));
$this->exit_status = $exit_status;
// "The client MAY ignore these messages."
// -- http://tools.ietf.org/html/rfc4254#section-6.10
continue 3;
default:
// "Some systems may not implement signals, in which case they SHOULD ignore this message."
// -- http://tools.ietf.org/html/rfc4254#section-6.9
continue 3;
}
}
switch ($this->channel_status[$channel]) {
case NET_SSH2_MSG_CHANNEL_OPEN:
switch ($type) {
@ -3489,76 +3781,6 @@ class SSH2
}
$this->channel_buffers[$channel][] = $data;
break;
case NET_SSH2_MSG_CHANNEL_EXTENDED_DATA:
/*
if ($client_channel == self::CHANNEL_EXEC) {
$this->_send_channel_packet($client_channel, chr(0));
}
*/
// currently, there's only one possible value for $data_type_code: NET_SSH2_EXTENDED_DATA_STDERR
if (strlen($response) < 8) {
return false;
}
extract(unpack('Ndata_type_code/Nlength', $this->_string_shift($response, 8)));
$data = $this->_string_shift($response, $length);
$this->stdErrorLog.= $data;
if ($skip_extended || $this->quiet_mode) {
break;
}
if ($client_channel == $channel) {
return $data;
}
if (!isset($this->channel_buffers[$channel])) {
$this->channel_buffers[$channel] = array();
}
$this->channel_buffers[$channel][] = $data;
break;
case NET_SSH2_MSG_CHANNEL_REQUEST:
if (strlen($response) < 4) {
return false;
}
extract(unpack('Nlength', $this->_string_shift($response, 4)));
$value = $this->_string_shift($response, $length);
switch ($value) {
case 'exit-signal':
$this->_string_shift($response, 1);
if (strlen($response) < 4) {
return false;
}
extract(unpack('Nlength', $this->_string_shift($response, 4)));
$this->errors[] = 'SSH_MSG_CHANNEL_REQUEST (exit-signal): ' . $this->_string_shift($response, $length);
$this->_string_shift($response, 1);
if (strlen($response) < 4) {
return false;
}
extract(unpack('Nlength', $this->_string_shift($response, 4)));
if ($length) {
$this->errors[count($this->errors)].= "\r\n" . $this->_string_shift($response, $length);
}
$this->_send_binary_packet(pack('CN', NET_SSH2_MSG_CHANNEL_EOF, $this->server_channels[$client_channel]));
$this->_send_binary_packet(pack('CN', NET_SSH2_MSG_CHANNEL_CLOSE, $this->server_channels[$channel]));
$this->channel_status[$channel] = NET_SSH2_MSG_CHANNEL_EOF;
break;
case 'exit-status':
if (strlen($response) < 5) {
return false;
}
extract(unpack('Cfalse/Nexit_status', $this->_string_shift($response, 5)));
$this->exit_status = $exit_status;
// "The client MAY ignore these messages."
// -- http://tools.ietf.org/html/rfc4254#section-6.10
break;
default:
// "Some systems may not implement signals, in which case they SHOULD ignore this message."
// -- http://tools.ietf.org/html/rfc4254#section-6.9
break;
}
break;
case NET_SSH2_MSG_CHANNEL_CLOSE:
$this->curTimeout = 0;

View File

@ -33,7 +33,7 @@
* POSSIBILITY OF SUCH DAMAGE.
*
* @package SimplePie
* @version 1.5
* @version 1.5.1
* @copyright 2004-2017 Ryan Parman, Geoffrey Sneddon, Ryan McCue
* @author Ryan Parman
* @author Geoffrey Sneddon
@ -50,7 +50,7 @@ define('SIMPLEPIE_NAME', 'SimplePie');
/**
* SimplePie Version
*/
define('SIMPLEPIE_VERSION', '1.5');
define('SIMPLEPIE_VERSION', '1.5.1');
/**
* SimplePie Build
@ -810,7 +810,7 @@ class SimplePie
}
/**
* Set the the default timeout for fetching remote feeds
* Set the default timeout for fetching remote feeds
*
* This allows you to change the maximum time the feed's server to respond
* and send the feed back.
@ -1320,6 +1320,11 @@ class SimplePie
}
}
// The default sanitize class gets set in the constructor, check if it has
// changed.
if ($this->registry->get_class('Sanitize') !== 'SimplePie_Sanitize') {
$this->sanitize = $this->registry->create('Sanitize');
}
if (method_exists($this->sanitize, 'set_registry'))
{
$this->sanitize->set_registry($this->registry);
@ -1644,33 +1649,18 @@ class SimplePie
try
{
$microformats = false;
if (function_exists('Mf2\parse')) {
if (class_exists('DOMXpath') && function_exists('Mf2\parse')) {
$doc = new DOMDocument();
@$doc->loadHTML($file->body);
$xpath = new DOMXpath($doc);
// Check for both h-feed and h-entry, as both a feed with no entries
// and a list of entries without an h-feed wrapper are both valid.
$position = 0;
while ($position = strpos($file->body, 'h-feed', $position))
{
$start = $position < 200 ? 0 : $position - 200;
$check = substr($file->body, $start, 400);
if ($microformats = preg_match('/class="[^"]*h-feed/', $check))
{
break;
}
$position += 7;
}
$position = 0;
while ($position = strpos($file->body, 'h-entry', $position))
{
$start = $position < 200 ? 0 : $position - 200;
$check = substr($file->body, $start, 400);
if ($microformats = preg_match('/class="[^"]*h-entry/', $check))
{
break;
}
$position += 7;
}
$query = '//*[contains(concat(" ", @class, " "), " h-feed ") or '.
'contains(concat(" ", @class, " "), " h-entry ")]';
$result = $xpath->query($query);
$microformats = $result->length !== 0;
}
// Now also do feed discovery, but if an h-entry was found don't
// Now also do feed discovery, but if microformats were found don't
// overwrite the current value of file.
$discovered = $locate->find($this->autodiscovery,
$this->all_discovered_feeds);
@ -2606,16 +2596,16 @@ class SimplePie
}
}
if (isset($this->data['links'][$rel]))
{
return $this->data['links'][$rel];
}
else if (isset($this->data['headers']['link']) &&
preg_match('/<([^>]+)>; rel='.preg_quote($rel).'/',
$this->data['headers']['link'], $match))
if (isset($this->data['headers']['link']) &&
preg_match('/<([^>]+)>; rel='.preg_quote($rel).'/',
$this->data['headers']['link'], $match))
{
return array($match[1]);
}
else if (isset($this->data['links'][$rel]))
{
return $this->data['links'][$rel];
}
else
{
return null;
@ -3155,7 +3145,7 @@ class SimplePie
if (($url = $this->get_link()) !== null)
{
return 'http://g.etfv.co/' . urlencode($url);
return 'https://www.google.com/s2/favicons?domain=' . urlencode($url);
}
return false;

View File

@ -136,8 +136,7 @@ class SimplePie_File
$this->url = $info['url'];
}
curl_close($fp);
$this->headers = explode("\r\n\r\n", $this->headers, $info['redirect_count'] + 1);
$this->headers = array_pop($this->headers);
$this->headers = SimplePie_HTTP_Parser::prepareHeaders($this->headers, $info['redirect_count'] + 1);
$parser = new SimplePie_HTTP_Parser($this->headers);
if ($parser->parse())
{

View File

@ -496,4 +496,25 @@ class SimplePie_HTTP_Parser
}
}
}
/**
* Prepare headers (take care of proxies headers)
*
* @param string $headers Raw headers
* @param integer $count Redirection count. Default to 1.
*
* @return string
*/
static public function prepareHeaders($headers, $count = 1)
{
$data = explode("\r\n\r\n", $headers, $count);
$data = array_pop($data);
if (false !== stripos($data, "HTTP/1.0 200 Connection established\r\n\r\n")) {
$data = str_ireplace("HTTP/1.0 200 Connection established\r\n\r\n", '', $data);
}
if (false !== stripos($data, "HTTP/1.1 200 Connection established\r\n\r\n")) {
$data = str_ireplace("HTTP/1.1 200 Connection established\r\n\r\n", '', $data);
}
return $data;
}
}

View File

@ -477,15 +477,15 @@ class SimplePie_Item
$label = null;
if (isset($category['attribs']['']['term']))
{
$term = $this->sanitize($category['attribs']['']['term'], SIMPLEPIE_CONSTRUCT_HTML);
$term = $this->sanitize($category['attribs']['']['term'], SIMPLEPIE_CONSTRUCT_TEXT);
}
if (isset($category['attribs']['']['scheme']))
{
$scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_HTML);
$scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
}
if (isset($category['attribs']['']['label']))
{
$label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_HTML);
$label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
}
$categories[] = $this->registry->create('Category', array($term, $scheme, $label, $type));
}
@ -493,10 +493,10 @@ class SimplePie_Item
{
// This is really the label, but keep this as the term also for BC.
// Label will also work on retrieving because that falls back to term.
$term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_HTML);
$term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
if (isset($category['attribs']['']['domain']))
{
$scheme = $this->sanitize($category['attribs']['']['domain'], SIMPLEPIE_CONSTRUCT_HTML);
$scheme = $this->sanitize($category['attribs']['']['domain'], SIMPLEPIE_CONSTRUCT_TEXT);
}
else
{
@ -508,11 +508,11 @@ class SimplePie_Item
$type = 'subject';
foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, $type) as $category)
{
$categories[] = $this->registry->create('Category', array($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_HTML), null, null, $type));
$categories[] = $this->registry->create('Category', array($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null, $type));
}
foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, $type) as $category)
{
$categories[] = $this->registry->create('Category', array($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_HTML), null, null, $type));
$categories[] = $this->registry->create('Category', array($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null, $type));
}
if (!empty($categories))
@ -649,7 +649,7 @@ class SimplePie_Item
$email = null;
if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
{
$name = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_HTML);
$name = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
}
if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
{
@ -657,7 +657,7 @@ class SimplePie_Item
}
if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
{
$email = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_HTML);
$email = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
}
if ($name !== null || $email !== null || $uri !== null)
{
@ -671,7 +671,7 @@ class SimplePie_Item
$email = null;
if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
{
$name = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_HTML);
$name = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
}
if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
{
@ -679,7 +679,7 @@ class SimplePie_Item
}
if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
{
$email = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_HTML);
$email = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
}
if ($name !== null || $email !== null || $url !== null)
{
@ -688,19 +688,19 @@ class SimplePie_Item
}
if ($author = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'author'))
{
$authors[] = $this->registry->create('Author', array(null, null, $this->sanitize($author[0]['data'], SIMPLEPIE_CONSTRUCT_HTML)));
$authors[] = $this->registry->create('Author', array(null, null, $this->sanitize($author[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT)));
}
foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'creator') as $author)
{
$authors[] = $this->registry->create('Author', array($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_HTML), null, null));
$authors[] = $this->registry->create('Author', array($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null));
}
foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'creator') as $author)
{
$authors[] = $this->registry->create('Author', array($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_HTML), null, null));
$authors[] = $this->registry->create('Author', array($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null));
}
foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'author') as $author)
{
$authors[] = $this->registry->create('Author', array($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_HTML), null, null));
$authors[] = $this->registry->create('Author', array($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null));
}
if (!empty($authors))

View File

@ -76,26 +76,17 @@ class SimplePie_Parser
public function parse(&$data, $encoding, $url = '')
{
if (function_exists('Mf2\parse')) {
if (class_exists('DOMXpath') && function_exists('Mf2\parse')) {
$doc = new DOMDocument();
@$doc->loadHTML($data);
$xpath = new DOMXpath($doc);
// Check for both h-feed and h-entry, as both a feed with no entries
// and a list of entries without an h-feed wrapper are both valid.
$position = 0;
while ($position = strpos($data, 'h-feed', $position)) {
$start = $position < 200 ? 0 : $position - 200;
$check = substr($data, $start, 400);
if (preg_match('/class="[^"]*h-feed/', $check)) {
return $this->parse_microformats($data, $url);
}
$position += 7;
}
$position = 0;
while ($position = strpos($data, 'h-entry', $position)) {
$start = $position < 200 ? 0 : $position - 200;
$check = substr($data, $start, 400);
if (preg_match('/class="[^"]*h-entry/', $check)) {
return $this->parse_microformats($data, $url);
}
$position += 7;
$query = '//*[contains(concat(" ", @class, " "), " h-feed ") or '.
'contains(concat(" ", @class, " "), " h-entry ")]';
$result = $xpath->query($query);
if ($result->length !== 0) {
return $this->parse_microformats($data, $url);
}
}
@ -465,7 +456,7 @@ class SimplePie_Parser
$h_feed = $mf_item;
break;
}
// Also look for an h-feed in the children of each top level item.
// Also look for h-feed or h-entry in the children of each top level item.
if (!isset($mf_item['children'][0]['type'])) continue;
if (in_array('h-feed', $mf_item['children'][0]['type'])) {
$h_feed = $mf_item['children'][0];
@ -474,6 +465,13 @@ class SimplePie_Parser
if (in_array('h-card', $mf_item['type'])) $feed_author = $mf_item;
break;
}
else if (in_array('h-entry', $mf_item['children'][0]['type'])) {
$entries = $mf_item['children'];
// In this case the parent of the h-entry list may be an h-card, so use
// it as the feed_author.
if (in_array('h-card', $mf_item['type'])) $feed_author = $mf_item;
break;
}
}
if (isset($h_feed['children'])) {
$entries = $h_feed['children'];
@ -485,7 +483,7 @@ class SimplePie_Parser
$feed_author = $mf['items'][0]['properties']['author'][0];
}
}
else {
else if (count($entries) === 0) {
$entries = $mf['items'];
}
for ($i = 0; $i < count($entries); $i++) {
@ -554,18 +552,21 @@ class SimplePie_Parser
$photo_list = array();
for ($j = 0; $j < count($entry['properties']['photo']); $j++) {
$photo = $entry['properties']['photo'][$j];
if (strpos($content, $photo) === false) {
if (!empty($photo) && strpos($content, $photo) === false) {
$photo_list[] = $photo;
}
}
// When there's more than one photo show the first and use a lightbox.
// Need a permanent, unique name for the image set, but don't have
// anything unique except for the content itself, so use that.
$count = count($photo_list);
if ($count > 1) {
$image_set_id = preg_replace('/[[:^alnum:]]/', '', $photo_list[0]);
$description = '<p>';
for ($j = 0; $j < $count; $j++) {
$hidden = $j === 0 ? '' : 'class="hidden" ';
$description .= '<a href="'.$photo_list[$j].'" '.$hidden.
'data-lightbox="image-set-'.$i.'">'.
'data-lightbox="image-set-'.$image_set_id.'">'.
'<img src="'.$photo_list[$j].'"></a>';
}
$description .= '<br><b>'.$count.' photos</b></p>';
@ -583,10 +584,18 @@ class SimplePie_Parser
$item['title'] = array(array('data' => $title));
}
$description .= $entry['properties']['content'][0]['html'];
if (isset($entry['properties']['in-reply-to'][0]['value'])) {
$in_reply_to = $entry['properties']['in-reply-to'][0]['value'];
$description .= '<p><span class="in-reply-to"></span> '.
'<a href="'.$in_reply_to.'">'.$in_reply_to.'</a><p>';
if (isset($entry['properties']['in-reply-to'][0])) {
$in_reply_to = '';
if (is_string($entry['properties']['in-reply-to'][0])) {
$in_reply_to = $entry['properties']['in-reply-to'][0];
}
else if (isset($entry['properties']['in-reply-to'][0]['value'])) {
$in_reply_to = $entry['properties']['in-reply-to'][0]['value'];
}
if ($in_reply_to !== '') {
$description .= '<p><span class="in-reply-to"></span> '.
'<a href="'.$in_reply_to.'">'.$in_reply_to.'</a><p>';
}
}
$item['description'] = array(array('data' => $description));
}
@ -627,7 +636,7 @@ class SimplePie_Parser
$image = array(array('child' => array('' => array('url' =>
array(array('data' => $feed_author['properties']['photo'][0]))))));
}
// Use the a name given for the h-feed, or get the title from the html.
// Use the name given for the h-feed, or get the title from the html.
if ($feed_title !== '') {
$feed_title = array(array('data' => htmlspecialchars($feed_title)));
}

View File

@ -65,7 +65,7 @@ The basic usage is simple:
- ``$options->setHelp()`` adds a general description
- ``$options->registerOption()`` adds an option
- ``$options->registerArgument()`` adds an argument
- ``$options->registerComman()`` adds a sub command
- ``$options->registerCommand()`` adds a sub command
- implement the ```main($options)``` method and do your business logic there
- ``$options->getOpts`` lets you access set options
- ``$options->getArgs()`` returns the remaining arguments after removing the options

View File

@ -56,6 +56,8 @@ abstract class CLI
*
* @param Options $options
* @return void
*
* @throws Exception
*/
abstract protected function setup(Options $options);
@ -66,6 +68,8 @@ abstract class CLI
*
* @param Options $options
* @return void
*
* @throws Exception
*/
abstract protected function main(Options $options);
@ -74,6 +78,8 @@ abstract class CLI
*
* Executes the setup() routine, adds default options, initiate the options parsing and argument checking
* and finally executes main()
*
* @throws Exception
*/
public function run()
{

View File

@ -99,9 +99,11 @@ class Colors
/**
* Convenience function to print a line in a given color
*
* @param string $line the line to print, a new line is added automatically
* @param string $color one of the available color names
* @param string $line the line to print, a new line is added automatically
* @param string $color one of the available color names
* @param resource $channel file descriptor to write to
*
* @throws Exception
*/
public function ptln($line, $color, $channel = STDOUT)
{
@ -158,6 +160,8 @@ class Colors
* reset the terminal color
*
* @param resource $channel file descriptor to write to
*
* @throws Exception
*/
public function reset($channel = STDOUT)
{

View File

@ -285,7 +285,7 @@ class Options
*
* @param mixed $option
* @param bool|string $default what to return if the option was not set
* @return bool|string
* @return bool|string|string[]
*/
public function getOpt($option = null, $default = false)
{
@ -325,6 +325,8 @@ class Options
* Builds a help screen from the available options. You may want to call it from -h or on error
*
* @return string
*
* @throws Exception
*/
public function help()
{

View File

@ -39,7 +39,7 @@ class TableFormatter
$width = @exec('tput cols');
}
if ($width) {
$this->max = $width;
$this->max = $width - 1;
}
if ($colors) {