1<?php
2/*************************
3  Coppermine Photo Gallery
4  ************************
5  Copyright (c) 2003-2016 Coppermine Dev Team
6  v1.0 originally written by Gregory Demar
7
8  This program is free software; you can redistribute it and/or modify
9  it under the terms of the GNU General Public License version 3
10  as published by the Free Software Foundation.
11
12  ********************************************
13  Coppermine version: 1.6.03
14  $HeadURL$
15**********************************************/
16
17 /***************************************************************/
18 /* PhpCaptcha                                                  */
19 /* Copyright  2005 Edward Eliot - http://www.ejeliot.com/     */
20 /* This class is Freeware, however please retain this          */
21 /* copyright notice when using                                 */
22 /* Last Updated: 26th November 2005                            */
23 /***************************************************************/
24
25if (!defined('IN_COPPERMINE')) die('Not in Coppermine...');
26
27   // start a PHP session - this class uses sessions to store the generated
28   // code. Comment out if you are calling already from your application
29   $session_name = session_name();
30   if ($superCage->cookie->keyExists($session_name)) {
31       session_id($superCage->cookie->getAlnum($session_name));
32   }
33
34   session_start();
35
36   class PhpCaptcha {
37      var $oImage;
38      var $aFonts;
39      var $iWidth;
40      var $iHeight;
41      var $iNumChars;
42      var $iNumLines;
43      var $iSpacing;
44      var $bCharShadow;
45      var $sOwnerText;
46      var $aCharSet;
47      var $sBackgroundImage;
48      var $sCode;
49
50      function __construct(
51         $aFonts, // array of TypeType fonts to use - specify full path
52         $iWidth = 200, // width of image
53         $iHeight = 50, // height of image
54         $iNumChars = 5, // number of characters to draw
55         $iNumLines = 70, // number of noise lines to draw
56         $bCharShadow = false, // add shadow to generated characters to further obscure code
57         $sOwnerText = '', // add owner text to bottom of CAPTCHA, usually your site address
58         $aCharSet = array(), // array of characters to select from - if blank uses upper case A - Z
59         $sBackgroundImage = '' // background image to use - if blank creates image with white background
60      ) {
61         // get parameters
62         $this->aFonts = $aFonts;
63         $this->iWidth = $iWidth;
64         $this->iHeight = $iHeight;
65         $this->iNumChars = $iNumChars;
66         $this->iNumLines = $iNumLines;
67         $this->bCharShadow = $bCharShadow;
68         $this->sOwnerText = $sOwnerText;
69         $this->aCharSet = $aCharSet;
70         $this->sBackgroundImage = $sBackgroundImage;
71
72         // calculate spacing between characters based on width of image
73         $this->iSpacing = (int)($this->iWidth / $this->iNumChars);
74      }
75
76      function DrawLines() {
77         for ($i = 0; $i < $this->iNumLines; $i++) {
78            $iRandColour = rand(100, 250);
79            $iLineColour = imagecolorallocate($this->oImage, $iRandColour, $iRandColour, $iRandColour);
80            imageline($this->oImage, rand(0, $this->iWidth), rand(0, $this->iHeight), rand(0, $this->iWidth), rand(0, $this->iHeight), $iLineColour);
81         }
82      }
83
84      function DrawOwnerText() {
85         $iBlack = imagecolorallocate($this->oImage, 0, 0, 0);
86         $iOwnerTextHeight = imagefontheight(2);
87         $iLineHeight = $this->iHeight - $iOwnerTextHeight - 4;
88
89         imageline($this->oImage, 0, $iLineHeight, $this->iWidth, $iLineHeight, $iBlack);
90         imagestring($this->oImage, 2, 3, $this->iHeight - $iOwnerTextHeight - 3, $this->sOwnerText, $iBlack);
91
92         $this->iHeight = $this->iHeight - $iOwnerTextHeight - 5;
93      }
94
95      function GenerateCode() {
96         // reset code
97         $this->sCode = '';
98
99         // loop through and generate the code letter by letter
100         for ($i = 0; $i < $this->iNumChars; $i++) {
101            if (count($this->aCharSet) > 0) {
102               // select random character and add to code string
103               $this->sCode .= $this->aCharSet[array_rand($this->aCharSet)];
104            } else {
105               // select random character and add to code string
106               $this->sCode .= chr(rand(65, 90));
107            }
108         }
109
110         // save code in session variable
111         $_SESSION['php_captcha'] = md5(strtoupper($this->sCode));
112      }
113
114      function DrawCharacters() {
115         // loop through and write out selected number of characters
116         for ($i = 0; $i < strlen($this->sCode); $i++) {
117            // select random font
118            $sCurrentFont = $this->aFonts[array_rand($this->aFonts)];
119
120            // select random greyscale colour
121            $iRandColour = rand(0, 100);
122            $iTextColour = imagecolorallocate($this->oImage, $iRandColour, $iRandColour, $iRandColour);
123
124            if ($this->bCharShadow) {
125               // shadow colour
126               $iRandColour = rand(0, 100);
127               $iShadowColour = imagecolorallocate($this->oImage, $iRandColour, $iRandColour, $iRandColour);
128            }
129
130            // select random font size
131            $iFontSize = rand(16, 25);
132
133            // select random angle
134            $iAngle = rand(-30, 30);
135
136            // get dimensions of character in selected font and text size
137            $aCharDetails = imageftbbox($iFontSize, $iAngle, $sCurrentFont, $this->sCode[$i]);
138
139            // calculate character starting coordinates
140            $iX = $this->iSpacing / 4 + $i * $this->iSpacing;
141            $iCharHeight = $aCharDetails[2] - $aCharDetails[5];
142            $iY = $this->iHeight / 2 + $iCharHeight / 4;
143
144            // write text to image
145            imagefttext($this->oImage, $iFontSize, $iAngle, $iX, $iY, $iTextColour, $sCurrentFont, $this->sCode[$i]);
146
147            if ($this->bCharShadow) {
148               $iOffsetAngle = rand(-30, 30);
149
150               $iRandOffsetX = rand(-5, 5);
151               $iRandOffsetY = rand(-5, 5);
152
153               imagefttext($this->oImage, $iFontSize, $iOffsetAngle, $iX + $iRandOffsetX, $iY + $iRandOffsetY, $iShadowColour, $sCurrentFont, $this->sCode[$i]);
154            }
155         }
156      }
157
158      function Create($sFilename = '') {
159         // check for required gd functions
160         if (!function_exists('imagecreate') || !function_exists('imagejpeg') || ($this->sBackgroundImage != '' && !function_exists('imagecreatetruecolor'))) {
161            return false;
162         }
163         // get background image if specified and copy to CAPTCHA
164         if ($this->sBackgroundImage != '') {
165            // create new image
166            $this->oImage = imagecreatetruecolor($this->iWidth, $this->iHeight);
167
168            // create background image
169            $oBackgroundImage = imagecreatefromjpeg($this->sBackgroundImage);
170
171            // copy background image
172            imagecopy($this->oImage, $oBackgroundImage, 0, 0, 0, 0, $this->iWidth, $this->iHeight);
173
174            // free memory used to create background image
175            imagedestroy($oBackgroundImage);
176         } else {
177            // create new image
178            $this->oImage = imagecreate($this->iWidth, $this->iHeight);
179         }
180
181         // allocate white background colour
182         imagecolorallocate($this->oImage, 255, 255, 255);
183
184         // check for owner text
185         if ($this->sOwnerText != '') {
186            $this->DrawOwnerText();
187         }
188
189         // check for background image before drawing lines
190         if ($this->sBackgroundImage == '') {
191            $this->DrawLines();
192         }
193
194         $this->GenerateCode();
195         $this->DrawCharacters();
196
197         // write out image to file or browser
198         if ($sFilename != '') {
199            // write stream to file
200            imagejpeg($this->oImage, $sFilename);
201         } else {
202            // tell browser that data is jpeg
203            header('Content-type: image/jpeg');
204
205            // write stream to browser
206            imagejpeg($this->oImage);
207         }
208
209         // free memory used in creating image
210         imagedestroy($this->oImage);
211
212         return true;
213      }
214
215      // call this method statically
216      static function Validate($sUserCode) {
217         if (md5(strtoupper($sUserCode)) == $_SESSION['php_captcha']) {
218            // clear to prevent re-use
219            $_SESSION['php_captcha'] = '';
220
221            return true;
222         }
223
224         return false;
225      }
226   }
227//EOF