View file captcha/index.php

File size: 8.14Kb
<?php
/**
*
*  This program is free software; you can redistribute it and/or modify
*  it
*
*  This program is distributed in the hope that it will be useful,
*  but WITHOUT ANY WARRANTY; without even the implied warranty of
*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*/

error_reporting( E_ALL );

define( 'ROOTPATH', realpath('..'));
define( 'EXT', substr(strrchr(__FILE__, '.'), 1));

include( ROOTPATH . '/includes/config.' . EXT );
include( ROOTPATH . '/includes/functions.' . EXT );
include( ROOTPATH . '/includes/functions_session.' . EXT );

switch( DBMS )
{
	case 'MySQL':
	include( ROOTPATH . '/includes/classes/mysql.db.class' );
	break;

	default:

	exit;
}

if( !($sql = new sql(DBMSHOST, DBUSER, DBPASS, DBNAME)) )
{
	exit;
}

if( !($qresult = $sql->query("SELECT * FROM `" . CATALOGUE_CONFIG . "` LIMIT 1;")) )
{
	exit;
}

if( $sql->num_rows() < 1 )
{
	exit;
}

$config = $sql->fetch_assoc( $qresult );

session_init( true );

$types = array('jpg', 'gif', 'png');
$type = isset( $_GET['type'] ) ? (string) $_GET['type'] : 'gif';

if( !in_array($type, $types) )
{
	$type = 'gif';
}

class KCAPTCHA
{
	function KCAPTCHA($type)
	{
		$alphabet = '0123456789abcdefghijklmnopqrstuvwxyz';
		$allowed_symbols = '0123456789';
		$fontsdir = 'fonts';
		$length = 3;
		$width = 90;
		$height = 45;
		$fluctuation_amplitude = 5;
		$no_spaces = true;
		$show_credits = false;
		$credits = '';
		$foreground_color = array(0, 0, 0);
		$background_color = array(255, 255, 255);
		$jpeg_quality = 90;

		$fonts = array();
		$fontsdir_absolute = dirname(__FILE__) . '/' . $fontsdir;

		if($handle = opendir($fontsdir_absolute))
		{
			while( false !== ($file = readdir($handle)) )
			{
				if(preg_match('/\.png$/i', $file))
				{
					$fonts[] = $fontsdir_absolute . '/' .$file;
				}
			}
		   
		closedir($handle);
		}	
	
		$alphabet_length = strlen($alphabet);
		
		while( true )
		{
			while( true )
			{
				$this->keystring = '';
				
				for($i = 0; $i < $length; $i++)
				{
					$this->keystring .= $allowed_symbols{rand(0, strlen($allowed_symbols) - 1)};
				}

				if( !preg_match('/cp|cb|ck|c6|c9|rn|rm|mm|co|do|cl|db|qp|qb|dp/', $this->keystring) ) break;
			}

			$_SESSION['captcha_key'] = isset( $_SESSION['captcha_key'] ) ? $_SESSION['captcha_key'] : NULL;

			if( $_SESSION['captcha_key'] !== NULL )
			{
				$this->keystring = $_SESSION['captcha_key'];
			}
		
			$font_file = $fonts[array_rand($fonts)];
			$font = imagecreatefrompng($font_file);
			imagealphablending($font, true);
			$fontfile_width = imagesx($font);
			$fontfile_height = imagesy($font) - 1;
			$font_metrics = array();
			$symbol = 0;
			$reading_symbol = false;

			for($i = 0; $i < $fontfile_width && $symbol < $alphabet_length; $i++)
			{
				$transparent = (imagecolorat($font, $i, 0) >> 24) == 127;

				if(!$reading_symbol && !$transparent)
				{
					$font_metrics[$alphabet[$symbol]]=array('start' => $i);
					$reading_symbol = true;
					continue;
				}

				if($reading_symbol && $transparent)
				{
					$font_metrics[$alphabet[$symbol]]['end'] = $i;
					$reading_symbol = false;
					$symbol++;
					continue;
				}
			}

			$img = imagecreatetruecolor($width, $height);
			imagealphablending($img, true);
			$white = imagecolorallocate($img, 255, 255, 255);
			$black = imagecolorallocate($img, 0, 0, 0);

			imagefilledrectangle($img, 0, 0, $width - 1, $height - 1, $white);

			$x = 1;

			for($i = 0; $i < $length; $i++)
			{
				$m = $font_metrics[$this->keystring[$i]];

				$y = rand(-$fluctuation_amplitude, $fluctuation_amplitude) + ($height - $fontfile_height)/2 + 2;

				if( $no_spaces )
				{
					$shift = 0;

					if($i > 0)
					{
						$shift = 1000;

						for($sy = 7; $sy < $fontfile_height - 20; $sy++)
						{
							for($sx = $m['start'] - 1; $sx < $m['end']; $sx++)
							{
				        			$rgb = imagecolorat($font, $sx, $sy);
				        			$opacity = $rgb >> 24;

								if($opacity < 127)
								{
									$left = $sx - $m['start'] + $x;
									$py = $sy + $y;

									if($py > $height) break;

									for($px = min($left, $width - 1); $px > $left - 12 && $px >= 0; $px--)
									{
						        			$color = imagecolorat($img, $px, $py) & 0xff;

										if($color + $opacity < 190)
										{
											if($shift > $left - $px)
											{
												$shift = $left - $px;
											}

											break;
										}
									}

									break;
								}
							}
						}

						if($shift == 1000) $shift = rand(4,6);
					}
				}
				else $shift = 1;

				imagecopy($img, $font, $x - $shift, $y, $m['start'], 1, $m['end'] - $m['start'], $fontfile_height);

				$x += $m['end'] - $m['start'] - $shift;
			}
			if($x < $width - 10) break;
		}

		$center = $x/2;

		$img2 = imagecreatetruecolor($width, $height + ($show_credits ? 12 : 0));
		$foreground = imagecolorallocate($img2, $foreground_color[0], $foreground_color[1], $foreground_color[2]);
		$background = imagecolorallocate($img2, $background_color[0], $background_color[1], $background_color[2]);
		imagefilledrectangle($img2, 0, $height, $width - 1, $height + 12, $foreground);
		$credits = empty($credits) ? $_SERVER['HTTP_HOST'] : $credits;
		imagestring($img2, 2, $width / 2 - imagefontwidth(2) * strlen($credits)/2, $height - 2, $credits, $background);

		$rand1 = rand(750000,1200000)/10000000;
		$rand2 = rand(750000,1200000)/10000000;
		$rand3 = rand(750000,1200000)/10000000;
		$rand4 = rand(750000,1200000)/10000000;

		$rand5 = rand(0,3141592)/500000;
		$rand6 = rand(0,3141592)/500000;
		$rand7 = rand(0,3141592)/500000;
		$rand8 = rand(0,3141592)/500000;

		$rand9 = rand(330,420)/110;
		$rand10 = rand(330,450)/110;

		for($x = 0; $x < $width; $x++)
		{
			for($y = 0; $y < $height; $y++)
			{
				$sx = $x + (sin($x * $rand1 + $rand5) + sin($y * $rand3 + $rand6)) * $rand9 - $width / 2 + $center + 1;
				$sy = $y + (sin($x * $rand2 + $rand7) + sin($y * $rand4 + $rand8)) * $rand10;

				if($sx < 0 || $sy < 0 || $sx >= $width - 1 || $sy >= $height - 1)
				{
					$color = 255;
					$color_x = 255;
					$color_y = 255;
					$color_xy = 255;
				}
				else
				{
					$color = imagecolorat($img, $sx, $sy) & 0xFF;
					$color_x = imagecolorat($img, $sx + 1, $sy) & 0xFF;
					$color_y = imagecolorat($img, $sx, $sy + 1) & 0xFF;
					$color_xy = imagecolorat($img, $sx + 1, $sy + 1) & 0xFF;
				}

				if($color == 0 && $color_x == 0 && $color_y == 0 && $color_xy == 0)
				{
					$newred = $foreground_color[0];
					$newgreen = $foreground_color[1];
					$newblue = $foreground_color[2];
				}
				elseif($color == 255 && $color_x == 255 && $color_y == 255 && $color_xy == 255)
				{
					$newred = $background_color[0];
					$newgreen = $background_color[1];
					$newblue = $background_color[2];	
				}
				else
				{
					$frsx = $sx - floor($sx);
					$frsy = $sy - floor($sy);
					$frsx1 = 1 - $frsx;
					$frsy1 = 1 - $frsy;

					$newcolor = (
						$color * $frsx1 * $frsy1 + 
						$color_x * $frsx * $frsy1 + 
						$color_y * $frsx1 * $frsy + 
						$color_xy * $frsx * $frsy);

					if($newcolor>255) $newcolor = 255;
					$newcolor = $newcolor / 255;
					$newcolor0 = 1 - $newcolor;

					$newred = $newcolor0 * $foreground_color[0] + $newcolor * $background_color[0];
					$newgreen = $newcolor0 * $foreground_color[1] + $newcolor * $background_color[1];
					$newblue = $newcolor0 * $foreground_color[2] + $newcolor * $background_color[2];
				}

				imagesetpixel($img2, $x, $y, imagecolorallocate($img2, $newred, $newgreen, $newblue));
			}
		}
		
		header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
		header('Cache-Control: no-cache, must-relative');

		switch($type)
		{
			case 'gif':
			header('Content-Type: image/gif');
			imagegif($img2);
			break;

			case 'jpg':
			header('Content-Type: image/jpeg');
			imagejpeg($img2, NULL, $jpeg_quality);
			break;

			case 'png':
			header('Content-Type: image/x-png');
			imagepng($img2);
			break;
		}
	}
}

$captcha = new KCAPTCHA( $type );
$_SESSION['captcha_key'] = $captcha->keystring;
?>