BasicCaptcha.php 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. <?php
  2. namespace Grav\Plugin\Form;
  3. use GdImage;
  4. use Grav\Common\Grav;
  5. class BasicCaptcha
  6. {
  7. protected $session = null;
  8. protected $key = 'basic_captcha_code';
  9. public function __construct()
  10. {
  11. $this->session = Grav::instance()['session'];
  12. }
  13. public function getCaptchaCode($length = null): string
  14. {
  15. $config = Grav::instance()['config']->get('plugins.form.basic_captcha');
  16. $type = $config['type'] ?? 'characters';
  17. if ($type == 'math') {
  18. $min = $config['math']['min'] ?? 1;
  19. $max = $config['math']['max'] ?? 12;
  20. $operators = $config['math']['operators'] ?? ['+','-','*'];
  21. $first_num = random_int($min, $max);
  22. $second_num = random_int($min, $max);
  23. $operator = $operators[array_rand($operators)];
  24. // calculator
  25. if ($operator === '-') {
  26. if ($first_num < $second_num) {
  27. $result = "$second_num - $first_num";
  28. $captcha_code = $second_num - $first_num;
  29. } else {
  30. $result = "$first_num-$second_num";
  31. $captcha_code = $first_num - $second_num;
  32. }
  33. } elseif ($operator === '*') {
  34. $result = "{$first_num} x {$second_num}";
  35. $captcha_code = $first_num * $second_num;
  36. } elseif ($operator === '/') {
  37. $result = "$first_num / second_num";
  38. $captcha_code = $first_num / $second_num;
  39. } elseif ($operator === '+') {
  40. $result = "$first_num + $second_num";
  41. $captcha_code = $first_num + $second_num;
  42. }
  43. } else {
  44. if ($length === null) {
  45. $length = $config['chars']['length'] ?? 6;
  46. }
  47. $random_alpha = md5(random_bytes(64));
  48. $captcha_code = substr($random_alpha, 0, $length);
  49. $result = $captcha_code;
  50. }
  51. $this->setSession($this->key, $captcha_code);
  52. return $result;
  53. }
  54. public function setSession($key, $value): void
  55. {
  56. $this->session->$key = $value;
  57. }
  58. public function getSession($key = null): ?string
  59. {
  60. if ($key === null) {
  61. $key = $this->key;
  62. }
  63. return $this->session->$key ?? null;
  64. }
  65. public function createCaptchaImage($captcha_code)
  66. {
  67. $config = Grav::instance()['config']->get('plugins.form.basic_captcha');
  68. $font = $config['chars']['font'] ?? 'zxx-xed.ttf';
  69. $target_layer = imagecreatetruecolor($config['chars']['box_width'], $config['chars']['box_height']);
  70. $bg = $this->hexToRgb($config['chars']['bg'] ?? '#ffffff');
  71. $text = $this->hexToRgb($config['chars']['text'] ?? '#000000');
  72. $captcha_background = imagecolorallocate($target_layer, $bg[0], $bg[1], $bg[2]);
  73. $captcha_text_color = imagecolorallocate($target_layer, $text[0], $text[1], $text[2]);
  74. $font_path = __DIR__ . '/../fonts/' . $font;
  75. imagefill($target_layer, 0, 0, $captcha_background);
  76. imagefttext($target_layer, $config['chars']['size'], 0, $config['chars']['start_x'], $config['chars']['start_y'], $captcha_text_color, $font_path, $captcha_code);
  77. return $target_layer;
  78. }
  79. public function renderCaptchaImage($imageData): void
  80. {
  81. header("Content-type: image/jpeg");
  82. imagejpeg($imageData);
  83. }
  84. public function validateCaptcha($formData): bool
  85. {
  86. $isValid = false;
  87. $capchaSessionData = $this->getSession();
  88. if ($capchaSessionData == $formData) {
  89. $isValid = true;
  90. }
  91. return $isValid;
  92. }
  93. private function hexToRgb($hex): array
  94. {
  95. return sscanf($hex, "#%02x%02x%02x");
  96. }
  97. }