| 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: | |