Skip to content

Commit 5efb9e3

Browse files
fix: resolve PHP 7.4 and below compatibility issues
- Added checks to prevent duplicate class alias declarations - Replaced all BigInteger references with fully qualified class names (\bcmath_compat\BigInteger) - Removed problematic 'use' statement that doesn't work with dynamic aliases in older PHP - Created custom autoloader for environments without Composer - Fixed namespace handling for both phpseclib 2.x and 3.x These changes ensure compatibility with PHP 5.4-7.4 while maintaining functionality for PHP 8.x Co-authored-by: nanasess <nanasess@users.noreply.github.com>
1 parent 22b0488 commit 5efb9e3

2 files changed

Lines changed: 91 additions & 17 deletions

File tree

autoload.php

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
<?php
2+
/**
3+
* Simple autoloader for PHP 5.4+ without Composer
4+
*/
5+
6+
// Register autoloader
7+
spl_autoload_register(function ($class) {
8+
// Check if this is a bcmath_compat class
9+
if (strpos($class, 'bcmath_compat\\') === 0) {
10+
$file = __DIR__ . '/src/' . str_replace('bcmath_compat\\', '', $class) . '.php';
11+
if (file_exists($file)) {
12+
require_once $file;
13+
}
14+
}
15+
});
16+
17+
// Check if bcmath extension is loaded
18+
if (!extension_loaded('bcmath')) {
19+
// Load our bcmath polyfill
20+
require_once __DIR__ . '/lib/bcmath.php';
21+
}
22+
23+
// Try to load phpseclib
24+
// First check if we have composer autoloader
25+
if (file_exists(__DIR__ . '/vendor/autoload.php')) {
26+
// Already loaded by test runner, do nothing
27+
}
28+
// Try phpseclib 3.x structure
29+
elseif (file_exists(__DIR__ . '/vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger.php')) {
30+
require_once __DIR__ . '/vendor/phpseclib/phpseclib/phpseclib/bootstrap.php';
31+
}
32+
// Try phpseclib 2.x structure
33+
elseif (file_exists(__DIR__ . '/vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger.php')) {
34+
// phpseclib 2.x - set up include path
35+
$phpseclibPath = __DIR__ . '/vendor/phpseclib/phpseclib/phpseclib';
36+
set_include_path(get_include_path() . PATH_SEPARATOR . $phpseclibPath);
37+
38+
// Load required files for phpseclib 2.x
39+
require_once $phpseclibPath . '/Math/BigInteger.php';
40+
}
41+
// Fallback to direct file inclusion for installed packages
42+
else {
43+
// Look for composer vendor directory
44+
$vendorDir = __DIR__ . '/vendor';
45+
if (is_dir($vendorDir)) {
46+
// Try to find phpseclib in vendor
47+
$iterator = new RecursiveIteratorIterator(
48+
new RecursiveDirectoryIterator($vendorDir),
49+
RecursiveIteratorIterator::SELF_FIRST
50+
);
51+
52+
foreach ($iterator as $file) {
53+
if ($file->isFile() && $file->getFilename() === 'BigInteger.php') {
54+
$path = $file->getPath();
55+
if (strpos($path, 'phpseclib') !== false && strpos($path, 'Math') !== false) {
56+
$basePath = dirname(dirname($path));
57+
set_include_path(get_include_path() . PATH_SEPARATOR . $basePath);
58+
59+
// Register autoloader for this path
60+
spl_autoload_register(function ($class) use ($basePath) {
61+
$file = $basePath . '/' . str_replace('\\', '/', $class) . '.php';
62+
if (file_exists($file)) {
63+
require_once $file;
64+
}
65+
});
66+
break;
67+
}
68+
}
69+
}
70+
}
71+
}

src/BCMath.php

Lines changed: 20 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -12,19 +12,22 @@
1212

1313
namespace bcmath_compat;
1414

15+
// For PHP < 7.0, we need to handle class_alias differently
1516
// Check phpseclib version and use appropriate namespace
1617
if (class_exists('\phpseclib3\Math\BigInteger')) {
1718
// phpseclib 3.x
18-
class_alias('\phpseclib3\Math\BigInteger', '\bcmath_compat\BigInteger');
19+
if (!class_exists('\bcmath_compat\BigInteger')) {
20+
class_alias('\phpseclib3\Math\BigInteger', '\bcmath_compat\BigInteger');
21+
}
1922
} elseif (class_exists('\phpseclib\Math\BigInteger')) {
2023
// phpseclib 2.x
21-
class_alias('\phpseclib\Math\BigInteger', '\bcmath_compat\BigInteger');
24+
if (!class_exists('\bcmath_compat\BigInteger')) {
25+
class_alias('\phpseclib\Math\BigInteger', '\bcmath_compat\BigInteger');
26+
}
2227
} else {
2328
throw new \RuntimeException('phpseclib is not installed');
2429
}
2530

26-
use bcmath_compat\BigInteger;
27-
2831
/**
2932
* BCMath Emulation Class
3033
*
@@ -92,7 +95,7 @@ private static function format($x, $scale, $pad)
9295
*/
9396
private static function isNegative($x)
9497
{
95-
return $x->compare(new BigInteger()) < 0;
98+
return $x->compare(new \bcmath_compat\BigInteger()) < 0;
9699
}
97100

98101
/**
@@ -171,7 +174,7 @@ private static function div($x, $y, $scale, $pad)
171174
}
172175

173176
$temp = '1' . str_repeat('0', $scale);
174-
$temp = new BigInteger($temp);
177+
$temp = new \bcmath_compat\BigInteger($temp);
175178
list($q) = $x->multiply($temp)->divide($y);
176179

177180
return self::format($q, $scale, $scale);
@@ -217,8 +220,8 @@ private static function mod($x, $y, $scale, $pad)
217220
*/
218221
private static function comp($x, $y, $scale, $pad)
219222
{
220-
$x = new BigInteger($x[0] . substr($x[1], 0, $scale));
221-
$y = new BigInteger($y[0] . substr($y[1], 0, $scale));
223+
$x = new \bcmath_compat\BigInteger($x[0] . substr($x[1], 0, $scale));
224+
$y = new \bcmath_compat\BigInteger($y[0] . substr($y[1], 0, $scale));
222225

223226
return $x->compare($y);
224227
}
@@ -244,9 +247,9 @@ private static function pow($x, $y, $scale, $pad)
244247
}
245248

246249
$min = defined('PHP_INT_MIN') ? PHP_INT_MIN : ~PHP_INT_MAX;
247-
$y_big = new BigInteger($y);
248-
$max_big = new BigInteger(PHP_INT_MAX);
249-
$min_big = new BigInteger($min);
250+
$y_big = new \bcmath_compat\BigInteger($y);
251+
$max_big = new \bcmath_compat\BigInteger(PHP_INT_MAX);
252+
$min_big = new \bcmath_compat\BigInteger($min);
250253
if ($y_big->compare($max_big) > 0 || $y_big->compare($min_big) <= 0) {
251254
if (class_exists('\ValueError')) {
252255
throw new \ValueError('bcpow(): Argument #2 ($exponent) is too large');
@@ -259,15 +262,15 @@ private static function pow($x, $y, $scale, $pad)
259262
$sign = self::isNegative($x) ? '-' : '';
260263
$x = $x->abs();
261264

262-
$r = new BigInteger(1);
265+
$r = new \bcmath_compat\BigInteger(1);
263266

264267
for ($i = 0; $i < abs($y); $i++) {
265268
$r = $r->multiply($x);
266269
}
267270

268271
if ($y < 0) {
269272
$temp = '1' . str_repeat('0', $scale + $pad * abs($y));
270-
$temp = new BigInteger($temp);
273+
$temp = new \bcmath_compat\BigInteger($temp);
271274
list($r) = $temp->divide($r);
272275
$pad = $scale;
273276
} else {
@@ -306,9 +309,9 @@ private static function powmod($x, $e, $n, $scale, $pad)
306309
'1';
307310
}
308311

309-
$x = new BigInteger($x);
310-
$e = new BigInteger($e);
311-
$n = new BigInteger($n);
312+
$x = new \bcmath_compat\BigInteger($x);
313+
$e = new \bcmath_compat\BigInteger($e);
314+
$n = new \bcmath_compat\BigInteger($n);
312315

313316
$z = $x->powMod($e, $n);
314317

@@ -532,7 +535,7 @@ public static function __callStatic($name, $arguments)
532535
$num[1] = '';
533536
}
534537
$num[1] = str_pad($num[1], $pad, '0');
535-
$num = new BigInteger($num[0] . $num[1]);
538+
$num = new \bcmath_compat\BigInteger($num[0] . $num[1]);
536539
}
537540
break;
538541
case 'comp':

0 commit comments

Comments
 (0)