[44] | 1 | <?php
|
---|
| 2 |
|
---|
| 3 | /*
|
---|
| 4 | * This class is taken in part from the Code of
|
---|
| 5 | * PhpCaptcha CAPTCHA generation library from Edward Eliot.
|
---|
| 6 | * class defaults - change to effect globally
|
---|
| 7 | */
|
---|
| 8 | session_start();
|
---|
| 9 | define('CAPCC_WIDTH', 120); // max 500
|
---|
| 10 | define('CAPCC_HEIGHT', 50); // max 200
|
---|
| 11 | define('CAPCC_NUM_CHARS', 4);
|
---|
| 12 | define('CAPCC_NUM_LINES', 20);
|
---|
| 13 | define('CAPCC_CHAR_SHADOW', false);
|
---|
| 14 | define('CAPCC_CHAR_SET', ''); // defaults to A-Z
|
---|
| 15 | define('CAPCC_CASE_INSENSITIVE', true);
|
---|
| 16 | define('CAPCC_BACKGROUND_IMAGES', '');
|
---|
| 17 | define('CAPCC_MIN_FONT_SIZE', 12);
|
---|
| 18 | define('CAPCC_MAX_FONT_SIZE', 20);
|
---|
| 19 | define('CAPCC_USE_COLOUR', true);
|
---|
| 20 | define('CAPCC_FILE_TYPE', 'png');
|
---|
| 21 |
|
---|
| 22 | /************************ End Default Options **********************/
|
---|
| 23 |
|
---|
| 24 | // don't edit below this line (unless you want to change the class!)
|
---|
| 25 |
|
---|
| 26 | class _odl_captcha {
|
---|
| 27 | var $oImage;
|
---|
| 28 | var $iWidth = CAPCC_WIDTH;
|
---|
| 29 | var $iHeight = CAPCC_HEIGHT;
|
---|
| 30 | var $aFonts;
|
---|
| 31 | var $iNumChars;
|
---|
| 32 | var $iNumLines;
|
---|
| 33 | var $iSpacing;
|
---|
| 34 | var $bCharShadow;
|
---|
| 35 | var $aCharSet;
|
---|
| 36 | var $bCaseInsensitive;
|
---|
| 37 | var $vBackgroundImages;
|
---|
| 38 | var $iMinFontSize;
|
---|
| 39 | var $iMaxFontSize;
|
---|
| 40 | var $bUseColour;
|
---|
| 41 | var $sFileType;
|
---|
| 42 | var $sCode = '';
|
---|
| 43 |
|
---|
| 44 |
|
---|
| 45 | function _odl_captcha($aFonts) {
|
---|
| 46 | // get parameters
|
---|
| 47 | $this->aFonts = $aFonts;
|
---|
| 48 | $this->SetNumChars(CAPCC_NUM_CHARS);
|
---|
| 49 | $this->SetNumLines(CAPCC_NUM_LINES);
|
---|
| 50 | $this->DisplayShadow(CAPCC_CHAR_SHADOW);
|
---|
| 51 | $this->SetCharSet(CAPCC_CHAR_SET);
|
---|
| 52 | $this->CaseInsensitive(CAPCC_CASE_INSENSITIVE);
|
---|
| 53 | $this->SetBackgroundImages(CAPCC_BACKGROUND_IMAGES);
|
---|
| 54 | $this->SetMinFontSize(CAPCC_MIN_FONT_SIZE);
|
---|
| 55 | $this->SetMaxFontSize(CAPCC_MAX_FONT_SIZE);
|
---|
| 56 | $this->UseColour(CAPCC_USE_COLOUR);
|
---|
| 57 | $this->SetFileType(CAPCC_FILE_TYPE);
|
---|
| 58 | $this->SetWidth(CAPCC_WIDTH);
|
---|
| 59 | $this->SetHeight(CAPCC_HEIGHT);
|
---|
| 60 | }
|
---|
| 61 |
|
---|
| 62 | function CalculateSpacing() {
|
---|
| 63 | $this->iSpacing = (int)($this->iWidth / $this->iNumChars);
|
---|
| 64 | }
|
---|
| 65 |
|
---|
| 66 | function SetWidth($iWidth) {
|
---|
| 67 | $this->iWidth = $iWidth;
|
---|
| 68 | if ($this->iWidth > 500) $this->iWidth = 500; // to prevent perfomance impact
|
---|
| 69 | $this->CalculateSpacing();
|
---|
| 70 | }
|
---|
| 71 |
|
---|
| 72 | function SetHeight($iHeight) {
|
---|
| 73 | $this->iHeight = $iHeight;
|
---|
| 74 | if ($this->iHeight > 200) $this->iHeight = 200; // to prevent performance impact
|
---|
| 75 | }
|
---|
| 76 |
|
---|
| 77 | function SetNumChars($iNumChars) {
|
---|
| 78 | $this->iNumChars = $iNumChars;
|
---|
| 79 | $this->CalculateSpacing();
|
---|
| 80 | }
|
---|
| 81 |
|
---|
| 82 | function SetNumLines($iNumLines) {
|
---|
| 83 | $this->iNumLines = $iNumLines;
|
---|
| 84 | }
|
---|
| 85 |
|
---|
| 86 | function DisplayShadow($bCharShadow) {
|
---|
| 87 | $this->bCharShadow = $bCharShadow;
|
---|
| 88 | }
|
---|
| 89 |
|
---|
| 90 |
|
---|
| 91 | function SetCharSet($vCharSet) {
|
---|
| 92 | // check for input type
|
---|
| 93 | if (is_array($vCharSet)) {
|
---|
| 94 | $this->aCharSet = $vCharSet;
|
---|
| 95 | } else {
|
---|
| 96 | if ($vCharSet != '') {
|
---|
| 97 | // split items on commas
|
---|
| 98 | $aCharSet = explode(',', $vCharSet);
|
---|
| 99 | // initialise array
|
---|
| 100 | $this->aCharSet = array();
|
---|
| 101 | // loop through items
|
---|
| 102 | foreach ($aCharSet as $sCurrentItem) {
|
---|
| 103 | // a range should have 3 characters, otherwise is normal character
|
---|
| 104 | if (strlen($sCurrentItem) == 3) {
|
---|
| 105 | // split on range character
|
---|
| 106 | $aRange = explode('-', $sCurrentItem);
|
---|
| 107 | // check for valid range
|
---|
| 108 | if (count($aRange) == 2 && $aRange[0] < $aRange[1]) {
|
---|
| 109 | // create array of characters from range
|
---|
| 110 | $aRange = range($aRange[0], $aRange[1]);
|
---|
| 111 | // add to charset array
|
---|
| 112 | $this->aCharSet = array_merge($this->aCharSet, $aRange);
|
---|
| 113 | }
|
---|
| 114 | } else {
|
---|
| 115 | $this->aCharSet[] = $sCurrentItem;
|
---|
| 116 | }
|
---|
| 117 | }
|
---|
| 118 | }
|
---|
| 119 | }
|
---|
| 120 | }
|
---|
| 121 |
|
---|
| 122 | function CaseInsensitive($bCaseInsensitive) {
|
---|
| 123 | $this->bCaseInsensitive = $bCaseInsensitive;
|
---|
| 124 | }
|
---|
| 125 |
|
---|
| 126 | function SetBackgroundImages($vBackgroundImages) {
|
---|
| 127 | $this->vBackgroundImages = $vBackgroundImages;
|
---|
| 128 | }
|
---|
| 129 |
|
---|
| 130 | function SetMinFontSize($iMinFontSize) {
|
---|
| 131 | $this->iMinFontSize = $iMinFontSize;
|
---|
| 132 | }
|
---|
| 133 |
|
---|
| 134 | function SetMaxFontSize($iMaxFontSize) {
|
---|
| 135 | $this->iMaxFontSize = $iMaxFontSize;
|
---|
| 136 | }
|
---|
| 137 |
|
---|
| 138 | function UseColour($bUseColour) {
|
---|
| 139 | $this->bUseColour = $bUseColour;
|
---|
| 140 | }
|
---|
| 141 |
|
---|
| 142 | function SetFileType($sFileType) {
|
---|
| 143 | // check for valid file type
|
---|
| 144 | if (in_array($sFileType, array('gif', 'png', 'jpeg'))) {
|
---|
| 145 | $this->sFileType = $sFileType;
|
---|
| 146 | } else {
|
---|
| 147 | $this->sFileType = 'jpeg';
|
---|
| 148 | }
|
---|
| 149 | }
|
---|
| 150 |
|
---|
| 151 | function DrawLines() {
|
---|
| 152 | for ($i = 0; $i < $this->iNumLines; $i++) {
|
---|
| 153 | // allocate colour
|
---|
| 154 | if ($this->bUseColour) {
|
---|
| 155 | $iLineColour = imagecolorallocate($this->oImage, rand(100, 250), rand(100, 250), rand(100, 250));
|
---|
| 156 | } else {
|
---|
| 157 | $iRandColour = rand(100, 250);
|
---|
| 158 | $iLineColour = imagecolorallocate($this->oImage, $iRandColour, $iRandColour, $iRandColour);
|
---|
| 159 | }
|
---|
| 160 | // draw line
|
---|
| 161 | imageline($this->oImage, rand(0, $this->iWidth), rand(0, $this->iHeight), rand(0, $this->iWidth), rand(0, $this->iHeight), $iLineColour);
|
---|
| 162 | }
|
---|
| 163 | }
|
---|
| 164 |
|
---|
| 165 | function GenerateCode() {
|
---|
| 166 | // reset code
|
---|
| 167 | $this->sCode = '';
|
---|
| 168 | // loop through and generate the code letter by letter
|
---|
| 169 | for ($i = 0; $i < $this->iNumChars; $i++) {
|
---|
| 170 | if (count($this->aCharSet) > 0) {
|
---|
| 171 | // select random character and add to code string
|
---|
| 172 | $this->sCode .= $this->aCharSet[array_rand($this->aCharSet)];
|
---|
| 173 | } else {
|
---|
| 174 | // select random character and add to code string
|
---|
| 175 | $this->sCode .= chr(rand(65, 90));
|
---|
| 176 | }
|
---|
| 177 | }
|
---|
| 178 | // save code in session variable
|
---|
| 179 | if ($this->bCaseInsensitive) {
|
---|
| 180 | $_SESSION[CAPCC_SESSION_ID] = strtoupper($this->sCode);
|
---|
| 181 | } else {
|
---|
| 182 | $_SESSION[CAPCC_SESSION_ID] = $this->sCode;
|
---|
| 183 | }
|
---|
| 184 | }
|
---|
| 185 |
|
---|
| 186 | function DrawCharacters() {
|
---|
| 187 | // loop through and write out selected number of characters
|
---|
| 188 | for ($i = 0; $i < strlen($this->sCode); $i++) {
|
---|
| 189 | // select random font
|
---|
| 190 | $sCurrentFont = $this->aFonts[array_rand($this->aFonts)];
|
---|
| 191 | // select random colour
|
---|
| 192 | if ($this->bUseColour) {
|
---|
| 193 | $iTextColour = imagecolorallocate($this->oImage, rand(0, 100), rand(0, 100), rand(0, 100));
|
---|
| 194 | if ($this->bCharShadow) {
|
---|
| 195 | // shadow colour
|
---|
| 196 | $iShadowColour = imagecolorallocate($this->oImage, rand(0, 100), rand(0, 100), rand(0, 100));
|
---|
| 197 | }
|
---|
| 198 | } else {
|
---|
| 199 | $iRandColour = rand(0, 100);
|
---|
| 200 | $iTextColour = imagecolorallocate($this->oImage, $iRandColour, $iRandColour, $iRandColour);
|
---|
| 201 | if ($this->bCharShadow) {
|
---|
| 202 | // shadow colour
|
---|
| 203 | $iRandColour = rand(0, 100);
|
---|
| 204 | $iShadowColour = imagecolorallocate($this->oImage, $iRandColour, $iRandColour, $iRandColour);
|
---|
| 205 | }
|
---|
| 206 | }
|
---|
| 207 | // select random font size
|
---|
| 208 | $iFontSize = rand($this->iMinFontSize, $this->iMaxFontSize);
|
---|
| 209 | // select random angle
|
---|
| 210 | $iAngle = rand(-30, 30);
|
---|
| 211 | // get dimensions of character in selected font and text size
|
---|
| 212 | $aCharDetails = imageftbbox($iFontSize, $iAngle, $sCurrentFont, $this->sCode[$i], array());
|
---|
| 213 | // calculate character starting coordinates
|
---|
| 214 | $iX = $this->iSpacing / 4 + $i * $this->iSpacing;
|
---|
| 215 | $iCharHeight = $aCharDetails[2] - $aCharDetails[5];
|
---|
| 216 | $iY = $this->iHeight / 2 + $iCharHeight / 4;
|
---|
| 217 | // write text to image
|
---|
| 218 | imagefttext($this->oImage, $iFontSize, $iAngle, $iX, $iY, $iTextColour, $sCurrentFont, $this->sCode[$i], array());
|
---|
| 219 | if ($this->bCharShadow) {
|
---|
| 220 | $iOffsetAngle = rand(-30, 30);
|
---|
| 221 | $iRandOffsetX = rand(-5, 5);
|
---|
| 222 | $iRandOffsetY = rand(-5, 5);
|
---|
| 223 | imagefttext($this->oImage, $iFontSize, $iOffsetAngle, $iX + $iRandOffsetX, $iY + $iRandOffsetY, $iShadowColour, $sCurrentFont, $this->sCode[$i], array());
|
---|
| 224 | }
|
---|
| 225 | }
|
---|
| 226 | }
|
---|
| 227 |
|
---|
| 228 | function create($sFilename = '') {
|
---|
| 229 | // check for required gd functions
|
---|
| 230 | if (!function_exists('imagecreate') ||
|
---|
| 231 | !function_exists("image$this->sFileType") || ($this->vBackgroundImages != '' && !function_exists('imagecreatetruecolor'))) {
|
---|
| 232 | return false;
|
---|
| 233 | }
|
---|
| 234 | // get background image if specified and copy to CAPTCHA
|
---|
| 235 | if (is_array($this->vBackgroundImages) || $this->vBackgroundImages != '') {
|
---|
| 236 | // create new image
|
---|
| 237 | $this->oImage = imagecreatetruecolor($this->iWidth, $this->iHeight);
|
---|
| 238 | // create background image
|
---|
| 239 | if (is_array($this->vBackgroundImages)) {
|
---|
| 240 | $iRandImage = array_rand($this->vBackgroundImages);
|
---|
| 241 | $oBackgroundImage = imagecreatefromjpeg($this->vBackgroundImages[$iRandImage]);
|
---|
| 242 | } else {
|
---|
| 243 | $oBackgroundImage = imagecreatefromjpeg($this->vBackgroundImages);
|
---|
| 244 | }
|
---|
| 245 | // copy background image
|
---|
| 246 | imagecopy($this->oImage, $oBackgroundImage, 0, 0, 0, 0, $this->iWidth, $this->iHeight);
|
---|
| 247 | // free memory used to create background image
|
---|
| 248 | imagedestroy($oBackgroundImage);
|
---|
| 249 | } else {
|
---|
| 250 | // create new image
|
---|
| 251 | $this->oImage = imagecreate($this->iWidth, $this->iHeight);
|
---|
| 252 | //$this->oImage = imagecreatetruecolor($this->iWidth, $this->iHeight);
|
---|
| 253 | }
|
---|
| 254 | // allocate white background colour
|
---|
| 255 | imagecolorallocate($this->oImage, 255, 255, 255);
|
---|
| 256 | // check for background image before drawing lines
|
---|
| 257 | if (!is_array($this->vBackgroundImages) && $this->vBackgroundImages == '') {
|
---|
| 258 | $this->DrawLines();
|
---|
| 259 | }
|
---|
| 260 | $this->GenerateCode();
|
---|
| 261 | $this->DrawCharacters();
|
---|
| 262 | // write out image to file or browser
|
---|
| 263 | $this->WriteFile($sFilename);
|
---|
| 264 | // free memory used in creating image
|
---|
| 265 | imagedestroy($this->oImage);
|
---|
| 266 | return true;
|
---|
| 267 | }
|
---|
| 268 |
|
---|
| 269 | function WriteFile($sFilename) {
|
---|
| 270 | if ($sFilename == '') {
|
---|
| 271 | // tell browser that data is jpeg
|
---|
| 272 | header("Content-type: image/" . $this->sFileType );
|
---|
| 273 | }
|
---|
| 274 | switch ($this->sFileType) {
|
---|
| 275 | case 'gif':
|
---|
| 276 | $sFilename != '' ? imagegif($this->oImage, $sFilename) : imagegif($this->oImage);
|
---|
| 277 | break;
|
---|
| 278 | case 'png':
|
---|
| 279 | $sFilename != '' ? imagepng($this->oImage, $sFilename) : imagepng($this->oImage);
|
---|
| 280 | break;
|
---|
| 281 | default:
|
---|
| 282 | $sFilename != '' ? imagejpeg($this->oImage, $sFilename) : imagejpeg($this->oImage);
|
---|
| 283 | }
|
---|
| 284 | }
|
---|
| 285 |
|
---|
| 286 | // call this method statically
|
---|
| 287 | function Validate($sUserCode, $bCaseInsensitive = true) {
|
---|
| 288 | if ($bCaseInsensitive) {
|
---|
| 289 | $sUserCode = strtoupper($sUserCode);
|
---|
| 290 | }
|
---|
| 291 | if (!empty($_SESSION[CAPCC_SESSION_ID]) && $sUserCode == $_SESSION[CAPCC_SESSION_ID]) {
|
---|
| 292 | // clear to prevent re-use
|
---|
| 293 | unset($_SESSION[CAPCC_SESSION_ID]);
|
---|
| 294 | return true;
|
---|
| 295 | }
|
---|
| 296 | return false;
|
---|
| 297 | }
|
---|
| 298 | }
|
---|
| 299 |
|
---|
| 300 | // example sub class
|
---|
| 301 | class _odl_captchaColour extends _odl_captcha {
|
---|
| 302 | function _odl_captchaColour($aFonts) {
|
---|
| 303 | // call parent constructor
|
---|
| 304 | parent::_odl_captcha($aFonts);
|
---|
| 305 |
|
---|
| 306 | // set options
|
---|
| 307 | $this->UseColour(true);
|
---|
| 308 | }
|
---|
| 309 | }
|
---|
| 310 | ?>
|
---|