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