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