Changeset 2175
- Timestamp:
- 08/29/2007 02:57:50 PM
- Files:
-
- trunk/demos/quickstart/protected/pages/Controls/Captcha.page (added)
- trunk/demos/quickstart/protected/pages/Controls/Samples/TCaptcha (added)
- trunk/demos/quickstart/protected/pages/Controls/Samples/TCaptcha/Home.page (added)
- trunk/demos/quickstart/protected/pages/Controls/Samples/TCaptcha/Home.php (added)
- trunk/demos/quickstart/protected/pages/Controls/Standard.page (modified) (1 diff)
- trunk/demos/quickstart/protected/pages/GettingStarted/NewFeatures.page (modified) (1 diff)
- trunk/framework/Exceptions/messages/messages.txt (modified) (1 diff)
- trunk/framework/Web/UI/WebControls/TCaptcha.php (modified) (6 diffs)
- trunk/framework/Web/UI/WebControls/assets/captcha.php (modified) (6 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/demos/quickstart/protected/pages/Controls/Standard.page
r2161 r2175 6 6 <li> 7 7 <a href="?page=Controls.Button">TButton</a> represents a click button on a Web page. It is mainly used to trigger page postback. 8 </li> 9 10 <li> 11 <a href="?page=Controls.Captcha">TCaptcha</a> displays a CAPTCHA to keep spammers from signing up for certain accounts online. 8 12 </li> 9 13 trunk/demos/quickstart/protected/pages/GettingStarted/NewFeatures.page
r2159 r2175 11 11 <li>Added a new control <a href="?page=Controls.TabPanel">TTabPanel</a> that displays tabbed views.</li> 12 12 <li>Added a new control <a href="?page=Controls.Keyboard">TKeyboard</a> that displays a virtual keyboard for text input.</li> 13 <li>Added a new module TCacheHttpSession that stores session data using a cache module to improve the session performance.</li>13 <li>Added a new control <a href="?page=Controls.Captcha">TCaptcha</a> that displays a CAPTCHA to keep spammers from signing up for certain accounts online. A related validator <tt>TCaptchaValidator</tt> is also implemented.</li> 14 14 <li>Added Oracle DB support to Active Record</li> 15 15 </ul> trunk/framework/Exceptions/messages/messages.txt
r2158 r2175 434 434 keyboard_forcontrol_required = TKeyboard.ForControl cannot be empty. 435 435 keyboard_forcontrol_invalid = TKeyboard.ForControl '{0}' is invalid. 436 437 captcha_tokenimagetheme_invalid = TCaptcha.TokenImageTheme must be an integer between {0} and {1}. 438 captcha_tokenfontsize_invalid = TCaptcha.TokenFontSize must be an integer between {0} and {1}. 439 captcha_mintokenlength_invalid = TCaptcha.MinTokenLength must be an integer between {0} and {1}. 440 captcha_maxtokenlength_invalid = TCaptcha.MaxTokenLength must be an integer between {0} and {1}. 441 captcha_tokenalphabet_invalid = TCaptcha.TokenAlphabet must be a string consisting of at least 2 characters. 442 captcha_privatekey_unknown = TCaptcha.PrivateKey is unknown. Please make sure that your assets directory is writable by the Web server process. 443 captcha_gd2_required = TCaptcha requires PHP GD2 extension. 444 captcha_imagettftext_required = TCaptcha requires PHP GD2 extension with TrueType font support. 445 captcha_imagepng_required = TCaptcha requires PHP GD2 extension with PNG image format support. trunk/framework/Web/UI/WebControls/TCaptcha.php
r2174 r2175 19 19 * to determine if the input is entered by a real user instead of some program. 20 20 * 21 * Unlike other CAPTCHA scripts, TCaptcha does not need session or cookie. 22 * 21 23 * The token (a string consisting of alphanumeric characters) displayed is automatically 22 24 * generated and can be configured in several ways. To specify the length of characters 23 25 * in the token, set {@link setMinTokenLength MinTokenLength} and {@link setMaxTokenLength MaxTokenLength}. 24 26 * To use case-insensitive comparison and generate upper-case-only token, set {@link setCaseSensitive CaseSensitive} 25 * to false. 27 * to false. More advanced users can try to set {@link setTokenAlphabet TokenAlphabet}, which 28 * specifies what characters can appear in tokens. 29 * 30 * To specify the appearance of the generated token image, set {@link setTokenImageTheme TokenImageTheme} 31 * to be an integer between 0 and 31. And to adjust the generated image size, set {@link setTokenFontSize TokenFontSize} 32 * (you may also set {@link TWebControl::setWidth Width}, but the scaled image may not look good.) 26 33 * 27 34 * Upon postback, user input can be validated by calling {@link validate()}. … … 30 37 * remain the same during multiple postbacks. A new one can be generated by calling 31 38 * {@link regenerateToken()} manually. 39 * 40 * The following template shows a typical use of TCaptcha control: 41 * <code> 42 * <com:TCaptcha ID="Captcha" /> 43 * <com:TTextBox ID="Input" /> 44 * <com:TCaptchaValidator CaptchaControl="Captcha" 45 * ControlToValidate="Input" 46 * ErrorMessage="You are challenged!" /> 47 * </code> 32 48 * 33 49 * @author Qiang Xue <qiang.xue@gmail.com> … … 42 58 private $_privateKey; 43 59 60 /** 61 * Checks the requirements needed for using TCaptcha. 62 */ 44 63 public function onInit($param) 45 64 { 46 65 parent::onInit($param); 47 66 $this->checkRequirements(); 67 } 68 69 /** 70 * @return integer the theme of the token image. Defaults to 0. 71 */ 72 public function getTokenImageTheme() 73 { 74 return $this->getViewState('TokenImageTheme',0); 75 } 76 77 /** 78 * Sets the theme of the token image. 79 * You may test each theme to find out the one you like the most. 80 * Below is the explanation of the theme value: 81 * It is treated as a 5-bit integer. Each bit toggles a specific feature of the image. 82 * Bit 0 (the least significant): whether the image is opaque (1) or transparent (0). 83 * Bit 1: whether we should add white noise to the image (1) or not (0). 84 * Bit 2: whether we should add a grid to the image (1) or not (0). 85 * Bit 3: whether we should add some scribbles to the image (1) or not (0). 86 * Bit 4: whether the image background should be morphed (1) or not (0). 87 * @param integer the theme of the token image. It must be an integer between 0 and 31. 88 */ 89 public function setTokenImageTheme($value) 90 { 91 $value=TPropertyValue::ensureInteger($value); 92 if($value>=0 && $value<=31) 93 $this->setViewState('TokenImageTheme',$value,0); 94 else 95 throw new TConfigurationException('captcha_tokenimagetheme_invalid',0,31); 96 } 97 98 /** 99 * @return integer the font size used for displaying the token in an image. Defaults to 30. 100 */ 101 public function getTokenFontSize() 102 { 103 return $this->getViewState('TokenFontSize',30); 104 } 105 106 /** 107 * Sets the font size used for displaying the token in an image. 108 * This property affects the generated token image size. 109 * The image width is proportional to this font size. 110 * @param integer the font size used for displaying the token in an image. It must be an integer between 20 and 100. 111 */ 112 public function setTokenFontSize($value) 113 { 114 $value=TPropertyValue::ensureInteger($value); 115 if($value>=20 && $value<=100) 116 $this->setViewState('TokenFontSize',$value,30); 117 else 118 throw new TConfigurationException('captcha_tokenfontsize_invalid',20,100); 48 119 } 49 120 … … 105 176 106 177 /** 107 * @return string the characters that may appear in the token. Defaults to '234578adefhijmnrtABDEFGHJLMN QRT'.178 * @return string the characters that may appear in the token. Defaults to '234578adefhijmnrtABDEFGHJLMNRT'. 108 179 */ 109 180 public function getTokenAlphabet() 110 181 { 111 return $this->getViewState('TokenAlphabet','234578adefhijmnrtABDEFGHJLMN QRT');182 return $this->getViewState('TokenAlphabet','234578adefhijmnrtABDEFGHJLMNRT'); 112 183 } 113 184 … … 119 190 if(strlen($value)<2) 120 191 throw new TConfigurationException('captcha_tokenalphabet_invalid'); 121 $this->setViewState('TokenAlphabet',$value,'234578adefhijmnrtABDEFGHJLMN QRT');192 $this->setViewState('TokenAlphabet',$value,'234578adefhijmnrtABDEFGHJLMNRT'); 122 193 } 123 194 … … 242 313 $options['caseSensitive']=$this->getCaseSensitive(); 243 314 $options['alphabet']=$this->getTokenAlphabet(); 315 $options['fontSize']=$this->getTokenFontSize(); 316 $options['theme']=$this->getTokenImageTheme(); 244 317 $str=serialize($options); 245 318 return base64_encode(md5($privateKey.$str).$str); trunk/framework/Web/UI/WebControls/assets/captcha.php
r2174 r2175 11 11 */ 12 12 13 define('THEME_OPAQUE_BACKGROUND',0x0001); 14 define('THEME_NOISY_BACKGROUND',0x0002); 15 define('THEME_HAS_GRID',0x0004); 16 define('THEME_HAS_SCRIBBLE',0x0008); 17 define('THEME_MORPH_BACKGROUND',0x0010); 18 13 19 require_once(dirname(__FILE__).'/captcha_key.php'); 14 20 15 21 $token='error'; 22 $theme=0; 23 16 24 if(isset($_GET['options'])) 17 25 { … … 28 36 $caseSensitive=$options['caseSensitive']; 29 37 $alphabet=$options['alphabet']; 38 $fontSize=$options['fontSize']; 39 $theme=$options['theme']; 30 40 $token=generateToken($publicKey,$privateKey,$alphabet,$tokenLength,$caseSensitive); 31 41 } … … 33 43 } 34 44 35 displayToken($token );45 displayToken($token,$fontSize,$theme); 36 46 37 47 function generateToken($publicKey,$privateKey,$alphabet,$tokenLength,$caseSensitive) … … 41 51 } 42 52 43 function hash2string($hex,$alphabet ='')53 function hash2string($hex,$alphabet) 44 54 { 45 55 if(strlen($alphabet)<2) 46 $alphabet='234578adefhijmnrtABDEFGHJLMN QRT';56 $alphabet='234578adefhijmnrtABDEFGHJLMNRT'; 47 57 $hexLength=strlen($hex); 48 58 $base=strlen($alphabet); … … 60 70 } 61 71 62 function displayToken($token) 63 { 72 function displayToken($token,$fontSize,$theme) 73 { 74 if(($fontSize=(int)$fontSize)<22) 75 $fontSize=22; 76 if($fontSize>100) 77 $fontSize=100; 64 78 $length=strlen($token); 65 $width=45*$length; 66 $height=70; 79 $padding=10; 80 $fontWidth=$fontSize; 81 $fontHeight=floor($fontWidth*1.5); 82 $width=$fontWidth*$length+$padding*2; 83 $height=$fontHeight; 67 84 $image=imagecreatetruecolor($width,$height); 85 86 addBackground 87 ( 88 $image, $width, $height, 89 $theme&THEME_OPAQUE_BACKGROUND, 90 $theme&THEME_NOISY_BACKGROUND, 91 $theme&THEME_HAS_GRID, 92 $theme&THEME_HAS_SCRIBBLE, 93 $theme&THEME_MORPH_BACKGROUND 94 ); 95 68 96 $font=dirname(__FILE__).DIRECTORY_SEPARATOR.'verase.ttf'; 69 $vred=rand(0,100); 70 $vgreen=rand(0,100); 71 $vblue=rand(0,100); 72 for($x=0;$x<$width;++$x) 73 { 74 for($y=0;$y<$height;++$y) 75 { 76 $vred+=rand(-2,2); 77 $vgreen+=rand(-2,2); 78 $vblue+=rand(-2,2); 79 if($vred<0) $vred=0; if($vred>150) $vred=75; 80 if($vgreen<0) $vgreen=0; if($vgreen>150) $vgreen=75; 81 if($vblue<0) $vblue=0; if($vblue>150) $vblue=75; 82 $col = imagecolorallocate($image, $vred, $vgreen, $vblue); 83 imagesetpixel($image, $x, $y, $col); 84 imagecolordeallocate($image, $col); 85 } 86 } 87 88 imagefilter($image,IMG_FILTER_GAUSSIAN_BLUR); 97 98 if(function_exists('imagefilter')) 99 imagefilter($image,IMG_FILTER_GAUSSIAN_BLUR); 100 89 101 for($i=0;$i<$length;$i++) 90 102 { 91 $vred = rand(150, 240); 92 $vgreen = rand(150, 240); 93 $vblue = rand(150, 240); 94 $col = imagecolorallocate($image, $vred, $vgreen, $vblue); 95 $char = $token[$i]; 96 imagettftext($image, rand(40, 50), rand(-10, 20), 13 + (40 * $i), rand(50, imagesy($image) - 10), $col, $font, $char); 97 imagecolordeallocate($image, $col); 103 $color=imagecolorallocate($image,rand(150,220),rand(150,220),rand(150,220)); 104 imagettftext($image,rand($fontWidth-10,$fontWidth),rand(-30, 30),$padding+$i*$fontWidth,rand($fontHeight-15,$fontHeight-10),$color,$font,$token[$i]); 105 imagecolordeallocate($image,$color); 98 106 } 99 imagefilter($image,IMG_FILTER_GAUSSIAN_BLUR);100 107 101 108 imagepng($image); … … 103 110 } 104 111 112 function addBackground($image,$width,$height,$opaque,$noisy,$hasGrid,$hasScribble,$morph) 113 { 114 $background=imagecreatetruecolor($width*2,$height*2); 115 $white=imagecolorallocate($background,255,255,255); 116 imagefill($background,0,0,$white); 117 118 if($opaque) 119 imagefill($background,0,0,imagecolorallocate($background,100,100,100)); 120 121 if($noisy) 122 addNoise($background,$width*2,$height*2); 123 124 if($hasGrid) 125 addGrid($background,$width*2,$height*2); 126 127 if($hasScribble) 128 addScribble($background,$width*2,$height*2); 129 130 if($morph) 131 morphImage($background,$width*2,$height*2); 132 133 imagecopy($image,$background,0,0,30,30,$width,$height); 134 135 if(!$opaque) 136 imagecolortransparent($image,$white); 137 } 138 139 function addNoise($image,$width,$height) 140 { 141 for($x=0;$x<$width;++$x) 142 { 143 for($y=0;$y<$height;++$y) 144 { 145 if(rand(0,100)<25) 146 { 147 $color=imagecolorallocate($image,rand(150,220),rand(150,220),rand(150,220)); 148 imagesetpixel($image,$x,$y,$color); 149 imagecolordeallocate($image,$color); 150 } 151 } 152 } 153 } 154 155 function addGrid($image,$width,$height) 156 { 157 for($i=0;$i<$width;$i+=rand(15,25)) 158 { 159 imagesetthickness($image,rand(2,6)); 160 $color=imagecolorallocate($image,rand(100,180),rand(100,180),rand(100,180)); 161 imageline($image,$i+rand(-10,20),0,$i+rand(-10,20),$height,$color); 162 imagecolordeallocate($image,$color); 163 } 164 for($i=0;$i<$height;$i+=rand(15,25)) 165 { 166 imagesetthickness($image,rand(2,6)); 167 $color=imagecolorallocate($image,rand(100,180),rand(100,180),rand(100,180)); 168 imageline($image,0,$i+rand(-10,20),$width,$i+rand(-10,20),$color); 169 imagecolordeallocate($image,$color); 170 } 171 } 172 173 function addScribble($image,$width,$height) 174 { 175 for($i=0;$i<8;$i++) 176 { 177 $color=imagecolorallocate($image,rand(100,180),rand(100,180),rand(100,180)); 178 $points=array(); 179 for($j=1;$j<rand(5,10);$j++) 180 { 181 $points[]=rand(2*(20*($i+1)),2*(50*($i+1))); 182 $points[]=rand(30,$height+30); 183 } 184 imagesetthickness($image,rand(2,6)); 185 imagepolygon($image,$points,intval(sizeof($points)/2),$color); 186 imagecolordeallocate($image,$color); 187 } 188 } 189 190 function morphImage($image,$width,$height) 191 { 192 $tempImage=imagecreatetruecolor($width,$height); 193 $chunk=rand(1,5); 194 for($x=$y=0;$x<$width;$x+=$chunk) 195 { 196 $chunk=rand(1,5); 197 $y+=rand(-1,1); 198 if($y>=$height) $y=$height-5; 199 if($y<0) $y=5; 200 imagecopy($tempImage,$image,$x,0,$x,$y,$chunk,$height); 201 } 202 for($x=$y=0;$y<$height;$y+=$chunk) 203 { 204 $chunk=rand(1,5); 205 $x+=rand(-1,1); 206 if($x>=$width) $x=$width-5; 207 if($x<0) $x=5; 208 imagecopy($image,$tempImage,$x,$y,0,$y,$width,$chunk); 209 } 210 } 211 105 212 ?>
