1: <?php
2:
3: namespace ZCL\Captcha;
4:
5: /**
6: * Класс, реализующий простейшую капчу.
7: * Для использования собственной реализации класс нужно отнаследовать
8: * и переопределить методы OnCode и OnImage
9: * Пример использования http://examples.zippy.com.ua/Example4
10: */
11: class Captcha extends \Zippy\Html\HtmlComponent implements \Zippy\Interfaces\AjaxRender, \Zippy\Interfaces\Requestable
12: {
13:
14: private static $timeout = 120;
15: private $refresh;
16: protected $code;
17: protected $created;
18: public $x = 60;
19: public $y = 20;
20:
21: /**
22: * Конструктор
23: *
24: * @param mixed $id
25: * @param mixed $refresh если true генерится код для обновления через AJAX
26: * @return Captcha
27: */
28: public function __construct($id, $refresh = true) {
29: parent::__construct($id);
30: $this->refresh = $refresh;
31: $this->Refresh();
32: }
33:
34: /**
35: * Реализует алгоритм прорисовки изображения.
36: * Может быть перегружен для пользовательской реализации.
37: * @return ссылка на ресурс изображения
38: */
39: protected function OnImage() {
40: $im = imagecreate($this->x, $this->y);
41: $bg = imagecolorallocate($im, 200, 255, 200);
42: $textcolor = imagecolorallocate($im, rand(0, 255), rand(0, 200), rand(0, 255));
43:
44: imagestring($im, 5, 2, 2, $this->code, $textcolor);
45:
46: for ($i = 0; $i < 5; $i++) {
47: $color = imagecolorallocate($im, rand(0, 255), rand(0, 200), rand(0, 255));
48: imageline($im, rand(0, 10), rand(1, 20), rand(50, 80), rand(1, 50), $color);
49: }
50: ob_start();
51: imagepng($im);
52: $contents = ob_get_contents();
53: ob_end_clean();
54:
55: return $contents;
56: }
57:
58: /**
59: * Реализует алгоритм вычисление кода. Может быть перегружен для пользовательской реализации
60: * @return строка с кодом
61: */
62: protected function OnCode() {
63: $chars = 'abdefhknrstyz23456789';
64: $length = rand(4, 6);
65: $numChars = strlen($chars);
66: $str = '';
67: for ($i = 0; $i < $length; $i++) {
68: $str .= substr($chars, rand(1, $numChars) - 1, 1);
69: }
70: return $str;
71: }
72:
73: /**
74: * Проверка кода
75: *
76: */
77: public function checkCode($code) {
78: if ($this->created + self::$timeout < time()) {
79: return false;
80: }
81: return $this->code == $code;
82: }
83:
84: /**
85: * Обновление кода капчи
86: *
87: */
88: public function Refresh() {
89: $this->code = $this->OnCode();
90: $this->created = time();
91: }
92:
93:
94:
95: /**
96: * Обработчик HTTP запроса. Возвращает изображение в бинарный
97: * поток или ссылку для атрибута src при обновлении изображения
98: *
99: */
100: public function RequestHandle() {
101:
102: if (\Zippy\WebApplication::$app->getRequest()->isAjaxRequest()) {
103: $this->Refresh();
104: \Zippy\WebApplication::$app->getResponse()->addAjaxResponse($this->AjaxAnswer());
105: }
106: }
107:
108: /**
109: * @see HttpComponent
110: *
111: */
112: protected function RenderImpl() {
113:
114: $url = $this->owner->getURLNode() . "::" . $this->id . "&ajax=true";
115: if ($this->refresh) {
116: $this->setAttribute("onclick", "getUpdate('{$url}');event.returnValue=false; return false;");
117: }
118: $im = $this->OnImage();
119:
120: $src = "data:image/png;base64," . base64_encode($im);
121:
122: $this->setAttribute('src', $src);
123: }
124:
125: /**
126: * возвращает код для обновления атрибута src
127: *
128: */
129: public function AjaxAnswer() {
130: $im = $this->OnImage();
131:
132: $src = "data:image/png;base64," . base64_encode($im);
133: return "$('#{$this->id}').attr('src','{$src}')";
134: }
135:
136: /**
137: * Возвращает код капчи
138: * @return string
139: */
140: public function getCode() {
141: return $this->code;
142: }
143:
144: }
145:
146:
147: