PageRenderTime 51ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

/application/lib/Newforms/Captcha.php

https://bitbucket.org/mustangostang/zfast
PHP | 312 lines | 226 code | 68 blank | 18 comment | 24 complexity | 83172919799bb7361620808e031d32f6 MD5 | raw file
  1. <?php
  2. require_once '__Field.php';
  3. class Newforms_Captcha extends Newforms___Field {
  4. public $maxlength = 255;
  5. public $url = '/captcha/';
  6. public function html() {
  7. if (!$this->cleaned_value() || !$this->saved_captcha()) {
  8. $Captcha = new Newforms_Captcha_Inner($this->__name);
  9. $Captcha->setBackground('ffffff');
  10. $Captcha->setFont('6186b2', 22);
  11. $Captcha->setJitterAngle(70);
  12. $Captcha->setJitterSize(25);
  13. $Captcha->setJitterTransparency(60);
  14. $Captcha->output();
  15. }
  16. return sprintf('
  17. <img src="%s?%s" alt="Captcha" />
  18. <input type="text" id="newforms_%s" name="%s" value="%s" maxlength="%s" class="%s" />',
  19. $this->url, $this->__name,
  20. $this->__name, $this->__name, htmlspecialchars($this->value()), $this->maxlength, $this->class);
  21. }
  22. public function builtinValidation() {
  23. $E = array();
  24. if (!$this->validate_captcha())
  25. $E[] = "????????? ???? ??? ???????? ???????.";
  26. return $E;
  27. }
  28. protected function saved_captcha() {
  29. $saved_captcha_key = 'captcha__' . $this->__name;
  30. if (empty($_SESSION[$saved_captcha_key])) return '';
  31. return trim($_SESSION[$saved_captcha_key]);
  32. }
  33. protected function clear_captcha() {
  34. $saved_captcha_key = 'captcha__' . $this->__name;
  35. unset ($_SESSION[$saved_captcha_key]);
  36. }
  37. public function validate_captcha() {
  38. $captcha = $this->cleaned_value();
  39. if (!$captcha)
  40. return false;
  41. // print_r ($_SESSION);
  42. if (!$this->saved_captcha())
  43. return false;
  44. if (trim($captcha) == $this->saved_captcha()) {
  45. $this->clear_captcha();
  46. return true;
  47. }
  48. return false;
  49. }
  50. }
  51. require_once 'Zend/Session/Namespace.php';
  52. /* Example:
  53. $Captcha = new Captcha();
  54. $Captcha->setBackground('ffffff');
  55. $Captcha->setFont('6186b2', 22);
  56. $Captcha->setJitterAngle(30);
  57. $Captcha->setJitterSize(10);
  58. $Captcha->setJitterTransparency(20);
  59. $Captcha->output();
  60. */
  61. class Newforms_Captcha_Inner {
  62. private $width = 100, $height = 70, $length = 4, $session_name, $request_name,
  63. $backgroundPath = '', $tiling = 'original',
  64. $fontColor = '000000', $fontSize = 12, $fontFace = '',
  65. $backgroundColor = 'ffffff',
  66. $jitterRotation = 0, $jitterHue = 0, $jitterTransparency = 0, $jitterSize = 0,
  67. $Vocabulary = array('0', '1', '2', '3', '4', '5', '6', '7', '8', '9'),
  68. $Image, $Colors = array(), $AllocatedColors = array(), $Letters = array(), $XCoords = array();
  69. public function __construct($name) {
  70. $this->session_name = 'captcha__' . $name;
  71. $this->request_name = $name;
  72. $this->fontFace = SHAREDROOT . 'misc/arial.ttf';
  73. $this->Colors[] = $this->backgroundColor;
  74. $this->Colors[] = $this->fontColor;
  75. }
  76. public function writeToSession() {
  77. $_SESSION[$this->session_name] = implode('', $this->Letters);
  78. }
  79. public function passedValidation() {
  80. if (empty($_REQUEST[$this->request_name]))
  81. return false;
  82. if (empty($_SESSION[$this->session_name]))
  83. return false;
  84. if (trim($_REQUEST[$this->request_name]) == trim($_SESSION[$this->session_name])) {
  85. $_SESSION[$this->session_name] = '';
  86. return true;
  87. }
  88. return false;
  89. }
  90. public function setWidth($width) {
  91. $this->width = intval($width);
  92. }
  93. public function setHeight($height) {
  94. $this->height = intval($height);
  95. }
  96. public function getWidth() {
  97. return $this->width;
  98. }
  99. public function getHeight() {
  100. return $this->width;
  101. }
  102. public function setBackground($color, $pathToImage = '', $tiling = 'original') {
  103. $this->backgroundColor = $color;
  104. $this->Colors[] = $color;
  105. }
  106. public function setFont($color, $size) {
  107. $this->Colors[] = $color;
  108. $this->fontSize = $size;
  109. $this->fontColor = $color;
  110. }
  111. public function setFontFace($pathToFont) {
  112. $this->fontFace = $pathToFont;
  113. }
  114. public function setJitterAngle($angleAlpha) {
  115. $this->jitterRotation = $angleAlpha;
  116. }
  117. public function setJitterHue($colorAlpha) {
  118. }
  119. public function setJitterTransparency($alphaChannelAlpha) {
  120. $this->jitterTransparency = $alphaChannelAlpha;
  121. }
  122. public function setJitterSize($sizeAlpha) {
  123. $this->jitterSize = $sizeAlpha;
  124. }
  125. public function setVocabularyPreset($vocabulary = 'digits') {
  126. }
  127. public function setVocabularyCustom($vocabulary) {
  128. }
  129. public function setLength($length) {
  130. }
  131. public function output() {
  132. $this->prepareCanvas();
  133. $this->tileBackground();
  134. for ($i = 1; $i <= $this->length; $i++) {
  135. $this->Letters[$i] = $this->randomLetter();
  136. }
  137. $this->findXCoords();
  138. for ($i = 1; $i <= $this->length; $i++) {
  139. $this->writeLetter($i);
  140. }
  141. $this->writeToSession();
  142. $this->outputToBuffer();
  143. }
  144. private function addColor($color, $opacity = 100) {
  145. $colorRed = hexdec(substr($color, 0, 2));
  146. $colorGreen = hexdec(substr($color, 2, 2));
  147. $colorBlue = hexdec(substr($color, 4, 2));
  148. if ($opacity != 100) {
  149. $colorRed = round($colorRed / 100 * $opacity);
  150. $colorGreen = round($colorGreen / 100 * $opacity);
  151. $colorBlue = round($colorBlue / 100 * $opacity);
  152. $_red = dechex($colorRed);
  153. if (strlen($_red) < 2)
  154. $_red = '0' . $_red;
  155. $_green = dechex($colorGreen);
  156. if (strlen($_green) < 2)
  157. $_green = '0' . $_green;
  158. $_blue = dechex($colorBlue);
  159. if (strlen($_blue) < 2)
  160. $_blue = '0' . $_blue;
  161. $color = $_red . $_green . $_blue;
  162. }
  163. $this->AllocatedColors[$color] = imagecolorallocate($this->Image, $colorRed, $colorGreen, $colorBlue);
  164. return $color;
  165. }
  166. private function prepareCanvas() {
  167. $this->Image = imagecreatetruecolor($this->width, $this->height);
  168. $this->Colors = array_unique($this->Colors);
  169. foreach ($this->Colors as $color)
  170. $this->addColor($color);
  171. imagefill($this->Image, 1, 1, $this->AllocatedColors[$this->backgroundColor]);
  172. }
  173. private function tileBackground() {
  174. }
  175. private function writeLetter($i) {
  176. $letter = $this->Letters[$i];
  177. $angle = $this->applyJitterAngle();
  178. $size = $this->applyJitterSize();
  179. $color = $this->applyJitterTransparency();
  180. // print_r ($this->XCoords);
  181. $x = $this->XCoords[$i];
  182. $y = $this->findVerticalMiddle($letter, $size, $angle);
  183. imagettftext($this->Image, $size, $angle, $x, $y, $this->AllocatedColors[$color], $this->fontFace, $letter);
  184. }
  185. private function applyJitterAngle() {
  186. if (!$this->jitterRotation)
  187. return 0;
  188. return rand(0, $this->jitterRotation) - floor($this->jitterRotation / 2);
  189. }
  190. private function applyJitterSize() {
  191. if (!$this->jitterSize)
  192. return $this->fontSize;
  193. return rand(0, $this->jitterSize) - floor($this->jitterSize / 2) + $this->fontSize;
  194. }
  195. private function applyJitterTransparency() {
  196. if (!$this->jitterTransparency)
  197. return $this->fontColor;
  198. $tempTransparency = rand(0, $this->jitterTransparency);
  199. //echo $tempTransparency;
  200. return $this->addColor($this->fontColor, 100 - $tempTransparency);
  201. }
  202. private function findXCoords() {
  203. $Widths = array();
  204. $totalLength = 0;
  205. for ($i = 1; $i <= $this->length; $i++) {
  206. $Box = imagettfbbox($this->fontSize, 0, $this->fontFace, $this->Letters[$i]);
  207. //print_r ($Box);
  208. $_length = $Box[2] - $Box[6];
  209. //echo $_length;
  210. $Widths[$i] = $_length;
  211. $totalLength += $_length;
  212. }
  213. $n = ceil(($this->width - $totalLength) / ($this->length - 1 + 4));
  214. //echo $n;
  215. $prevWidth = $n * 2;
  216. for ($i = 1; $i <= $this->length; $i++) {
  217. $this->XCoords[$i] = $prevWidth;
  218. $prevWidth += $Widths[$i] + $n;
  219. }
  220. }
  221. private function findVerticalMiddle($letter, $size, $angle) {
  222. $Box = imagettfbbox($size, $angle, $this->fontFace, $letter);
  223. $height = $Box[7] - $Box[3];
  224. $startingY = round(($this->height - $height) / 2);
  225. return $startingY;
  226. }
  227. private function randomLetter() {
  228. $RandomVocabulary = array_rand($this->Vocabulary, 1);
  229. return $RandomVocabulary;
  230. }
  231. private function outputToBrowser() {
  232. header("Content-Type: image/png");
  233. imagepng($this->Image);
  234. }
  235. private function outputToBuffer() {
  236. ob_start();
  237. imagepng ($this->Image);
  238. $image = ob_get_clean();
  239. $_SESSION[$this->session_name . '_data'] = $image;
  240. }
  241. }