<?php
//******************************************************//
//           /////////                 ////   /////
//              //                    // //  //  //
//             //      /////  ////// ////   ////
//            //      //     ////   //  // //  //
//        /////////  /////  ////// /////  /////
//******************************************************//
// icebb.net // 1.0
//******************************************************//
// CAPTCHA image generation module
// $Id: make_image.php 339 2006-07-10 18:02:15Z mutantmonkey $
//******************************************************//

class captcha
{
	// main configuration
	var $width					= 200;
	var $height					= 50;
	
	var $captcha_id;
	var $correct_word;
	var $fonts;

	/**
	 * Constructor
	 */
	function captcha()
	{
		global $icebb,$db,$std;
		
		// load code from URL
		$this->captcha_id		= wash_key($_GET['s']);

		$result					= $db->query("SELECT * FROM icebb_captcha WHERE id='{$this->captcha_id}'");// AND ip='{$icebb->user['ip']}'");
		
		$r						= $db->fetch_row($result);
		$wordNum				= $r['word_num'];
		
		// open up dictionary and choose a word
		$words					= @file("langs/{$icebb->lang_id}/captcha.dict");
		
		$this->correct_word		= $words[$wordNum];
		$this->correct_word		= str_replace("\n",'',$this->correct_word);
		
		if($db->get_num_rows($result)<=0)
		{
			$this->correct_word	= "ERROR";
		}
		
		if($icebb->settings['img_engine']=='imagemagick')
		{
			$this->load_fonts();
			$im_image			= new captcha_imagemagick(&$this);
			return $im_image->imagemagick_make();
		}
		else {
			$this->load_fonts();
			$gd_image			= new captcha_gd(&$this);
			return $gd_image->gd_make();
		}
	}
	
	function load_fonts()
	{
		global $icebb;
	
		$dir						= "skins/{$icebb->skin->skin_id}/images/captcha/fonts/";
		if($dh = @opendir($dir))
		{
			while(false !== ($file = @readdir($dh)))
			{
				if(stristr($file,'.ttf') !== false)
				{
					$this->fonts[]	= "{$dir}{$file}";
				}
			}
			@closedir($dh);
		}
	}
}

/**
 * Word verification using ImageMagick
 */
class captcha_imagemagick extends captcha
{
	var $im_convert_path	= '/usr/bin/convert';

	var $rand_bgs			= array('plasma:grey-pink','plasma:grey-grey','plasma:pink-red','plasma:steelblue-white','plasma:pink-white');
	var $fonts				= array('Courier','Helvetica','Helvetica-Narrow','Palatino-Roman','Times-Roman');

	/**
	 * Constructor
	 * @param 		object		Calling class
	 */
	function captcha_imagemagick($parent)
	{
		global $icebb;
	
		$this->captcha		= &$parent;
		
		$this->im_convert_path= $icebb->settings['imagemagick_convert_path'];
	
		$which_to_use		= rand(0,count($this->rand_bgs)-1);
		$this->bgcolor		= $this->rand_bgs[$which_to_use];
		$this->fillcolor	= "\"rgb(".mt_rand(0,150).",".mt_rand(0,150).",".mt_rand(0,150).")\"";
		
		$this->font			= $this->captcha->fonts[mt_rand(0,count($this->captcha->fonts)-1)];
		
		return $this->imagemagick_make();
	}
	
	/**
	 * Nice and simple. Generates the image using the width, background color, fill color, font,
	 * and correct word set above.
	 */
	function imagemagick_make()
	{
		// adjust for border
		$w					= $this->captcha->width-2;
		$h					= $this->captcha->height-2;
		
		$convert[]			= "-size {$w}x{$h} null: -matte";
		$convert[]			= "-font {$this->font} -fill {$this->fillcolor} -pointsize 32";
		$convert[]			= "-annotate +".mt_rand(5,45)."+".mt_rand(25,45)." '{$this->captcha->correct_word}'";

		$randy				= mt_rand(0,3);
		switch($randy)
		{
			case 0:
				$convert[]	= '-swirl '.mt_rand(30,55);
				break;
			case 1:
				$convert[]	= '-swirl '.mt_rand(20,40);
				$convert[]	= '-background none -wave '.mt_rand(1,3).'x'.mt_rand(60,70);
				break;
			case 2:
				$convert[]	= '-background none -wave '.mt_rand(3,5).'x'.mt_rand(40,60);
				break;
			case 3:
				$convert[]	= '-swirl '.mt_rand(20,40).' -spread .'.rand(3,7);
				break;
		}
		
		$cmds				= implode(' ',$convert);
		@exec("{$this->im_convert_path} {$cmds} uploads/{$this->captcha->captcha_id}.png");
		$convert			= array();
		
		$convert[]			= "-size {$w}x{$h} {$this->bgcolor}";// -quality 75";
		$convert[]			= "uploads/{$this->captcha->captcha_id}.png";
		$convert[]			= "-gravity center -composite";
		$convert[]			= "-fill {$this->fillcolor} -draw \"path 'M ".rand(0,25).",".rand(0,25)." L ".rand(150,200).",".rand(40,45)." M ".rand(0,25).",".rand(10,50)." L ".rand(150,200).",".rand(10,50)."'\"";
		$convert[]			= '-bordercolor black -border 1';

		$cmds				= implode(' ',$convert);
		@exec("{$this->im_convert_path} {$cmds} uploads/{$this->captcha->captcha_id}.png");
		//echo "convert {$cmds} {$this->captcha->captcha_id}.png";exit();
		
		@header('Content-type: image/png');
		echo @file_get_contents("uploads/{$this->captcha->captcha_id}.png");
		
		// remove temporary image
		@unlink("uploads/{$this->captcha->captcha_id}.png");
	}
}

/**
 * Word verification using GD
 */
class captcha_gd extends captcha
{
	// configuration
	var $strikeTexth			= false;
	var $strikeTextv			= false;
	var $showGrid				= false;
	var $ultraDistort			= false;
	
	var $noisyImg				= true;
	var $noise_type				= 2;
	var $noise_amount			= 400;
	var $noise_color			= '130,130,130';
	
	var $rotateImg				= false;
	
	var $add_color				= false;
	var $add_vertical_lines		= false;
	var $add_blur				= true;
	
	var $bg_color				= '255,255,255';
	var $text_color				= '100,100,100';
	
	var $format					= 'jpeg';
	
	// when using a TTF, you may want to use a darker font color
	//var $ttfFile				= 'modules/login/palr46w.ttf';

	/**
	 * Constructor
	 * @param 		object		Calling class
	 */
	function captcha_gd($parent)
	{
		global $icebb,$std;
		
		$this->captcha		= &$parent;
		
		if(!function_exists('jpeg'))
		{
			$this->format		= 'png';
		}
	
		$this->width			= $this->captcha->width;
		$this->height			= $this->captcha->height;
	
		$this->noise_color		= rand(100,160).','.rand(100,160).',255';//'.rand(100,160);
		$this->noise_color		= explode(',',$this->noise_color);
		//$this->bg_color			= rand(250,255).','.rand(250,255).','.rand(250,255);
		$this->bg_color			= explode(',',$this->bg_color);	
		$this->text_color		= explode(',',$this->text_color);
		
		// can we use a TTF?
		if(function_exists('imagettftext'))
		{
			$this->ttfFile		= $this->captcha->fonts[mt_rand(0,count($this->captcha->fonts)-1)];
		}
	}
	
	/**
	 * This one's a little big longer. It's some really old code I wrote a long time ago, but
	 * it's a bit more flexible than the ImageMagick code above because it's been changed so much.
	 */
	function gd_make()
	{
		global $icebb,$std;
		
		// create image
		$im						= @imagecreate($this->width,$this->height);
			
		// allocate colors
		$background_color		= imagecolorallocate($im,$this->bg_color[0],$this->bg_color[1],$this->bg_color[2]);
		$lgray					= imagecolorallocate($im,220,220,220);
		$gray					= imagecolorallocate($im,200,200,200);
		$dgray					= imagecolorallocate($im,180,180,180);
		$black					= imagecolorallocate($im,0,0,0);
		$white					= imagecolorallocate($im,255,255, 255);
		$text					= imagecolorallocate($im,$this->text_color[0],$this->text_color[1],$this->text_color[2]);

		imagefill($im,0,0,$background_color);

		imageline($im, 0, 0, 200, 0, $lgray);
		imageline($im, 0, 49, 200, 49, $lgray);
		imageline($im, 0, 0, 0, 50, $lgray);
		imageline($im, 199, 0, 199, 50, $lgray);
		
		for($i=0;$i<=10;$i++)
		{
			$main_color[$i]	= imagecolorallocate($im,mt_rand(100,255),mt_rand(100,255),mt_rand(100,255));
		}
	
		for($x=1;$x<=$this->captcha->width;$x++)
		{
			for($y=1;$y<=$this->captcha->height;$y++)
			{
				imagesetpixel($im,$x,$y,$main_color[mt_rand(0,10)]);
			}
		}
		
		if($this->add_color==true && function_exists('imagefilledellipse'))
		{
			$rcolor_start			= 200;
			$rcolor_end				= 255;
		
			$rand_color				= imagecolorallocate($im,rand($rcolor_start,$rcolor_end),rand($rcolor_start,$rcolor_end),rand($rcolor_start,$rcolor_end));
			imagefilledellipse($im,50,50,80,120,$rand_color);
			imagefilledellipse($im,150,50,80,120,$rand_color);
			
			$rand_color2			= imagecolorallocate($im,rand($rcolor_start,$rcolor_end),rand($rcolor_start,$rcolor_end),rand($rcolor_start,$rcolor_end));
			imagefilledellipse($im,100,50,80,120,$rand_color2);		
		}
		
		if($this->ultraDistort	== true)
		{
			// create text in background to fool ocr
			$captchaBgNum		= mt_rand(1000000,9999999);
			imagestring($im, 3, 20, 5,  $captchaBgNum.' '.$captchaBgNum.' '.$captchaBgNum, $lgray);
			imagestring($im, 3, 20, 10,  $captchaBgNum.' '.$captchaBgNum.' '.$captchaBgNum, $gray);
			imagestring($im, 3, 20, 15,  $captchaBgNum.' '.$captchaBgNum.' '.$captchaBgNum, $dgray);
			imagestring($im, 3, 20, 20,  $captchaBgNum.' '.$captchaBgNum.' '.$captchaBgNum, $edgray);
			imagestring($im, 3, 20, 25,  $captchaBgNum.' '.$captchaBgNum.' '.$captchaBgNum, $dgray);
			imagestring($im, 3, 20, 30,  $captchaBgNum.' '.$captchaBgNum.' '.$captchaBgNum, $gray);
			imagestring($im, 3, 20, 35,  $captchaBgNum.' '.$captchaBgNum.' '.$captchaBgNum, $lgray);
		}	
		
		if($this->noisyImg==true)
		{
			$i					= 0;
			$noisy_color		= imagecolorallocate($im,$this->noise_color[0],$this->noise_color[1],$this->noise_color[2]);
		
			if($this->noise_type== 1)
			{
				// create some noise
				while($i<$this->noise_amount)
				{
					$x=rand(0,200);		$x2=rand(0,200);
					$y=rand(0,30);		$y2=rand(0,50);
		
					imageline($im,$x2,$y2,$x,$y,$noisy_color);
					imageline($im,$x,$y,$x2,$y2,$noisy_color);
					$i++;
				}
			}
			else if($this->noise_type== 2)
			{
				// create some noise - granier than above
				while($i<$this->noise_amount)
				{
					$x=rand(0,200);		$x2=rand(0,200);
					$y=rand(0,50);		$y2=rand(0,50);
		
					imageline($im,$x+1,$y+1,$x,$y,$noisy_color);
					imageline($im,$x2+1,$y2+1,$x2,$y2,$noisy_color);
					$i++;
				}
			}
		}
		
		if($this->ttfFile!='')
		{
			imagettftext($im,20,rand(-10,10),30,30,$text,$this->ttfFile,$this->captcha->correct_word);
		}
		else {
			$tempim				= @imagecreatetruecolor($this->width,$this->height*2);
			$tblack				= imagecolorallocate($tempim,0,0,0);
			$tweiss				= imagecolorallocate($tempim,255,255,255);
			$ttext				= imagecolorallocate($tempim,$this->text_color[0],$this->text_color[1],$this->text_color[2]);
			$tnone				= imagecolorallocate($tempim,200,200,200);
			
			imagecolortransparent($tempim,$tnone);
			imagefill($tempim,0,0,$tnone);
			imagestring($tempim,5,rand(2,6),rand(0,2),$this->captcha->correct_word,$ttext);
			
			//$tempim				= imagerotate($tempim,rand(-3,3),$tnone);
			imagecolortransparent($tempim,$tnone);
			imagecopyresized($im,$tempim,5,0,0,0,$this->width,$this->height,$this->width/2,($this->height/2)-($this->height/8));
			//imagecopymerge($im,$tempim,0,0,0,0,$this->width,$this->height,90);
			
			imagedestroy($tempim);
			
			// remove blur
			//$this->add_blur		= 0;
		}

		// adds horizontal lines through text
		if($this->strikeTexth==true)
		{
			imageline($im, 0, 6, 200, 6, $white);
			imageline($im, 0, 8, 200, 8, $white);
			imageline($im, 0, 10, 200, 10, $white);
			imageline($im, 0, 12, 200, 12, $white);
			imageline($im, 0, 14, 200, 14, $white);
			imageline($im, 0, 16, 200, 16, $white);
			imageline($im, 0, 18, 200, 18, $white);
			imageline($im, 0, 20, 200, 20, $white);
			imageline($im, 0, 22, 200, 22, $white);
			imageline($im, 0, 24, 200, 24, $white);
			imageline($im, 0, 26, 200, 26, $white);
			imageline($im, 0, 28, 200, 28, $white);
			imageline($im, 0, 30, 200, 30, $white);
			imageline($im, 0, 32, 200, 32, $white);
			imageline($im, 0, 34, 200, 34, $white);
			imageline($im, 0, 36, 200, 36, $white);
			imageline($im, 0, 38, 200, 38, $white);
			imageline($im, 0, 40, 200, 40, $white);
			imageline($im, 0, 42, 200, 42, $white);
			imageline($im, 0, 44, 200, 44, $white);
			imageline($im, 0, 46, 200, 46, $white);
			imageline($im, 0, 48, 200, 48, $white);
		}
		
		// adds vertical lines through text
		if($this->strikeTextv==true)
		{
			imageline($im, 6, 0, 6, 6, $white);
			imageline($im, 8, 0, 8, 8, $white);
			imageline($im, 10, 0, 10, 50, $white);
			imageline($im, 12, 0, 12, 50, $white);
			imageline($im, 14, 0, 14, 50, $white);
			imageline($im, 16, 0, 16, 50, $white);
			imageline($im, 18, 0, 18, 50, $white);
			imageline($im, 20, 0, 20, 50, $white);
			imageline($im, 22, 0, 22, 50, $white);
			imageline($im, 24, 0, 24, 50, $white);
			imageline($im, 26, 0, 26, 50, $white);
			imageline($im, 28, 0, 28, 50, $white);
			imageline($im, 30, 0, 30, 50, $white);
			imageline($im, 32, 0, 32, 50, $white);
			imageline($im, 34, 0, 34, 50, $white);
			imageline($im, 36, 0, 36, 50, $white);
			imageline($im, 38, 0, 38, 50, $white);
			imageline($im, 40, 0, 40, 50, $white);
			imageline($im, 42, 0, 42, 50, $white);
			imageline($im, 44, 0, 44, 50, $white);
			imageline($im, 46, 0, 46, 50, $white);
			imageline($im, 48, 0, 48, 50, $white);
			imageline($im, 50, 0, 50, 50, $white);
			imageline($im, 52, 0, 52, 50, $white);
			imageline($im, 54, 0, 54, 50, $white);
			imageline($im, 56, 0, 56, 50, $white);
			imageline($im, 58, 0, 58, 50, $white);
			imageline($im, 60, 0, 60, 50, $white);
			imageline($im, 62, 0, 62, 50, $white);
			imageline($im, 64, 0, 64, 50, $white);
			imageline($im, 66, 0, 66, 50, $white);
			imageline($im, 68, 0, 68, 50, $white);
			imageline($im, 70, 0, 70, 50, $white);
			imageline($im, 72, 0, 72, 50, $white);
			imageline($im, 74, 0, 74, 50, $white);
			imageline($im, 76, 0, 76, 50, $white);
			imageline($im, 78, 0, 78, 50, $white);
			imageline($im, 80, 0, 80, 50, $white);
			imageline($im, 82, 0, 82, 50, $white);
			imageline($im, 84, 0, 84, 50, $white);
			imageline($im, 86, 0, 86, 50, $white);
			imageline($im, 88, 0, 88, 50, $white);
			imageline($im, 90, 0, 90, 50, $white);
			imageline($im, 92, 0, 92, 50, $white);
			imageline($im, 94, 0, 94, 50, $white);
			imageline($im, 96, 0, 96, 50, $white);
			imageline($im, 98, 0, 98, 50, $white);
			imageline($im, 106, 0, 106, 6, $white);
			imageline($im, 108, 0, 108, 8, $white);
			imageline($im, 110, 0, 110, 50, $white);
			imageline($im, 112, 0, 112, 50, $white);
			imageline($im, 114, 0, 114, 50, $white);
			imageline($im, 116, 0, 116, 50, $white);
			imageline($im, 118, 0, 118, 50, $white);
			imageline($im, 120, 0, 120, 50, $white);
			imageline($im, 122, 0, 122, 50, $white);
			imageline($im, 124, 0, 124, 50, $white);
			imageline($im, 126, 0, 126, 50, $white);
			imageline($im, 128, 0, 128, 50, $white);
			imageline($im, 130, 0, 130, 50, $white);
			imageline($im, 132, 0, 132, 50, $white);
			imageline($im, 134, 0, 134, 50, $white);
			imageline($im, 136, 0, 136, 50, $white);
			imageline($im, 138, 0, 138, 50, $white);
			imageline($im, 140, 0, 140, 50, $white);
			imageline($im, 142, 0, 142, 50, $white);
			imageline($im, 144, 0, 144, 50, $white);
			imageline($im, 146, 0, 146, 50, $white);
			imageline($im, 148, 0, 148, 50, $white);
			imageline($im, 150, 0, 150, 50, $white);
			imageline($im, 152, 0, 152, 50, $white);
			imageline($im, 154, 0, 154, 50, $white);
			imageline($im, 156, 0, 156, 50, $white);
			imageline($im, 158, 0, 158, 50, $white);
			imageline($im, 160, 0, 160, 50, $white);
			imageline($im, 162, 0, 162, 50, $white);
			imageline($im, 164, 0, 164, 50, $white);
			imageline($im, 166, 0, 166, 50, $white);
			imageline($im, 168, 0, 168, 50, $white);
			imageline($im, 170, 0, 170, 50, $white);
			imageline($im, 172, 0, 172, 50, $white);
			imageline($im, 174, 0, 174, 50, $white);
			imageline($im, 176, 0, 176, 50, $white);
			imageline($im, 178, 0, 178, 50, $white);
			imageline($im, 180, 0, 180, 50, $white);
			imageline($im, 182, 0, 182, 50, $white);
			imageline($im, 184, 0, 184, 50, $white);
			imageline($im, 186, 0, 186, 50, $white);
			imageline($im, 188, 0, 188, 50, $white);
			imageline($im, 190, 0, 190, 50, $white);
			imageline($im, 192, 0, 192, 50, $white);
			imageline($im, 194, 0, 194, 50, $white);
			imageline($im, 196, 0, 196, 50, $white);
			imageline($im, 198, 0, 198, 50, $white);
		}
		
		// create grid (helps fool ocr)
		if($this->showGrid==true)
		{
			imageline($im, 10, 0, 10, 50, $lgray);
			imageline($im, 20, 0, 20, 50, $lgray);
			imageline($im, 30, 0, 30, 50, $lgray);
			imageline($im, 40, 0, 40, 50, $lgray);
			imageline($im, 50, 0, 50, 50, $lgray);
			imageline($im, 60, 0, 60, 50, $lgray);
			imageline($im, 70, 0, 70, 50, $lgray);
			imageline($im, 80, 0, 80, 50, $lgray);
			imageline($im, 90, 0, 90, 50, $lgray);
			imageline($im, 100, 0, 100, 50, $lgray);
			imageline($im, 110, 0, 110, 50, $lgray);
			imageline($im, 120, 0, 120, 50, $lgray);
			imageline($im, 130, 0, 130, 50, $lgray);
			imageline($im, 140, 0, 140, 50, $lgray);
			imageline($im, 150, 0, 150, 50, $lgray);
			imageline($im, 160, 0, 160, 50, $lgray);
			imageline($im, 170, 0, 170, 50, $lgray);
			imageline($im, 180, 0, 180, 50, $lgray);
			imageline($im, 190, 0, 190, 50, $lgray);
			imageline($im, 0, 10, 200, 10, $lgray);
			imageline($im, 0, 20, 200, 20, $lgray);
			imageline($im, 0, 30, 200, 30, $lgray);
			imageline($im, 0, 40, 200, 40, $lgray);
			imageline($im, 0, 50, 200, 50, $lgray);
		}
		
		if($this->rotateImg==true && function_exists('imagerotate'))
		{
			// degrees to rotate?
			$deg		= rand(-5,5);
			
			// fix 0 degree rotation
			if($deg	       == 0)
			{
				$deg	= rand(1,2);
			}
			
			// rotate the image
			$img2		= imagerotate($im,$deg,0);
			
			// resize to it's normal square size
			imagecopyresized($im,$img2,0,0,0,0,imagesx($im),imagesy($im),imagesx($img2),imagesy($img2));
			imagedestroy($img2);
		}

		if($this->add_vertical_lines==true)
		{
			for($i=0;$i<$this->width;$i=$i+5)
			{
				imageline($im,$i,0,$i,$this->width,$lgray);
			}
		}
		
		if($this->add_blur==true)
		{
			if(function_exists('imagefilter'))
			{
				@imagefilter($this->im,IMG_FILTER_GAUSSIAN_BLUR);
			}
			else {
				// Old fashioned blur... (PHP 4 sucks!)
				$img3			= @imagecreate($this->width,$this->height);
				imagefill($img3,0,0,imagecolorallocate($img3,$this->bg_color[0],$this->bg_color[1],$this->bg_color[2]));
				imagecopymerge($img3,$im,0,1,0,0,$this->width,$this->height,70);
				imagecopymerge($im,$img3,0,0,1,0,$this->width,$this->height,70);
				imagecopymerge($img3,$im,1,0,0,0,$this->width,$this->height,70);
				imagecopymerge($im,$img3,0,0,0,1,$this->width,$this->height,70);
				imagedestroy($img3);
			}
		}
		
		if($this->ultraDistort==true)
		{
			// just some added distortion, thought it looked nice
			for($i=0;$i<$this->height;$i=$i+5)
			{
				imageline($im,0,$i,$this->width,$this->height,$dgray);
			}
		}
		
		// border
		imageline($im,0,0,$this->captcha->width,0,$black);
		imageline($im,0,($this->captcha->height)-1,$this->captcha->width,($this->captcha->height)-1,$black);
		imageline($im,0,0,0,$this->captcha->height,$black);
		imageline($im,($this->captcha->width)-1,0,($this->captcha->width)-1,$this->captcha->height,$black);

		//imagejpeg($im,'',25);
		@header("Content-type: image/{$this->format}");
		($this->format=='jpeg') ? imagejpeg($im) : imagepng($im);
		imagedestroy($im);
	}
}

$captcha_da = new captcha();
?>
