1: | <?php
|
2: | |
3: | |
4: | |
5: | |
6: | |
7: | |
8: | |
9: | |
10: | |
11: | |
12: | |
13: | |
14: | |
15: | |
16: | |
17: | |
18: |
|
19: |
|
20: | include __DIR__ . '/../../../../mainfile.php';
|
21: |
|
22: | error_reporting(0);
|
23: | $xoopsLogger->activated = false;
|
24: |
|
25: | |
26: | |
27: |
|
28: | class XoopsCaptchaImageHandler
|
29: | {
|
30: | public $config = array();
|
31: | public $code;
|
32: | public $mode = 'gd';
|
33: | public $invalid = false;
|
34: |
|
35: | public $oImage;
|
36: | public $font;
|
37: | public $spacing;
|
38: | public $width;
|
39: | public $height;
|
40: |
|
41: | public $captchaHandler;
|
42: |
|
43: | |
44: | |
45: |
|
46: | public function __construct()
|
47: | {
|
48: | xoops_load('XoopsCaptcha');
|
49: | $this->captchaHandler = XoopsCaptcha::getInstance();
|
50: | $this->config = $this->captchaHandler->loadConfig('image');
|
51: | }
|
52: |
|
53: | public function loadImage()
|
54: | {
|
55: | $this->generateCode();
|
56: | $this->createImage();
|
57: | }
|
58: |
|
59: | |
60: | |
61: |
|
62: | public function generateCode()
|
63: | {
|
64: | if ($this->invalid) {
|
65: | return false;
|
66: | }
|
67: |
|
68: | if ($this->mode === 'bmp') {
|
69: | $this->config['num_chars'] = 4;
|
70: | $this->code = mt_rand(pow(10, $this->config['num_chars'] - 1), (int)str_pad('9', $this->config['num_chars'], '9'));
|
71: | } else {
|
72: | $raw_code = md5(uniqid(mt_rand(), 1));
|
73: | if (!empty($this->config['skip_characters'])) {
|
74: | $valid_code = str_replace($this->config['skip_characters'], '', $raw_code);
|
75: | $this->code = substr($valid_code, 0, $this->config['num_chars']);
|
76: | } else {
|
77: | $this->code = substr($raw_code, 0, $this->config['num_chars']);
|
78: | }
|
79: | if (!$this->config['casesensitive']) {
|
80: | $this->code = strtoupper($this->code);
|
81: | }
|
82: | }
|
83: | $this->captchaHandler->setCode($this->code);
|
84: |
|
85: | return true;
|
86: | }
|
87: |
|
88: | |
89: | |
90: |
|
91: | public function createImage()
|
92: | {
|
93: | if ($this->invalid) {
|
94: | header('Content-type: image/gif');
|
95: | readfile(XOOPS_ROOT_PATH . '/images/subject/icon2.gif');
|
96: |
|
97: | return null;
|
98: | }
|
99: |
|
100: | if ($this->mode === 'bmp') {
|
101: | return $this->createImageBmp();
|
102: | } else {
|
103: | return $this->createImageGd();
|
104: | }
|
105: | }
|
106: |
|
107: | |
108: | |
109: | |
110: | |
111: | |
112: |
|
113: | public function getList($name, $extension = '')
|
114: | {
|
115: | xoops_load('XoopsCache');
|
116: | if ($items = XoopsCache::read("captcha_captcha_{$name}")) {
|
117: | return $items;
|
118: | }
|
119: |
|
120: | require_once XOOPS_ROOT_PATH . '/class/xoopslists.php';
|
121: | $file_path = XOOPS_ROOT_PATH . "/class/captcha/image/{$name}";
|
122: | $files = XoopsLists::getFileListAsArray($file_path);
|
123: | $items = array();
|
124: | foreach ($files as $item) {
|
125: | if (empty($extension) || preg_match("/(\.{$extension})$/i", $item)) {
|
126: | $items[] = $item;
|
127: | }
|
128: | }
|
129: | XoopsCache::write("captcha_captcha_{$name}", $items);
|
130: |
|
131: | return $items;
|
132: | }
|
133: |
|
134: | |
135: | |
136: | |
137: | |
138: | |
139: | |
140: | |
141: | |
142: | |
143: | |
144: |
|
145: | public function createImageGd()
|
146: | {
|
147: | $this->loadFont();
|
148: | $this->setImageSize();
|
149: |
|
150: | $this->oImage = imagecreatetruecolor((int)$this->width, (int)$this->height);
|
151: | $background = imagecolorallocate($this->oImage, 255, 255, 255);
|
152: | imagefilledrectangle($this->oImage, 0, 0, (int)$this->width, (int)$this->height, $background);
|
153: |
|
154: | switch ($this->config['background_type']) {
|
155: | default:
|
156: | case 0:
|
157: | $this->drawBars();
|
158: | break;
|
159: |
|
160: | case 1:
|
161: | $this->drawCircles();
|
162: | break;
|
163: |
|
164: | case 2:
|
165: | $this->drawLines();
|
166: | break;
|
167: |
|
168: | case 3:
|
169: | $this->drawRectangles();
|
170: | break;
|
171: |
|
172: | case 4:
|
173: | $this->drawEllipses();
|
174: | break;
|
175: |
|
176: | case 5:
|
177: | $this->drawPolygons();
|
178: | break;
|
179: |
|
180: | case 100:
|
181: | $this->createFromFile();
|
182: | break;
|
183: | }
|
184: | $this->drawBorder();
|
185: | $this->drawCode();
|
186: |
|
187: | header('Content-type: image/jpeg');
|
188: | if (!imagejpeg($this->oImage)) {
|
189: |
|
190: | return false;
|
191: | }
|
192: |
|
193: | if (!imagedestroy($this->oImage)) {
|
194: |
|
195: | return false;
|
196: | }
|
197: |
|
198: | return true;
|
199: | }
|
200: |
|
201: | public function loadFont()
|
202: | {
|
203: | $fonts = $this->getList('fonts', 'ttf');
|
204: | $this->font = XOOPS_ROOT_PATH . '/class/captcha/image/fonts/' . $fonts[array_rand($fonts)];
|
205: | }
|
206: |
|
207: | public function setImageSize()
|
208: | {
|
209: | $MaxCharWidth = 0;
|
210: | $MaxCharHeight = 0;
|
211: | $oImage = imagecreatetruecolor(100, 100);
|
212: | $text_color = imagecolorallocate($oImage, mt_rand(0, 100), mt_rand(0, 100), mt_rand(0, 100));
|
213: | $FontSize = $this->config['fontsize_max'];
|
214: | for ($Angle = -30; $Angle <= 30; ++$Angle) {
|
215: | for ($i = 65; $i <= 90; ++$i) {
|
216: | $CharDetails = imageftbbox($FontSize, $Angle, $this->font, chr($i), array());
|
217: | $_MaxCharWidth = abs($CharDetails[0] + $CharDetails[2]);
|
218: | if ($_MaxCharWidth > $MaxCharWidth) {
|
219: | $MaxCharWidth = $_MaxCharWidth;
|
220: | }
|
221: | $_MaxCharHeight = abs($CharDetails[1] + $CharDetails[5]);
|
222: | if ($_MaxCharHeight > $MaxCharHeight) {
|
223: | $MaxCharHeight = $_MaxCharHeight;
|
224: | }
|
225: | }
|
226: | }
|
227: | imagedestroy($oImage);
|
228: |
|
229: | $this->height = $MaxCharHeight + 2;
|
230: | $this->spacing = (int)(($this->config['num_chars'] * $MaxCharWidth) / $this->config['num_chars']);
|
231: | $this->width = ($this->config['num_chars'] * $MaxCharWidth) + ($this->spacing / 2);
|
232: | }
|
233: |
|
234: | |
235: | |
236: | |
237: | |
238: |
|
239: | public function loadBackground()
|
240: | {
|
241: | $RandBackground = null;
|
242: | if ($backgrounds = $this->getList('backgrounds', '(gif|jpg|png)')) {
|
243: | $RandBackground = XOOPS_ROOT_PATH . '/class/captcha/image/backgrounds/' . $backgrounds[array_rand($backgrounds)];
|
244: | }
|
245: |
|
246: | return $RandBackground;
|
247: | }
|
248: |
|
249: | |
250: | |
251: |
|
252: | public function createFromFile()
|
253: | {
|
254: | if ($RandImage = $this->loadBackground()) {
|
255: | $ImageType = @getimagesize($RandImage);
|
256: | if (isset($ImageType[2])) {
|
257: | switch ($ImageType[2]) {
|
258: | case 1:
|
259: | $BackgroundImage = imagecreatefromgif($RandImage);
|
260: | break;
|
261: |
|
262: | case 2:
|
263: | $BackgroundImage = imagecreatefromjpeg($RandImage);
|
264: | break;
|
265: |
|
266: | case 3:
|
267: | $BackgroundImage = imagecreatefrompng($RandImage);
|
268: | break;
|
269: | }
|
270: | }
|
271: | }
|
272: | if (!empty($BackgroundImage)) {
|
273: | imagecopyresized($this->oImage, $BackgroundImage, 0, 0, 0, 0, imagesx($this->oImage), imagesy($this->oImage), imagesx($BackgroundImage), imagesy($BackgroundImage));
|
274: | imagedestroy($BackgroundImage);
|
275: | } else {
|
276: | $this->drawBars();
|
277: | }
|
278: | }
|
279: |
|
280: | |
281: | |
282: |
|
283: | public function drawCode()
|
284: | {
|
285: | for ($i = 0; $i < $this->config['num_chars']; ++$i) {
|
286: |
|
287: | $text_color = imagecolorallocate($this->oImage, mt_rand(0, 100), mt_rand(0, 100), mt_rand(0, 100));
|
288: |
|
289: |
|
290: | $Angle = mt_rand(10, 30);
|
291: | if ($i % 2) {
|
292: | $Angle = mt_rand(-30, -10);
|
293: | }
|
294: |
|
295: |
|
296: | $FontSize = mt_rand($this->config['fontsize_min'], $this->config['fontsize_max']);
|
297: |
|
298: | $CharDetails = imageftbbox($FontSize, $Angle, $this->font, $this->code[$i], array());
|
299: | $CharHeight = abs($CharDetails[1] + $CharDetails[5]);
|
300: |
|
301: |
|
302: | $posX = ($this->spacing / 2) + ($i * $this->spacing);
|
303: | $posY = 2 + ($this->height / 2) + ($CharHeight / 4);
|
304: |
|
305: | imagefttext($this->oImage, $FontSize, $Angle, (int)$posX, (int)$posY, $text_color, $this->font, $this->code[$i], array());
|
306: | }
|
307: | }
|
308: |
|
309: | |
310: | |
311: |
|
312: | public function drawBorder()
|
313: | {
|
314: | $rgb = mt_rand(50, 150);
|
315: | $border_color = imagecolorallocate($this->oImage, $rgb, $rgb, $rgb);
|
316: | imagerectangle($this->oImage, 0, 0, $this->width - 1, $this->height - 1, $border_color);
|
317: | }
|
318: |
|
319: | |
320: | |
321: |
|
322: | public function drawCircles()
|
323: | {
|
324: | for ($i = 1; $i <= $this->config['background_num']; ++$i) {
|
325: | $randomcolor = imagecolorallocate($this->oImage, mt_rand(190, 255), mt_rand(190, 255), mt_rand(190, 255));
|
326: | imagefilledellipse($this->oImage, mt_rand(0, $this->width - 10), mt_rand(0, $this->height - 3), mt_rand(10, 20), mt_rand(20, 30), $randomcolor);
|
327: | }
|
328: | }
|
329: |
|
330: | |
331: | |
332: |
|
333: | public function drawLines()
|
334: | {
|
335: | for ($i = 0; $i < $this->config['background_num']; ++$i) {
|
336: | $randomcolor = imagecolorallocate($this->oImage, mt_rand(190, 255), mt_rand(190, 255), mt_rand(190, 255));
|
337: | imageline($this->oImage, mt_rand(0, $this->width), mt_rand(0, $this->height), mt_rand(0, $this->width), mt_rand(0, $this->height), $randomcolor);
|
338: | }
|
339: | }
|
340: |
|
341: | |
342: | |
343: |
|
344: | public function drawRectangles()
|
345: | {
|
346: | for ($i = 1; $i <= $this->config['background_num']; ++$i) {
|
347: | $randomcolor = imagecolorallocate($this->oImage, mt_rand(190, 255), mt_rand(190, 255), mt_rand(190, 255));
|
348: | imagefilledrectangle($this->oImage, mt_rand(0, $this->width), mt_rand(0, $this->height), mt_rand(0, $this->width), mt_rand(0, $this->height), $randomcolor);
|
349: | }
|
350: | }
|
351: |
|
352: | |
353: | |
354: |
|
355: | public function drawBars()
|
356: | {
|
357: | for ($i = 0; $i <= $this->height;) {
|
358: | $randomcolor = imagecolorallocate($this->oImage, mt_rand(190, 255), mt_rand(190, 255), mt_rand(190, 255));
|
359: | imageline($this->oImage, 0, (int)$i, (int)$this->width, (int)$i, (int)$randomcolor);
|
360: | $i += 2.5;
|
361: | }
|
362: | for ($i = 0; $i <= $this->width;) {
|
363: | $randomcolor = imagecolorallocate($this->oImage, mt_rand(190, 255), mt_rand(190, 255), mt_rand(190, 255));
|
364: | imageline($this->oImage, (int)$i, 0, (int)$i, (int)$this->height, (int)$randomcolor);
|
365: | $i += 2.5;
|
366: | }
|
367: | }
|
368: |
|
369: | |
370: | |
371: |
|
372: | public function drawEllipses()
|
373: | {
|
374: | for ($i = 1; $i <= $this->config['background_num']; ++$i) {
|
375: | $randomcolor = imagecolorallocate($this->oImage, mt_rand(190, 255), mt_rand(190, 255), mt_rand(190, 255));
|
376: | imageellipse($this->oImage, mt_rand(0, $this->width), mt_rand(0, $this->height), mt_rand(0, $this->width), mt_rand(0, $this->height), $randomcolor);
|
377: | }
|
378: | }
|
379: |
|
380: | |
381: | |
382: |
|
383: | public function drawPolygons()
|
384: | {
|
385: | for ($i = 1; $i <= $this->config['background_num']; ++$i) {
|
386: | $randomcolor = imagecolorallocate($this->oImage, mt_rand(190, 255), mt_rand(190, 255), mt_rand(190, 255));
|
387: | $coords = array();
|
388: | for ($j = 1; $j <= $this->config['polygon_point']; ++$j) {
|
389: | $coords[] = mt_rand(0, $this->width);
|
390: | $coords[] = mt_rand(0, $this->height);
|
391: | }
|
392: | imagefilledpolygon($this->oImage, $coords, $this->config['polygon_point'], $randomcolor);
|
393: | }
|
394: | }
|
395: |
|
396: |
|
397: | |
398: | |
399: | |
400: | |
401: | |
402: | |
403: |
|
404: | public function createImageBmp($file = '')
|
405: | {
|
406: | $image = '';
|
407: |
|
408: | if (empty($file)) {
|
409: | header('Content-type: image/bmp');
|
410: | echo $image;
|
411: | } else {
|
412: | return $image;
|
413: | }
|
414: | return null;
|
415: | }
|
416: | }
|
417: |
|
418: | $imageHandler = new XoopsCaptchaImageHandler();
|
419: | $imageHandler->loadImage();
|
420: | |