noalyss Version-10
NOALYSS : serveur de comptabilité et ERP (2002)
Loading...
Searching...
No Matches
securimage.php
Go to the documentation of this file.
1<?php
2
3/**
4 * Project: Securimage: A PHP class for creating and managing form CAPTCHA images<br />
5 * File: securimage.php<br />
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or any later version.<br /><br />
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.<br /><br />
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA<br /><br />
20 *
21 * Any modifications to the library should be indicated clearly in the source code
22 * to inform users that the changes are not a part of the original software.<br /><br />
23 *
24 * If you found this script useful, please take a quick moment to rate it.<br />
25 * http://www.hotscripts.com/rate/49400.html Thanks.
26 *
27 * @link http://www.phpcaptcha.org Securimage PHP CAPTCHA
28 * @link http://www.phpcaptcha.org/latest.zip Download Latest Version
29 * @link http://www.phpcaptcha.org/Securimage_Docs/ Online Documentation
30 * @copyright 2009 Drew Phillips
31 * @author Drew Phillips <drew@drew-phillips.com>
32 * @version 2.0.1 BETA (December 6th, 2009)
33 * @package Securimage
34 *
35 */
36
37/**
38 ChangeLog
39
40 2.0.1
41 - Add support for browsers with cookies disabled (requires php5, sqlite) maps users to md5 hashed ip addresses and md5 hashed codes for security
42 - Add fallback to gd fonts if ttf support is not enabled or font file not found (Mike Challis http://www.642weather.com/weather/scripts.php)
43 - Check for previous definition of image type constants (Mike Challis)
44 - Fix mime type settings for audio output
45 - Fixed color allocation issues with multiple colors and background images, consolidate allocation to one function
46 - Ability to let codes expire after a given length of time
47 - Allow HTML color codes to be passed to Securimage_Color (suggested by Mike Challis)
48
49 2.0.0
50 - Add mathematical distortion to characters (using code from HKCaptcha)
51 - Improved session support
52 - Added Securimage_Color class for easier color definitions
53 - Add distortion to audio output to prevent binary comparison attack (proposed by Sven "SavageTiger" Hagemann [insecurity.nl])
54 - Flash button to stream mp3 audio (Douglas Walsh www.douglaswalsh.net)
55 - Audio output is mp3 format by default
56 - Change font to AlteHaasGrotesk by yann le coroller
57 - Some code cleanup
58
59 1.0.4 (unreleased)
60 - Ability to output audible codes in mp3 format to stream from flash
61
62 1.0.3.1
63 - Error reading from wordlist in some cases caused words to be cut off 1 letter short
64
65 1.0.3
66 - Removed shadow_text from code which could cause an undefined property error due to removal from previous version
67
68 1.0.2
69 - Audible CAPTCHA Code wav files
70 - Create codes from a word list instead of random strings
71
72 1.0
73 - Added the ability to use a selected character set, rather than a-z0-9 only.
74 - Added the multi-color text option to use different colors for each letter.
75 - Switched to automatic session handling instead of using files for code storage
76 - Added GD Font support if ttf support is not available. Can use internal GD fonts or load new ones.
77 - Added the ability to set line thickness
78 - Added option for drawing arced lines over letters
79 - Added ability to choose image type for output
80
81 */
82
83/**
84 * Output images in JPEG format
85 */
86if (!defined('SI_IMAGE_JPEG'))
87 define('SI_IMAGE_JPEG', 1);
88/**
89 * Output images in PNG format
90 */
91if (!defined('SI_IMAGE_PNG'))
92 define('SI_IMAGE_PNG', 2);
93/**
94 * Output images in GIF format (not recommended)
95 * Must have GD >= 2.0.28!
96 */
97if (!defined('SI_IMAGE_GIF'))
98 define('SI_IMAGE_GIF', 3);
99
100/**
101 * Securimage CAPTCHA Class.
102 *
103 * @package Securimage
104 * @subpackage classes
105 *
106 */
108
109 /**
110 * The desired width of the CAPTCHA image.
111 *
112 * @var int
113 */
115
116 /**
117 * The desired width of the CAPTCHA image.
118 *
119 * @var int
120 */
122
123 /**
124 * The image format for output.<br />
125 * Valid options: SI_IMAGE_PNG, SI_IMAGE_JPG, SI_IMAGE_GIF
126 *
127 * @var int
128 */
130
131 /**
132 * The length of the code to generate.
133 *
134 * @var int
135 */
137
138 /**
139 * The character set for individual characters in the image.<br />
140 * Letters are converted to uppercase.<br />
141 * The font must support the letters or there may be problematic substitutions.
142 *
143 * @var string
144 */
146
147 /**
148 * Create codes using this word list
149 *
150 * @var string The path to the word list to use for creating CAPTCHA codes
151 */
153
154 /**
155 * Use wordlist of not
156 *
157 * @var bool true to use wordlist file, false to use random code
158 */
159 var $use_wordlist = false;
160
161 /**
162 * Note: Use of GD fonts is not recommended as many distortion features are not available<br />
163 * The GD font to use.<br />
164 * Internal gd fonts can be loaded by their number.<br />
165 * Alternatively, a file path can be given and the font will be loaded from file.
166 *
167 * @var mixed
168 */
170
171 /**
172 * The approximate size of the font in pixels.<br />
173 * This does not control the size of the font because that is determined by the GD font itself.<br />
174 * This is used to aid the calculations of positioning used by this class.<br />
175 *
176 * @var int
177 */
179
180 /**
181 * Use a gd font instead of TTF
182 *
183 * @var bool true for gd font, false for TTF
184 */
186
187 // Note: These font options below do not apply if you set $use_gd_font to true with the exception of $text_color
188
189 /**
190 * The path to the TTF font file to load.
191 *
192 * @var string
193 */
195
196 /**
197 * How much to distort image, higher = more distortion.<br />
198 * Distortion is only available when using TTF fonts.<br />
199 *
200 * @var float
201 */
203
204 /**
205 * The minimum angle in degrees, with 0 degrees being left-to-right reading text.<br />
206 * Higher values represent a counter-clockwise rotation.<br />
207 * For example, a value of 90 would result in bottom-to-top reading text.<br />
208 * This value along with maximum angle distance do not need to be very high with perturbation
209 *
210 * @var int
211 */
213
214 /**
215 * The minimum angle in degrees, with 0 degrees being left-to-right reading text.<br />
216 * Higher values represent a counter-clockwise rotation.<br />
217 * For example, a value of 90 would result in bottom-to-top reading text.
218 *
219 * @var int
220 */
222
223 /**
224 * The X-Position on the image where letter drawing will begin.<br />
225 * This value is in pixels from the left side of the image.
226 *
227 * @var int
228 * @deprecated 2.0
229 */
231
232 /**
233 * The background color for the image as a Securimage_Color.<br />
234 *
235 * @var Securimage_Color
236 */
238
239 /**
240 * Scan this directory for gif, jpg, and png files to use as background images.<br />
241 * A random image file will be picked each time.<br />
242 * Change from null to the full path to your directory.<br />
243 * i.e. var $background_directory = $_SERVER['DOCUMENT_ROOT'] . '/securimage/backgrounds';
244 * Make sure not to pass a background image to the show function, otherwise this directive is ignored.
245 *
246 * @var string
247 */
248 var $background_directory = null; //'./backgrounds';
249
250 /**
251 * The text color to use for drawing characters as a Securimage_Color.<br />
252 * This value is ignored if $use_multi_text is set to true.<br />
253 * Make sure this contrasts well with the background color or image.<br />
254 *
255 * @see Securimage::$use_multi_text
256 * @var Securimage_Color
257 */
259
260 /**
261 * Set to true to use multiple colors for each character.
262 *
263 * @see Securimage::$multi_text_color
264 * @var boolean
265 */
267
268 /**
269 * Array of Securimage_Colors which will be randomly selected for each letter.<br />
270 *
271 * @var array
272 */
274
275 /**
276 * Set to true to make the characters appear transparent.
277 *
278 * @see Securimage::$text_transparency_percentage
279 * @var boolean
280 */
282
283 /**
284 * The percentage of transparency, 0 to 100.<br />
285 * A value of 0 is completely opaque, 100 is completely transparent (invisble)
286 *
287 * @see Securimage::$use_transparent_text
288 * @var int
289 */
291
292
293 // Line options
294 /**
295 * Draw vertical and horizontal lines on the image.
296 *
297 * @see Securimage::$line_color
298 * @see Securimage::$draw_lines_over_text
299 * @var boolean
300 */
302
303 /**
304 * Color of lines drawn over text
305 *
306 * @var string
307 */
309
310 /**
311 * Draw the lines over the text.<br />
312 * If fales lines will be drawn before putting the text on the image.
313 *
314 * @var boolean
315 */
317
318 /**
319 * Text to write at the bottom corner of captcha image
320 *
321 * @since 2.0
322 * @var string Signature text
323 */
325
326 /**
327 * Color to use for writing signature text
328 *
329 * @since 2.0
330 * @var Securimage_Color
331 */
333
335 /**
336 * Full path to the WAV files to use to make the audio files, include trailing /.<br />
337 * Name Files [A-Z0-9].wav
338 *
339 * @since 1.0.1
340 * @var string
341 */
343
344 /**
345 * Type of audio file to generate (mp3 or wav)
346 *
347 * @var string
348 */
350
351 /**
352 * The session name to use if not the default. Blank for none
353 *
354 * @see http://php.net/session_name
355 * @since 2.0
356 * @var string
357 */
359
360 /**
361 * The amount of time in seconds that a code remains valid.<br />
362 * Any code older than this number will be considered invalid even if entered correctly.<br />
363 * Any non-numeric or value less than 1 disables this functionality.
364 *
365 * @var int
366 */
368
369 /**
370 * Path to the file to use for storing codes for users.<br />
371 * THIS FILE MUST ABSOLUTELY NOT BE ACCESSIBLE FROM A WEB BROWSER!!<br />
372 * Put this file in a directory below the web root or one that is restricted (i.e. an apache .htaccess file with deny from all)<br />
373 * If you cannot meet those requirements your forms may not be completely protected.<br />
374 * You could obscure the database file name but this is also not recommended.
375 *
376 * @var string
377 */
379
380 /**
381 * Use an SQLite database for storing codes as a backup to sessions.<br />
382 * Note: Sessions will still be used
383 */
385
386
387 //END USER CONFIGURATION
388 //There should be no need to edit below unless you really know what you are doing.
389
390 /**
391 * The gd image resource.
392 *
393 * @access private
394 * @var resource
395 */
396 var $im;
397
398 /**
399 * Temporary image for rendering
400 *
401 * @access private
402 * @var resource
403 */
405
406 /**
407 * Internal scale factor for anti-alias @hkcaptcha
408 *
409 * @access private
410 * @since 2.0
411 * @var int
412 */
413 var $iscale; // internal scale factor for anti-alias @hkcaptcha
414
415 /**
416 * The background image resource
417 *
418 * @access private
419 * @var resource
420 */
422
423 /**
424 * The code generated by the script
425 *
426 * @access private
427 * @var string
428 */
429 var $code;
430
431 /**
432 * The code that was entered by the user
433 *
434 * @access private
435 * @var string
436 */
438
439 /**
440 * Whether or not the correct code was entered
441 *
442 * @access private
443 * @var boolean
444 */
446
447 /**
448 * Handle to SQLite database
449 *
450 * @access private
451 * @var resource
452 */
454
455 /**
456 * Color resource for image line color
457 *
458 * @access private
459 * @var int
460 */
462
463 /**
464 * Array of colors for multi colored codes
465 *
466 * @access private
467 * @var array
468 */
470
471 /**
472 * Color resource for image font color
473 *
474 * @access private
475 * @var int
476 */
478
479 /**
480 * Color resource for image signature color
481 *
482 * @access private
483 * @var int
484 */
486
487 /**
488 * Color resource for image background color
489 *
490 * @access private
491 * @var int
492 */
494
495
496 /**
497 * Class constructor.<br />
498 * Because the class uses sessions, this will attempt to start a session if there is no previous one.<br />
499 * If you do not start a session before calling the class, the constructor must be called before any
500 * output is sent to the browser.
501 *
502 * <code>
503 * $securimage = new Securimage();
504 * </code>
505 *
506 */
507 function __construct()
508 {
509 // Initialize session or attach to existing
510 if ( session_id() == '' ) { // no session has been started yet, which is needed for validation
511 if (trim($this->session_name) != '') {
512 session_name($this->session_name); // set session name if provided
513 }
514 session_start();
515 }
516
517 // Set Default Values
518 $this->image_width = 230;
519 $this->image_height = 80;
520 $this->image_type = SI_IMAGE_PNG;
521
522 $this->code_length = 6;
523 $this->charset = 'ABCDEFGHKLMNPRSTUVWYZabcdefghklmnprstuvwyz23456789';
524 $this->wordlist_file = './words/words.txt';
525 $this->use_wordlist = false;
526
527 $this->gd_font_file = 'gdfonts/automatic.gdf';
528 $this->use_gd_font = false;
529 $this->gd_font_size = 24;
530 $this->text_x_start = 15;
531
532 $this->ttf_file = './AHGBold.ttf';
533
534 $this->perturbation = 0.75;
535 $this->iscale = 5;
536 $this->text_angle_minimum = 0;
537 $this->text_angle_maximum = 0;
538
539 $this->image_bg_color = new Securimage_Color(0xff, 0xff, 0xff);
540 $this->text_color = new Securimage_Color(0x3d, 0x3d, 0x3d);
541 $this->multi_text_color = array(new Securimage_Color(0x0, 0x20, 0xCC),
542 new Securimage_Color(0x0, 0x30, 0xEE),
543 new Securimage_color(0x0, 0x40, 0xCC),
544 new Securimage_Color(0x0, 0x50, 0xEE),
545 new Securimage_Color(0x0, 0x60, 0xCC));
546 $this->use_multi_text = false;
547
548 $this->use_transparent_text = false;
550
551 $this->num_lines = 10;
552 $this->line_color = new Securimage_Color(0x3d, 0x3d, 0x3d);
553 $this->draw_lines_over_text = true;
554
555 $this->image_signature = '';
556 $this->signature_color = new Securimage_Color(0x20, 0x50, 0xCC);
557 $this->signature_font = './AHGBold.ttf';
558
559 $this->audio_path = './audio/';
560 $this->audio_format = 'mp3';
561 $this->session_name = '';
562 $this->expiry_time = 900;
563
564 $this->sqlite_database = 'database/securimage.sqlite';
565 $this->use_sqlite_db = false;
566
567 $this->sqlite_handle = false;
568 }
569
570 /**
571 * Generate a code and output the image to the browser.
572 *
573 * <code>
574 * <?php
575 * include 'securimage.php';
576 * $securimage = new Securimage();
577 * $securimage->show('bg.jpg');
578 * ?>
579 * </code>
580 *
581 * @param string $background_image The path to an image to use as the background for the CAPTCHA
582 */
583 function show($background_image = "")
584 {
585 if($background_image != "" && is_readable($background_image)) {
586 $this->bgimg = $background_image;
587 }
588
589 $this->doImage();
590 }
591
592 /**
593 * Validate the code entered by the user.
594 *
595 * <code>
596 * $code = $_POST['code'];
597 * if ($securimage->check($code) == false) {
598 * die("Sorry, the code entered did not match.");
599 * } else {
600 * $valid = true;
601 * }
602 * </code>
603 * @param string $code The code the user entered
604 * @return boolean true if the code was correct, false if not
605 */
606 function check($code)
607 {
608 $this->code_entered = $code;
609 $this->validate();
610 return $this->correct_code;
611 }
612
613 /**
614 * Output audio file with HTTP headers to browser
615 *
616 * <code>
617 * $sound = new Securimage();
618 * $sound->audio_format = 'mp3';
619 * $sound->outputAudioFile();
620 * </code>
621 *
622 * @since 2.0
623 */
625 {
626 if (strtolower($this->audio_format) == 'wav') {
627 header('Content-type: audio/x-wav');
628 $ext = 'wav';
629 } else {
630 header('Content-type: audio/mpeg'); // default to mp3
631 $ext = 'mp3';
632 }
633
634 header("Content-Disposition: attachment; filename=\"securimage_audio.{$ext}\"");
635 header('Cache-Control: no-store, no-cache, must-revalidate');
636 header('Expires: Sun, 1 Jan 2000 12:00:00 GMT');
637 header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . 'GMT');
638
639 $audio = $this->getAudibleCode($ext);
640
641 header('Content-Length: ' . strlen($audio));
642
643 echo $audio;
644 exit;
645 }
646
647 /**
648 * Generate and output the image
649 *
650 * @access private
651 *
652 */
653 function doImage()
654 {
655 if ($this->use_gd_font == true || $this->iscale == null || $this->iscale == 0) {
656 $this->iscale = 1;
657 }
658 if($this->use_transparent_text == true || $this->bgimg != "") {
659 $this->im = imagecreatetruecolor($this->image_width, $this->image_height);
660 $this->tmpimg = imagecreatetruecolor($this->image_width * $this->iscale, $this->image_height * $this->iscale);
661
662 } else { //no transparency
663 $this->im = imagecreate($this->image_width, $this->image_height);
664 $this->tmpimg = imagecreate($this->image_width * $this->iscale, $this->image_height * $this->iscale);
665 }
666
667 $this->allocateColors();
668 imagepalettecopy($this->tmpimg, $this->im);
669
670 $this->setBackground();
671
672 $this->createCode();
673
674 if (!$this->draw_lines_over_text && $this->num_lines > 0) $this->drawLines();
675
676 $this->drawWord();
677 if ($this->use_gd_font == false && is_readable($this->ttf_file)) $this->distortedCopy();
678
679 if ($this->draw_lines_over_text && $this->num_lines > 0) $this->drawLines();
680
681 if (trim($this->image_signature) != '') $this->addSignature();
682
683 $this->output();
684
685 }
686
687 /**
688 * Allocate all colors that will be used in the CAPTCHA image
689 *
690 * @since 2.0.1
691 * @access private
692 */
693 function allocateColors()
694 {
695 // allocate bg color first for imagecreate
696 $this->gdbgcolor = imagecolorallocate($this->im, $this->image_bg_color->r??0, $this->image_bg_color->g??0, $this->image_bg_color->b??0);
697
698 $this->text_color->r=$this->text_color->r??rand(0,255);
699 $this->text_color->g=$this->text_color->g??rand(0,255);
700 $this->text_color->b=$this->text_color->b??rand(0,255);
701 $this->line_color->r=$this->line_color->r??rand(0,255);
702 $this->line_color->g=$this->line_color->g??rand(0,255);
703 $this->line_color->b=$this->line_color->b??rand(0,255);
704
705
706
707 $alpha = intval($this->text_transparency_percentage / 100 * 127);
708
709 if ($this->use_transparent_text == true) {
710 $this->gdtextcolor = imagecolorallocatealpha($this->im, $this->text_color->r, $this->text_color->g, $this->text_color->b, $alpha);
711 $this->gdlinecolor = imagecolorallocatealpha($this->im, $this->line_color->r, $this->line_color->g, $this->line_color->b, $alpha);
712 } elseif ( $this->text_color != null ) {
713 $this->gdtextcolor = imagecolorallocate($this->im, $this->text_color->r, $this->text_color->g, $this->text_color->b);
714 $this->gdlinecolor = imagecolorallocate($this->im, $this->line_color->r, $this->line_color->g, $this->line_color->b);
715 } else {
716 $red=rand(0,255);
717 $green=rand(0,255);
718 $blue=rand(0,255);
719 $this->gdtextcolor = imagecolorallocate($this->im, $red, $green,$blue);
720 $this->gdlinecolor = imagecolorallocate($this->im, $red, $green, $blue);
721 }
722
723 $this->gdsignaturecolor = imagecolorallocate($this->im, $this->signature_color->r??0, $this->signature_color->g??0, $this->signature_color->b??0);
724
725 if ($this->use_multi_text == true) {
726 $this->gdmulticolor = array();
727
728 foreach($this->multi_text_color??[] as $color) {
729 $color->r=$color->r??rand(0,255);
730 $color->g= $color->g??rand(0,255);
731 $color->b=$color->b??rand(0,255);
732 if ($this->use_transparent_text == true) {
733 $this->gdmulticolor[] = imagecolorallocatealpha($this->im, $color->r, $color->g, $color->b, $alpha);
734 } else {
735 $this->gdmulticolor[] = imagecolorallocate($this->im, $color->r, $color->g, $color->b);
736 }
737 }
738 }
739 }
740
741 /**
742 * Set the background of the CAPTCHA image
743 *
744 * @access private
745 *
746 */
747 function setBackground()
748 {
749 imagefilledrectangle($this->im, 0, 0, $this->image_width * $this->iscale, $this->image_height * $this->iscale, $this->gdbgcolor);
750 imagefilledrectangle($this->tmpimg, 0, 0, $this->image_width * $this->iscale, $this->image_height * $this->iscale, $this->gdbgcolor);
751
752 if ($this->bgimg == '') {
753 if ($this->background_directory != null && is_dir($this->background_directory) && is_readable($this->background_directory)) {
755 if ($img != false) {
756 $this->bgimg = $img;
757 }
758 }
759 }
760
761 $dat = @getimagesize($this->bgimg);
762 if($dat == false) {
763 return;
764 }
765
766 switch($dat[2]) {
767 case 1: $newim = @imagecreatefromgif($this->bgimg); break;
768 case 2: $newim = @imagecreatefromjpeg($this->bgimg); break;
769 case 3: $newim = @imagecreatefrompng($this->bgimg); break;
770 case 15: $newim = @imagecreatefromwbmp($this->bgimg); break;
771 case 16: $newim = @imagecreatefromxbm($this->bgimg); break;
772 default: return;
773 }
774
775 if(!$newim) return;
776
777 imagecopyresized($this->im, $newim, 0, 0, 0, 0, $this->image_width, $this->image_height, imagesx($newim), imagesy($newim));
778 }
779
780 /**
781 * Return the full path to a random gif, jpg, or png from the background directory.
782 *
783 * @access private
784 * @see Securimage::$background_directory
785 * @return mixed false if none found, string $path if found
786 */
788 {
789 $images = array();
790
791 if ($dh = opendir($this->background_directory)) {
792 while (($file = readdir($dh)) !== false) {
793 if (preg_match('/(jpg|gif|png)$/i', $file)) $images[] = $file;
794 }
795
796 closedir($dh);
797
798 if (sizeof($images) > 0) {
799 return rtrim($this->background_directory, '/') . '/' . $images[rand(0, sizeof($images)-1)];
800 }
801 }
802
803 return false;
804 }
805
806 /**
807 * Draw random curvy lines over the image<br />
808 * Modified code from HKCaptcha
809 *
810 * @since 2.0
811 * @access private
812 *
813 */
814 function drawLines()
815 {
816 for ($line = 0; $line < $this->num_lines; ++$line) {
817 $x = $this->image_width * (1 + $line) / ($this->num_lines + 1);
818 $x += (0.5 - $this->frand()) * $this->image_width / $this->num_lines;
819 $y = rand($this->image_height * 0.1, $this->image_height * 0.9);
820
821 $theta = ($this->frand()-0.5) * M_PI * 0.7;
822 $w = $this->image_width;
823 $len = rand($w * 0.4, $w * 0.7);
824 $lwid = rand(0, 2);
825
826 $k = $this->frand() * 0.6 + 0.2;
827 $k = $k * $k * 0.5;
828 $phi = $this->frand() * 6.28;
829 $step = 0.5;
830 $dx = $step * cos($theta);
831 $dy = $step * sin($theta);
832 $n = $len / $step;
833 $amp = 1.5 * $this->frand() / ($k + 5.0 / $len);
834 $x0 = $x - 0.5 * $len * cos($theta);
835 $y0 = $y - 0.5 * $len * sin($theta);
836
837 $ldx = round(-$dy * $lwid);
838 $ldy = round($dx * $lwid);
839
840 for ($i = 0; $i < $n; ++$i) {
841 $x = $x0 + $i * $dx + $amp * $dy * sin($k * $i * $step + $phi);
842 $y = $y0 + $i * $dy - $amp * $dx * sin($k * $i * $step + $phi);
843 $x=(int) $x;
844 $y=(int) $y;
845 imagefilledrectangle($this->im, $x, $y, $x + $lwid, $y + $lwid, $this->gdlinecolor);
846 }
847 }
848 }
849
850 /**
851 * Draw the CAPTCHA code over the image
852 *
853 * @access private
854 *
855 */
856 function drawWord()
857 {
858 $width2 = $this->image_width * $this->iscale;
859 $height2 = $this->image_height * $this->iscale;
860
861 if ($this->use_gd_font == true || !is_readable($this->ttf_file??"")) {
862 if (!is_int($this->gd_font_file)) { //is a file name
863 $font = @imageloadfont($this->gd_font_file??"");
864 if ($font == false) {
865 trigger_error("Failed to load GD Font file {$this->gd_font_file} ", E_USER_WARNING);
866 return;
867 }
868 } else { //gd font identifier
869 $font = $this->gd_font_file;
870 }
871
872 imagestring($this->im, $font, $this->text_x_start, ($this->image_height / 2) - ($this->gd_font_size / 2), $this->code, $this->gdtextcolor);
873 } else { //ttf font
874 $font_size = $height2 * .35;
875 $bb = imagettfbbox($font_size, 0, $this->ttf_file, $this->code);
876 $tx = $bb[4] - $bb[0];
877 $ty = $bb[5] - $bb[1];
878 $x = floor($width2 / 2 - $tx / 2 - $bb[0]);
879 $y = round($height2 / 2 - $ty / 2 - $bb[1]);
880
881 $strlen = strlen($this->code);
882 if (!is_array($this->multi_text_color)) $this->use_multi_text = false;
883
884
885 if ($this->use_multi_text == false && $this->text_angle_minimum == 0 && $this->text_angle_maximum == 0) { // no angled or multi-color characters
886 imagettftext($this->tmpimg, $font_size, 0, $x, $y, $this->gdtextcolor, $this->ttf_file, $this->code);
887 } else {
888 for($i = 0; $i < $strlen; ++$i) {
889 $angle = rand($this->text_angle_minimum, $this->text_angle_maximum);
890 $y = rand($y - 5, $y + 5);
891 if ($this->use_multi_text == true) {
892 $font_color = $this->gdmulticolor[rand(0, sizeof($this->gdmulticolor) - 1)];
893 } else {
894 $font_color = $this->gdtextcolor;
895 }
896
897 $ch = $this->code[$i];
898
899 imagettftext($this->tmpimg, $font_size, $angle, $x, $y, $font_color, $this->ttf_file, $ch);
900
901 // estimate character widths to increment $x without creating spaces that are too large or too small
902 // these are best estimates to align text but may vary between fonts
903 // for optimal character widths, do not use multiple text colors or character angles and the complete string will be written by imagettftext
904 if (strpos('abcdeghknopqsuvxyz', $ch) !== false) {
905 $min_x = $font_size - ($this->iscale * 6);
906 $max_x = $font_size - ($this->iscale * 6);
907 } else if (strpos('ilI1', $ch) !== false) {
908 $min_x = $font_size / 5;
909 $max_x = $font_size / 3;
910 } else if (strpos('fjrt', $ch) !== false) {
911 $min_x = $font_size - ($this->iscale * 12);
912 $max_x = $font_size - ($this->iscale * 12);
913 } else if ($ch == 'wm') {
914 $min_x = $font_size;
915 $max_x = $font_size + ($this->iscale * 3);
916 } else { // numbers, capitals or unicode
917 $min_x = $font_size + ($this->iscale * 2);
918 $max_x = $font_size + ($this->iscale * 5);
919 }
920
921 $x += rand((int)$min_x,(int) $max_x);
922 } //for loop
923 } // angled or multi-color
924 } //else ttf font
925 //$this->im = $this->tmpimg;
926 //$this->output();
927 } //function
928
929 /**
930 * Warp text from temporary image onto final image.<br />
931 * Modified for securimage
932 *
933 * @access private
934 * @since 2.0
935 * @author Han-Kwang Nienhuys modified
936 * @copyright Han-Kwang Neinhuys
937 *
938 */
939 function distortedCopy()
940 {
941 $numpoles = 3; // distortion factor
942
943 // make array of poles AKA attractor points
944 for ($i = 0; $i < $numpoles; ++$i) {
945 $px[$i] = rand((int) ($this->image_width * 0.3), (int)( $this->image_width * 0.7));
946 $py[$i] = rand((int) ($this->image_height * 0.3),(int) ($this->image_height * 0.7));
947 $rad[$i] = rand((int) ($this->image_width * 0.4), (int) ($this->image_width * 0.7));
948 $tmp = -$this->frand() * 0.15 - 0.15;
949 $amp[$i] = $this->perturbation * $tmp;
950 }
951
952 $bgCol = imagecolorat($this->tmpimg, 0, 0);
953 $width2 = $this->iscale * $this->image_width;
954 $height2 = $this->iscale * $this->image_height;
955
956 imagepalettecopy($this->im, $this->tmpimg); // copy palette to final image so text colors come across
957
958 // loop over $img pixels, take pixels from $tmpimg with distortion field
959 for ($ix = 0; $ix < $this->image_width; ++$ix) {
960 for ($iy = 0; $iy < $this->image_height; ++$iy) {
961 $x = $ix;
962 $y = $iy;
963
964 for ($i = 0; $i < $numpoles; ++$i) {
965 $dx = $ix - $px[$i];
966 $dy = $iy - $py[$i];
967 if ($dx == 0 && $dy == 0) continue;
968
969 $r = sqrt($dx * $dx + $dy * $dy);
970 if ($r > $rad[$i]) continue;
971
972 $rscale = $amp[$i] * sin(3.14 * $r / $rad[$i]);
973 $x += $dx * $rscale;
974 $y += $dy * $rscale;
975 }
976
977 $c = $bgCol;
978 $x *= $this->iscale;
979 $y *= $this->iscale;
980
981 if ($x >= 0 && $x < $width2 && $y >= 0 && $y < $height2) {
982 $c = imagecolorat($this->tmpimg, (int) $x,(int) $y);
983 }
984
985 if ($c != $bgCol) { // only copy pixels of letters to preserve any background image
986 imagesetpixel($this->im, $ix, $iy, $c);
987 }
988 }
989 }
990 }
991
992 /**
993 * Create a code and save to the session
994 *
995 * @access private
996 * @since 1.0.1
997 *
998 */
999 function createCode()
1000 {
1001 $this->code = false;
1002
1003 if ($this->use_wordlist && is_readable($this->wordlist_file)) {
1004 $this->code = $this->readCodeFromFile();
1005 }
1006
1007 if ($this->code == false) {
1008 $this->code = $this->generateCode($this->code_length);
1009 }
1010
1011 $this->saveData();
1012 }
1013
1014 /**
1015 * Generate a code
1016 *
1017 * @access private
1018 * @param int $len The code length
1019 * @return string
1020 */
1021 function generateCode($len)
1022 {
1023 $code = '';
1024
1025 for($i = 1, $cslen = strlen($this->charset??""); $i <= $len; ++$i) {
1026 $code .= $this->charset[rand(0, $cslen - 1)];
1027 }
1028 return $code;
1029 }
1030
1031 /**
1032 * Reads a word list file to get a code
1033 *
1034 * @access private
1035 * @since 1.0.2
1036 * @return mixed false on failure, a word on success
1037 */
1039 {
1040 $fp = @fopen($this->wordlist_file, 'rb');
1041 if (!$fp) return false;
1042
1043 $fsize = filesize($this->wordlist_file);
1044 if ($fsize < 32) return false; // too small of a list to be effective
1045
1046 if ($fsize < 128) {
1047 $max = $fsize; // still pretty small but changes the range of seeking
1048 } else {
1049 $max = 128;
1050 }
1051
1052 fseek($fp, rand(0, $fsize - $max), SEEK_SET);
1053 $data = fread($fp, 128); // read a random 128 bytes from file
1054 fclose($fp);
1055 $data = preg_replace("/\r?\n/", "\n", $data);
1056
1057 $start = strpos($data, "\n", rand(0, 100)) + 1; // random start position
1058 $end = strpos($data, "\n", $start); // find end of word
1059
1060 return strtolower(substr($data, $start, $end - $start)); // return substring in 128 bytes
1061 }
1062
1063 /**
1064 * Output image to the browser
1065 *
1066 * @access private
1067 *
1068 */
1069 function output()
1070 {
1071 header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
1072 header("Last-Modified: " . gmdate("D, d M Y H:i:s") . "GMT");
1073 header("Cache-Control: no-store, no-cache, must-revalidate");
1074 header("Cache-Control: post-check=0, pre-check=0", false);
1075 header("Pragma: no-cache");
1076
1077 switch($this->image_type)
1078 {
1079 case SI_IMAGE_JPEG:
1080 header("Content-Type: image/jpeg");
1081 imagejpeg($this->im, null, 90);
1082 break;
1083
1084 case SI_IMAGE_GIF:
1085 header("Content-Type: image/gif");
1086 imagegif($this->im);
1087 break;
1088
1089 default:
1090 header("Content-Type: image/png");
1091 imagepng($this->im);
1092 break;
1093 }
1094
1095 imagedestroy($this->im);
1096 exit;
1097 }
1098
1099 /**
1100 * Get WAV or MP3 file data of the spoken code.<br />
1101 * This is appropriate for output to the browser as audio/x-wav or audio/mpeg
1102 *
1103 * @since 1.0.1
1104 * @return string WAV or MP3 data
1105 *
1106 */
1107 function getAudibleCode($format = 'wav')
1108 {
1109 $letters = array();
1110 $code = $this->getCode();
1111
1112 if ($code == '') {
1113 $this->createCode();
1114 $code = $this->getCode();
1115 }
1116
1117 for($i = 0; $i < strlen($code); ++$i) {
1118 $letters[] = $code[$i];
1119 }
1120
1121 if ($format == 'mp3') {
1122 return $this->generateMP3($letters);
1123 } else {
1124 return $this->generateWAV($letters);
1125 }
1126 }
1127
1128 /**
1129 * Set the path to the audio directory.<br />
1130 *
1131 * @since 1.0.4
1132 * @return bool true if the directory exists and is readble, false if not
1133 */
1134 function setAudioPath($audio_directory)
1135 {
1136 if (is_dir($audio_directory) && is_readable($audio_directory)) {
1137 $this->audio_path = $audio_directory;
1138 return true;
1139 } else {
1140 return false;
1141 }
1142 }
1143
1144 /**
1145 * Save the code in the session
1146 *
1147 * @access private
1148 *
1149 */
1150 function saveData()
1151 {
1152 $_SESSION['securimage_code_value'] = strtolower($this->code);
1153 $_SESSION['securimage_code_ctime'] = time();
1154
1155 $this->saveCodeToDatabase();
1156 }
1157
1158 /**
1159 * Validate the code to the user code
1160 *
1161 * @access private
1162 *
1163 */
1164 function validate()
1165 {
1166 $code='';
1167 // retrieve code from session, if no code exists check sqlite database if supported.
1168
1169 if (isset($_SESSION['securimage_code_value']) && trim($_SESSION['securimage_code_value']) != '') {
1170 if ($this->isCodeExpired($_SESSION['securimage_code_ctime']) == false) {
1171 $code = $_SESSION['securimage_code_value'];
1172 }
1173 } else if ($this->use_sqlite_db == true && function_exists('sqlite_open')) { // no code in session - may mean user has cookies turned off
1174 $this->openDatabase();
1175 $code = $this->getCodeFromDatabase();
1176 } else {
1177 // session code invalid or non-existant and code not found in sqlite db or sqlite is not available
1178 $code = '';
1179 }
1180
1181 $code = trim(strtolower($code));
1182 $code_entered = trim(strtolower($this->code_entered));
1183 $this->correct_code = false;
1184
1185 if ($code != '') {
1186 if ($code == $code_entered) {
1187 $this->correct_code = true;
1188 $_SESSION['securimage_code_value'] = '';
1189 $_SESSION['securimage_code_ctime'] = '';
1190 $this->clearCodeFromDatabase();
1191 }
1192 }
1193 }
1194
1195 /**
1196 * Get the captcha code
1197 *
1198 * @since 1.0.1
1199 * @return string
1200 */
1201 function getCode()
1202 {
1203 if (isset($_SESSION['securimage_code_value']) && !empty($_SESSION['securimage_code_value'])) {
1204 return strtolower($_SESSION['securimage_code_value']);
1205 } else {
1206 if ($this->sqlite_handle == false) $this->openDatabase();
1207
1208 return $this->getCodeFromDatabase(); // attempt to get from database, returns empty string if sqlite is not available or disabled
1209 }
1210 }
1211
1212 /**
1213 * Check if the user entered code was correct
1214 *
1215 * @access private
1216 * @return boolean
1217 */
1218 function checkCode()
1219 {
1220 return $this->correct_code;
1221 }
1222
1223 /**
1224 * Generate a wav file by concatenating individual files
1225 *
1226 * @since 1.0.1
1227 * @access private
1228 * @param array $letters Array of letters to build a file from
1229 * @return string WAV file data
1230 */
1231 function generateWAV($letters)
1232 {
1233 $data_len = 0;
1234 $files = array();
1235 $out_data = '';
1236
1237 foreach ($letters as $letter) {
1238 $filename = $this->audio_path . strtoupper($letter) . '.wav';
1239
1240 $fp = fopen($filename, 'rb');
1241
1242 $file = array();
1243
1244 $data = fread($fp, filesize($filename)); // read file in
1245
1246 $header = substr($data, 0, 36);
1247 $body = substr($data, 44);
1248
1249
1250 $data = unpack('NChunkID/VChunkSize/NFormat/NSubChunk1ID/VSubChunk1Size/vAudioFormat/vNumChannels/VSampleRate/VByteRate/vBlockAlign/vBitsPerSample', $header);
1251
1252 $file['sub_chunk1_id'] = $data['SubChunk1ID'];
1253 $file['bits_per_sample'] = $data['BitsPerSample'];
1254 $file['channels'] = $data['NumChannels'];
1255 $file['format'] = $data['AudioFormat'];
1256 $file['sample_rate'] = $data['SampleRate'];
1257 $file['size'] = $data['ChunkSize'] + 8;
1258 $file['data'] = $body;
1259
1260 if ( ($p = strpos($file['data'], 'LIST')) !== false) {
1261 // If the LIST data is not at the end of the file, this will probably break your sound file
1262 $info = substr($file['data'], $p + 4, 8);
1263 $data = unpack('Vlength/Vjunk', $info);
1264 $file['data'] = substr($file['data'], 0, $p);
1265 $file['size'] = $file['size'] - (strlen($file['data']) - $p);
1266 }
1267
1268 $files[] = $file;
1269 $data = null;
1270 $header = null;
1271 $body = null;
1272
1273 $data_len += strlen($file['data']);
1274
1275 fclose($fp);
1276 }
1277
1278 $out_data = '';
1279 for($i = 0; $i < sizeof($files); ++$i) {
1280 if ($i == 0) { // output header
1281 $out_data .= pack('C4VC8', ord('R'), ord('I'), ord('F'), ord('F'), $data_len + 36, ord('W'), ord('A'), ord('V'), ord('E'), ord('f'), ord('m'), ord('t'), ord(' '));
1282
1283 $out_data .= pack('VvvVVvv',
1284 16,
1285 $files[$i]['format'],
1286 $files[$i]['channels'],
1287 $files[$i]['sample_rate'],
1288 $files[$i]['sample_rate'] * (($files[$i]['bits_per_sample'] * $files[$i]['channels']) / 8),
1289 ($files[$i]['bits_per_sample'] * $files[$i]['channels']) / 8,
1290 $files[$i]['bits_per_sample'] );
1291
1292 $out_data .= pack('C4', ord('d'), ord('a'), ord('t'), ord('a'));
1293
1294 $out_data .= pack('V', $data_len);
1295 }
1296
1297 $out_data .= $files[$i]['data'];
1298 }
1299
1300 $this->scrambleAudioData($out_data, 'wav');
1301 return $out_data;
1302 }
1303
1304 /**
1305 * Randomly modify the audio data to scramble sound and prevent binary recognition.<br />
1306 * Take care not to "break" the audio file by leaving the header data intact.
1307 *
1308 * @since 2.0
1309 * @access private
1310 * @param $data Sound data in mp3 of wav format
1311 */
1312 function scrambleAudioData(&$data, $format)
1313 {
1314 if ($format == 'wav') {
1315 $start = strpos($data, 'data') + 4; // look for "data" indicator
1316 if ($start === false) $start = 44; // if not found assume 44 byte header
1317 } else { // mp3
1318 $start = 4; // 4 byte (32 bit) frame header
1319 }
1320
1321 $start += rand(1, 64); // randomize starting offset
1322 $datalen = strlen($data) - $start - 256; // leave last 256 bytes unchanged
1323
1324 for ($i = $start; $i < $datalen; $i += 64) {
1325 $ch = ord($data[$i]);
1326 if ($ch < 9 || $ch > 119) continue;
1327
1328 $data[$i] = chr($ch + rand(-8, 8));
1329 }
1330 }
1331
1332 /**
1333 * Generate an mp3 file by concatenating individual files
1334 * @since 1.0.4
1335 * @access private
1336 * @param array $letters Array of letters to build a file from
1337 * @return string MP3 file data
1338 */
1339 function generateMP3($letters)
1340 {
1341 $data_len = 0;
1342 $files = array();
1343 $out_data = '';
1344
1345 foreach ($letters as $letter) {
1346 $filename = $this->audio_path . strtoupper($letter) . '.mp3';
1347
1348 $fp = fopen($filename, 'rb');
1349 $data = fread($fp, filesize($filename)); // read file in
1350
1351 $this->scrambleAudioData($data, 'mp3');
1352 $out_data .= $data;
1353
1354 fclose($fp);
1355 }
1356
1357
1358 return $out_data;
1359 }
1360
1361 /**
1362 * Generate random number less than 1
1363 * @since 2.0
1364 * @access private
1365 * @return float
1366 */
1367 function frand()
1368 {
1369 return 0.0001*rand(0,9999);
1370 }
1371
1372 /**
1373 * Print signature text on image
1374 *
1375 * @since 2.0
1376 * @access private
1377 *
1378 */
1379 function addSignature()
1380 {
1381 if ($this->use_gd_font) {
1382 imagestring($this->im, 5, $this->image_width - (strlen($this->image_signature) * 10), $this->image_height - 20, $this->image_signature, $this->gdsignaturecolor);
1383 } else {
1384
1385 $bbox = imagettfbbox(10, 0, $this->signature_font, $this->image_signature);
1386 $textlen = $bbox[2] - $bbox[0];
1387 $x = $this->image_width - $textlen - 5;
1388 $y = $this->image_height - 3;
1389
1390 imagettftext($this->im, 10, 0, $x, $y, $this->gdsignaturecolor, $this->signature_font, $this->image_signature);
1391 }
1392 }
1393
1394 /**
1395 * Get hashed IP address of remote user
1396 *
1397 * @access private
1398 * @since 2.0.1
1399 * @return string
1400 */
1401 function getIPHash()
1402 {
1403 return strtolower(md5($_SERVER['REMOTE_ADDR']));
1404 }
1405
1406 /**
1407 * Open SQLite database
1408 *
1409 * @access private
1410 * @since 2.0.1
1411 * @return bool true if database was opened successfully
1412 */
1413 function openDatabase()
1414 {
1415 $this->sqlite_handle = false;
1416
1417 if ($this->use_sqlite_db && function_exists('sqlite_open')) {
1418 $this->sqlite_handle = sqlite_open($this->sqlite_database, 0666, $error);
1419
1420 if ($this->sqlite_handle !== false) {
1421 $res = sqlite_query($this->sqlite_handle, "PRAGMA table_info(codes)");
1422 if (sqlite_num_rows($res) == 0) {
1423 sqlite_query($this->sqlite_handle, "CREATE TABLE codes (iphash VARCHAR(32) PRIMARY KEY, code VARCHAR(32) NOT NULL, created INTEGER)");
1424 }
1425 }
1426
1427 return $this->sqlite_handle != false;
1428 }
1429
1430 return $this->sqlite_handle;
1431 }
1432
1433 /**
1434 * Save captcha code to sqlite database
1435 *
1436 * @access private
1437 * @since 2.0.1
1438 * @return bool true if code was saved, false if not
1439 */
1441 {
1442 $success = false;
1443
1444 $this->openDatabase();
1445
1446 if ($this->use_sqlite_db && $this->sqlite_handle !== false) {
1447 $ip = $this->getIPHash();
1448 $time = time();
1449 $code = $_SESSION['securimage_code_value']; // hash code for security - if cookies are disabled the session still exists at this point
1450 $success = sqlite_query($this->sqlite_handle, "INSERT OR REPLACE INTO codes(iphash, code, created) VALUES('$ip', '$code', $time)");
1451 }
1452
1453 return $success !== false;
1454 }
1455
1456 /**
1457 * Get stored captcha code from sqlite database based on ip address hash
1458 *
1459 * @access private
1460 * @since 2.0.1
1461 * @return string captcha code
1462 */
1464 {
1465 $code = '';
1466
1467 if ($this->use_sqlite_db && $this->sqlite_handle !== false) {
1468 $ip = $this->getIPHash();
1469
1470 $res = sqlite_query($this->sqlite_handle, "SELECT * FROM codes WHERE iphash = '$ip'");
1471 if ($res && sqlite_num_rows($res) > 0) {
1472 $res = sqlite_fetch_array($res);
1473
1474 if ($this->isCodeExpired($res['created']) == false) {
1475 $code = $res['code'];
1476 }
1477 }
1478 }
1479
1480 return $code;
1481 }
1482
1483 /**
1484 * Delete a code from the database by ip address hash
1485 *
1486 * @access private
1487 * @since 2.0.1
1488 */
1490 {
1491 if ($this->sqlite_handle !== false) {
1492 $ip = $this->getIPHash();
1493
1494 sqlite_query($this->sqlite_handle, "DELETE FROM codes WHERE iphash = '$ip'");
1495 }
1496 }
1497
1498 /**
1499 * Purge codes over a day old from database
1500 *
1501 * @access private
1502 * @since 2.0.1
1503 */
1505 {
1506 if ($this->use_sqlite_db && $this->sqlite_handle !== false) {
1507 $now = time();
1508 $limit = (!is_numeric($this->expiry_time) || $this->expiry_time < 1) ? 86400 : $this->expiry_time;
1509
1510 sqlite_query($this->sqlite_handle, "DELETE FROM codes WHERE $now - created > $limit");
1511 }
1512 }
1513
1514 /**
1515 * Check a code to see if it is expired based on creation time
1516 *
1517 * @access private
1518 * @since 2.0.1
1519 * @param $creation_time unix timestamp of code creation time
1520 * @return bool true if code has expired, false if not
1521 */
1522 function isCodeExpired($creation_time)
1523 {
1524 $expired = true;
1525
1526 if (!is_numeric($this->expiry_time) || $this->expiry_time < 1) {
1527 $expired = false;
1528 } else if (time() - $creation_time < $this->expiry_time) {
1529 $expired = false;
1530 }
1531
1532 return $expired;
1533 }
1534
1535} /* class Securimage */
1536
1537
1538/**
1539 * Color object for Securimage CAPTCHA
1540 *
1541 * @since 2.0
1542 * @package Securimage
1543 * @subpackage classes
1544 *
1545 */
1547 /**
1548 * Red component: 0-255
1549 *
1550 * @var int
1551 */
1552 var $r;
1553 /**
1554 * Green component: 0-255
1555 *
1556 * @var int
1557 */
1558 var $g;
1559 /**
1560 * Blue component: 0-255
1561 *
1562 * @var int
1563 */
1564 var $b;
1565
1566 /**
1567 * Create a new Securimage_Color object.<br />
1568 * Specify the red, green, and blue components using their HTML hex code equivalent.<br />
1569 * Example: The code for the HTML color #4A203C is:<br />
1570 * $color = new Securimage_Color(0x4A, 0x20, 0x3C);
1571 *
1572 * @param $red Red component 0-255
1573 * @param $green Green component 0-255
1574 * @param $blue Blue component 0-255
1575 */
1576 function __construct($red, $green = null, $blue = null)
1577 {
1578 if ($green == null && $blue == null && preg_match('/^#[a-f0-9]{3,6}$/i', $red)) {
1579 $col = substr($red, 1);
1580 if (strlen($col) == 3) {
1581 $red = str_repeat(substr($col, 0, 1), 2);
1582 $green = str_repeat(substr($col, 1, 1), 2);
1583 $blue = str_repeat(substr($col, 2, 1), 2);
1584 } else {
1585 $red = substr($col, 0, 2);
1586 $green = substr($col, 2, 2);
1587 $blue = substr($col, 4, 2);
1588 }
1589
1590 $red = hexdec($red);
1591 $green = hexdec($green);
1592 $blue = hexdec($blue);
1593 } else {
1594 if ($red < 0) $red = 0;
1595 if ($red > 255) $red = 255;
1596 if ($green < 0) $green = 0;
1597 if ($green > 255) $green = 255;
1598 if ($blue < 0) $blue = 0;
1599 if ($blue > 255) $blue = 255;
1600 }
1601
1602 $this->r = $red;
1603 $this->g = $green;
1604 $this->b = $blue;
1605 }
1606}
catch(Exception $exc) if(! $g_user->can_write_action($ag_id)) $r
foreach($array as $idx=> $m) $w
$p
Definition calendar.php:9
__construct($red, $green=null, $blue=null)
Create a new Securimage_Color object.
validate()
Validate the code to the user code.
check($code)
Validate the code entered by the user.
scrambleAudioData(&$data, $format)
Randomly modify the audio data to scramble sound and prevent binary recognition.
saveData()
Save the code in the session.
drawLines()
Draw random curvy lines over the image Modified code from HKCaptcha.
isCodeExpired($creation_time)
Check a code to see if it is expired based on creation time.
saveCodeToDatabase()
Save captcha code to sqlite database.
output()
Output image to the browser.
allocateColors()
Allocate all colors that will be used in the CAPTCHA image.
purgeOldCodesFromDatabase()
Purge codes over a day old from database.
outputAudioFile()
Output audio file with HTTP headers to browser.
$text_transparency_percentage
drawWord()
Draw the CAPTCHA code over the image.
getCodeFromDatabase()
Get stored captcha code from sqlite database based on ip address hash.
$use_sqlite_db
Use an SQLite database for storing codes as a backup to sessions.
setAudioPath($audio_directory)
Set the path to the audio directory.
createCode()
Create a code and save to the session.
getAudibleCode($format='wav')
Get WAV or MP3 file data of the spoken code.
clearCodeFromDatabase()
Delete a code from the database by ip address hash.
openDatabase()
Open SQLite database.
__construct()
Class constructor.
generateMP3($letters)
Generate an mp3 file by concatenating individual files.
doImage()
Generate and output the image.
distortedCopy()
Warp text from temporary image onto final image.
setBackground()
Set the background of the CAPTCHA image.
show($background_image="")
Generate a code and output the image to the browser.
checkCode()
Check if the user entered code was correct.
generateCode($len)
Generate a code.
getBackgroundFromDirectory()
Return the full path to a random gif, jpg, or png from the background directory.
getIPHash()
Get hashed IP address of remote user.
generateWAV($letters)
Generate a wav file by concatenating individual files.
readCodeFromFile()
Reads a word list file to get a code.
addSignature()
Print signature text on image.
frand()
Generate random number less than 1.
getCode()
Get the captcha code.
$n
Definition compute.php:54
$c
Definition compute.php:48
for($e=0; $e< count($afiche); $e++) exit
if(count($a_accounting)==0) $header
if( $delta< 0) elseif( $delta==0)
Project: Securimage: A PHP class for creating and managing form CAPTCHA images File: securimage....
$img audio_format
$img image_height
$img use_multi_text
$img text_transparency_percentage
$img image_type
$img background_directory
$img num_lines
$img perturbation
$img line_color
$img bgimg
$img image_width
$img text_angle_minimum
$img image_signature
$img use_transparent_text
$img multi_text_color
$img text_angle_maximum
$img image_bg_color
$img signature_color
$img use_wordlist