diff options
author | David M <davidmj@users.sourceforge.net> | 2006-11-03 23:09:16 +0000 |
---|---|---|
committer | David M <davidmj@users.sourceforge.net> | 2006-11-03 23:09:16 +0000 |
commit | 8b0ec6e02d5a53ea3d1b87abd122d39cc3e8366f (patch) | |
tree | 22bae5ecbab9dbf8390ab3763f53c15c822c9198 /phpBB/includes/captcha/captcha_gd.php | |
parent | 7ab232a45504ef357a19d9ab58dd27c454e12784 (diff) | |
download | forums-8b0ec6e02d5a53ea3d1b87abd122d39cc3e8366f.tar forums-8b0ec6e02d5a53ea3d1b87abd122d39cc3e8366f.tar.gz forums-8b0ec6e02d5a53ea3d1b87abd122d39cc3e8366f.tar.bz2 forums-8b0ec6e02d5a53ea3d1b87abd122d39cc3e8366f.tar.xz forums-8b0ec6e02d5a53ea3d1b87abd122d39cc3e8366f.zip |
- compress is nicer (fixed a bug :P)
- UTF-8 code is nicer (fixed a bug :P)
- new CAPTCHA. Replaced the old one for size and usability issues. The old CAPTCHA will most likely be released as a separate package
git-svn-id: file:///svn/phpbb/trunk@6549 89ea8834-ac86-4346-8a33-228a782c2dd0
Diffstat (limited to 'phpBB/includes/captcha/captcha_gd.php')
-rw-r--r-- | phpBB/includes/captcha/captcha_gd.php | 3434 |
1 files changed, 81 insertions, 3353 deletions
diff --git a/phpBB/includes/captcha/captcha_gd.php b/phpBB/includes/captcha/captcha_gd.php index 34b1684f3c..e249a46c04 100644 --- a/phpBB/includes/captcha/captcha_gd.php +++ b/phpBB/includes/captcha/captcha_gd.php @@ -9,3429 +9,157 @@ */ /** -* This file is getting too large. -* -* Only bugfixes allowed from now on. -* If a policy can not be fixed with the minimum amount of code it gets removed. -*/ - -/** -* Main gd based captcha class -* -* Thanks to Robert Hetzler (Xore) +* Based on PHP-Class hn_captcha Version 1.3, released 11-Apr-2006 +* Original Author - Horst Nogajski, horst@nogajski.de * * @package VC */ class captcha { - /** - * Create the image containing $code - */ - function execute($code, $policy) - { - $this->$policy(str_split($code)); - } - - /** - * Send image and destroy - */ - function send_image(&$image) - { - header('Content-Type: image/png'); - header('Cache-control: no-cache, no-store'); - imagepng($image); - imagedestroy($image); - } - - /** - * - */ - function wave_height($x, $y, $factor = 1, $tweak = 1) - { - return ((sin($x / (3 * $factor)) + sin($y / (3 * $factor))) * 10 * $tweak); - } - - /** - * - */ - function grid_height($x, $y, $factor = 1, $x_grid, $y_grid) - { - return ( (!($x % ($x_grid * $factor)) || !($y % ($y_grid * $factor))) ? 3 : 0); - } - - /** - * - */ - function draw_shape($type, $img, $x_min, $y_min, $x_max, $y_max, $color) - { - switch ($type) - { - case 'Square': - imagefilledpolygon($img, array($x_min, $y_max, $x_min, $y_min, $x_max, $y_min, $x_max, $y_max), 4, $color); - break; - - case 'TriangleUp': - imagefilledpolygon($img, array($x_min, $y_max, ($x_min + $x_max) / 2, $y_min, $x_max, $y_max), 3, $color); - break; - - case 'TriangleDown': - imagefilledpolygon($img, array($x_min, $y_min, ($x_min + $x_max) / 2, $y_max, $x_max, $y_min), 3, $color); - break; - - case 'Circle': - imagefilledellipse($img, ($x_min + $x_max) / 2, ($y_min + $y_max) / 2, $x_max - $x_min, $y_max - $y_min, $color); - break; - } - } - - /** - * - */ - function draw_pattern($seed, $img, $x_min, $y_min, $x_max, $y_max, $colors, $thickness = 1) - { - $x_size = ($x_max - $x_min) / 4; - $y_size = ($y_max - $y_min) / 4; - $bitmap = substr($seed, 16, 4); - $numcolors = sizeof($colors) - 1; - for ($y = 0; $y < 4; ++$y) - { - $map = hexdec(substr($bitmap, $y, 1)); - for ($x = 0; $x < 4; ++$x) - { - if ($map & (1 << $x)) - { - $char = hexdec(substr($seed, ($y << 2) + $x, 1)); - if (!($char >> 2)) - { - switch ($char & 3) - { - case 0: - $shape = 'Circle'; - break; - - case 1: - $shape = 'Square'; - break; - - case 2: - $shape = 'TriangleUp'; - break; - - case 3: - $shape = 'TriangleDown'; - break; - } - $this->draw_shape($shape, $img, $x_min + ($x * $x_size), $y_min + ($y * $y_size), $x_min + (($x + 1) * $x_size), $y_min + (($y + 1) * $y_size), $colors[array_rand($colors)]); - } - } - } - } - - $cells = array(); - for ($i = 0; $i < 6; ++$i) - { - $cells = hexdec(substr($seed, 20 + ($i << 1), 2)); - $x1 = $cells & 3; - $cells = $cells >> 2; - $y1 = $cells & 3; - $cells = $cells >> 2; - $x2 = $cells & 3; - $cells = $cells >> 2; - $y2 = $cells & 3; - $x1_real = $x_min + (($x1 + 0.5) * $x_size); - $y1_real = $y_min + (($y1 + 0.5) * $y_size); - $x2_real = $x_min + (($x2 + 0.5) * $x_size); - $y2_real = $y_min + (($y2 + 0.5) * $y_size); - if ($thickness > 1) - { - imagesetthickness($img, $thickness); - } - imageline($img, $x1_real, $y1_real, $x2_real, $y2_real, $colors[array_rand($colors)]); - if ($thickness > 1) - { - imagesetthickness($img, 1); - } - } - } - - /** - * - */ - function get_char_string() - { - static $chars = false; - static $charcount = 0; - if (!$chars) - { - $chars = array_merge(range('A', 'Z'), range('1', '9')); - } - $word = ''; - for ($i = mt_rand(6, 8); $i > 0; --$i) - { - $word .= $chars[array_rand($chars)]; - } - return $word; - } - - /** - * shape - */ - function policy_shape($code) - { - global $config, $user; - // Generate image - $img_x = 800; - $img_y = 250; - $img = imagecreatetruecolor($img_x, $img_y); - - // Generate colors - $c = new color_manager($img, array( - 'random' => true, - 'min_saturation' => 70, - 'min_value' => 65, - )); - - $primaries = $c->color_scheme('background', 'tetradic', false); - - $noise = array_shift($primaries); - $noise = $c->mono_range($noise, 'value', 5, false); - $primaries = $c->mono_range($primaries, 'value', 5, false); - - // Generate code characters - $characters = array(); - $sizes = array(); - $bounding_boxes = array(); - $width_avail = $img_x; - $code_num = sizeof($code); - $char_class = $this->captcha_char('char_ttf'); - for ( $i = 0; $i < $code_num; ++$i ) - { - $characters[$i] = new $char_class($code[$i]); - list($min, $max) = $characters[$i]->range(); - $sizes[$i] = mt_rand($min, $max / 2); - $box = $characters[$i]->dimensions($sizes[$i]); - $width_avail -= ($box[2] - $box[0]); - $bounding_boxes[$i] = $box; - } - - // Redistribute leftover x-space - $offset = array(); - for ( $i = 0; $i < $code_num; ++$i ) - { - $denom = ($code_num - $i); - $denom = max(1.5, $denom); - $offset[$i] = mt_rand(0, (1.5 * $width_avail) / $denom); - $width_avail -= $offset[$i]; - } - - // Add some line noise - if ($config['policy_shape_noise_line']) - { - $this->noise_line($img, 0, 0, $img_x, $img_y, $c->r('background'), $primaries, $noise); - } - - $real = mt_rand(0, 3); - $patterns = array('', '', '', ''); - for ($i = 32; $i > 0; --$i) - { - $patterns[$i & 3] .= str_pad(dechex(mt_rand(0, 65535)), 4, '0', STR_PAD_LEFT); - } - - - for ($i = 0; $i < 4; ++$i) - { - /*if ($i) - { - $y = 5 + ($i * 60); - imageline($img, 550, $y, 650, $y, $fontcolors[0]); - }*/ - $this->draw_pattern($patterns[$i], $img, 525, 10 + ($i * 60), 575, ($i + 1) * 60, $primaries); - if ($i == $real) - { - $this->draw_pattern($patterns[$i], $img, 25, 25, 225, 225, $primaries, 3); - for ($j = 0; $j < $code_num; ++$j) - { - $character = new $char_class($code[$j]); - $character->drawchar(25, 600 + ($j * 25), 35 + ($i * 60), $img, $c->r('background'), $primaries); - } - } - else - { - $word = $this->get_char_string(); - for ($j = strlen($word) - 1; $j >= 0; --$j) - { - $character = new $char_class(substr($word, $j, 1)); - $character->drawchar(25, 600 + ($j * 25), 35 + ($i * 60), $img, $c->r('background'), $primaries); - } - } - } - - $count = sizeof($user->lang['CAPTCHA']['shape']); - $line_height = $img_y / ($count + 1); - for ($i = 0; $i < $count; ++$i) - { - $text = $user->lang['CAPTCHA']['shape'][$i]; - $line_width = strlen($text) * 4.5; // ( / 2, * 9 ) - imagestring($img, 6, ($img_x / 2) - $line_width - 1, $line_height * ($i + 1) - 1, $text, $c->r('black')); - imagestring($img, 6, ($img_x / 2) - $line_width - 1, $line_height * ($i + 1) + 1, $text, $c->r('black')); - imagestring($img, 6, ($img_x / 2) - $line_width + 1, $line_height * ($i + 1) + 1, $text, $c->r('black')); - imagestring($img, 6, ($img_x / 2) - $line_width + 1, $line_height * ($i + 1) - 1, $text, $c->r('black')); - imagestring($img, 6, ($img_x / 2) - $line_width, $line_height * ($i + 1), $text, $c->r('white')); - } - - - // Add some pixel noise - if ($config['policy_shape_noise_pixel']) - { - $this->noise_pixel($img, 0, 0, $img_x, $img_y, $c->r('background'), $primaries, $noise, $config['policy_shape_noise_pixel']); - } - - // Send image - $this->send_image($img); - } - - function policy_composite($code) - { - // Generate image - $img_x = 800; - $img_y = 250; - $img = imagecreate($img_x, $img_y); - - $map = captcha_vectors(); - $fonts = captcha_load_ttf_fonts(); - - // Generate basic colors - $c = new color_manager($img, 'white'); - $c->allocate_named('primary', array( - 'random' => true, - 'min_saturation' => 50, - 'min_value' => 75, - )); - $bg_colors = $c->color_scheme('primary', 'triadic', false); - $text_colors = $c->mono_range('primary', 'saturation', 6); - $bg_colors = $c->mono_range($bg_colors, 'saturation', 6); - - // Specificy image portion dimensions. - $count = sizeof($code); - $cellsize = $img_x / $count; - $y_range = min($cellsize, $img_y); - $y_max = $img_y - $y_range; - $y_off = array(); // consecutive vertical offset of characters - $color = array(); // color of characters - $y_off[0] = mt_rand(0, $y_max); - for ($i = 1; $i < $count; ++$i) - { - // each consective character can be as much as 50% closer to the top or bottom of the image as the previous - $diff = mt_rand(-50, 50); - if ($diff > 0) - { - $y_off[$i] = $y_off[$i - 1] + ((($y_max - $y_off[$i - 1]) * $diff) / 100); - } - else - { - $y_off[$i] = $y_off[$i - 1] * ((100 + $diff) / 100); - } - } - - $range = 0.075; - - $chars = array_merge(range('A', 'Z'), range('1', '9')); - - // draw some characters. if they're within the vector spec of the code character, color them differently - for ($i = 0; $i < 8000; ++$i) - { - $degree = mt_rand(-30, 30); - $x = mt_rand(0, $img_x - 1); - $y = mt_rand(0, $img_y); - $text = $chars[array_rand($chars)]; - $char = $x / $cellsize; - $meta_x = ((($x % $cellsize) / $cellsize) * 1.5) - 0.25; - $meta_y = (($img_y - $y) - $y_off[$char]) / $y_range; - $font = $fonts[array_rand($fonts)]; - - $distance = vector_distance($map[$code[$char]], $meta_x, $meta_y, $range); - - $switch = !(rand() % 100); - - imagettftext($img, 10, $degree, $x, $y, - (($distance <= $range) xor $switch) ? - $c->r_rand($text_colors) : - $c->r_rand($bg_colors), - $font, $text); - - } - - // Send image - $this->send_image($img); - } - - function policy_stencil($code) - { - // Generate image - $img_x = 800; - $img_y = 250; - $img = imagecreatetruecolor($img_x, $img_y); - $stencil = imagecreatetruecolor($img_x, $img_y); - - $map = captcha_vectors(); - $fonts = captcha_load_ttf_fonts(); - - // Generate colors - $c = new color_manager($img, 'black'); - $cs = new color_manager($stencil, 'gray'); - - $c->allocate_named('primary', array( - 'random' => true, - 'min_saturation' => 75, - 'min_value' => 80, - )); - - $secondary = $c->color_scheme('primary', 'triadic', false); - - //imagefill($stencil, 0, 0, $black2); - //imagefill($img, 0, 0, $white1); - - $chars = array_merge(range('A', 'Z'), range('1', '9')); - $step = 20; - $density = 4; - for ($i = 0; $i < $img_x; $i += $step) - { - for ($j = 0; $j < $img_y; $j += $step) - { - for ($k = 0; $k < $density; ++$k) - { - $degree = mt_rand(-30, 30); - $x = mt_rand($i, $i + $step); - $y = mt_rand($j, $j + $step); - $char = $chars[array_rand($chars)]; - $font = $fonts[array_rand($fonts)]; - imagettftext($stencil, mt_rand(20, 30), $degree, $x, $y, $cs->r('black'), $font, $char); - } - } - } - - for ($i = 0; $i < 3; ++$i) - { - $degree1 = mt_rand(-30, 30); - $degree2 = mt_rand(-30, 30); - $x1 = mt_rand(0, $img_x - 1); - $x2 = mt_rand(0, $img_x - 1); - $y1 = mt_rand(0, $img_y); - $y2 = mt_rand(0, $img_y); - $char1 = $chars[array_rand($chars)]; - $char2 = $chars[array_rand($chars)]; - $font1 = $fonts[array_rand($fonts)]; - $font2 = $fonts[array_rand($fonts)]; - - imagettftext($img, mt_rand(75, 100), $degree1, $x1, $y1, $secondary[0], $font1, $char1); - imagettftext($img, mt_rand(75, 100), $degree2, $x2, $y2, $secondary[1], $font2, $char2); - } - - $characters = array(); - $sizes = array(); - $bounding_boxes = array(); - $width_avail = $img_x; - $code_num = sizeof($code); - $char_class = $this->captcha_char('char_ttf'); - for ($i = 0; $i < $code_num; ++$i) - { - $characters[$i] = new $char_class($code[$i]); - $sizes[$i] = mt_rand(75, 100); - $box = $characters[$i]->dimensions($sizes[$i]); - $width_avail -= ($box[2] - $box[0]); - $bounding_boxes[$i] = $box; - } - - // - // Redistribute leftover x-space - // - $offset = array(); - for ($i = 0; $i < $code_num; ++$i) - { - $denom = ($code_num - $i); - $denom = max(1.5, $denom); - $offset[$i] = mt_rand(0, (1.5 * $width_avail) / $denom); - $width_avail -= $offset[$i]; - } - - // Draw the text - $xoffset = 0; - for ($i = 0; $i < $code_num; ++$i) - { - $characters[$i] = new $char_class($code[$i]); - $dimm = $bounding_boxes[$i]; - $xoffset += ($offset[$i] - $dimm[0]); - $yoffset = mt_rand(-$dimm[1], $img_y - $dimm[3]); - $characters[$i]->drawchar($sizes[$i], $xoffset, $yoffset, $img, $c->r('background'), array($c->r('primary'))); - $xoffset += $dimm[2]; - } - - for ($i = 0; $i < $img_x; ++$i) - { - for ($j = 0; $j < $img_y; ++$j) - { - // if the stencil is not black, set the pixel in the image to gray - if (imagecolorat($stencil, $i, $j)) - { - imagesetpixel($img, $i, $j, $c->r('gray')); - } - } - } - - // Send image - $this->send_image($img); - } - - function policy_cells($code) - { - global $user; - // Generate image - $img_x = 800; - $img_y = 250; - $img = imagecreate($img_x, $img_y); - - $fonts = captcha_load_ttf_fonts(); - - $map = captcha_vectors(); - - // - // Generate colors - // - $c = new color_manager($img, 'white'); - - $c->allocate_named('primary', array( - 'random' => true, - 'min_saturation' => 30, - 'min_value' => 65, - )); - $primaries = $c->color_scheme('primary', 'tetradic'); - $bg_colors = $c->mono_range($primaries, 'value', 4, false); - shuffle($primaries); - shuffle($bg_colors); - - // Randomize the characters on the right and the left - $left_characters = array(); - $right_characters = array(); - $chars = array_merge(range('A', 'Z'), range('1', '9')); - $chars_size = sizeof($chars) - 1; - $alpha = range('A', 'Z'); - $alpha_size = sizeof($alpha) - 1; - for ($i = 0; $i < 25; ++$i) - { - $left_characters[$i] = $alpha[mt_rand(0, $alpha_size)]; - $right_characters[$i] = $chars[mt_rand(0, $chars_size)]; - } - - // Pick locations for our code, shuffle the rest into 3 separate queues - $code_count = sizeof($code); - $code_order = range(0, 24); - shuffle($code_order); - $remaining = array_splice($code_order, $code_count); - $lineups = array($code_order, array(), array(), array()); - for ($i = sizeof($remaining) - 1; $i >= 0; --$i) - { - $lineups[mt_rand(1, 3)][] = $remaining[$i]; - } - - // overwrite the randomized left and right values with our code, where applicable - for ($i = 0; $i < $code_count; ++$i) - { - $left_characters[$code_order[$i]] = $i + 1; - $right_characters[$code_order[$i]] = $code[$i]; - } - - - $offset1 = 50; - $offset2 = 550; - - // Draw the cells and right hand characters - $xs = $ys = array(); - for ($i = 0; $i < 25; ++$i) - { - $xs[$i] = $offset1 + 20 + (($i % 5) * 40) + mt_rand(-13, 13); - $ys[$i] = 45 + (intval($i / 5) * 40) + mt_rand(-13, 13); - - $bg = $c->r_rand($bg_colors); - - // fill the cells with the background colors - imagefilledrectangle($img, - $offset1 + 1 + (($i % 5) * 40), 26 + (intval($i / 5) * 40), - $offset1 + 39 + (($i % 5) * 40), 64 + (intval($i / 5) * 40), - $bg); - imagefilledrectangle($img, - $offset2 + 1 + (($i % 5) * 40), 26 + (intval($i / 5) * 40), - $offset2 + 39 + (($i % 5) * 40), 64 + (intval($i / 5) * 40), - $bg); - - $level = intval($i / 5); - $pos = $i % 5; - imagettftext($img, 12, 0, - $offset2 + 15 + ($pos * 40), 50 + ($level * 40), - $c->is_dark($bg) ? $c->r('white'): $c->r('black'), $fonts['genr102.ttf'], $right_characters[$i]); - } - - // draw the lines that appear between nodes (visual hint) - for ($k = 0; $k < 4; ++$k ) - { - $lineup = $lineups[$k]; - for ($i = 1, $size = sizeof($lineup); $i < $size; ++$i ) - { - imageline($img, - $xs[$lineup[$i - 1]], $ys[$lineup[$i - 1]], - $xs[$lineup[$i]], $ys[$lineup[$i]], - $primaries[$k]); - } - } - - // draw the actual nodes - $textcolor = $c->is_dark($primaries[0]) ? $c->r('white') : $c->r('black'); - for ($k = 0; $k < 4; ++$k ) - { - for ($j = 0, $size = sizeof($lineups[$k]); $j < $size; ++$j ) - { - $i = $lineups[$k][$j]; - imagefilledellipse($img, - $xs[$i], $ys[$i], - 20, 20, - $primaries[$k]); - imagettftext($img, 12, 0, - $xs[$i] - 5, $ys[$i] + 5, - $textcolor, $fonts['genr102.ttf'], $left_characters[$i]); - } - } - - // Draw poly behind explain text - $points = mt_rand(3, 6); - $arc = 360 / $points; - $vertices = array(); - $c_x = $img_x / 2; - $c_y = $img_y / 2; - $radius = $img_y / 2.5; - $start = deg2rad(mt_rand(0, 360)); - for ($i = 0; $i < $points; ++$i) - { - $rad = $start + deg2rad(($arc * $i) + mt_rand(-10, 10)); - $vertices[] = $c_x + (cos($rad) * $radius); - $vertices[] = $c_y + (sin($rad) * $radius); - } - imagefilledpolygon($img, $vertices, $points, $primaries[mt_rand(0,3)]); - - // draw explain text - $count = sizeof($user->lang['CAPTCHA']['cells']); - $line_height = $img_y / ($count + 1); - for ($i = 0; $i < $count; ++$i) - { - $text = $user->lang['CAPTCHA']['cells'][$i]; - $line_width = strlen($text) * 4.5; // ( / 2, * 9 ) - imagestring($img, 6, ($img_x / 2) - $line_width - 1, $line_height * ($i + 1) - 1, $text, $c->r('black')); - imagestring($img, 6, ($img_x / 2) - $line_width - 1, $line_height * ($i + 1) + 1, $text, $c->r('black')); - imagestring($img, 6, ($img_x / 2) - $line_width + 1, $line_height * ($i + 1) + 1, $text, $c->r('black')); - imagestring($img, 6, ($img_x / 2) - $line_width + 1, $line_height * ($i + 1) - 1, $text, $c->r('black')); - imagestring($img, 6, ($img_x / 2) - $line_width, $line_height * ($i + 1), $text, $c->r('white')); - } - - // Send image - $this->send_image($img); - } - - /** - * entropy - */ - function policy_entropy($code) + function execute($code) { global $config; - // Generate image - $img_x = 800; - $img_y = 250; - $img = imagecreatetruecolor($img_x, $img_y); - - // Generate colors - $c = new color_manager($img, array( - 'random' => true, - 'min_value' => 60, - ), 'hsv'); + $stats = gd_info(); - $scheme = $c->color_scheme('background', 'triadic', false); - $scheme = $c->mono_range($scheme, 'both', 10, false); - shuffle($scheme); - $bg_colors = array_splice($scheme, mt_rand(6, 12)); - - // Generate code characters - $characters = $sizes = $bounding_boxes = array(); - $width_avail = $img_x; - $code_num = sizeof($code); - - for ($i = 0; $i < $code_num; ++$i) - { - $char_class = $this->captcha_char(); - $characters[$i] = new $char_class($code[$i]); - - list($min, $max) = $characters[$i]->range(); - $sizes[$i] = mt_rand($min, $max); - $box = $characters[$i]->dimensions($sizes[$i]); - $width_avail -= ($box[2] - $box[0]); - $bounding_boxes[$i] = $box; - } - - // Redistribute leftover x-space - $offset = array(); - for ($i = 0; $i < $code_num; ++$i) + if (substr($stats['GD Version'], 0, 7) === 'bundled') { - $denom = ($code_num - $i); - $denom = max(1.5, $denom); - $offset[$i] = mt_rand(0, (1.5 * $width_avail) / $denom); - $width_avail -= $offset[$i]; + $bundled = true; } - - // Add some line noise - if ($config['policy_entropy_noise_line']) - { - $this->noise_line($img, 0, 0, $img_x, $img_y, $c->r('background'), $scheme, $bg_colors); - } - - // Draw the text - $xoffset = 0; - for ($i = 0; $i < $code_num; ++$i) - { - $dimm = $bounding_boxes[$i]; - $xoffset += ($offset[$i] - $dimm[0]); - $yoffset = mt_rand(-$dimm[1], $img_y - $dimm[3]); - $characters[$i]->drawchar($sizes[$i], $xoffset, $yoffset, $img, $c->r('background'), $scheme); - $xoffset += $dimm[2]; - } - - // Add some pixel noise - if ($config['policy_entropy_noise_pixel']) + else { - $this->noise_pixel($img, 0, 0, $img_x, $img_y, $c->r('background'), $scheme, $bg_colors, $config['policy_entropy_noise_pixel']); + $bundled = false; } - // Send image - $this->send_image($img); - } - - /** - * 3dbitmap - */ - function policy_3dbitmap($code) - { - // Generate image - $img_x = 700; - $img_y = 225; - $img = imagecreatetruecolor($img_x, $img_y); - $x_grid = mt_rand(6, 10); - $y_grid = mt_rand(6, 10); - - // Ok, so lets cut to the chase. We could accurately represent this in 3d and - // do all the appropriate linear transforms. my questions is... why bother? - // The computational overhead is unnecessary when you consider the simple fact: - // we're not here to accurately represent a model, but to just show off some random-ish - // polygons - - // Conceive of 3 spaces. - // 1) planar-space (discrete "pixel" grid) - // 2) 3-space. (planar-space with z/height aspect) - // 3) image space (pixels on the screen) - - // resolution of the planar-space we're embedding the text code in - $plane_x = 90; - $plane_y = 25; - - $subdivision_factor = 2; - - // $box is the 4 points in img_space that correspond to the corners of the plane in 3-space - $box = array(array(), array(), array(), array()); - - // Top left - $box[0][0] = mt_rand(20, 40); - $box[0][1] = mt_rand(40, 60); - - // Top right - $box[1][0] = mt_rand($img_x - 80, $img_x - 60); - $box[1][1] = mt_rand(10, 30); - - // Bottom right - $box[2][0] = mt_rand($img_x - 40, $img_x - 20); - $box[2][1] = mt_rand($img_y - 50, $img_y - 30); - - // Bottom left. - // because we want to be able to make shortcuts in the 3d->2d, - // we'll calculate the 4th point so that it forms a proper trapezoid - $box[3][0] = $box[2][0] + $box[0][0] - $box[1][0]; - $box[3][1] = $box[2][1] + $box[0][1] - $box[1][1]; - $c = new color_manager($img, array( - 'random' => true, - 'min_saturation' => 50, - 'min_value' => 65, - )); - - $r1 = $c->random_color(array( - 'min_value' => 20, - 'max_value' => 50, - )); - $r2 = $c->random_color(array( - 'min_value' => 70, - 'max_value' => 100, - )); - $rdata = mt_rand(0,1) ? array( - $c->colors[$r1], - $c->colors[$r2], - ) : array( - $c->colors[$r2], - $c->colors[$r1], - ); - - $colors = array(); - for ($i = 0; $i < 60; ++$i) + preg_match('/[\\d.]+/', $stats['GD Version'], $version); + if (version_compare($version[0], '2.0.1', '>=')) { - $colors[$i - 30] = $c->allocate(array( - $rdata[0][0], - (($i * $rdata[0][1]) + ((60 - $i) * $rdata[1][1])) / 60, - (($i * $rdata[0][2]) + ((60 - $i) * $rdata[1][2])) / 60, - )); + $gd_version = 2; } - - // $img_buffer is the last row of 3-space positions (converted to img-space), cached - // (using this means we don't need to recalculate all 4 positions for each new polygon, - // merely the newest point that we're adding, which is then cached. - $img_buffer = array(array(), array()); - - // In image-space, the x- and y-offset necessary to move one unit in the x-direction in planar-space - $dxx = ($box[1][0] - $box[0][0]) / ($subdivision_factor * $plane_x); - $dxy = ($box[1][1] - $box[0][1]) / ($subdivision_factor * $plane_x); - - // In image-space, the x- and y-offset necessary to move one unit in the y-direction in planar-space - $dyx = ($box[3][0] - $box[0][0]) / ($subdivision_factor * $plane_y); - $dyy = ($box[3][1] - $box[0][1]) / ($subdivision_factor * $plane_y); - - // Initial captcha-letter offset in planar-space - $plane_offset_x = 2; - $plane_offset_y = 5; - - // character map - $map = captcha_bitmaps(); - - // matrix - $plane = array(); - - // for each character, we'll silkscreen it into our boolean pixel plane - for ($c = 0, $code_num = sizeof($code); $c < $code_num; ++$c) + else { - $letter = $code[$c]; - - for ($x = $map['width'] - 1; $x >= 0; --$x) - { - for ($y = $map['height'] - 1; $y >= 0; --$y) - { - if ($map['data'][$letter][$y][$x]) - { - $plane[$y + $plane_offset_y + (($c & 1) ? 1 : -1)][$x + $plane_offset_x] = true; - } - } - } - $plane_offset_x += 11; + $gd_version = 1; } - // calculate our first buffer, we can't actually draw polys with these yet - // img_pos_prev == screen x,y location to our immediate left. - // img_pos_cur == current screen x,y location - // we calculate screen position of our - // current cell based on the difference from the previous cell - // rather than recalculating from absolute coordinates - // What we cache into the $img_buffer contains the raised text coordinates. - $img_pos_prev = $img_buffer[0][0] = $box[0]; - $cur_height = $prev_height = $this->wave_height(0, 0, $subdivision_factor); - $full_x = $plane_x * $subdivision_factor; - $full_y = $plane_y * $subdivision_factor; + // set dimension of image + $lx = 360; + $ly = 96; - for ($x = 1; $x <= $full_x; ++$x) + // create the image, stay compat with older versions of GD + if ($gd_version === 2) { - $cur_height = $this->wave_height($x, 0, $subdivision_factor); - $offset = $cur_height - $prev_height; - $img_pos_cur = array($img_pos_prev[0] + $dxx, - $img_pos_prev[1] + $dxy + $offset); - - $img_buffer[0][$x] = $img_pos_cur; - $img_pos_prev = $img_pos_cur; - $prev_height = $cur_height; + $func1 = 'imagecreatetruecolor'; + $func2 = 'imagecolorallocate'; } - - for ($y = 1; $y <= $full_y; ++$y) + else { - // swap buffers - $buffer_cur = $y & 1; - $buffer_prev = 1 - $buffer_cur; - - $prev_height = $this->wave_height(0, $y, $subdivision_factor); - $offset = $prev_height - $this->wave_height(0, $y - 1, $subdivision_factor); - $img_pos_cur = array($img_buffer[$buffer_prev][0][0] + $dyx, - $img_buffer[$buffer_prev][0][1] + $dyy + $offset); - $img_pos_prev = $img_pos_cur; - - $img_buffer[$buffer_cur][0] = $img_pos_cur; - - for ($x = 1; $x <= $full_x; ++$x) - { - $cur_height = $this->wave_height($x, $y, $subdivision_factor) + $this->grid_height($x, $y, 1, $x_grid, $y_grid); - - //height is a z-factor, not a y-factor - $offset = $cur_height - $prev_height; - $img_pos_cur = array($img_pos_prev[0] + $dxx, - $img_pos_prev[1] + $dxy + $offset); - - //(height is float, index it to an int, get closest color) - $color = $colors[intval($cur_height)]; - $img_pos_prev = $img_pos_cur; - $prev_height = $cur_height; - - $y_index_old = intval(($y - 1) / $subdivision_factor); - $y_index_new = intval($y / $subdivision_factor); - $x_index_old = intval(($x - 1) / $subdivision_factor); - $x_index_new = intval($x / $subdivision_factor); - - if (!empty($plane[$y_index_new][$x_index_new])) - { - $offset2 = $this->wave_height($x, $y, $subdivision_factor, 1) - 30 - $cur_height; - $img_pos_cur[1] += $offset2; - $color = $colors[20]; - } - $img_buffer[$buffer_cur][$x] = $img_pos_cur; - - // Smooth the edges as much as possible by having not more than one low<->high traingle per square - // Otherwise, just - $diag_down = (empty($plane[$y_index_old][$x_index_old]) == empty($plane[$y_index_new][$x_index_new])); - $diag_up = (empty($plane[$y_index_old][$x_index_new]) == empty($plane[$y_index_new][$x_index_old])); - - // natural switching - $mode = ($x + $y) & 1; - - // override if it requires it - if ($diag_down != $diag_up) - { - $mode = $diag_up; - } - - if ($mode) - { - // +-/ / - // 1 |/ 2 /| - // / /-+ - $poly1 = array_merge($img_buffer[$buffer_cur][$x - 1], $img_buffer[$buffer_prev][$x - 1], $img_buffer[$buffer_prev][$x]); - $poly2 = array_merge($img_buffer[$buffer_cur][$x - 1], $img_buffer[$buffer_cur][$x], $img_buffer[$buffer_prev][$x]); - } - else - { - // \ \-+ - // 1 |\ 2 \| - // +-\ \ - $poly1 = array_merge($img_buffer[$buffer_cur][$x - 1], $img_buffer[$buffer_prev][$x - 1], $img_buffer[$buffer_cur][$x]); - $poly2 = array_merge($img_buffer[$buffer_prev][$x - 1], $img_buffer[$buffer_prev][$x], $img_buffer[$buffer_cur][$x]); - } - - imagefilledpolygon($img, $poly1, 3, $color); - imagefilledpolygon($img, $poly2, 3, $color); - } + $func1 = 'imagecreate'; + $func2 = 'imagecolorclosest'; } - // Send image on it's merry way - $this->send_image($img); - } + $image = $func1($lx, $ly); - /** - * overlap - */ - function policy_overlap($code) - { - global $config; - $char_size = 40; - $overlap_factor = .32; - - // Generate image - $img_x = 250; - $img_y = 120; - $img = imagecreatetruecolor($img_x, $img_y); - - // Generate colors - $c = new color_manager($img, array( - 'random' => true, - 'min_saturation' => 70, - 'min_value' => 65, - )); - - $primaries = $c->color_scheme('background', 'triadic', false); - $text = mt_rand(0, 1); - $c->name_color('text', $primaries[$text]); - $noise = $c->mono_range($primaries[1 - $text], 'both', 6, false); - - // Generate code characters - $characters = $bounding_boxes = array(); - $width_avail = $img_x; - - // Get the character rendering scheme - $char_class = $this->captcha_char('char_ttf'); - $code_num = sizeof($code); - - for ($i = 0; $i < $code_num; ++$i) + if ($bundled) { - $characters[$i] = new $char_class($code[$i], array('angle' => 0)); - $box = $characters[$i]->dimensions($char_size); - $width_avail -= ((1 - $overlap_factor) * ($box[2] - $box[0])); - $bounding_boxes[$i] = $box; + imageantialias($image, true); } - // Redistribute leftover x-space - $offset = mt_rand(0, $width_avail); - - // Add some line noise - if ($config['policy_overlap_noise_line']) - { - $this->noise_line($img, 0, 0, $img_x, $img_y, $c->r('background'), array($c->r('text')), $noise); - } + // set background color + $back = imagecolorallocate($image, mt_rand(224, 255), mt_rand(224, 255), mt_rand(224, 255)); + imagefilledrectangle($image, 0, 0, $lx, $ly, $back); - // Draw the text - $min = 10 - $bounding_boxes[0][1]; - $max = ($img_y - 10) - $bounding_boxes[0][3]; - $med = ($max + $min) / 2; - - $yoffset = mt_rand($med, $max); - $char_num = sizeof($characters); - - imagesetthickness($img, 3); - for ($i = 0; $i < $char_num; ++$i) + // allocates the 216 websafe color palette to the image + if ($gd_version === 1) { - if ($i) + for ($r = 0; $r <= 255; $r += 51) { - imageline($img, $old_x + mt_rand(-3, 3), $old_y - 70 + mt_rand(-3, 3), $offset + mt_rand(-3, 3), $yoffset - 70 + mt_rand(-3, 3), $c->r('text')); - imageline($img, $old_x + mt_rand(-3, 3), $old_y + 30 + mt_rand(-3, 3), $offset + mt_rand(-3, 3), $yoffset + 30 + mt_rand(-3, 3), $c->r('text')); - } - - $dimm = $bounding_boxes[$i]; - $offset -= $dimm[0]; - $characters[$i]->drawchar($char_size, $offset, $yoffset, $img, $c->r('background'), array($c->r('text'))); - - $old_x = $offset; - $old_y = $yoffset; - - $offset += $dimm[2]; - $offset -= (($dimm[2] - $dimm[0]) * $overlap_factor); - $yoffset += ($i & 1) ? ((1 - $overlap_factor) * ($dimm[3] - $dimm[1])) : ((1 - $overlap_factor) * ($dimm[1] - $dimm[3])); - } - - imagesetthickness($img, 1); - - // Add some medium pixel noise - if ($config['policy_overlap_noise_pixel']) - { - $this->noise_pixel($img, 0, 0, $img_x, $img_y, $c->r('background'), array($c->r('text')), $noise, $config['policy_overlap_noise_pixel']); - } - - // Send image - $this->send_image($img); - } - - /** - * Noise pixel - */ - function noise_pixel($img, $min_x, $min_y, $max_x, $max_y, $bg, $font, $non_font, $override = false) - { - $noise_modules = array('noise_pixel_light', 'noise_pixel_medium', 'noise_pixel_heavy'); - - if ($override == false) - { - $override = array_rand($override); - } - - // Use the module $override, else a random picked one... - $module = $noise_modules[intval($override) - 1]; - - switch ($module) - { - case 'noise_pixel_light': - - for ($x = $min_x; $x < $max_x; $x += mt_rand(9, 18)) + for ($g = 0; $g <= 255; $g += 51) { - for ($y = $min_y; $y < $max_y; $y += mt_rand(4, 9)) + for ($b = 0; $b <= 255; $b += 51) { - imagesetpixel($img, $x, $y, $non_font[array_rand($non_font)]); + imagecolorallocate($image, $r, $g, $b); } } - - for ($y = $min_y; $y < $max_y; $y += mt_rand(9, 18)) - { - for ($x = $min_x; $x < $max_x; $x += mt_rand(4, 9)) - { - imagesetpixel($img, $x, $y, $non_font[array_rand($non_font)]); - } - } - - break; - - case 'noise_pixel_medium': - - for ($x = $min_x; $x < $max_x; $x += mt_rand(4, 9)) - { - for ($y = $min_y; $y < $max_y; $y += mt_rand(2, 5)) - { - imagesetpixel($img, $x, $y, $non_font[array_rand($non_font)]); - } - } - - for ($y = $min_y; $y < $max_y; $y += mt_rand(4, 9)) - { - for ($x = $min_x; $x < $max_x; $x += mt_rand(2, 5)) - { - imagesetpixel($img, $x, $y, $non_font[array_rand($non_font)]); - } - } - - break; - - case 'noise_pixel_heavy': - - for ($x = $min_x; $x < $max_x; $x += mt_rand(4, 9)) - { - for ($y = $min_y; $y < $max_y; $y++) - { - imagesetpixel($img, $x, $y, $non_font[array_rand($non_font)]); - } - } - - for ($y = $min_y; $y < $max_y; $y+= mt_rand(4, 9)) - { - for ($x = $min_x; $x < $max_x; $x++) - { - imagesetpixel($img, $x, $y, $non_font[array_rand($non_font)]); - } - } - - break; - } - } - - /** - * Noise line - */ - function noise_line($img, $min_x, $min_y, $max_x, $max_y, $bg, $font, $non_font) - { - imagesetthickness($img, 2); - $x1 = $min_x; - $x2 = $max_x; - $y1 = $min_y; - $y2 = $min_y; - - do - { - $line = array_merge( - array_fill(0, mt_rand(30, 60), $non_font[array_rand($non_font)]), - array_fill(0, mt_rand(30, 60), $bg) - ); - - imagesetstyle($img, $line); - imageline($img, $x1, $y1, $x2, $y2, IMG_COLOR_STYLED); - - $y1 += mt_rand(12, 35); - $y2 += mt_rand(12, 35); - } - while ($y1 < $max_y && $y2 < $max_y); - - $x1 = $min_x; - $x2 = $min_x; - $y1 = $min_y; - $y2 = $max_y; - - do - { - $line = array_merge( - array_fill(0, mt_rand(30, 60), $non_font[array_rand($non_font)]), - array_fill(0, mt_rand(30, 60), $bg) - ); - - imagesetstyle($img, $line); - imageline($img, $x1, $y1, $x2, $y2, IMG_COLOR_STYLED); - - $x1 += mt_rand(12, 35); - $x2 += mt_rand(12, 35); - } - while ($x1 < $max_x && $x2 < $max_x); - imagesetthickness($img, 1); - } - - /** - * Randomly determine which char class to use - * Able to define static one with override - */ - function captcha_char($override = false) - { - static $character_classes = array(); - - // Some people have GD but no TTF support - if (sizeof($character_classes) == 0) - { - $character_classes = array('char_vector', 'char_hatches', 'char_cube3d', 'char_dots'); - - if (function_exists('imagettfbbox') && function_exists('imagettftext')) - { - $character_classes[] = 'char_ttf'; - } - } - - // Use the module $override, else a random picked one... - $class = ($override !== false && in_array($override, $character_classes)) ? $override : $character_classes[array_rand($character_classes)]; - - return $class; - } -} - -/** -* @package VC -*/ -class char_dots -{ - var $vectors; - var $space; - var $radius; - var $letter; - var $width_percent; - - /** - * Constuctor - */ - function char_dots($letter = '', $args = false) - { - $width_percent = false; - if (is_array($args)) - { - $width_percent = (!empty($args['width_percent'])) ? $args['width_percent'] : false; - } - - $this->vectors = captcha_vectors(); - $this->width_percent = (!empty($width_percent)) ? max(25, min(150, intval($width_percent))) : mt_rand(60, 90); - - $this->space = 10; - $this->radius = 3; - $this->density = 3; - $this->letter = $letter; - } - - /** - * Draw a character - */ - function drawchar($scale, $xoff, $yoff, $img, $background, $colors) - { - $vectorset = $this->vectors[$this->letter]; - $height = $scale; - $width = (($scale * $this->width_percent) / 100); - $color = $colors[array_rand($colors)]; - - if (sizeof($vectorset)) - { - foreach ($vectorset as $veclist) - { - switch ($veclist[0]) - { - case 'line': - - $dx = ($veclist[3] - $veclist[1]) * $width; - $dy = ($veclist[4] - $veclist[2]) * -$height; - - $len = sqrt(($dx * $dx) + ($dy * $dy)); - - $inv_dx = -($dy / $len); - $inv_dy = ($dx / $len); - - for ($i = 0; $i < $len; ++$i) - { - for ($k = 0; $k <= $this->density; ++$k) - { - $shift = mt_rand(-$this->radius, $this->radius); - imagesetpixel($img, - $xoff + ($veclist[1] * $width) + (($i * $dx) / $len) + ($inv_dx * $shift), - $yoff + ((1 - $veclist[2]) * $height) + (($i * $dy) / $len) + ($inv_dy * $shift), - $color); - } - } - - break; - - case 'arc': - - $arclengthdeg = $veclist[6] - $veclist[5]; - $arclengthdeg += ( $arclengthdeg < 0 ) ? 360 : 0; - - $arclength = ((($veclist[3] * $width) + ($veclist[4] * $height)) * M_PI) / 2; - - $arclength = ($arclength * $arclengthdeg) / 360; - - $x_c = $veclist[1] * $width; - $y_c = (1 - $veclist[2]) * $height; - $increment = ($arclengthdeg / $arclength); - - for ($i = 0; $i < $arclengthdeg; $i += $increment) - { - $theta = deg2rad(($i + $veclist[5]) % 360); - $x_o = cos($theta); - $y_o = sin($theta); - $pre_width = ($veclist[3] * 0.5 * $width); - $pre_height = ($veclist[4] * 0.5 * $height); - for ($k = 0; $k <= $this->density; ++$k) - { - $shift = mt_rand(-$this->radius, $this->radius); - $x_o1 = $x_o * ($pre_width + $shift); - $y_o1 = $y_o * ($pre_height + $shift); - imagesetpixel($img, - $xoff + $x_c + $x_o1, - $yoff + $y_c + $y_o1, - $color); - } - } - - break; - - default: - // Do nothing with bad input - break; - } } } - } - - /* - * return a roughly acceptable range of sizes for rendering with this texttype - */ - function range() - { - return array(60, 80); - } - /** - * dimensions - */ - function dimensions($size) - { - return array(-4, -4, (($size * $this->width_percent) / 100) + 4, $size + 4); - } -} -/** -* @package VC -*/ -class char_vector -{ - var $vectors; - var $width_percent; - var $letter; - - /** - * Constructor - */ - function char_vector($letter = '', $args = false) - { - $width_percent = false; - if (is_array($args)) - { - $width_percent = (!empty($args['width_percent'])) ? $args['width_percent'] : false; - } - - $this->vectors = captcha_vectors(); - $this->width_percent = (!empty($width_percent)) ? max(25, min(150, intval($width_percent))) : mt_rand(60,90); - $this->letter = $letter; - } - - /** - * Draw a character - */ - function drawchar($scale, $xoff, $yoff, $img, $background, $colors) - { - $vectorset = $this->vectors[$this->letter]; - $height = $scale; - $width = (($scale * $this->width_percent) / 100); - $color = $colors[array_rand($colors)]; - - if (sizeof($vectorset)) + // fill with noise or grid + if ($config['captcha_gd_noise']) { - foreach ($vectorset as $veclist) + // random characters in background with random position, angle, color + for ($i = 0 ; $i < 72; $i++) { - for ($i = 0; $i < 9; ++$i) - { - $xp = $i % 3; - $yp = ($i - $xp) / 3; - $xp--; - $yp--; - - switch ($veclist[0]) - { - case 'line': - imageline($img, - $xoff + $xp + ($veclist[1] * $width), - $yoff + $yp + ((1 - $veclist[2]) * $height), - $xoff + $xp + ($veclist[3] * $width), - $yoff + $yp + ((1 - $veclist[4]) * $height), - $color - ); - break; - - case 'arc': - imagearc($img, - $xoff + $xp + ($veclist[1] * $width), - $yoff + $yp + ((1 - $veclist[2]) * $height), - $veclist[3] * $width, - $veclist[4] * $height, - $veclist[5], - $veclist[6], - $color - ); - break; - } - } + $size = mt_rand(8, 23); + $angle = mt_rand(0, 360); + $x = mt_rand(0, 360); + $y = mt_rand(0, (int)($ly - ($size / 5))); + $color = $func2($image, mt_rand(160, 224), mt_rand(160, 224), mt_rand(160, 224)); + $text = chr(mt_rand(45, 250)); + imagettftext($image, $size, $angle, $x, $y, $color, $this->get_font(), $text); } } - } - - /* - * return a roughly acceptable range of sizes for rendering with this texttype - */ - function range() - { - return array(50, 80); - } - - /** - * dimensions - */ - function dimensions($size) - { - return array(-2, -2, (($size * $this->width_percent) / 100 ) + 2, $size + 2); - } -} - -/** -* @package VC -*/ -class char_ttf -{ - var $angle = 0; - var $fontfile = ''; - var $letter = ''; - - /** - * Constructor - */ - function char_ttf($letter = '', $args = false) - { - $font = $angle = false; - - if (is_array($args)) - { - $font = (!empty($args['font'])) ? $args['font'] : false; - $angle = (isset($args['angle'])) ? $args['angle'] : false; - } - - $fonts = captcha_load_ttf_fonts(); - - if (empty($font) || !isset($fonts[$font])) - { - $font = array_rand($fonts); - } - - $this->fontfile = $fonts[$font]; - $this->angle = ($angle !== false) ? intval($angle) : mt_rand(-40, 40); - $this->letter = $letter; - } - - /** - * Draw a character - */ - function drawchar($scale, $xoff, $yoff, $img, $background, $colors) - { - $color = $colors[array_rand($colors)]; - imagettftext($img, $scale, $this->angle, $xoff, $yoff, $color, $this->fontfile, $this->letter); - } - - /* - * return a roughly acceptable range of sizes for rendering with this texttype - */ - function range() - { - return array(36, 150); - } - - /** - * Dimensions - */ - function dimensions($scale) - { - $data = imagettfbbox($scale, $this->angle, $this->fontfile, $this->letter); - return ($this->angle > 0) ? array($data[6], $data[5], $data[2], $data[1]) : array($data[0], $data[7], $data[4], $data[3]); - } -} - -/** -* @package VC -*/ -class char_hatches -{ - var $vectors; - var $space; - var $radius; - var $letter; - - /** - * Constructor - */ - function char_hatches($letter = '', $args = false) - { - $width_percent = false; - if (is_array($args)) - { - $width_percent = (!empty($args['width_percent'])) ? $args['width_percent'] : false; - } - - $this->vectors = captcha_vectors(); - $this->width_percent = (!empty($width_percent)) ? max(25, min(150, intval($width_percent))) : mt_rand(60, 90); - - $this->space = 10; - $this->radius = 3; - $this->letter = $letter; - } - - /** - * Draw a character - */ - function drawchar($scale, $xoff, $yoff, $img, $background, $colors) - { - $vectorset = $this->vectors[$this->letter]; - $height = $scale; - $width = (($scale * $this->width_percent) / 100); - $color = $colors[array_rand($colors)]; - - if (sizeof($vectorset)) + else { - foreach ($vectorset as $veclist) + // generate grid + for ($i = 0; $i < $lx; $i += 13) { - switch ($veclist[0]) - { - case 'line': - $dx = ($veclist[3] - $veclist[1]) * $width; - $dy = ($veclist[4] - $veclist[2]) * -$height; - - $idx = -$dy; - $idy = $dx; - - $length = sqrt(pow($dx, 2) + pow($dy, 2)); - - $hatches = $length / $this->space; - - for ($p = 0; $p <= $hatches; ++$p) - { - if (!$p && !mt_rand(0, 9) && ($hatches > 3)) - { - continue; - } - - $xp = 1; - $yp = -2; - for ($i = 0; $i < 9; ++$i) - { - $xp += !($i % 3) ? -2 : 1; - $yp += !($i % 3) ? 1 : 0; - - $x_o = ((($p * $veclist[1]) + (($hatches - $p) * $veclist[3])) * $width ) / $hatches; - $y_o = $height - (((($p * $veclist[2]) + (($hatches - $p) * $veclist[4])) * $height ) / $hatches); - $x_1 = $xoff + $xp + $x_o; - $y_1 = $yoff + $yp + $y_o; - - $x_d1 = (($dx - $idx) * $this->radius) / $length; - $y_d1 = (($dy - $idy) * $this->radius) / $length; - - $x_d2 = (($dx - $idx) * -$this->radius) / $length; - $y_d2 = (($dy - $idy) * -$this->radius) / $length; - - imageline($img, $x_1 + $x_d1, $y_1 + $y_d1, $x_1 + $x_d2, $y_1 + $y_d2, $color); - } - } - break; - - case 'arc': - $arclengthdeg = $veclist[6] - $veclist[5]; - $arclengthdeg += ( $arclengthdeg < 0 ) ? 360 : 0; - - $arclength = ((($veclist[3] * $width) + ($veclist[4] * $height)) * M_PI) / 2; - $arclength = ($arclength * $arclengthdeg) / 360; - - $hatches = $arclength / $this->space; - - $hatchdeg = ($arclengthdeg * $this->space) / $arclength; - $shiftdeg = ($arclengthdeg * $this->radius) / $arclength; - - $x_c = $veclist[1] * $width; - $y_c = (1 - $veclist[2]) * $height; - - for ($p = 0; $p <= $arclengthdeg; $p += $hatchdeg) - { - if (!mt_rand(0, 9) && ($hatches > 3) && !$p) - { - continue; - } - - $theta1 = deg2rad(($p + $veclist[5] - $shiftdeg) % 360); - $theta2 = deg2rad(($p + $veclist[5] + $shiftdeg) % 360); - $x_o1 = cos($theta1) * (($veclist[3] * 0.5 * $width) - $this->radius); - $y_o1 = sin($theta1) * (($veclist[4] * 0.5 * $height) - $this->radius); - $x_o2 = cos($theta2) * (($veclist[3] * 0.5 * $width) + $this->radius); - $y_o2 = sin($theta2) * (($veclist[4] * 0.5 * $height) + $this->radius); - - $xp = 1; - $yp = -2; - for ($i = 0; $i < 9; ++$i) - { - $xp += !($i % 3) ? -2 : 1; - $yp += !($i % 3) ? 1 : 0; - - imageline($img, - $xoff + $xp + $x_c + $x_o1, - $yoff + $yp + $y_c + $y_o1, - $xoff + $xp + $x_c + $x_o2, - $yoff + $yp + $y_c + $y_o2, - $color - ); - } - } - break; - } + $color = $func2($image, mt_rand(160, 224), mt_rand(160, 224), mt_rand(160, 224)); + imageline($image, $i, 0, $i, $ly, $color); } - } - } - - /* - * return a roughly acceptable range of sizes for rendering with this texttype - */ - function range() - { - return array(60, 80); - } - - /** - * Dimensions - */ - function dimensions($size) - { - return array(-4, -4, (($size * $this->width_percent) / 100) + 4, $size + 4); - } -} - -/** -* @package VC -*/ -class char_cube3d -{ - // need to abstract out the cube3d from the cubechar - var $bitmaps; - - var $basis_matrix = array(array(1, 0, 0), array(0, 1, 0), array(0, 0, 1)); - var $abs_x = array(1, 0); - var $abs_y = array(0, 1); - var $x = 0; - var $y = 1; - var $z = 2; - var $letter = ''; - - function char_cube3d($letter) - { - $this->bitmaps = captcha_bitmaps(); - - $this->basis_matrix[0][0] = mt_rand(-600, 600); - $this->basis_matrix[0][1] = mt_rand(-600, 600); - $this->basis_matrix[0][2] = (mt_rand(0, 1) * 2000) - 1000; - $this->basis_matrix[1][0] = mt_rand(-1000, 1000); - $this->basis_matrix[1][1] = mt_rand(-1000, 1000); - $this->basis_matrix[1][2] = mt_rand(-1000, 1000); - - $this->normalize($this->basis_matrix[0]); - $this->normalize($this->basis_matrix[1]); - $this->basis_matrix[2] = $this->cross_product($this->basis_matrix[0], $this->basis_matrix[1]); - $this->normalize($this->basis_matrix[2]); - - // $this->basis_matrix[1] might not be (probably isn't) orthogonal to $basis_matrix[0] - $this->basis_matrix[1] = $this->cross_product($this->basis_matrix[0], $this->basis_matrix[2]); - $this->normalize($this->basis_matrix[1]); - - // Make sure our cube is facing into the canvas (assuming +z == in) - for ($i = 0; $i < 3; ++$i) - { - if ($this->basis_matrix[$i][2] < 0) + for ($i = 0; $i < $ly; $i += 11) { - $this->basis_matrix[$i][0] *= -1; - $this->basis_matrix[$i][1] *= -1; - $this->basis_matrix[$i][2] *= -1; + $color = $func2($image, mt_rand(160, 224), mt_rand(160, 224), mt_rand(160, 224)); + imageline($image, 0, $i, $lx, $i, $color); } } - // Force our "z" basis vector to be the one with greatest absolute z value - $this->x = 0; - $this->y = 1; - $this->z = 2; + $len = strlen($code); - // Swap "y" with "z" - if ($this->basis_matrix[1][2] > $this->basis_matrix[2][2]) + for ($i = 0, $x = mt_rand(20, 40); $i < $len; $i++) { - $this->z = 1; - $this->y = 2; - } + $text = strtoupper($code[$i]); + $angle = mt_rand(-30, 30); + $size = mt_rand(20, 40); + $y = mt_rand((int)($size * 1.5), (int)($ly - ($size / 7))); - // Swap "x" with "z" - if ($this->basis_matrix[0][2] > $this->basis_matrix[$this->z][2]) - { - $this->x = $this->z; - $this->z = 0; - } + $color = $func2($image, mt_rand(0, 127), mt_rand(0, 127), mt_rand(0, 127)); + $shadow = $func2($image, mt_rand(127, 254), mt_rand(127, 254), mt_rand(127, 254)); + $font = $this->get_font(); - // Still need to determine which of $x,$y are which. - // wrong orientation if y's y-component is less than it's x-component - // likewise if x's x-component is less than it's y-component - // if they disagree, go with the one with the greater weight difference. - // rotate if positive - $weight = (abs($this->basis_matrix[$this->x][1]) - abs($this->basis_matrix[$this->x][0])) + - (abs($this->basis_matrix[$this->y][0]) - abs($this->basis_matrix[$this->y][1])); + imagettftext($image, $size, $angle, $x + (int)($size / 15), $y, $shadow, $font, $text); + imagettftext($image, $size, $angle, $x, $y - (int)($size / 15), $color, $font, $text); - // Swap "x" with "y" - if ($weight > 0) - { - list($this->x, $this->y) = array($this->y, $this->x); + $x += $size + 4; } - $this->abs_x = array($this->basis_matrix[$this->x][0], $this->basis_matrix[$this->x][1]); - $this->abs_y = array($this->basis_matrix[$this->y][0], $this->basis_matrix[$this->y][1]); - - if ($this->abs_x[0] < 0) - { - $this->abs_x[0] *= -1; - $this->abs_x[1] *= -1; - } - - if ($this->abs_y[1] > 0) - { - $this->abs_y[0] *= -1; - $this->abs_y[1] *= -1; - } - - $this->letter = $letter; - } - - /** - * - */ - function draw($im, $scale, $xoff, $yoff, $face, $xshadow, $yshadow) - { - $origin = array(0, 0, 0); - $xvec = $this->scale($this->basis_matrix[$this->x], $scale); - $yvec = $this->scale($this->basis_matrix[$this->y], $scale); - $face_corner = $this->sum2($xvec, $yvec); - - $zvec = $this->scale($this->basis_matrix[$this->z], $scale); - $x_corner = $this->sum2($xvec, $zvec); - $y_corner = $this->sum2($yvec, $zvec); - - imagefilledpolygon($im, $this->gen_poly($xoff, $yoff, $origin, $xvec, $x_corner, $zvec), 4, $yshadow); - imagefilledpolygon($im, $this->gen_poly($xoff, $yoff, $origin, $yvec, $y_corner, $zvec), 4, $xshadow); - imagefilledpolygon($im, $this->gen_poly($xoff, $yoff, $origin, $xvec, $face_corner, $yvec), 4, $face); - } - - /** - * Draw a character - */ - function drawchar($scale, $xoff, $yoff, $img, $background, $colors) - { - $width = $this->bitmaps['width']; - $height = $this->bitmaps['height']; - $bitmap = $this->bitmaps['data'][$this->letter]; - - $color1 = $colors[array_rand($colors)]; - $color2 = $colors[array_rand($colors)]; - - $swapx = ($this->basis_matrix[$this->x][0] > 0); - $swapy = ($this->basis_matrix[$this->y][1] < 0); - - for ($y = 0; $y < $height; ++$y) - { - for ($x = 0; $x < $width; ++$x) - { - $xp = ($swapx) ? ($width - $x - 1) : $x; - $yp = ($swapy) ? ($height - $y - 1) : $y; - - if ($bitmap[$height - $yp - 1][$xp]) - { - $dx = $this->scale($this->abs_x, ($xp - ($swapx ? ($width / 2) : ($width / 2) - 1)) * $scale); - $dy = $this->scale($this->abs_y, ($yp - ($swapy ? ($height / 2) : ($height / 2) - 1)) * $scale); - $xo = $xoff + $dx[0] + $dy[0]; - $yo = $yoff + $dx[1] + $dy[1]; - - $origin = array(0, 0, 0); - $xvec = $this->scale($this->basis_matrix[$this->x], $scale); - $yvec = $this->scale($this->basis_matrix[$this->y], $scale); - $face_corner = $this->sum2($xvec, $yvec); - - $zvec = $this->scale($this->basis_matrix[$this->z], $scale); - $x_corner = $this->sum2($xvec, $zvec); - $y_corner = $this->sum2($yvec, $zvec); - - imagefilledpolygon($img, $this->gen_poly($xo, $yo, $origin, $xvec, $x_corner,$zvec), 4, $color1); - imagefilledpolygon($img, $this->gen_poly($xo, $yo, $origin, $yvec, $y_corner,$zvec), 4, $color2); - - $face = $this->gen_poly($xo, $yo, $origin, $xvec, $face_corner, $yvec); - - imagefilledpolygon($img, $face, 4, $background); - imagepolygon($img, $face, 4, $color1); - } - } - } - } - - /* - * return a roughly acceptable range of sizes for rendering with this texttype - */ - function range() - { - return array(5, 10); - } - - /** - * Vector length - */ - function vectorlen($vector) - { - return sqrt(pow($vector[0], 2) + pow($vector[1], 2) + pow($vector[2], 2)); - } - - /** - * Normalize - */ - function normalize(&$vector, $length = 1) - { - $length = (( $length < 1) ? 1 : $length); - $length /= $this->vectorlen($vector); - $vector[0] *= $length; - $vector[1] *= $length; - $vector[2] *= $length; - } - - /** - * - */ - function cross_product($vector1, $vector2) - { - $retval = array(0, 0, 0); - $retval[0] = (($vector1[1] * $vector2[2]) - ($vector1[2] * $vector2[1])); - $retval[1] = -(($vector1[0] * $vector2[2]) - ($vector1[2] * $vector2[0])); - $retval[2] = (($vector1[0] * $vector2[1]) - ($vector1[1] * $vector2[0])); - - return $retval; - } - - /** - * - */ - function sum($vector1, $vector2) - { - return array($vector1[0] + $vector2[0], $vector1[1] + $vector2[1], $vector1[2] + $vector2[2]); - } - - /** - * - */ - function sum2($vector1, $vector2) - { - return array($vector1[0] + $vector2[0], $vector1[1] + $vector2[1]); - } - - /** - * - */ - function scale($vector, $length) - { - if (sizeof($vector) == 2) - { - return array($vector[0] * $length, $vector[1] * $length); - } - - return array($vector[0] * $length, $vector[1] * $length, $vector[2] * $length); - } - - /** - * - */ - function gen_poly($xoff, $yoff, &$vec1, &$vec2, &$vec3, &$vec4) - { - $poly = array(); - $poly[0] = $xoff + $vec1[0]; - $poly[1] = $yoff + $vec1[1]; - $poly[2] = $xoff + $vec2[0]; - $poly[3] = $yoff + $vec2[1]; - $poly[4] = $xoff + $vec3[0]; - $poly[5] = $yoff + $vec3[1]; - $poly[6] = $xoff + $vec4[0]; - $poly[7] = $yoff + $vec4[1]; - - return $poly; - } - - /** - * dimensions - */ - function dimensions($size) - { - $xn = $this->scale($this->basis_matrix[$this->x], -($this->bitmaps['width'] / 2) * $size); - $xp = $this->scale($this->basis_matrix[$this->x], ($this->bitmaps['width'] / 2) * $size); - $yn = $this->scale($this->basis_matrix[$this->y], -($this->bitmaps['height'] / 2) * $size); - $yp = $this->scale($this->basis_matrix[$this->y], ($this->bitmaps['height'] / 2) * $size); - - $p = array(); - $p[0] = $this->sum2($xn, $yn); - $p[1] = $this->sum2($xp, $yn); - $p[2] = $this->sum2($xp, $yp); - $p[3] = $this->sum2($xn, $yp); - - $min_x = $max_x = $p[0][0]; - $min_y = $max_y = $p[0][1]; - - for ($i = 1; $i < 4; ++$i) - { - $min_x = ($min_x > $p[$i][0]) ? $p[$i][0] : $min_x; - $min_y = ($min_y > $p[$i][1]) ? $p[$i][1] : $min_y; - $max_x = ($max_x < $p[$i][0]) ? $p[$i][0] : $max_x; - $max_y = ($max_y < $p[$i][1]) ? $p[$i][1] : $max_y; - } - - return array($min_x, $min_y, $max_x, $max_y); - } -} - -/** -* Return bitmaps -*/ -function captcha_bitmaps() -{ - return array( - 'width' => 9, - 'height' => 15, - 'data' => array( - 'A' => array( - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,1,0,1,0,0,0), - array(0,0,0,1,0,1,0,0,0), - array(0,0,0,1,0,1,0,0,0), - array(0,0,1,0,0,0,1,0,0), - array(0,0,1,0,0,0,1,0,0), - array(0,0,1,0,0,0,1,0,0), - array(0,1,0,0,0,0,0,1,0), - array(0,1,0,0,0,0,0,1,0), - array(0,1,1,1,1,1,1,1,0), - array(0,1,0,0,0,0,0,1,0), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - ), - 'B' => array( - array(1,1,1,1,1,1,1,0,0), - array(1,0,0,0,0,0,0,1,0), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,1,0), - array(1,1,1,1,1,1,1,0,0), - array(1,0,0,0,0,0,0,1,0), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,1,0), - array(1,1,1,1,1,1,1,0,0), - ), - 'C' => array( - array(0,0,1,1,1,1,1,0,0), - array(0,1,0,0,0,0,0,1,0), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,1,0), - array(0,0,1,1,1,1,1,0,0), - ), - 'D' => array( - array(1,1,1,1,1,1,1,0,0), - array(1,0,0,0,0,0,0,1,0), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,1,0), - array(1,1,1,1,1,1,1,0,0), - ), - 'E' => array( - array(1,1,1,1,1,1,1,1,1), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,1,1,1,1,1,1,1,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,1,1,1,1,1,1,1,1), - ), - 'F' => array( - array(1,1,1,1,1,1,1,1,1), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,1,1,1,1,1,1,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - ), - 'G' => array( - array(0,0,1,1,1,1,1,0,0), - array(0,1,0,0,0,0,0,1,0), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,1,1,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,1,0), - array(0,0,1,1,1,1,1,0,0), - ), - 'H' => array( - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,1,1,1,1,1,1,1,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - ), - 'I' => array( - array(1,1,1,1,1,1,1,1,1), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(1,1,1,1,1,1,1,1,1), - ), - 'J' => array( - array(1,1,1,1,1,1,1,1,1), - array(0,0,0,0,0,1,0,0,0), - array(0,0,0,0,0,1,0,0,0), - array(0,0,0,0,0,1,0,0,0), - array(0,0,0,0,0,1,0,0,0), - array(0,0,0,0,0,1,0,0,0), - array(0,0,0,0,0,1,0,0,0), - array(0,0,0,0,0,1,0,0,0), - array(0,0,0,0,0,1,0,0,0), - array(0,0,0,0,0,1,0,0,0), - array(0,0,0,0,0,1,0,0,0), - array(1,0,0,0,0,1,0,0,0), - array(1,0,0,0,0,1,0,0,0), - array(0,1,0,0,1,0,0,0,0), - array(0,0,1,1,0,0,0,0,0), - ), - 'K' => array( // New 'K', supplied by NeoThermic - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,1,0), - array(1,0,0,0,0,0,1,0,0), - array(1,0,0,0,0,1,0,0,0), - array(1,0,0,0,1,0,0,0,0), - array(1,0,0,1,0,0,0,0,0), - array(1,0,1,0,0,0,0,0,0), - array(1,1,0,0,0,0,0,0,0), - array(1,0,1,0,0,0,0,0,0), - array(1,0,0,1,0,0,0,0,0), - array(1,0,0,0,1,0,0,0,0), - array(1,0,0,0,0,1,0,0,0), - array(1,0,0,0,0,0,1,0,0), - array(1,0,0,0,0,0,0,1,0), - array(1,0,0,0,0,0,0,0,1), - ), - 'L' => array( - array(0,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,1,1,1,1,1,1,1,1), - ), - 'M' => array( - array(1,1,0,0,0,0,0,1,1), - array(1,1,0,0,0,0,0,1,1), - array(1,0,1,0,0,0,1,0,1), - array(1,0,1,0,0,0,1,0,1), - array(1,0,1,0,0,0,1,0,1), - array(1,0,0,1,0,1,0,0,1), - array(1,0,0,1,0,1,0,0,1), - array(1,0,0,1,0,1,0,0,1), - array(1,0,0,0,1,0,0,0,1), - array(1,0,0,0,1,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - ), - 'N' => array( - array(1,1,0,0,0,0,0,0,1), - array(1,1,0,0,0,0,0,0,1), - array(1,0,1,0,0,0,0,0,1), - array(1,0,1,0,0,0,0,0,1), - array(1,0,0,1,0,0,0,0,1), - array(1,0,0,1,0,0,0,0,1), - array(1,0,0,0,1,0,0,0,1), - array(1,0,0,0,1,0,0,0,1), - array(1,0,0,0,1,0,0,0,1), - array(1,0,0,0,0,1,0,0,1), - array(1,0,0,0,0,1,0,0,1), - array(1,0,0,0,0,0,1,0,1), - array(1,0,0,0,0,0,1,0,1), - array(1,0,0,0,0,0,0,1,1), - array(1,0,0,0,0,0,0,1,1), - ), - 'O' => array( - array(0,0,1,1,1,1,1,0,0), - array(0,1,0,0,0,0,0,1,0), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,1,0), - array(0,0,1,1,1,1,1,0,0), - ), - 'P' => array( - array(1,1,1,1,1,1,1,0,0), - array(1,0,0,0,0,0,0,1,0), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,1,0), - array(1,1,1,1,1,1,1,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - ), - 'Q' => array( - array(0,0,1,1,1,1,1,0,0), - array(0,1,0,0,0,0,0,1,0), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,1,0,0,1), - array(1,0,0,0,0,0,1,0,1), - array(0,1,0,0,0,0,0,1,0), - array(0,0,1,1,1,1,1,0,1), - ), - 'R' => array( - array(1,1,1,1,1,1,1,0,0), - array(1,0,0,0,0,0,0,1,0), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,1,0), - array(1,1,1,1,1,1,1,0,0), - array(1,1,1,0,0,0,0,0,0), - array(1,0,0,1,0,0,0,0,0), - array(1,0,0,0,1,0,0,0,0), - array(1,0,0,0,0,1,0,0,0), - array(1,0,0,0,0,0,1,0,0), - array(1,0,0,0,0,0,0,1,0), - array(1,0,0,0,0,0,0,0,1), - ), - 'S' => array( - array(0,0,1,1,1,1,1,0,0), - array(0,1,0,0,0,0,0,1,0), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(0,0,1,1,1,1,1,0,0), - array(0,0,0,0,0,0,0,1,0), - array(0,0,0,0,0,0,0,0,1), - array(0,0,0,0,0,0,0,0,1), - array(0,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,1,0), - array(0,0,1,1,1,1,1,0,0), - ), - 'T' => array( - array(1,1,1,1,1,1,1,1,1), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - ), - 'U' => array( - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,1,0), - array(0,0,1,1,1,1,1,0,0), - ), - 'V' => array( - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,1,0), - array(0,1,0,0,0,0,0,1,0), - array(0,1,0,0,0,0,0,1,0), - array(0,0,1,0,0,0,1,0,0), - array(0,0,1,0,0,0,1,0,0), - array(0,0,1,0,0,0,1,0,0), - array(0,0,1,0,0,0,1,0,0), - array(0,0,0,1,0,1,0,0,0), - array(0,0,0,1,0,1,0,0,0), - array(0,0,0,1,0,1,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - ), - 'W' => array( // New 'W', supplied by MHobbit - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,1,0,0,0,1), - array(1,0,0,0,1,0,0,0,1), - array(1,0,0,1,0,1,0,0,1), - array(1,0,0,1,0,1,0,0,1), - array(1,0,0,1,0,1,0,0,1), - array(1,0,1,0,0,0,1,0,1), - array(1,0,1,0,0,0,1,0,1), - array(1,0,1,0,0,0,1,0,1), - array(1,1,0,0,0,0,0,1,1), - array(1,1,0,0,0,0,0,1,1), - ), - 'X' => array( - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,1,0), - array(0,1,0,0,0,0,0,1,0), - array(0,0,1,0,0,0,1,0,0), - array(0,0,0,1,0,1,0,0,0), - array(0,0,0,1,0,1,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,1,0,1,0,0,0), - array(0,0,0,1,0,1,0,0,0), - array(0,0,1,0,0,0,1,0,0), - array(0,1,0,0,0,0,1,0,0), - array(0,1,0,0,0,0,0,1,0), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - ), - 'Y' => array( - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,1,0), - array(0,1,0,0,0,0,0,1,0), - array(0,0,1,0,0,0,1,0,0), - array(0,0,1,0,0,0,1,0,0), - array(0,0,0,1,0,1,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - ), - 'Z' => array( // New 'Z' supplied by Anon - array(1,1,1,1,1,1,1,1,1), - array(1,0,0,0,0,0,0,0,1), - array(0,0,0,0,0,0,0,0,1), - array(0,0,0,0,0,0,0,1,0), - array(0,0,0,0,0,0,1,0,0), - array(0,0,0,0,0,1,0,0,0), - array(0,0,0,0,0,1,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,1,0,0,0,0,0), - array(0,0,0,1,0,0,0,0,0), - array(0,0,1,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,1), - array(1,1,1,1,1,1,1,1,1), - ), - '1' => array( - array(0,0,0,1,1,0,0,0,0), - array(0,0,1,0,1,0,0,0,0), - array(0,1,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,1,1,1,1,1,1,1,0), - ), - '2' => array( // New '2' supplied by Anon - array(0,0,0,1,1,1,0,0,0), - array(0,0,1,0,0,0,1,0,0), - array(0,1,0,0,0,0,1,1,0), - array(0,0,0,0,0,0,0,0,1), - array(0,0,0,0,0,0,0,0,1), - array(0,0,0,0,0,0,0,1,1), - array(0,0,0,0,0,0,0,1,0), - array(0,0,0,0,0,0,1,0,0), - array(0,0,0,0,0,1,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,1,0,0,0,0,0), - array(0,0,1,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(1,1,1,1,1,1,1,1,1), - array(0,0,0,0,0,0,0,0,0), - ), - '3' => array( - array(0,0,1,1,1,1,1,0,0), - array(0,1,0,0,0,0,0,1,0), - array(1,0,0,0,0,0,0,0,1), - array(0,0,0,0,0,0,0,0,1), - array(0,0,0,0,0,0,0,0,1), - array(0,0,0,0,0,0,0,0,1), - array(0,0,0,0,0,0,0,1,0), - array(0,0,0,0,0,1,1,0,0), - array(0,0,0,0,0,0,0,1,0), - array(0,0,0,0,0,0,0,0,1), - array(0,0,0,0,0,0,0,0,1), - array(0,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,1,0), - array(0,0,1,1,1,1,1,0,0), - ), - '4' => array( - array(0,0,0,0,0,0,1,1,0), - array(0,0,0,0,0,1,0,1,0), - array(0,0,0,0,1,0,0,1,0), - array(0,0,0,1,0,0,0,1,0), - array(0,0,1,0,0,0,0,1,0), - array(0,1,0,0,0,0,0,1,0), - array(1,0,0,0,0,0,0,1,0), - array(1,0,0,0,0,0,0,1,0), - array(1,1,1,1,1,1,1,1,1), - array(0,0,0,0,0,0,0,1,0), - array(0,0,0,0,0,0,0,1,0), - array(0,0,0,0,0,0,0,1,0), - array(0,0,0,0,0,0,0,1,0), - array(0,0,0,0,0,0,0,1,0), - array(0,0,0,0,0,0,0,1,0), - ), - '5' => array( - array(1,1,1,1,1,1,1,1,1), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(0,0,1,1,1,1,1,0,0), - array(0,0,0,0,0,0,0,1,0), - array(0,0,0,0,0,0,0,0,1), - array(0,0,0,0,0,0,0,0,1), - array(0,0,0,0,0,0,0,0,1), - array(0,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,1,0), - array(0,0,1,1,1,1,1,0,0), - ), - '6' => array( - array(0,0,1,1,1,1,1,0,0), - array(0,1,0,0,0,0,0,1,0), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,1,1,1,1,0,0), - array(1,0,1,0,0,0,0,1,0), - array(1,1,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,1,0), - array(0,0,1,1,1,1,1,0,0), - ), - '7' => array( - array(1,1,1,1,1,1,1,1,1), - array(0,0,0,0,0,0,0,0,1), - array(0,0,0,0,0,0,0,1,0), - array(0,0,0,0,0,0,0,1,0), - array(0,0,0,0,0,0,1,0,0), - array(0,0,0,0,0,1,0,0,0), - array(0,0,0,0,0,1,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,1,0,0,0,0,0), - array(0,0,0,1,0,0,0,0,0), - array(0,0,1,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - ), - '8' => array( - array(0,0,1,1,1,1,1,0,0), - array(0,1,0,0,0,0,0,1,0), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,1,0), - array(0,0,1,1,1,1,1,0,0), - array(0,1,0,0,0,0,0,1,0), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,1,0), - array(0,0,1,1,1,1,1,0,0), - ), - '9' => array( - array(0,0,1,1,1,1,1,0,0), - array(0,1,0,0,0,0,0,1,0), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,1,1), - array(0,1,0,0,0,0,1,0,1), - array(0,0,1,1,1,1,0,0,1), - array(0,0,0,0,0,0,0,0,1), - array(0,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,1,0), - array(0,0,1,1,1,1,1,0,0), - ), - ) - ); -} - - -/** -* Load True Type Fonts -*/ -function captcha_load_ttf_fonts() -{ - static $load_files = array(); - - if (sizeof($load_files) > 0) - { - return $load_files; + // Output image + header('Content-Type: image/png'); + header('Cache-control: no-cache, no-store'); + imagepng($image); + imagedestroy($image); } - global $phpbb_root_path; - - $dr = opendir($phpbb_root_path . 'includes/captcha/fonts'); - while (false !== ($entry = readdir($dr))) + function get_font() { - if (strtolower(pathinfo($entry, PATHINFO_EXTENSION)) == 'ttf') - { - $load_files[$entry] = $phpbb_root_path . 'includes/captcha/fonts/' . $entry; - } - } - closedir($dr); - - return $load_files; -} - - -/** -* Return vectors -*/ -function captcha_vectors() -{ - return array( - 'A' => array( - array('line', 0.00, 0.00, 0.50, 1.00, 1.10714871779, 1.11803398875), - array('line', 1.00, 0.00, 0.50, 1.00, 2.0344439358, 1.11803398875), - array('line', 0.25, 0.50, 0.75, 0.50, 0.00, 0.50), - ), - 'B' => array( - array('line', 0.00, 0.00, 0.00, 1.00, 1.57079632679, 1.00), - array('line', 0.00, 1.00, 0.70, 1.00, 0.00, 0.70), - array('line', 0.00, 0.50, 0.70, 0.50, 0.00, 0.70), - array('line', 0.00, 0.00, 0.70, 0.00, 0.00, 0.70), - array('arc', 0.70, 0.75, 0.60, 0.50, 270, 90), - array('arc', 0.70, 0.25, 0.60, 0.50, 270, 90), - ), - 'C' => array( - array('arc', 0.50, 0.50, 1.00, 1.00, 45, 315), - ), - 'D' => array( - array('line', 0.00, 0.00, 0.00, 1.00, 1.57079632679, 1.00), - array('line', 0.00, 0.00, 0.50, 0.00, 0.00, 0.50), - array('line', 0.00, 1.00, 0.50, 1.00, 0.00, 0.50), - array('arc', 0.50, 0.50, 1.00, 1.00, 270, 90), - ), - 'E' => array( - array('line', 0.00, 0.00, 1.00, 0.00, 0.00, 1.00), - array('line', 0.00, 0.00, 0.00, 1.00, 1.57079632679, 1.00), - array('line', 0.00, 1.00, 1.00, 1.00, 0.00, 1.00), - array('line', 0.00, 0.50, 0.50, 0.50, 0.00, 0.50), - ), - 'F' => array( - array('line', 0.00, 0.00, 0.00, 1.00, 1.57079632679, 1.00), - array('line', 0.00, 1.00, 1.00, 1.00, 0.00, 1.00), - array('line', 0.00, 0.50, 0.50, 0.50, 0.00, 0.50), - ), - 'G' => array( - array('line', 0.50, 0.50, 1.00, 0.50, 0.00, 0.50), - array('line', 1.00, 0.00, 1.00, 0.50, 1.57079632679, 0.50), - array('arc', 0.50, 0.50, 1.00, 1.00, 0, 315), - ), - 'H' => array( - array('line', 0.00, 0.00, 0.00, 1.00, 1.57079632679, 1.00), - array('line', 1.00, 0.00, 1.00, 1.00, 1.57079632679, 1.00), - array('line', 0.00, 0.50, 1.00, 0.50, 0.00, 1.00), - ), - 'I' => array( - array('line', 0.00, 0.00, 1.00, 0.00, 0.00, 1.00), - array('line', 0.00, 1.00, 1.00, 1.00, 0.00, 1.00), - array('line', 0.50, 0.00, 0.50, 1.00, 1.57079632679, 1.00), - ), - 'J' => array( - array('line', 1.00, 1.00, 1.00, 0.25, -1.57079632679, 0.75), - array('arc', 0.50, 0.25, 1.00, 0.50, 0, 180), - ), - 'K' => array( - array('line', 0.00, 0.00, 0.00, 1.00, 1.57079632679, 1.00), - array('line', 0.00, 0.50, 1.00, 1.00, 0.463647609001, 1.11803398875), - array('line', 0.00, 0.50, 1.00, 0.00, -0.463647609001, 1.11803398875), - ), - 'L' => array( - array('line', 0.00, 0.00, 0.00, 1.00, 1.57079632679, 1.00), - array('line', 0.00, 0.00, 1.00, 0.00, 0.00, 1.00), - ), - 'M' => array( - array('line', 0.00, 0.00, 0.00, 1.00, 1.57079632679, 1.00), - array('line', 0.50, 0.50, 0.00, 1.00, 2.35619449019, 0.707106781187), - array('line', 0.50, 0.50, 1.00, 1.00, 0.785398163397, 0.707106781187), - array('line', 1.00, 0.00, 1.00, 1.00, 1.57079632679, 1.00), - ), - 'N' => array( - array('line', 0.00, 0.00, 0.00, 1.00, 1.57079632679, 1.00), - array('line', 0.00, 1.00, 1.00, 0.00, -0.785398163397, 1.41421356237), - array('line', 1.00, 0.00, 1.00, 1.00, 1.57079632679, 1.00), - ), - 'O' => array( - array('arc', 0.50, 0.50, 1.00, 1.00, 0, 360), - ), - 'P' => array( - array('line', 0.00, 0.00, 0.00, 1.00, 1.57079632679, 1.00), - array('line', 0.00, 1.00, 0.70, 1.00, 0.00, 0.70), - array('line', 0.00, 0.50, 0.70, 0.50, 0.00, 0.70), - array('arc', 0.70, 0.75, 0.60, 0.50, 270, 90), - ), - 'Q' => array( - array('line', 0.70, 0.30, 1.00, 0.00, -0.785398163397, 0.424264068712), - array('arc', 0.50, 0.50, 1.00, 1.00, 0, 360), - ), - 'R' => array( - array('line', 0.00, 0.00, 0.00, 1.00, 1.57079632679, 1.00), - array('line', 0.00, 1.00, 0.70, 1.00, 0.00, 0.70), - array('line', 0.00, 0.50, 0.70, 0.50, 0.00, 0.70), - array('line', 0.50, 0.50, 1.00, 0.00, -0.785398163397, 0.707106781187), - array('arc', 0.70, 0.75, 0.60, 0.50, 270, 90), - ), - 'S' => array( - array('arc', 0.50, 0.75, 1.00, 0.50, 90, 360), - array('arc', 0.50, 0.25, 1.00, 0.50, 270, 180), - ), - 'T' => array( - array('line', 0.00, 1.00, 1.00, 1.00, 0.00, 1.00), - array('line', 0.50, 0.00, 0.50, 1.00, 1.57079632679, 1.00), - ), - 'U' => array( - array('line', 0.00, 1.00, 0.00, 0.25, -1.57079632679, 0.75), - array('line', 1.00, 1.00, 1.00, 0.25, -1.57079632679, 0.75), - array('arc', 0.50, 0.25, 1.00, 0.50, 0, 180), - ), - 'V' => array( - array('line', 0.00, 1.00, 0.50, 0.00, -1.10714871779, 1.11803398875), - array('line', 1.00, 1.00, 0.50, 0.00, -2.0344439358, 1.11803398875), - ), - 'W' => array( - array('line', 0.00, 1.00, 0.25, 0.00, -1.32581766367, 1.0307764064), - array('line', 0.50, 0.50, 0.25, 0.00, -2.0344439358, 0.559016994375), - array('line', 0.50, 0.50, 0.75, 0.00, -1.10714871779, 0.559016994375), - array('line', 1.00, 1.00, 0.75, 0.00, -1.81577498992, 1.0307764064), - ), - 'X' => array( - array('line', 0.00, 1.00, 1.00, 0.00, -0.785398163397, 1.41421356237), - array('line', 0.00, 0.00, 1.00, 1.00, 0.785398163397, 1.41421356237), - ), - 'Y' => array( - array('line', 0.00, 1.00, 0.50, 0.50, -0.785398163397, 0.707106781187), - array('line', 1.00, 1.00, 0.50, 0.50, -2.35619449019, 0.707106781187), - array('line', 0.50, 0.50, 0.50, 0.00, -1.57079632679, 0.50), - ), - 'Z' => array( - array('line', 0.00, 1.00, 1.00, 1.00, 0.00, 1.00), - array('line', 0.00, 0.00, 1.00, 1.00, 0.785398163397, 1.41421356237), - array('line', 0.00, 0.00, 1.00, 0.00, 0.00, 1.00), - ), - '1' => array( - array('line', 0.00, 0.75, 0.50, 1.00, 0.463647609001, 0.559016994375), - array('line', 0.50, 0.00, 0.50, 1.00, 1.57079632679, 1.00), - array('line', 0.00, 0.00, 1.00, 0.00, 0.00, 1.00), - ), - '2' => array( - array('line', 0.00, 0.00, 1.00, 0.00, 0.00, 1.00), - array('arc', 0.50, 0.70, 1.00, 0.60, 180, 360), - array('arc', 0.50, 0.70, 1.00, 0.70, 0, 90), - array('arc', 0.50, 0.00, 1.00, 0.70, 180, 270), - ), - '3' => array( - array('arc', 0.50, 0.75, 1.00, 0.50, 180, 90), - array('arc', 0.50, 0.25, 1.00, 0.50, 270, 180), - ), - '4' => array( - array('line', 0.70, 0.00, 0.70, 1.00, 1.57079632679, 1.00), - array('line', 0.00, 0.50, 0.70, 1.00, 0.620249485983, 0.860232526704), - array('line', 0.00, 0.50, 1.00, 0.50, 0.00, 1.00), - ), - '5' => array( - array('line', 0.00, 1.00, 1.00, 1.00, 0.00, 1.00), - array('line', 0.00, 1.00, 0.00, 0.60, -1.57079632679, 0.4), - array('line', 0.00, 0.60, 0.50, 0.60, 0.00, 0.50), - array('arc', 0.50, 0.30, 1.00, 0.60, 270, 180), - ), - '6' => array( - array('arc', 0.50, 0.50, 1.00, 1.00, 90, 315), - array('arc', 0.50, 0.30, 0.80, 0.60, 0, 360), - ), - '7' => array( - array('line', 0.00, 1.00, 1.00, 1.00, 0.00, 1.00), - array('line', 0.50, 0.00, 1.00, 1.00, 1.10714871779, 1.11803398875), - ), - '8' => array( - array('arc', 0.50, 0.75, 1.00, 0.50, 0, 360), - array('arc', 0.50, 0.25, 1.00, 0.50, 0, 360), - ), - '9' => array( - array('arc', 0.50, 0.50, 1.00, 1.00, 270, 135), - array('arc', 0.50, 0.70, 0.80, 0.60, 0, 360), - ) - ); -} - -/** -* @package VC -*/ -class color_manager -{ - var $img; - var $mode; - var $colors; - var $named_colors; - var $named_rgb = array( - 'red' => array(0xff, 0x00, 0x00), - 'maroon' => array(0x80, 0x00, 0x00), - 'yellow' => array(0xff, 0xff, 0x00), - 'olive' => array(0x80, 0x80, 0x00), - 'lime' => array(0x00, 0xff, 0x00), - 'green' => array(0x00, 0x80, 0x00), - 'aqua' => array(0x00, 0xff, 0xff), - 'teal' => array(0x00, 0x80, 0x80), - 'blue' => array(0x00, 0x00, 0xff), - 'navy' => array(0x00, 0x00, 0x80), - 'fuchsia' => array(0xff, 0x00, 0xff), - 'purple' => array(0x80, 0x00, 0x80), - 'white' => array(0xff, 0xff, 0xff), - 'silver' => array(0xc0, 0xc0, 0xc0), - 'gray' => array(0x80, 0x80, 0x80), - 'black' => array(0x00, 0x00, 0x00), - ); - - /** - * Create the color manager, link it to - * the image resource - */ - function color_manager($img, $background = false, $mode = 'ahsv') - { - $this->img = $img; - $this->mode = $mode; - $this->colors = array(); - $this->named_colors = array(); - if ($background !== false) - { - $bg = $this->allocate_named('background', $background); - imagefill($this->img, 0, 0, $bg); - } - } - - /** - * Lookup a named color resource - */ - function r($named_color) - { - if (isset($this->named_colors[$named_color])) - { - return $this->named_colors[$named_color]; - } - if (isset($this->named_rgb[$named_color])) - { - return $this->allocate_named($named_color, $this->named_rgb[$named_color], 'rgb'); - } - return false; - } - - /** - * Assign a name to a color resource - */ - function name_color($name, $resource) - { - $this->named_colors[$name] = $resource; - } - - /** - * random color resource - */ - function r_rand($colors) - { - return $colors[array_rand($colors)]; - } - - /** - * names and allocates a color resource - */ - function allocate_named($name, $color, $mode = false) - { - $resource = $this->allocate($color, $mode); - if ($resource !== false) - { - $this->name_color($name, $resource); - } - return $resource; - } - - /** - * allocates a specified color into the image - */ - function allocate($color, $mode = false) - { - if ($mode === false) - { - $mode = $this->mode; - } - if (!is_array($color)) - { - if (isset($this->named_rgb[$color])) - { - return $this->allocate_named($color, $this->named_rgb[$color], 'rgb'); - } - if (!is_int($color)) - { - return false; - } - $mode = 'rgb'; - $color = array( - 255 & ($color >> 16), - 255 & ($color >> 8), - 255 & $color, - ); - } - - if (isset($color['mode'])) - { - $mode = $color['mode']; - unset($color['mode']); - } - if (isset($color['random'])) - { - unset($color['random']); - // everything else is params - return $this->random_color($color, $mode); - } - - $rgb = color_manager::model_convert($color, $mode, 'rgb'); - $store = ($this->mode == 'rgb') ? $rgb : color_manager::model_convert($color, $mode, $this->mode); - $resource = imagecolorallocate($this->img, $rgb[0], $rgb[1], $rgb[2]); - - $this->colors[$resource] = $store; - - return $resource; - } - - /** - * randomly generates a color, with optional params - */ - function random_color($params = array(), $mode = false) - { - if ($mode === false) - { - $mode = $this->mode; - } - switch ($mode) - { - case 'rgb': - - // @TODO random rgb generation. do we intend to do this, or is it just too tedious? - - break; - - case 'ahsv': - case 'hsv': - default: - - $default_params = array( - 'hue_bias' => false, // degree / 'r'/'g'/'b'/'c'/'m'/'y' /'o' - 'hue_range' => false, // if hue bias, then difference range +/- from bias - 'min_saturation' => 30, // 0 - 100 - 'max_saturation' => 100, // 0 - 100 - 'min_value' => 30, // 0 - 100 - 'max_value' => 100, // 0 - 100 - ); - - $alt = ($mode == 'ahsv'); - - $params = array_merge($default_params, $params); - - $min_hue = 0; - $max_hue = 359; - $min_saturation = max(0, $params['min_saturation']); - $max_saturation = min(100, $params['max_saturation']); - $min_value = max(0, $params['min_value']); - $max_value = min(100, $params['max_value']); - - if ($params['hue_bias'] !== false) - { - if (is_numeric($params['hue_bias'])) - { - $h = intval($params['hue_bias']) % 360; - } - else - { - switch ($params['hue_bias']) - { - case 'o': - $h = $alt ? 60 : 30; - break; - - case 'y': - $h = $alt ? 120 : 60; - break; - - case 'g': - $h = $alt ? 180 : 120; - break; - - case 'c': - $h = $alt ? 210 : 180; - break; - - case 'b': - $h = 240; - break; - - case 'm': - $h = 300; - break; - - case 'r': - default: - $h = 0; - break; - } - } - - $min_hue = $h + 360; - $max_hue = $h + 360; - - if ($params['hue_range']) - { - $min_hue -= min(180, $params['hue_range']); - $max_hue += min(180, $params['hue_range']); - } - } - - $h = mt_rand($min_hue, $max_hue); - $s = mt_rand($min_saturation, $max_saturation); - $v = mt_rand($min_value, $max_value); - - return $this->allocate(array($h, $s, $v), $mode); - - break; - } - } + static $fonts = array(); - function color_scheme($resource, $scheme, $include_original = true) - { - $mode = (in_array($this->mode, array('hsv', 'ahsv'), true) ? $this->mode : 'hsv'); - if (($pre = $this->r($resource)) !== false) - { - $resource = $pre; - } - $color = color_manager::model_convert($this->colors[$resource], $this->mode, $mode); - $results = $include_original ? array($resource) : array(); - - switch ($scheme) + if (!sizeof($fonts)) { - case 'complement': - - $color2 = $color; - $color2[0] += 180; - $results[] = $this->allocate($color2, $mode); - - break; - - case 'triadic': - - $color2 = $color3 = $color; - $color2[0] += 120; - $color3[0] += 240; - $results[] = $this->allocate($color2, $mode); - $results[] = $this->allocate($color3, $mode); - - break; - - case 'tetradic': - - $color2 = $color3 = $color4 = $color; - $color2[0] += 30; - $color3[0] += 180; - $color4[0] += 210; - $results[] = $this->allocate($color2, $mode); - $results[] = $this->allocate($color3, $mode); - $results[] = $this->allocate($color4, $mode); - - break; - - case 'analogous': - - $color2 = $color3 = $color; - $color2[0] += 30; - $color3[0] += 330; - $results[] = $this->allocate($color2, $mode); - $results[] = $this->allocate($color3, $mode); - - break; - } - return $results; - } + global $phpbb_root_path; - function mono_range($resource, $type = 'both', $count = 5, $include_original = true) - { - if (is_array($resource)) - { - $results = array(); - for ($i = 0, $size = sizeof($resource); $i < $size; ++$i) + $dr = opendir($phpbb_root_path . 'includes/captcha/fonts'); + while (false !== ($entry = readdir($dr))) { - $results = array_merge($results, $this->mono_range($resource[$i], $type, $count, $include_original)); - } - return $results; - } - $mode = (in_array($this->mode, array('hsv', 'ahsv'), true) ? $this->mode : 'ahsv'); - if (($pre = $this->r($resource)) !== false) - { - $resource = $pre; - } - $color = color_manager::model_convert($this->colors[$resource], $this->mode, $mode); - - $results = array(); - if ($include_original) - { - $results[] = $resource; - $count--; - } - - switch ($type) - { - case 'saturation': - - $pivot = $color[1]; - $num_below = intval(($pivot * $count) / 100); - $num_above = $count - $num_below; - - for ($i = $num_above; $i > 0; --$i) - { - $color[1] = (($i * 100) + (($num_above - $i) * $pivot)) / $num_above; - $results[] = $this->allocate($color, $mode); - } - - ++$num_below; - - for ($i = $num_below - 1; $i > 0; --$i) - { - $color[1] = ($i * $pivot) / $num_below;; - $results[] = $this->allocate($color, $mode); - } - - return $results; - - break; - - case 'value': - - $pivot = $color[2]; - $num_below = intval(($pivot * $count) / 100); - $num_above = $count - $num_below; - - for ($i = $num_above; $i > 0; --$i) - { - $color[2] = (($i * 100) + (($num_above - $i) * $pivot)) / $num_above; - $results[] = $this->allocate($color, $mode); - } - - ++$num_below; - - for ($i = $num_below - 1; $i > 0; --$i) - { - $color[2] = ($i * $pivot) / $num_below;; - $results[] = $this->allocate($color, $mode); - } - - return $results; - - break; - - case 'both': - - // This is a hard problem. I chicken out and do an even triangle - // the problem is that it disregards the original saturation and value, - // and as such a generated result might come arbitrarily close to our original value. - $length = ceil(sqrt($count * 2)); - for ($i = $length; $i > 0; --$i) - { - for ($j = $i; $j > 0; --$j) - { - $color[1] = ($i * 100) / $length; - $color[2] = ($j * 100) / $i; - $results[] = $this->allocate($color, $mode); - --$count; - if (!$count) - { - return $results; - } - } - } - - return $results; - - break; - } - - return false; - } - - function is_dark($resource) - { - $color = (($pre = $this->r($resource)) !== false) ? $this->colors[$pre] : $this->colors[$resource]; - switch($this->mode) - { - case 'ahsv': - case 'hsv': - - return ($color[2] <= 50); - - break; - - case 'rgb': - - return (max($color[0], $color[1], $color[2]) <= 128); - - break; - } - return false; - } - - /** - * Convert from one color model to another - * - * note: properly following coding standards here yields unweildly amounts of whitespace, rendering this less than easily readable - * - */ - function model_convert($color, $from_model, $to_model) - { - if ($from_model == $to_model) - { - return $color; - } - switch ($to_model) - { - case 'hsv': - switch($from_model) - { - case 'ahsv': - return color_manager::ah2h($color); - break; - - case 'rgb': - return color_manager::rgb2hsv($color); - break; - } - break; - - case 'ahsv': - switch($from_model) - { - case 'hsv': - return color_manager::h2ah($color); - break; - - case 'rgb': - return color_manager::h2ah(color_manager::rgb2hsv($color)); - break; - } - break; - - case 'rgb': - switch($from_model) + if (strtolower(pathinfo($entry, PATHINFO_EXTENSION)) == 'ttf') { - case 'hsv': - return color_manager::hsv2rgb($color); - break; - - case 'ahsv': - return color_manager::hsv2rgb(color_manager::ah2h($color)); - break; + $fonts[] = $phpbb_root_path . 'includes/captcha/fonts/' . $entry; } - break; - } - return false; - } - - /** - * Slightly altered from wikipedia's algorithm - */ - function hsv2rgb($hsv) - { - color_manager::normalize_hue($hsv[0]); - $h = $hsv[0]; - $s = min(1, max(0, $hsv[1] / 100)); - $v = min(1, max(0, $hsv[2] / 100)); - - $hi = floor($hsv[0] / 60); // calculate hue sector - - $p = $v * (1 - $s); // calculate opposite color - $f = ($h / 60) - $hi; // calculate distance between hex vertices - if (!($hi & 1)) // coming in or going out? - { - $f = 1 - $f; - } - $q = $v * (1 - ($f * $s)); // calculate adjacent color - - switch ($hi) - { - case 0: - $rgb = array($v, $q, $p); - break; - - case 1: - $rgb = array($q, $v, $p); - break; - - case 2: - $rgb = array($p, $v, $q); - break; - - case 3: - $rgb = array($p, $q, $v); - break; - - case 4: - $rgb = array($q, $p, $v); - break; - - case 5: - $rgb = array($v, $p, $q); - break; - - default: - return array(0, 0, 0); - break; - } - return array(255 * $rgb[0], 255 * $rgb[1], 255 * $rgb[2]); - } - - /** - * (more than) Slightly altered from wikipedia's algorithm - */ - function rgb2hsv($rgb) - { - $r = min(255, max(0, $rgb[0])); - $g = min(255, max(0, $rgb[1])); - $b = min(255, max(0, $rgb[2])); - $max = max($r, $g, $b); - $min = min($r, $g, $b); - - $v = $max / 255; - $s = (!$max) ? 0 : 1 - ($min / $max); - $h = $max - $min; // if max - min is 0, we want hue to be 0 anyway. - if ($h) - { - switch ($max) - { - case $g: - $h = 120 + (60 * ($b - $r) / $h); - break; - - case $b: - $h = 240 + (60 * ($r - $g) / $h); - break; - - case $r: - $h = 360 + (60 * ($g - $b) / $h); - break; } + closedir($dr); } - color_manager::normalize_hue($h); - return array($h, $s * 100, $v * 100); - } - - /** - * Bleh - */ - function normalize_hue(&$hue) - { - $hue %= 360; - if ($hue < 0) - { - $hue += 360; - } - } - - /** - * Alternate hue to hue - */ - function ah2h($ahue) - { - if (is_array($ahue)) - { - $ahue[0] = color_manager::ah2h($ahue[0]); - return $ahue; - } - color_manager::normalize_hue($ahue); - if ($ahue >= 240) // blue through red is already ok - { - return $ahue; - } - if ($ahue >= 180) // ahue green is at 180 - { - // return (240 - (2 * (240 - $ahue))); - return (2 * $ahue) - 240; // equivalent - } - if ($ahue >= 120) // ahue yellow is at 120 (RYB rather than RGB) - { - return $ahue - 60; - } - return $ahue / 2; - } - /** - * hue to Alternate hue - */ - function h2ah($hue) - { - if (is_array($hue)) - { - $hue[0] = color_manager::h2ah($hue[0]); - return $hue; - } - color_manager::normalize_hue($hue); - if ($hue >= 240) // blue through red is already ok - { - return $hue; - } - else if ($hue <= 60) - { - return $hue * 2; - } - else if ($hue <= 120) - { - return $hue + 60; - } - else - { - return ($hue + 240) / 2; - } - } -} - -function vector_distance(&$char, $x, $y, $range = 0.1) -{ - $distance = $range + 1; - foreach ($char AS $vector) - { - $d = $range + 1; - switch ($vector[0]) - { - case 'arc': - - $dx = $x - $vector[1]; - $dy = -($y - $vector[2]); //because our arcs are upside-down.... - if (abs($dx) > abs($dy)) - { - $phi = rad2deg(atan(($dy * $vector[3])/($dx * $vector[4]))); - $phi += ($dx < 0) ? 180 : 360; - $phi %= 360; - } - else - { - $phi = 90 - rad2deg(atan(($dx * $vector[4])/($dy * $vector[3]))); - $phi += ($dy < 0) ? 180 : 360; - $phi %= 360; - } - - $internal = $vector[6] > $vector[5]; //external wraps over the 360 point - $low = $phi >= $vector[5]; //phi is above our low range - $high = $phi <= $vector[6]; //phi is below our high range. - if ($internal ? ($low && $high) : ($low || $high)) //if it wraps, it can only be one or the other - { - $radphi = deg2rad($phi); // i'm awesome. or not. - $px = cos($radphi) * 0.5 * $vector[3]; - $py = sin($radphi) * 0.5 * $vector[4]; - $d = sqrt(pow($px - $dx, 2) + pow($py - $dy, 2)); - } - - break; - - case 'line': - - $bx = $x - $vector[1]; - $by = $y - $vector[2]; - $dx = cos($vector[5]); - $dy = sin($vector[5]); - $r = ($by * $dx) - ($bx * $dy); - if ($r < $range && $r > -$range) - { - if (abs($dx) > abs($dy)) - { - $s = (($bx + ($dy * $r)) / $dx); - } - else - { - $s = (($by + ($dx * $r)) / $dy); - } - if ($s > -$range) - { - if ($s < 0) - { - $d = sqrt(pow($s, 2) + pow($r, 2)); - } - elseif ($s < $vector[6]) - { - $d = $r; - } - elseif ($s < $vector[6] + $range) - { - $d = sqrt(pow($s - $vector[6], 2) + pow($r, 2)); - } - } - } - - break; - } - $distance = min($distance, abs($d)); + return $fonts[array_rand($fonts)]; } - return $distance; } ?>
\ No newline at end of file |