Skip to content

Commit 3fb1428

Browse files
Merge pull request #63 from julienloizelet/feature/62-gregwar-captcha-fix-for-php81
Feature/62 gregwar captcha fix for php81
2 parents 4c4f379 + adf3924 commit 3fb1428

File tree

4 files changed

+86
-7
lines changed

4 files changed

+86
-7
lines changed

examples/auto-prepend/scripts/bounce-via-auto-prepend.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
use CrowdSecBouncer\StandAloneBounce;
77

88
$bounce = new StandAloneBounce();
9-
$bounce->init($crowdSecStandaloneBouncerConfig);
109
$bounce->setDebug($crowdSecStandaloneBouncerConfig['debug_mode']);
10+
$bounce->setDisplayErrors($crowdSecStandaloneBouncerConfig['display_errors']);
11+
$bounce->init($crowdSecStandaloneBouncerConfig);
1112
$bounce->safelyBounce();

src/Bouncer.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
require_once __DIR__.'/templates/captcha.php';
66
require_once __DIR__.'/templates/access-forbidden.php';
77

8-
use Gregwar\Captcha\CaptchaBuilder;
8+
use CrowdSecBouncer\Fixes\Gregwar\Captcha\CaptchaBuilder;
99
use Gregwar\Captcha\PhraseBuilder;
1010
use IPLib\Factory;
1111
use Monolog\Handler\NullHandler;
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
<?php
2+
3+
4+
namespace CrowdSecBouncer\Fixes\Gregwar\Captcha;
5+
6+
use Gregwar\Captcha\CaptchaBuilder as GregwarCaptchaBuilder;
7+
8+
/**
9+
* Override to fix "implicit conversion error on PHP 8.1"
10+
* @see https://github.com/crowdsecurity/php-cs-bouncer/issues/62 and
11+
* @see https://github.com/Gregwar/Captcha/pull/101/files
12+
*
13+
*/
14+
class CaptchaBuilder extends GregwarCaptchaBuilder {
15+
16+
17+
/**
18+
* Writes the phrase on the image
19+
*/
20+
protected function writePhrase($image, $phrase, $font, $width, $height)
21+
{
22+
$length = mb_strlen($phrase);
23+
if ($length === 0) {
24+
return \imagecolorallocate($image, 0, 0, 0);
25+
}
26+
27+
// Gets the text size and start position
28+
$size = (int) round($width / $length) - $this->rand(0, 3) - 1;
29+
$box = \imagettfbbox($size, 0, $font, $phrase);
30+
$textWidth = $box[2] - $box[0];
31+
$textHeight = $box[1] - $box[7];
32+
$x = (int) round(($width - $textWidth) / 2);
33+
$y = (int) round(($height - $textHeight) / 2) + $size;
34+
35+
if (!$this->textColor) {
36+
$textColor = array($this->rand(0, 150), $this->rand(0, 150), $this->rand(0, 150));
37+
} else {
38+
$textColor = $this->textColor;
39+
}
40+
$col = \imagecolorallocate($image, $textColor[0], $textColor[1], $textColor[2]);
41+
42+
// Write the letters one by one, with random angle
43+
for ($i=0; $i<$length; $i++) {
44+
$symbol = mb_substr($phrase, $i, 1);
45+
$box = \imagettfbbox($size, 0, $font, $symbol);
46+
$w = $box[2] - $box[0];
47+
$angle = $this->rand(-$this->maxAngle, $this->maxAngle);
48+
$offset = $this->rand(-$this->maxOffset, $this->maxOffset);
49+
\imagettftext($image, $size, $angle, $x, $y + $offset, $col, $font, $symbol);
50+
$x += $w;
51+
}
52+
53+
return $col;
54+
}
55+
56+
57+
/**
58+
* Returns a random number or the next number in the
59+
* fingerprint
60+
*/
61+
protected function rand($min, $max)
62+
{
63+
if (!is_array($this->fingerprint)) {
64+
$this->fingerprint = array();
65+
}
66+
67+
if ($this->useFingerprint) {
68+
$value = current($this->fingerprint);
69+
next($this->fingerprint);
70+
} else {
71+
$value = mt_rand((int) $min, (int) $max);
72+
$this->fingerprint[] = $value;
73+
}
74+
75+
return $value;
76+
}
77+
78+
}

src/StandAloneBounce.php

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ public function getBouncerInstance(): Bouncer
121121
$maxRemediationLevel = Constants::REMEDIATION_BAN;
122122
break;
123123
default:
124-
throw new Exception("Unknown $bouncingLevel");
124+
throw new BouncerException("Unknown $bouncingLevel");
125125
}
126126

127127
// Instanciate the bouncer
@@ -343,7 +343,7 @@ public function sendResponse(?string $body, int $statusCode = 200): void
343343
header('Pragma: no-cache');
344344
break;
345345
default:
346-
throw new Exception("Unhandled code ${statusCode}");
346+
throw new BouncerException("Unhandled code $statusCode");
347347
}
348348
if (null !== $body) {
349349
echo $body;
@@ -353,10 +353,10 @@ public function sendResponse(?string $body, int $statusCode = 200): void
353353

354354
public function safelyBounce(): void
355355
{
356-
// If there is any technical problem while bouncing, don't block the user. Bypass boucing and log the error.
356+
// If there is any technical problem while bouncing, don't block the user. Bypass bouncing and log the error.
357357
try {
358-
set_error_handler(function ($errno, $errstr, $errfile, $errline) {
359-
throw new BouncerException($errstr, $errno, 0, $errfile, $errline);
358+
set_error_handler(function ($errno, $errstr) {
359+
throw new BouncerException("$errstr (Error level: $errno)");
360360
});
361361
$this->run();
362362
restore_error_handler();

0 commit comments

Comments
 (0)