Take two:
[www-register-wizard.git] / plugins / captcha_pi.php
1 <?php  if ( ! defined('BASEPATH')) exit('No direct script access allowed');\r
2 /**\r
3  * CodeIgniter\r
4  *\r
5  * An open source application development framework for PHP 4.3.2 or newer\r
6  *\r
7  * @package             CodeIgniter\r
8  * @author              ExpressionEngine Dev Team\r
9  * @copyright   Copyright (c) 2008, EllisLab, Inc.\r
10  * @license             http://codeigniter.com/user_guide/license.html\r
11  * @link                http://codeigniter.com\r
12  * @since               Version 1.0\r
13  * @filesource\r
14  */\r
15 \r
16 // ------------------------------------------------------------------------\r
17 \r
18 /*\r
19 Instructions:\r
20 \r
21 Load the plugin using:\r
22 \r
23         $this->load->plugin('captcha');\r
24 \r
25 Once loaded you can generate a captcha like this:\r
26         \r
27         $vals = array(\r
28                                         'word'           => 'Random word',\r
29                                         'img_path'       => './captcha/',\r
30                                         'img_url'        => 'http://example.com/captcha/',\r
31                                         'font_path'      => './system/fonts/texb.ttf',\r
32                                         'img_width'      => '150',\r
33                                         'img_height' => 30,\r
34                                         'expiration' => 7200\r
35                                 );\r
36         \r
37         $cap = create_captcha($vals);\r
38         echo $cap['image'];\r
39         \r
40 \r
41 NOTES:\r
42         \r
43         The captcha function requires the GD image library.\r
44         \r
45         Only the img_path and img_url are required.\r
46         \r
47         If a "word" is not supplied, the function will generate a random\r
48         ASCII string.  You might put together your own word library that\r
49         you can draw randomly from.\r
50         \r
51         If you do not specify a path to a TRUE TYPE font, the native ugly GD\r
52         font will be used.\r
53         \r
54         The "captcha" folder must be writable (666, or 777)\r
55         \r
56         The "expiration" (in seconds) signifies how long an image will\r
57         remain in the captcha folder before it will be deleted.  The default\r
58         is two hours.\r
59 \r
60 RETURNED DATA\r
61 \r
62 The create_captcha() function returns an associative array with this data:\r
63 \r
64   [array]\r
65   (\r
66         'image' => IMAGE TAG\r
67         'time'  => TIMESTAMP (in microtime)\r
68         'word'  => CAPTCHA WORD\r
69   )\r
70 \r
71 The "image" is the actual image tag:\r
72 <img src="http://example.com/captcha/12345.jpg" width="140" height="50" />\r
73 \r
74 The "time" is the micro timestamp used as the image name without the file\r
75 extension.  It will be a number like this:  1139612155.3422\r
76 \r
77 The "word" is the word that appears in the captcha image, which if not\r
78 supplied to the function, will be a random string.\r
79 \r
80 \r
81 ADDING A DATABASE\r
82 \r
83 In order for the captcha function to prevent someone from posting, you will need\r
84 to add the information returned from create_captcha() function to your database.\r
85 Then, when the data from the form is submitted by the user you will need to verify\r
86 that the data exists in the database and has not expired.\r
87 \r
88 Here is a table prototype:\r
89 \r
90         CREATE TABLE captcha (\r
91          captcha_id bigint(13) unsigned NOT NULL auto_increment,\r
92          captcha_time int(10) unsigned NOT NULL,\r
93          ip_address varchar(16) default '0' NOT NULL,\r
94          word varchar(20) NOT NULL,\r
95          PRIMARY KEY `captcha_id` (`captcha_id`),\r
96          KEY `word` (`word`)\r
97         )\r
98 \r
99 \r
100 Here is an example of usage with a DB.\r
101 \r
102 On the page where the captcha will be shown you'll have something like this:\r
103 \r
104         $this->load->plugin('captcha');\r
105         $vals = array(\r
106                                         'img_path'       => './captcha/',\r
107                                         'img_url'        => 'http://example.com/captcha/'\r
108                                 );\r
109         \r
110         $cap = create_captcha($vals);\r
111 \r
112         $data = array(\r
113                                         'captcha_id'    => '',\r
114                                         'captcha_time'  => $cap['time'],\r
115                                         'ip_address'    => $this->input->ip_address(),\r
116                                         'word'                  => $cap['word']\r
117                                 );\r
118 \r
119         $query = $this->db->insert_string('captcha', $data);\r
120         $this->db->query($query);\r
121                 \r
122         echo 'Submit the word you see below:';\r
123         echo $cap['image'];\r
124         echo '<input type="text" name="captcha" value="" />';\r
125 \r
126 \r
127 Then, on the page that accepts the submission you'll have something like this:\r
128 \r
129         // First, delete old captchas\r
130         $expiration = time()-7200; // Two hour limit\r
131         $DB->query("DELETE FROM captcha WHERE captcha_time < ".$expiration);            \r
132 \r
133         // Then see if a captcha exists:\r
134         $sql = "SELECT COUNT(*) AS count FROM captcha WHERE word = ? AND ip_address = ? AND date > ?";\r
135         $binds = array($_POST['captcha'], $this->input->ip_address(), $expiration);\r
136         $query = $this->db->query($sql, $binds);\r
137         $row = $query->row();\r
138 \r
139         if ($row->count == 0)\r
140         {\r
141                 echo "You must submit the word that appears in the image";\r
142         }\r
143 \r
144 */\r
145 \r
146 \r
147         \r
148 /**\r
149 |==========================================================\r
150 | Create Captcha\r
151 |==========================================================\r
152 |\r
153 */\r
154 function create_captcha($data = '', $img_path = '', $img_url = '', $font_path = '')\r
155 {               \r
156         $defaults = array('word' => '', 'img_path' => '', 'img_url' => '', 'img_width' => '150', 'img_height' => '30', 'font_path' => '', 'expiration' => 7200);                \r
157         \r
158         foreach ($defaults as $key => $val)\r
159         {\r
160                 if ( ! is_array($data))\r
161                 {\r
162                         if ( ! isset($$key) OR $$key == '')\r
163                         {\r
164                                 $$key = $val;\r
165                         }\r
166                 }\r
167                 else\r
168                 {                       \r
169                         $$key = ( ! isset($data[$key])) ? $val : $data[$key];\r
170                 }\r
171         }\r
172         \r
173         if ($img_path == '' OR $img_url == '')\r
174         {\r
175                 return FALSE;\r
176         }\r
177 \r
178         if ( ! @is_dir($img_path))\r
179         {\r
180                 return FALSE;\r
181         }\r
182         \r
183         if ( ! is_really_writable($img_path))\r
184         {\r
185                 return FALSE;\r
186         }\r
187                         \r
188         if ( ! extension_loaded('gd'))\r
189         {\r
190                 return FALSE;\r
191         }               \r
192         \r
193         // -----------------------------------\r
194         // Remove old images    \r
195         // -----------------------------------\r
196                         \r
197         list($usec, $sec) = explode(" ", microtime());\r
198         $now = ((float)$usec + (float)$sec);\r
199                         \r
200         $current_dir = @opendir($img_path);\r
201         \r
202         while($filename = @readdir($current_dir))\r
203         {\r
204                 if ($filename != "." and $filename != ".." and $filename != "index.html")\r
205                 {\r
206                         $name = str_replace(".jpg", "", $filename);\r
207                 \r
208                         if (($name + $expiration) < $now)\r
209                         {\r
210                                 @unlink($img_path.$filename);\r
211                         }\r
212                 }\r
213         }\r
214         \r
215         @closedir($current_dir);\r
216 \r
217         // -----------------------------------\r
218         // Do we have a "word" yet?\r
219         // -----------------------------------\r
220         \r
221    if ($word == '')\r
222    {\r
223                 $pool = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';\r
224 \r
225                 $str = '';\r
226                 for ($i = 0; $i < 8; $i++)\r
227                 {\r
228                         $str .= substr($pool, mt_rand(0, strlen($pool) -1), 1);\r
229                 }\r
230                 \r
231                 $word = $str;\r
232    }\r
233         \r
234         // -----------------------------------\r
235         // Determine angle and position \r
236         // -----------------------------------\r
237         \r
238         $length = strlen($word);\r
239         $angle  = ($length >= 6) ? rand(-($length-6), ($length-6)) : 0;\r
240         $x_axis = rand(6, (360/$length)-16);                    \r
241         $y_axis = ($angle >= 0 ) ? rand($img_height, $img_width) : rand(6, $img_height);\r
242         \r
243         // -----------------------------------\r
244         // Create image\r
245         // -----------------------------------\r
246                         \r
247         // PHP.net recommends imagecreatetruecolor(), but it isn't always available\r
248         if (function_exists('imagecreatetruecolor'))\r
249         {\r
250                 $im = imagecreatetruecolor($img_width, $img_height);\r
251         }\r
252         else\r
253         {\r
254                 $im = imagecreate($img_width, $img_height);\r
255         }\r
256                         \r
257         // -----------------------------------\r
258         //  Assign colors\r
259         // -----------------------------------\r
260         \r
261         $bg_color               = imagecolorallocate ($im, 255, 255, 255);\r
262         $border_color   = imagecolorallocate ($im, 153, 102, 102);\r
263         $text_color             = imagecolorallocate ($im, 204, 153, 153);\r
264         $grid_color             = imagecolorallocate($im, 255, 182, 182);\r
265         $shadow_color   = imagecolorallocate($im, 255, 240, 240);\r
266 \r
267         // -----------------------------------\r
268         //  Create the rectangle\r
269         // -----------------------------------\r
270         \r
271         ImageFilledRectangle($im, 0, 0, $img_width, $img_height, $bg_color);\r
272         \r
273         // -----------------------------------\r
274         //  Create the spiral pattern\r
275         // -----------------------------------\r
276         \r
277         $theta          = 1;\r
278         $thetac         = 7;\r
279         $radius         = 16;\r
280         $circles        = 20;\r
281         $points         = 32;\r
282 \r
283         for ($i = 0; $i < ($circles * $points) - 1; $i++)\r
284         {\r
285                 $theta = $theta + $thetac;\r
286                 $rad = $radius * ($i / $points );\r
287                 $x = ($rad * cos($theta)) + $x_axis;\r
288                 $y = ($rad * sin($theta)) + $y_axis;\r
289                 $theta = $theta + $thetac;\r
290                 $rad1 = $radius * (($i + 1) / $points);\r
291                 $x1 = ($rad1 * cos($theta)) + $x_axis;\r
292                 $y1 = ($rad1 * sin($theta )) + $y_axis;\r
293                 imageline($im, $x, $y, $x1, $y1, $grid_color);\r
294                 $theta = $theta - $thetac;\r
295         }\r
296 \r
297         // -----------------------------------\r
298         //  Write the text\r
299         // -----------------------------------\r
300         \r
301         $use_font = ($font_path != '' AND file_exists($font_path) AND function_exists('imagettftext')) ? TRUE : FALSE;\r
302                 \r
303         if ($use_font == FALSE)\r
304         {\r
305                 $font_size = 5;\r
306                 $x = rand(0, $img_width/($length/3));\r
307                 $y = 0;\r
308         }\r
309         else\r
310         {\r
311                 $font_size      = 16;\r
312                 $x = rand(0, $img_width/($length/1.5));\r
313                 $y = $font_size+2;\r
314         }\r
315 \r
316         for ($i = 0; $i < strlen($word); $i++)\r
317         {\r
318                 if ($use_font == FALSE)\r
319                 {\r
320                         $y = rand(0 , $img_height/2);\r
321                         imagestring($im, $font_size, $x, $y, substr($word, $i, 1), $text_color);\r
322                         $x += ($font_size*2);\r
323                 }\r
324                 else\r
325                 {               \r
326                         $y = rand($img_height/2, $img_height-3);\r
327                         imagettftext($im, $font_size, $angle, $x, $y, $text_color, $font_path, substr($word, $i, 1));\r
328                         $x += $font_size;\r
329                 }\r
330         }\r
331         \r
332 \r
333         // -----------------------------------\r
334         //  Create the border\r
335         // -----------------------------------\r
336 \r
337         imagerectangle($im, 0, 0, $img_width-1, $img_height-1, $border_color);          \r
338 \r
339         // -----------------------------------\r
340         //  Generate the image\r
341         // -----------------------------------\r
342         \r
343         $img_name = $now.'.jpg';\r
344 \r
345         ImageJPEG($im, $img_path.$img_name);\r
346         \r
347         $img = "<img src=\"$img_url$img_name\" width=\"$img_width\" height=\"$img_height\" style=\"border:0;\" alt=\" \" />";\r
348         \r
349         ImageDestroy($im);\r
350                 \r
351         return array('word' => $word, 'time' => $now, 'image' => $img);\r
352 }\r
353 \r
354 \r
355 /* End of file captcha_pi.php */\r
356 /* Location: ./system/plugins/captcha_pi.php */