diff options
author | Frederic Guillot <fred@kanboard.net> | 2017-10-25 16:22:10 -0700 |
---|---|---|
committer | Frederic Guillot <fred@kanboard.net> | 2017-10-25 16:22:10 -0700 |
commit | 9e2b2a32fd0e967ad3184e9a5d091a29953acb91 (patch) | |
tree | 00822e24aa1110c73ca455a8d096ef296c008cbc /vendor/gregwar/captcha | |
parent | c507c5416251c505cb3e088a03c6664bed73c812 (diff) |
Include composer dependencies in repo
Diffstat (limited to 'vendor/gregwar/captcha')
22 files changed, 1198 insertions, 0 deletions
diff --git a/vendor/gregwar/captcha/.gitignore b/vendor/gregwar/captcha/.gitignore new file mode 100644 index 00000000..5a275919 --- /dev/null +++ b/vendor/gregwar/captcha/.gitignore @@ -0,0 +1,3 @@ +demo/*.jpg +demo/*.pgm +demo/temp/ diff --git a/vendor/gregwar/captcha/.travis.yml b/vendor/gregwar/captcha/.travis.yml new file mode 100644 index 00000000..9c4b7049 --- /dev/null +++ b/vendor/gregwar/captcha/.travis.yml @@ -0,0 +1,12 @@ +language: php + +php: + - 5.3.3 + - 5.3 + - 5.4 + - 5.5 + - 5.6 + +script: + - composer install + - phpunit diff --git a/vendor/gregwar/captcha/CaptchaBuilder.php b/vendor/gregwar/captcha/CaptchaBuilder.php new file mode 100644 index 00000000..bc6173fe --- /dev/null +++ b/vendor/gregwar/captcha/CaptchaBuilder.php @@ -0,0 +1,720 @@ +<?php + +namespace Gregwar\Captcha; + +use \Exception; + +/** + * Builds a new captcha image + * Uses the fingerprint parameter, if one is passed, to generate the same image + * + * @author Gregwar <g.passault@gmail.com> + * @author Jeremy Livingston <jeremy.j.livingston@gmail.com> + */ +class CaptchaBuilder implements CaptchaBuilderInterface +{ + /** + * @var array + */ + protected $fingerprint = array(); + + /** + * @var bool + */ + protected $useFingerprint = false; + + /** + * @var array + */ + protected $textColor = null; + + /** + * @var array + */ + protected $backgroundColor = null; + + /** + * @var array + */ + protected $backgroundImages = array(); + + /** + * @var resource + */ + protected $contents = null; + + /** + * @var string + */ + protected $phrase = null; + + /** + * @var PhraseBuilderInterface + */ + protected $builder; + + /** + * @var bool + */ + protected $distortion = true; + + /** + * The maximum number of lines to draw in front of + * the image. null - use default algorithm + */ + protected $maxFrontLines = null; + + /** + * The maximum number of lines to draw behind + * the image. null - use default algorithm + */ + protected $maxBehindLines = null; + + /** + * The maximum angle of char + */ + protected $maxAngle = 8; + + /** + * The maximum offset of char + */ + protected $maxOffset = 5; + + /** + * Is the interpolation enabled ? + * + * @var bool + */ + protected $interpolation = true; + + /** + * Ignore all effects + * + * @var bool + */ + protected $ignoreAllEffects = false; + + /** + * Allowed image types for the background images + * + * @var array + */ + protected $allowedBackgroundImageTypes = array('image/png', 'image/jpeg', 'image/gif'); + + /** + * The image contents + */ + public function getContents() + { + return $this->contents; + } + + /** + * Enable/Disables the interpolation + * + * @param $interpolate bool True to enable, false to disable + * + * @return CaptchaBuilder + */ + public function setInterpolation($interpolate = true) + { + $this->interpolation = $interpolate; + + return $this; + } + + /** + * Temporary dir, for OCR check + */ + public $tempDir = 'temp/'; + + public function __construct($phrase = null, PhraseBuilderInterface $builder = null) + { + if ($builder === null) { + $this->builder = new PhraseBuilder; + } else { + $this->builder = $builder; + } + + if ($phrase === null) { + $phrase = $this->builder->build(); + } + + $this->phrase = $phrase; + } + + /** + * Setting the phrase + */ + public function setPhrase($phrase) + { + $this->phrase = (string) $phrase; + } + + /** + * Enables/disable distortion + */ + public function setDistortion($distortion) + { + $this->distortion = (bool) $distortion; + + return $this; + } + + public function setMaxBehindLines($maxBehindLines) + { + $this->maxBehindLines = $maxBehindLines; + + return $this; + } + + public function setMaxFrontLines($maxFrontLines) + { + $this->maxFrontLines = $maxFrontLines; + + return $this; + } + + public function setMaxAngle($maxAngle) + { + $this->maxAngle = $maxAngle; + + return $this; + } + + public function setMaxOffset($maxOffset) + { + $this->maxOffset = $maxOffset; + + return $this; + } + + /** + * Gets the captcha phrase + */ + public function getPhrase() + { + return $this->phrase; + } + + /** + * Returns true if the given phrase is good + */ + public function testPhrase($phrase) + { + return ($this->builder->niceize($phrase) == $this->builder->niceize($this->getPhrase())); + } + + /** + * Instantiation + */ + public static function create($phrase = null) + { + return new self($phrase); + } + + /** + * Sets the text color to use + */ + public function setTextColor($r, $g, $b) + { + $this->textColor = array($r, $g, $b); + + return $this; + } + + /** + * Sets the background color to use + */ + public function setBackgroundColor($r, $g, $b) + { + $this->backgroundColor = array($r, $g, $b); + + return $this; + } + + /** + * Sets the ignoreAllEffects value + * + * @param bool $ignoreAllEffects + * @return CaptchaBuilder + */ + public function setIgnoreAllEffects($ignoreAllEffects) + { + $this->ignoreAllEffects = $ignoreAllEffects; + + return $this; + } + + /** + * Sets the list of background images to use (one image is randomly selected) + */ + public function setBackgroundImages(array $backgroundImages) + { + $this->backgroundImages = $backgroundImages; + + return $this; + } + + /** + * Draw lines over the image + */ + protected function drawLine($image, $width, $height, $tcol = null) + { + if ($tcol === null) { + $tcol = imagecolorallocate($image, $this->rand(100, 255), $this->rand(100, 255), $this->rand(100, 255)); + } + + if ($this->rand(0, 1)) { // Horizontal + $Xa = $this->rand(0, $width/2); + $Ya = $this->rand(0, $height); + $Xb = $this->rand($width/2, $width); + $Yb = $this->rand(0, $height); + } else { // Vertical + $Xa = $this->rand(0, $width); + $Ya = $this->rand(0, $height/2); + $Xb = $this->rand(0, $width); + $Yb = $this->rand($height/2, $height); + } + imagesetthickness($image, $this->rand(1, 3)); + imageline($image, $Xa, $Ya, $Xb, $Yb, $tcol); + } + + /** + * Apply some post effects + */ + protected function postEffect($image) + { + if (!function_exists('imagefilter')) { + return; + } + + if ($this->backgroundColor != null || $this->textColor != null) { + return; + } + + // Negate ? + if ($this->rand(0, 1) == 0) { + imagefilter($image, IMG_FILTER_NEGATE); + } + + // Edge ? + if ($this->rand(0, 10) == 0) { + imagefilter($image, IMG_FILTER_EDGEDETECT); + } + + // Contrast + imagefilter($image, IMG_FILTER_CONTRAST, $this->rand(-50, 10)); + + // Colorize + if ($this->rand(0, 5) == 0) { + imagefilter($image, IMG_FILTER_COLORIZE, $this->rand(-80, 50), $this->rand(-80, 50), $this->rand(-80, 50)); + } + } + + /** + * Writes the phrase on the image + */ + protected function writePhrase($image, $phrase, $font, $width, $height) + { + $length = strlen($phrase); + if ($length === 0) { + return imagecolorallocate($image, 0, 0, 0); + } + + // Gets the text size and start position + $size = $width / $length - $this->rand(0, 3) - 1; + $box = imagettfbbox($size, 0, $font, $phrase); + $textWidth = $box[2] - $box[0]; + $textHeight = $box[1] - $box[7]; + $x = ($width - $textWidth) / 2; + $y = ($height - $textHeight) / 2 + $size; + + if (!count($this->textColor)) { + $textColor = array($this->rand(0, 150), $this->rand(0, 150), $this->rand(0, 150)); + } else { + $textColor = $this->textColor; + } + $col = imagecolorallocate($image, $textColor[0], $textColor[1], $textColor[2]); + + // Write the letters one by one, with random angle + for ($i=0; $i<$length; $i++) { + $box = imagettfbbox($size, 0, $font, $phrase[$i]); + $w = $box[2] - $box[0]; + $angle = $this->rand(-$this->maxAngle, $this->maxAngle); + $offset = $this->rand(-$this->maxOffset, $this->maxOffset); + imagettftext($image, $size, $angle, $x, $y + $offset, $col, $font, $phrase[$i]); + $x += $w; + } + + return $col; + } + + /** + * Try to read the code against an OCR + */ + public function isOCRReadable() + { + if (!is_dir($this->tempDir)) { + @mkdir($this->tempDir, 0755, true); + } + + $tempj = $this->tempDir . uniqid('captcha', true) . '.jpg'; + $tempp = $this->tempDir . uniqid('captcha', true) . '.pgm'; + + $this->save($tempj); + shell_exec("convert $tempj $tempp"); + $value = trim(strtolower(shell_exec("ocrad $tempp"))); + + @unlink($tempj); + @unlink($tempp); + + return $this->testPhrase($value); + } + + /** + * Builds while the code is readable against an OCR + */ + public function buildAgainstOCR($width = 150, $height = 40, $font = null, $fingerprint = null) + { + do { + $this->build($width, $height, $font, $fingerprint); + } while ($this->isOCRReadable()); + } + + /** + * Generate the image + */ + public function build($width = 150, $height = 40, $font = null, $fingerprint = null) + { + if (null !== $fingerprint) { + $this->fingerprint = $fingerprint; + $this->useFingerprint = true; + } else { + $this->fingerprint = array(); + $this->useFingerprint = false; + } + + if ($font === null) { + $font = __DIR__ . '/Font/captcha'.$this->rand(0, 5).'.ttf'; + } + + if (empty($this->backgroundImages)) { + // if background images list is not set, use a color fill as a background + $image = imagecreatetruecolor($width, $height); + if ($this->backgroundColor == null) { + $bg = imagecolorallocate($image, $this->rand(200, 255), $this->rand(200, 255), $this->rand(200, 255)); + } else { + $color = $this->backgroundColor; + $bg = imagecolorallocate($image, $color[0], $color[1], $color[2]); + } + $this->background = $bg; + imagefill($image, 0, 0, $bg); + } else { + // use a random background image + $randomBackgroundImage = $this->backgroundImages[rand(0, count($this->backgroundImages)-1)]; + + $imageType = $this->validateBackgroundImage($randomBackgroundImage); + + $image = $this->createBackgroundImageFromType($randomBackgroundImage, $imageType); + } + + // Apply effects + if (!$this->ignoreAllEffects) { + $square = $width * $height; + $effects = $this->rand($square/3000, $square/2000); + + // set the maximum number of lines to draw in front of the text + if ($this->maxBehindLines != null && $this->maxBehindLines > 0) { + $effects = min($this->maxBehindLines, $effects); + } + + if ($this->maxBehindLines !== 0) { + for ($e = 0; $e < $effects; $e++) { + $this->drawLine($image, $width, $height); + } + } + } + + // Write CAPTCHA text + $color = $this->writePhrase($image, $this->phrase, $font, $width, $height); + + // Apply effects + if (!$this->ignoreAllEffects) { + $square = $width * $height; + $effects = $this->rand($square/3000, $square/2000); + + // set the maximum number of lines to draw in front of the text + if ($this->maxFrontLines != null && $this->maxFrontLines > 0) { + $effects = min($this->maxFrontLines, $effects); + } + + if ($this->maxFrontLines !== 0) { + for ($e = 0; $e < $effects; $e++) { + $this->drawLine($image, $width, $height, $color); + } + } + } + + // Distort the image + if ($this->distortion && !$this->ignoreAllEffects) { + $image = $this->distort($image, $width, $height, $bg); + } + + // Post effects + if (!$this->ignoreAllEffects) { + $this->postEffect($image); + } + + $this->contents = $image; + + return $this; + } + + /** + * Distorts the image + */ + public function distort($image, $width, $height, $bg) + { + $contents = imagecreatetruecolor($width, $height); + $X = $this->rand(0, $width); + $Y = $this->rand(0, $height); + $phase = $this->rand(0, 10); + $scale = 1.1 + $this->rand(0, 10000) / 30000; + for ($x = 0; $x < $width; $x++) { + for ($y = 0; $y < $height; $y++) { + $Vx = $x - $X; + $Vy = $y - $Y; + $Vn = sqrt($Vx * $Vx + $Vy * $Vy); + + if ($Vn != 0) { + $Vn2 = $Vn + 4 * sin($Vn / 30); + $nX = $X + ($Vx * $Vn2 / $Vn); + $nY = $Y + ($Vy * $Vn2 / $Vn); + } else { + $nX = $X; + $nY = $Y; + } + $nY = $nY + $scale * sin($phase + $nX * 0.2); + + if ($this->interpolation) { + $p = $this->interpolate( + $nX - floor($nX), + $nY - floor($nY), + $this->getCol($image, floor($nX), floor($nY), $bg), + $this->getCol($image, ceil($nX), floor($nY), $bg), + $this->getCol($image, floor($nX), ceil($nY), $bg), + $this->getCol($image, ceil($nX), ceil($nY), $bg) + ); + } else { + $p = $this->getCol($image, round($nX), round($nY), $bg); + } + + if ($p == 0) { + $p = $bg; + } + + imagesetpixel($contents, $x, $y, $p); + } + } + + return $contents; + } + + /** + * Saves the Captcha to a jpeg file + */ + public function save($filename, $quality = 90) + { + imagejpeg($this->contents, $filename, $quality); + } + + /** + * Gets the image GD + */ + public function getGd() + { + return $this->contents; + } + + /** + * Gets the image contents + */ + public function get($quality = 90) + { + ob_start(); + $this->output($quality); + + return ob_get_clean(); + } + + /** + * Gets the HTML inline base64 + */ + public function inline($quality = 90) + { + return 'data:image/jpeg;base64,' . base64_encode($this->get($quality)); + } + + /** + * Outputs the image + */ + public function output($quality = 90) + { + imagejpeg($this->contents, null, $quality); + } + + /** + * @return array + */ + public function getFingerprint() + { + return $this->fingerprint; + } + + /** + * Returns a random number or the next number in the + * fingerprint + */ + protected function rand($min, $max) + { + if (!is_array($this->fingerprint)) { + $this->fingerprint = array(); + } + + if ($this->useFingerprint) { + $value = current($this->fingerprint); + next($this->fingerprint); + } else { + $value = mt_rand($min, $max); + $this->fingerprint[] = $value; + } + + return $value; + } + + /** + * @param $x + * @param $y + * @param $nw + * @param $ne + * @param $sw + * @param $se + * + * @return int + */ + protected function interpolate($x, $y, $nw, $ne, $sw, $se) + { + list($r0, $g0, $b0) = $this->getRGB($nw); + list($r1, $g1, $b1) = $this->getRGB($ne); + list($r2, $g2, $b2) = $this->getRGB($sw); + list($r3, $g3, $b3) = $this->getRGB($se); + + $cx = 1.0 - $x; + $cy = 1.0 - $y; + + $m0 = $cx * $r0 + $x * $r1; + $m1 = $cx * $r2 + $x * $r3; + $r = (int) ($cy * $m0 + $y * $m1); + + $m0 = $cx * $g0 + $x * $g1; + $m1 = $cx * $g2 + $x * $g3; + $g = (int) ($cy * $m0 + $y * $m1); + + $m0 = $cx * $b0 + $x * $b1; + $m1 = $cx * $b2 + $x * $b3; + $b = (int) ($cy * $m0 + $y * $m1); + + return ($r << 16) | ($g << 8) | $b; + } + + /** + * @param $image + * @param $x + * @param $y + * + * @return int + */ + protected function getCol($image, $x, $y, $background) + { + $L = imagesx($image); + $H = imagesy($image); + if ($x < 0 || $x >= $L || $y < 0 || $y >= $H) { + return $background; + } + + return imagecolorat($image, $x, $y); + } + + /** + * @param $col + * + * @return array + */ + protected function getRGB($col) + { + return array( + (int) ($col >> 16) & 0xff, + (int) ($col >> 8) & 0xff, + (int) ($col) & 0xff, + ); + } + + /** + * Validate the background image path. Return the image type if valid + * + * @param string $backgroundImage + * @return string + * @throws Exception + */ + protected function validateBackgroundImage($backgroundImage) + { + // check if file exists + if (!file_exists($backgroundImage)) { + $backgroundImageExploded = explode('/', $backgroundImage); + $imageFileName = count($backgroundImageExploded) > 1? $backgroundImageExploded[count($backgroundImageExploded)-1] : $backgroundImage; + + throw new Exception('Invalid background image: ' . $imageFileName); + } + + // check image type + $finfo = finfo_open(FILEINFO_MIME_TYPE); // return mime type ala mimetype extension + $imageType = finfo_file($finfo, $backgroundImage); + finfo_close($finfo); + + if (!in_array ($imageType, $this->allowedBackgroundImageTypes)) { + throw new Exception('Invalid background image type! Allowed types are: ' . join(', ', $this->allowedBackgroundImageTypes)); + } + + return $imageType; + } + + /** + * Create background image from type + * + * @param string $backgroundImage + * @param string $imageType + * @return resource + * @throws Exception + */ + protected function createBackgroundImageFromType($backgroundImage, $imageType) + { + switch ($imageType) { + case 'image/jpeg': + $image = imagecreatefromjpeg($backgroundImage); + break; + case 'image/png': + $image = imagecreatefrompng($backgroundImage); + break; + case 'image/gif': + $image = imagecreatefromgif($backgroundImage); + break; + + default: + throw new Exception('Not supported file type for background image!'); + break; + } + + return $image; + } +} diff --git a/vendor/gregwar/captcha/CaptchaBuilderInterface.php b/vendor/gregwar/captcha/CaptchaBuilderInterface.php new file mode 100644 index 00000000..bdebf38f --- /dev/null +++ b/vendor/gregwar/captcha/CaptchaBuilderInterface.php @@ -0,0 +1,30 @@ +<?php + +namespace Gregwar\Captcha; + +/** + * A Captcha builder + */ +interface CaptchaBuilderInterface +{ + /** + * Builds the code + */ + public function build($width, $height, $font, $fingerprint); + + /** + * Saves the code to a file + */ + public function save($filename, $quality); + + /** + * Gets the image contents + */ + public function get($quality); + + /** + * Outputs the image + */ + public function output($quality); +} + diff --git a/vendor/gregwar/captcha/Font/captcha0.ttf b/vendor/gregwar/captcha/Font/captcha0.ttf Binary files differnew file mode 100644 index 00000000..139f0b43 --- /dev/null +++ b/vendor/gregwar/captcha/Font/captcha0.ttf diff --git a/vendor/gregwar/captcha/Font/captcha1.ttf b/vendor/gregwar/captcha/Font/captcha1.ttf Binary files differnew file mode 100644 index 00000000..bb1abf6b --- /dev/null +++ b/vendor/gregwar/captcha/Font/captcha1.ttf diff --git a/vendor/gregwar/captcha/Font/captcha2.ttf b/vendor/gregwar/captcha/Font/captcha2.ttf Binary files differnew file mode 100644 index 00000000..8d1f31e8 --- /dev/null +++ b/vendor/gregwar/captcha/Font/captcha2.ttf diff --git a/vendor/gregwar/captcha/Font/captcha3.ttf b/vendor/gregwar/captcha/Font/captcha3.ttf Binary files differnew file mode 100644 index 00000000..d232902c --- /dev/null +++ b/vendor/gregwar/captcha/Font/captcha3.ttf diff --git a/vendor/gregwar/captcha/Font/captcha4.ttf b/vendor/gregwar/captcha/Font/captcha4.ttf Binary files differnew file mode 100644 index 00000000..ab154440 --- /dev/null +++ b/vendor/gregwar/captcha/Font/captcha4.ttf diff --git a/vendor/gregwar/captcha/Font/captcha5.ttf b/vendor/gregwar/captcha/Font/captcha5.ttf Binary files differnew file mode 100644 index 00000000..f7cd9986 --- /dev/null +++ b/vendor/gregwar/captcha/Font/captcha5.ttf diff --git a/vendor/gregwar/captcha/ImageFileHandler.php b/vendor/gregwar/captcha/ImageFileHandler.php new file mode 100644 index 00000000..6b6bdb87 --- /dev/null +++ b/vendor/gregwar/captcha/ImageFileHandler.php @@ -0,0 +1,106 @@ +<?php + +namespace Gregwar\Captcha; + +use Symfony\Component\Finder\Finder; + +/** + * Handles actions related to captcha image files including saving and garbage collection + * + * @author Gregwar <g.passault@gmail.com> + * @author Jeremy Livingston <jeremy@quizzle.com> + */ +class ImageFileHandler +{ + /** + * Name of folder for captcha images + * @var string + */ + protected $imageFolder; + + /** + * Absolute path to public web folder + * @var string + */ + protected $webPath; + + /** + * Frequency of garbage collection in fractions of 1 + * @var int + */ + protected $gcFreq; + + /** + * Maximum age of images in minutes + * @var int + */ + protected $expiration; + + /** + * @param $imageFolder + * @param $webPath + * @param $gcFreq + * @param $expiration + */ + public function __construct($imageFolder, $webPath, $gcFreq, $expiration) + { + $this->imageFolder = $imageFolder; + $this->webPath = $webPath; + $this->gcFreq = $gcFreq; + $this->expiration = $expiration; + } + + /** + * Saves the provided image content as a file + * + * @param string $contents + * + * @return string + */ + public function saveAsFile($contents) + { + $this->createFolderIfMissing(); + + $filename = md5(uniqid()) . '.jpg'; + $filePath = $this->webPath . '/' . $this->imageFolder . '/' . $filename; + imagejpeg($contents, $filePath, 15); + + return '/' . $this->imageFolder . '/' . $filename; + } + + /** + * Randomly runs garbage collection on the image directory + * + * @return bool + */ + public function collectGarbage() + { + if (!mt_rand(1, $this->gcFreq) == 1) { + return false; + } + + $this->createFolderIfMissing(); + + $finder = new Finder(); + $criteria = sprintf('<= now - %s minutes', $this->expiration); + $finder->in($this->webPath . '/' . $this->imageFolder) + ->date($criteria); + + foreach($finder->files() as $file) { + unlink($file->getPathname()); + } + + return true; + } + + /** + * Creates the folder if it doesn't exist + */ + protected function createFolderIfMissing() + { + if (!file_exists($this->webPath . '/' . $this->imageFolder)) { + mkdir($this->webPath . '/' . $this->imageFolder, 0755); + } + } +} + diff --git a/vendor/gregwar/captcha/LICENSE b/vendor/gregwar/captcha/LICENSE new file mode 100644 index 00000000..7db6ad8e --- /dev/null +++ b/vendor/gregwar/captcha/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) <2012-2015> Grégoire Passault + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/vendor/gregwar/captcha/PhraseBuilder.php b/vendor/gregwar/captcha/PhraseBuilder.php new file mode 100644 index 00000000..b94bd61c --- /dev/null +++ b/vendor/gregwar/captcha/PhraseBuilder.php @@ -0,0 +1,34 @@ +<?php + +namespace Gregwar\Captcha; + +/** + * Generates random phrase + * + * @author Gregwar <g.passault@gmail.com> + */ +class PhraseBuilder implements PhraseBuilderInterface +{ + /** + * Generates random phrase of given length with given charset + */ + public function build($length = 5, $charset = 'abcdefghijklmnpqrstuvwxyz123456789') + { + $phrase = ''; + $chars = str_split($charset); + + for ($i = 0; $i < $length; $i++) { + $phrase .= $chars[array_rand($chars)]; + } + + return $phrase; + } + + /** + * "Niceize" a code + */ + public function niceize($str) + { + return strtr(strtolower($str), '01', 'ol'); + } +} diff --git a/vendor/gregwar/captcha/PhraseBuilderInterface.php b/vendor/gregwar/captcha/PhraseBuilderInterface.php new file mode 100644 index 00000000..0a4f5361 --- /dev/null +++ b/vendor/gregwar/captcha/PhraseBuilderInterface.php @@ -0,0 +1,21 @@ +<?php + +namespace Gregwar\Captcha; + +/** + * Interface for the PhraseBuilder + * + * @author Gregwar <g.passault@gmail.com> + */ +interface PhraseBuilderInterface +{ + /** + * Generates random phrase of given length with given charset + */ + public function build($length, $charset); + + /** + * "Niceize" a code + */ + public function niceize($str); +} diff --git a/vendor/gregwar/captcha/README.md b/vendor/gregwar/captcha/README.md new file mode 100644 index 00000000..9f6c17a9 --- /dev/null +++ b/vendor/gregwar/captcha/README.md @@ -0,0 +1,108 @@ +Captcha +======= + +![Captchas examples](http://gregwar.com/captchas.png) + +Installation +============ + +With composer : + +``` json +{ + ... + "require": { + "gregwar/captcha": "1.*" + } +} +``` + +Usage +===== + +You can create a captcha with the `CaptchaBuilder` : + +```php +<?php + +use Gregwar\Captcha\CaptchaBuilder; + +$builder = new CaptchaBuilder; +$builder->build(); +``` + +You can then save it to a file : + +```php +<?php + +$builder->save('out.jpg'); +``` + +Or output it directly : + +```php +<?php + +header('Content-type: image/jpeg'); +$builder->output(); +``` + +Or inline it directly in the HTML page: + +```php +<img src="<?php echo $builder->inline(); ?>" /> +``` + +You'll be able to get the code and compare it with a user input : + +```php +<?php + +// Example: storing the phrase in the session to test for the user +// input later +$_SESSION['phrase'] = $builder->getPhrase(); +``` + +You can compare the phrase with user input: +```php +if($builder->testPhrase($userInput)) { + // instructions if user phrase is good +} +else { + // user phrase is wrong +} +``` + +API +=== + +You can use theses functions : + +* **__construct($phrase = null)**, constructs the builder with the given phrase, if the phrase is null, a random one will be generated +* **getPhrase()**, allow you to get the phrase contents +* **setDistortion($distortion)**, enable or disable the distortion, call it before `build()` +* **isOCRReadable()**, returns `true` if the OCR can be read using the `ocrad` software, you'll need to have shell_exec enabled, imagemagick and ocrad installed +* **buildAgainstOCR($width = 150, $height = 40, $font = null)**, builds a code until it is not readable by `ocrad` +* **build($width = 150, $height = 40, $font = null)**, builds a code with the given $width, $height and $font. By default, a random font will be used from the library +* **save($filename, $quality = 80)**, saves the captcha into a jpeg in the $filename, with the given quality +* **get($quality = 80)**, returns the jpeg data +* **output($quality = 80)**, directly outputs the jpeg code to a browser +* **setBackgroundColor($r, $g, $b)**, sets the background color to force it (this will disable many effects and is not recommended) +* **setBackgroundImages(array($imagepath1, $imagePath2))**, Sets custom background images to be used as captcha background. It is recommended to disable image effects when passing custom images for background (ignore_all_effects). A random image is selected from the list passed, the full paths to the image files must be passed. +* **setInterpolation($interpolate)**, enable or disable the interpolation (enabled by default), disabling it will be quicker but the images will look uglier +* **setIgnoreAllEffects($ignoreAllEffects)**, disable all effects on the captcha image. Recommended to use when passing custom background images for the captcha. +* **testPhrase($phrase)**, returns true if the given phrase is good +* **setMaxBehindLines($lines)**, sets the maximum number of lines behind the code +* **setMaxFrontLines($lines)**, sets the maximum number of lines on the front of the code + +Symfony 2 Bundle +================ + +You can have a look at the following repository to enjoy the Symfony 2 bundle packaging this captcha generator : +https://github.com/Gregwar/CaptchaBundle + +License +======= + +This library is under MIT license, have a look to the `LICENSE` file diff --git a/vendor/gregwar/captcha/autoload.php b/vendor/gregwar/captcha/autoload.php new file mode 100644 index 00000000..8b3fa392 --- /dev/null +++ b/vendor/gregwar/captcha/autoload.php @@ -0,0 +1,16 @@ +<?php + +/** +* Registers an autoload for all the classes in Gregwar\Captcha +*/ +spl_autoload_register(function ($className) { + $namespace = 'Gregwar\\Captcha'; + + if (strpos($className, $namespace) === 0) { + $className = str_replace($namespace, '', $className); + $fileName = __DIR__ . '/' . str_replace('\\', '/', $className) . '.php'; + if (file_exists($fileName)) { + require($fileName); + } + } +}); diff --git a/vendor/gregwar/captcha/composer.json b/vendor/gregwar/captcha/composer.json new file mode 100644 index 00000000..ef79423b --- /dev/null +++ b/vendor/gregwar/captcha/composer.json @@ -0,0 +1,28 @@ +{ + "name": "gregwar/captcha", + "type": "captcha", + "description": "Captcha generator", + "keywords": ["captcha", "spam", "bot"], + "homepage": "https://github.com/Gregwar/Captcha", + "license": "MIT", + "authors": [ + { + "name": "Grégoire Passault", + "email": "g.passault@gmail.com", + "homepage": "http://www.gregwar.com/" + }, + { + "name": "Jeremy Livingston", + "email": "jeremy.j.livingston@gmail.com" + } + ], + "require": { + "php": ">=5.3.0", + "ext-gd": "*" + }, + "autoload": { + "psr-4": { + "Gregwar\\Captcha\\": "/" + } + } +} diff --git a/vendor/gregwar/captcha/demo/demo.php b/vendor/gregwar/captcha/demo/demo.php new file mode 100644 index 00000000..7852745f --- /dev/null +++ b/vendor/gregwar/captcha/demo/demo.php @@ -0,0 +1,14 @@ +<?php + +include(__DIR__.'/../CaptchaBuilderInterface.php'); +include(__DIR__.'/../PhraseBuilderInterface.php'); +include(__DIR__.'/../CaptchaBuilder.php'); +include(__DIR__.'/../PhraseBuilder.php'); + +use Gregwar\Captcha\CaptchaBuilder; + +$captcha = new CaptchaBuilder; +$captcha + ->build() + ->save('out.jpg') +; diff --git a/vendor/gregwar/captcha/demo/fingerprint.php b/vendor/gregwar/captcha/demo/fingerprint.php new file mode 100644 index 00000000..ce30d991 --- /dev/null +++ b/vendor/gregwar/captcha/demo/fingerprint.php @@ -0,0 +1,15 @@ +<?php + +include(__DIR__.'/../CaptchaBuilderInterface.php'); +include(__DIR__.'/../PhraseBuilderInterface.php'); +include(__DIR__.'/../CaptchaBuilder.php'); +include(__DIR__.'/../PhraseBuilder.php'); + +use Gregwar\Captcha\CaptchaBuilder; + +echo count(CaptchaBuilder::create() + ->build() + ->getFingerprint() +); + +echo "\n"; diff --git a/vendor/gregwar/captcha/demo/index.php b/vendor/gregwar/captcha/demo/index.php new file mode 100644 index 00000000..e543883b --- /dev/null +++ b/vendor/gregwar/captcha/demo/index.php @@ -0,0 +1,15 @@ +<!DOCTYPE html> +<body> + <html> + <meta charset="utf-8" /> + </html> + <body> + <h1>Captchas gallery</h1> + <?php for ($x=0; $x<8; $x++) { ?> + <?php for ($y=0; $y<5; $y++) { ?> + <img src="output.php?n=<?php echo 5*$x+$y; ?>" /> + <?php } ?> + <br /> + <?php } ?> + </body> +</body> diff --git a/vendor/gregwar/captcha/demo/ocr.php b/vendor/gregwar/captcha/demo/ocr.php new file mode 100644 index 00000000..3d745f65 --- /dev/null +++ b/vendor/gregwar/captcha/demo/ocr.php @@ -0,0 +1,42 @@ +<?php + +include(__DIR__.'/../CaptchaBuilderInterface.php'); +include(__DIR__.'/../PhraseBuilderInterface.php'); +include(__DIR__.'/../CaptchaBuilder.php'); +include(__DIR__.'/../PhraseBuilder.php'); + +use Gregwar\Captcha\CaptchaBuilder; + +/** + * Generates 1000 captchas and try to read their code with the + * ocrad OCR + */ + +$tests = 10000; +$passed = 0; + +shell_exec('rm passed*.jpg'); + +for ($i=0; $i<$tests; $i++) { + echo "Captcha $i/$tests... "; + + $captcha = new CaptchaBuilder; + + $captcha + ->setDistortion(false) + ->build() + ; + + if ($captcha->isOCRReadable()) { + $passed++; + $captcha->save("passed$passed.jpg"); + echo "passed at ocr... "; + } else { + echo "failed... "; + } + + echo "pass rate: ".round(100*$passed/($i+1),2)."%\n"; +} + +echo "\n"; +echo "Over, $passed/$tests readed with OCR\n"; diff --git a/vendor/gregwar/captcha/demo/output.php b/vendor/gregwar/captcha/demo/output.php new file mode 100644 index 00000000..2a4f3303 --- /dev/null +++ b/vendor/gregwar/captcha/demo/output.php @@ -0,0 +1,15 @@ +<?php + +include(__DIR__.'/../CaptchaBuilderInterface.php'); +include(__DIR__.'/../PhraseBuilderInterface.php'); +include(__DIR__.'/../CaptchaBuilder.php'); +include(__DIR__.'/../PhraseBuilder.php'); + +use Gregwar\Captcha\CaptchaBuilder; + +header('Content-type: image/jpeg'); + +CaptchaBuilder::create() + ->build() + ->output() +; |