Page 1 of 1

Audio with CAPTCHA Code

Posted: Fri Jun 02, 2006 11:54 pm
by tecktalkcm0391
I need help with his code, by: bokehman from his website at: http://bokehman.com/

First page displays CATPTCHA

Code: Select all

<?php
// The following three lines must be at the top of  your script. 
session_start();
define('CAPTCHA_PATH', $_SERVER['DOCUMENT_ROOT'].'/captcha/'); // Path to captcha
require_once(CAPTCHA_PATH.'captcha.php');


// The following is an HTML demo
print   '<h1>CAPTCHA</h1>'."\n";
		
// Validation section

if(isset($_POST['captcha'])){
	if(captcha_validate()){
		print '<p>Success! <br>You entered the correct code! <br><a href="http://'.$_SERVER['HTTP_HOST'].$_SERVER['PHP_SELF'].'">Here\'s another one to try!</a></p>';
	}else{
		print '<p>Failure! <br>You entered the wrong code! <br><a href="http://'.$_SERVER['HTTP_HOST'].$_SERVER['PHP_SELF'].'">Here\'s another one to try!</a></p>';
	}
    

    
    
    
// Form section    
}else{
print   '<div style="float: left;"><img id="mainimage" style="border: 1px solid #555;" src="http://'.$_SERVER['HTTP_HOST'].
		$_SERVER['PHP_SELF'].'?image" width="140" height="90" alt="CAPTCHA image">'."\n".
        '<br>I can\'t read that image...<br>'."\n".
        '<a href="#" onclick="document.getElementById(\'mainimage\').src=\'http://'.$_SERVER['HTTP_HOST'].$_SERVER['PHP_SELF'].'?image=\' + new Date; return false;">give me an easier one!</a>'."\n".
        '</div><form style="margin-top: 0; margin-bottom: 3px;" action="http://'.$_SERVER['HTTP_HOST'].$_SERVER['PHP_SELF'].'" method="post">'."\n".
        '<input type="text" name="captcha" style="width: 100px; height: 24px; margin-top: 5px; border: 1px solid #555; margin-left: 10px; text-align: center;">'."\n".
        '<span style="color: red;">*</span> <i>case sensitive</i><br>'."\n".
        '<input type="submit" name="submit" value="try me" style="width: 100px; height: 24px; margin-left: 10px; margin-top: 5px;">'."\n".
        '</form><br><br><br><br>'."\n".
        
        '<div style="clear: both"><p> <a href="http://'.$_SERVER['HTTP_HOST'].$_SERVER['PHP_SELF'].'?audio">CAPTCHA code in audio form</a>'."\n".
        ' (.wav file, typically 60kB)</div>'."\n";
}

?>

CAPTCHA PAGE: (captcha.php)

Code: Select all

<?php

// Section image: create a CAPTCHA image
if(isset($_GET['image'])){ 
     captcha_image();
    
// Section audio: create a .WAV file containing the contents of $_SESSION['captcha'] in voice form
}elseif(isset($_GET['audio'])){  
	if(empty($_SESSION['captcha']))exit;
	$length = strlen($_SESSION['captcha']);
	$files = array();
	for($i = 0; $i < $length; $i++){
		$alphanumeric = substr($_SESSION['captcha'], $i, 1);
	   	if(preg_match('/[A-Z]/', $alphanumeric)) $files[] = CAPTCHA_PATH.'capital.wav';
		if(preg_match('/[a-z]/', $alphanumeric)) $files[] = CAPTCHA_PATH.'lower.wav';
		$files[] = CAPTCHA_PATH.strtolower($alphanumeric).'.wav';
	}
	$ChunkID_ = array(0x52, 0x49, 0x46, 0x46);       //"RIFF" big endian
	$FileFormat_ = array(0x57, 0x41, 0x56, 0x45);    //"WAVE" big endian
	$Subchunk1ID_ = array(0x66, 0x6D, 0x74, 0x20);   //"fmt" big endian
	$AudioFormat_ = array(0x1, 0x0);                 //PCM = 1 little endian
	$Channels_ = array(0x1, 0x0);                    //Mono = 1 little endian(0x1, 0x0)... Stereo = 2 little endian(0x2, 0x0) 
	$SampleRate_ = array(0x70, 0x17, 0x0, 0x0);      //6000hz little endian, Hex 1770 (array(0x70, 0x17, 0x0, 0x0)) or 44100hz little endian, Hex AC44 (array(0x44, 0xAC, 0x0, 0x0))
	$BitsPerSample_ = array(0x10, 0x0);              //16 little endian
	$Subchunk2ID_ = array(0x64, 0x61, 0x74, 0x61);   //"data" big endian
	
	$Stitcher = new CStitcher();
	$file = new FILESTRUCT();
	$Stitcher->StitchFiles($file, $files);
	
	header('Content-type: audio/x-wav', true);
	header('Content-Disposition: attachment;filename=captcha.wav');
	
	foreach($file->ChunkID as $val) {
	    print chr($val);
	} 
	foreach($file->ChunkSize as $val) {
	    print chr($val);
	} 
	foreach($file->Format as $val) {
	    print chr($val);
	} 
	foreach($file->Subchunk1ID as $val) {
	    print chr($val);
	} 
	foreach($file->Subchunk1Size as $val) {
	    print chr($val);
	} 
	foreach($file->AudioFormat as $val) {
	    print chr($val);
	} 
	foreach($file->NumChannels as $val) {
	    print chr($val);
	} 
	foreach($file->SampleRate as $val) {
	    print chr($val);
	} 
	foreach($file->ByteRate as $val) {
	    print chr($val);
	} 
	foreach($file->BlockAlign as $val) {
	    print chr($val);
	} 
	foreach($file->BitsPerSample as $val) {
	    print chr($val);
	} 
	foreach($file->Subchunk2ID as $val) {
	    print chr($val);
	} 
	foreach($file->Subchunk2Size as $val) {
	    print chr($val);
	} 
	foreach($file->Data as $val) {
	    print chr($val);
	} 

	exit;

// Block direct download of .WAV and .ttf files
}elseif(isset($_GET['wav']) or isset($_GET['ttf'])){
	send_404();

	
// Stop direct opening of this file	
}elseif('captcha.php' == basename($_SERVER['PHP_SELF'])){
	send_404();
}

function send_404()
{
	header('HTTP/1.x 404 Not Found');
	print '<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">'."\n".
	'<html><head>'."\n".
	'<title>404 Not Found</title>'."\n".
	'</head><body>'."\n".
	'<h1>Not Found</h1>'."\n".
	'<p>The requested URL '.
	str_replace(strstr($_SERVER['REQUEST_URI'], '?'), '', $_SERVER['REQUEST_URI']).
	' was not found on this server.</p>'."\n".
	'</body></html>'."\n";
	exit;
}

function captcha_validate()
{
	if(trim($_POST['captcha']) == $_SESSION['captcha'])
	{
		$_SESSION['captcha'] = NULL;
		return true;
	}
	return false;
}

function captcha_image()
{
	function create_captcha_code($len = 4){
	   $e = base64_encode(pack("h*", sha1(mt_rand())));
	   $_SESSION['captcha'] = str_replace('l', '2', str_replace('O', '3', str_replace('0', '4', str_replace('1', '5', str_replace('o', '6', str_replace('I', '7', substr(strtr($e, "+/=", "xyz"), 0, $len)))))));//substr(strtr($e, "+/=", "xyz"), 0, $len);
	}
	
	function rand_string($len = 28){
	   $e = base64_encode(pack("h*", sha1(mt_rand())));
	   return substr(strtr($e, "+/=", "xyz"), 0, $len);
	}
	$dir = opendir(CAPTCHA_PATH);
		while (false !== ($file = readdir($dir))) {
		   if (eregi('ttf{1}$', $file)){
				$fonts[] = CAPTCHA_PATH.$file;		    
			}
		}
	closedir($dir);
	
	if(!empty($fonts) and is_array($fonts)){
		shuffle($fonts);
		$font = $fonts['0'];
		if(isset($fonts['1'])){
			$background_font = $fonts['1'];
		}else{
			$background_font = $fonts['0'];
		}
	}
	
	
	create_captcha_code();
	$colour1 = mt_rand(125, 175);
	$colour2 = mt_rand(50, 235);
	$colour3 = ((420 - ($colour1 + $colour2)) + mt_rand(-10, 10));
	$colours = array($colour1, $colour2, $colour3); 
	shuffle($colours);
	
	$text_colour1 = mt_rand(55, 75);
	$text_colour2 = mt_rand(20, 145);
	$text_colour3 = ((240 - ($text_colour1 + $text_colour2)) + mt_rand(-5, 5));
	$text_colours = array($text_colour1, $text_colour2, $text_colour3);
	shuffle($text_colours);
	
	if($text_colour1 > 60){ $text_shadow1 = $text_colour1 - 60; }else{ $text_shadow1 = 0;}
	if($text_colour2 > 60){ $text_shadow2 = $text_colour2 - 60; }else{ $text_shadow2 = 0;}
	if($text_colour3 > 60){ $text_shadow3 = $text_colour3 - 60; }else{ $text_shadow3 = 0;}
	
	$alpha_string = '';
	for($i = 0; $i < 25; $i++){
		$alpha_string .= rand_string().rand_string().rand_string()."\n";
	}
	foreach($colours as $colour){
		$hidden[] = $colour + (mt_rand(15, 255 - $colour) - 15);
	}
	
	header ('Content-type: image/jpeg');
	
	$image = @imagecreate(140, 90); // image dimensions
	$background_colour = imagecolorallocate($image, $colours['0'],$colours['1'],$colours['2']);
	$text_shadow = imagecolorallocate($image, $text_shadow1, $text_shadow2, $text_shadow3);
	$text_colour = imagecolorallocate($image, $text_colours['0'],$text_colours['1'],$text_colours['2']);
	$hidden = imagecolorallocate($image, $hidden['0'],$hidden['1'],$hidden['2']);
	if(!empty($font) and is_readable($font)){
		$angle = mt_rand(-20, 20);
		$xCoord = mt_rand(4, 36);
		$xCoord = $xCoord + round($angle/4);
		$yCoord = mt_rand(0, 22);
		imagettftext($image, mt_rand(10,15), mt_rand(60, 120), -70, 180, $hidden, $background_font, $alpha_string);
		imagettftext($image, 27, $angle, 2 + $xCoord, 43 + ceil($angle/1.5) + $yCoord, $text_shadow, $font, $_SESSION['captcha']);
		imagettftext($image, 27, $angle, $xCoord, 42 + ceil($angle/1.5) + $yCoord, $text_colour, $font, $_SESSION['captcha']);
	}else{
		imagestring($image, 5, 26, 19, $_SESSION['captcha'], $text_shadow);
		imagestring($image, 5, 25, 18, $_SESSION['captcha'], $text_colour);
	}
	imagejpeg($image, null, 100);
	imagedestroy($image);	
	exit;
}

// The classes and functions below manage splicing the various .WAV audio files. They 
// originally came from an excellent tutorial found on: http://www.builderau.com.au/
// http://www.builderau.com.au/webdev/soa/ ... 704,00.htm

class FILESTRUCT {
    var $ChunkID;
    var $ChunkSize;
    var $Format;
    var $Subchunk1ID;
    var $Subchunk1Size;
    var $AudioFormat;
    var $NumChannels;
    var $SampleRate;
    var $ByteRate;
    var $BlockAlign;
    var $BitsPerSample;
    var $Subchunk2ID;
    var $Subchunk2Size;
    var $Data;

    function FILESTRUCT() {
        $this->ChunkID = array(0x0, 0x0, 0x0, 0x0);      //4
        $this->ChunkSize = array(0x0, 0x0, 0x0, 0x0);    //4
        $this->Format = array(0x0, 0x0, 0x0, 0x0);       //4
        $this->Subchunk1ID = array(0x0, 0x0, 0x0, 0x0);  //4
        $this->Subchunk1Size = array(0x0, 0x0, 0x0, 0x0);//4
        $this->AudioFormat = array(0x0, 0x0);            //2
        $this->NumChannels = array(0x0, 0x0);            //2
        $this->SampleRate = array(0x0, 0x0, 0x0, 0x0);   //4
        $this->ByteRate = array(0x0, 0x0, 0x0, 0x0);     //4
        $this->BlockAlign = array(0x0, 0x0);             //2
        $this->BitsPerSample = array(0x0, 0x0);          //2
        $this->Subchunk2ID = array(0x0, 0x0, 0x0, 0x0);  //4
        $this->Subchunk2Size = array(0x0, 0x0, 0x0, 0x0);//4
        $this->Data = array();
    }
}

class CStitcher {

    function StitchFiles(&$fsFile, &$sFiles) {

        $fsFiles = array(); //() As FILESTRUCT
        $lFileSize = 0;
	$lOffset = 0;
        $bData = array(); //() As Byte
        
        for ($i = 0; $i < count($sFiles); $i++) {
            $fsFiles[$i] = new FILESTRUCT();
            SetFile($fsFiles[$i], $sFiles[$i]);
            $lSize = CalcLittleEndianValue($fsFiles[$i]->Subchunk2Size);
            $lFileSize = $lFileSize + $lSize;
            $bData = array_merge($bData, $fsFiles[$i]->Data);
            $lOffset = $lOffset + $lSize;
        }
        $fsFile->ChunkID = $GLOBALS["ChunkID_"];
        $fsFile->ChunkSize = GetLittleEndianByteArray(36 + $lFileSize);
        $fsFile->Format = $GLOBALS["FileFormat_"];
        $fsFile->Subchunk1ID = $GLOBALS["Subchunk1ID_"];
        $fsFile->Subchunk1Size = array(0x10, 0x0, 0x0, 0x0);
        $fsFile->AudioFormat = $GLOBALS["AudioFormat_"];
        $fsFile->NumChannels = $GLOBALS["Channels_"];
        $fsFile->SampleRate = $GLOBALS["SampleRate_"];
        $fsFile->ByteRate = GetLittleEndianByteArray(
                                            CalcLittleEndianValue($GLOBALS["SampleRate_"]) *
                                            CalcLittleEndianValue($GLOBALS["Channels_"]) *
                                            (CalcLittleEndianValue($GLOBALS["BitsPerSample_"]) / );
        $fsFile->BlockAlign = array_splice(GetLittleEndianByteArray(CalcLittleEndianValue($GLOBALS["Channels_"]) *
                                                                    (CalcLittleEndianValue($GLOBALS["BitsPerSample_"]) / ), 0, 2);
        $fsFile->BitsPerSample = $GLOBALS["BitsPerSample_"];
        $fsFile->Subchunk2ID = $GLOBALS["Subchunk2ID_"];
        $fsFile->Subchunk2Size = GetLittleEndianByteArray($lFileSize);
	$fsFile->Data = $bData;
    }


}

function SetFile(&$fsFile_, $sFileName) {
    $lSize = 1;
    if (file_exists($sFileName)) {
        $fil = fopen($sFileName, "rb");
        $contents = fread($fil, count($fsFile_->ChunkID));
	$fsFile_->ChunkID = bin_split($contents, 1);
        $contents = fread($fil, count($fsFile_->ChunkSize));
	$fsFile_->ChunkSize = bin_split($contents, 1);
        $contents = fread($fil, count($fsFile_->Format));
	$fsFile_->Format = bin_split($contents, 1);
        $contents = fread($fil, count($fsFile_->Subchunk1ID));
	$fsFile_->Subchunk1ID = bin_split($contents, 1);
        $contents = fread($fil, count($fsFile_->Subchunk1Size));
	$fsFile_->Subchunk1Size = bin_split($contents, 1);
        $contents = fread($fil, count($fsFile_->AudioFormat));
	$fsFile_->AudioFormat = bin_split($contents, 1);
        $contents = fread($fil, count($fsFile_->NumChannels));
	$fsFile_->NumChannels = bin_split($contents, 1);
        $contents = fread($fil, count($fsFile_->SampleRate));
	$fsFile_->SampleRate = bin_split($contents, 1);
        $contents = fread($fil, count($fsFile_->ByteRate));
	$fsFile_->ByteRate = bin_split($contents, 1);
        $contents = fread($fil, count($fsFile_->BlockAlign));
	$fsFile_->BlockAlign = bin_split($contents, 1);
        $contents = fread($fil, count($fsFile_->BitsPerSample));
	$fsFile_->BitsPerSample = bin_split($contents, 1);
        $contents = fread($fil, count($fsFile_->Subchunk2ID));
	$fsFile_->Subchunk2ID = bin_split($contents, 1);
        $contents = fread($fil, count($fsFile_->Subchunk2Size));
	$fsFile_->Subchunk2Size = bin_split($contents, 1);
        $lSize = CalcLittleEndianValue($fsFile_->Subchunk2Size);
	$contents = fread($fil, $lSize);
	$fsFile_->Data = bin_split($contents, 1);
        fclose($fil);
    }
}

function CalcLittleEndianValue(&$bValue) {
    $lSize_ = 0;
    for ($iByte = 0; $iByte < count($bValue); $iByte++) {
        $lSize_ += ($bValue[$iByte] * pow(16, ($iByte * 2)));
    }
    return $lSize_;
}

function GetLittleEndianByteArray($lValue) {
    $running = 0;
    $b = array(0, 0, 0, 0);
    $running = $lValue / pow(16,6);
    $b[3] = floor($running);
    $running -= $b[3];
    $running *= 256;
    $b[2] = floor($running);
    $running -= $b[2];
    $running *= 256;
    $b[1] = floor($running);
    $running -= $b[1];
    $running *= 256;
    $b[0] = round($running);
    return $b;
}


function bin_split($text, $c)
{
 $arr = array();
 $len = strlen($text);
 $a = 0;
 while($a < $len)
 {
  if ($a + $c > $len)
  {
   $c = $len - $a;
  }
  $arr[$a] = ord(substr($text, $a, $c));
  $a += $c;
 }
 return $arr;
}

?>
I've already changed it just a bit, but I want to make it so that when the audio file is requested, it opens up a new window, and plays the file, instead of the way its doing it now. Can anyone help me? --- I do have my own CAPTCHA page that I created. but I am working on the audio part. and couldn't figure it out.

Posted: Sat Jun 03, 2006 5:17 am
by s.dot
What is "the way it's doing it now"?

You could put the data that needs to be sent to the script in a form and ues the submit button as the audio "link".

Posted: Sat Jun 03, 2006 6:26 am
by bokehman
Opening something in a new window is a javascript function and can be done as follows:

Code: Select all

echo '<a href="http://'.$_SERVER['HTTP_HOST'].$_SERVER['PHP_SELF'].'?audio" onclick="return !window.location(this.href)">CAPTCHA code in audio form</a>';

Posted: Sat Jun 03, 2006 12:19 pm
by tecktalkcm0391
Ok. that works, now how could I make a pop-up window come up with come code like this in it

Code: Select all

<embed src="LINK TO AUDIO CODE" hidden="false" autostart="true" loop="0">
<noembed>Your browser doesn't support EMBED, but you can still listen to the background sound of this page by<a href="LINK TO AUDIO CODE"> clicking here.</a></noembed>
So that it would open up and just play the code, without them having to open it on their computer, or where i just stays in the browser.

Posted: Sat Jun 03, 2006 1:24 pm
by bokehman
tecktalkcm0391 wrote:Ok. that works, now how could I make a pop-up window come up with come code like this in it

Code: Select all

<embed src="LINK TO AUDIO CODE" hidden="false" autostart="true" loop="0">
<noembed>Your browser doesn't support EMBED, but you can still listen to the background sound of this page by<a href="LINK TO AUDIO CODE"> clicking here.</a></noembed>
So that it would open up and just play the code, without them having to open it on their computer, or where i just stays in the browser.
<embed> is not a valid element (and I don't believe it ever has been).

Posted: Sat Jun 03, 2006 9:16 pm
by tecktalkcm0391
I am talking about the HTML code in that post.
http://www.tips-tricks.com/sound.asp --- That tells you about the HTML Code.

Posted: Sun Jun 04, 2006 4:02 am
by bokehman
tecktalkcm0391 wrote:I am talking about the HTML code in that post.
http://www.tips-tricks.com/sound.asp --- That tells you about the HTML Code.
Don't use that tutorial as a reference. What it is recommending is the use of a load of completely invalid mark up.

Posted: Sun Jun 04, 2006 10:20 pm
by tecktalkcm0391
then how do you make a file play on a website!

Posted: Mon Jun 05, 2006 3:50 am
by bokehman
I don't really see what you didn't like about the method that was already implemented. It worked fine and the code was valid. The whole point of this audio feature is to raise the level of accessibility of your site but for some reason you wish to put it in a javascript pop up window and use invalid mark which will have precisely the opposite effect. If you are still not convinced then you need to research the <object> element.

Posted: Tue Jun 06, 2006 8:54 am
by tecktalkcm0391
The only reason that I want it in the window is because on my computers in order to listen to it you have to download it to the desktop, cause if you just click open, then the sound isn't their. I was trying to make it simplier for everyone to use.

Posted: Tue Jun 06, 2006 9:36 am
by Roja
tecktalkcm0391 wrote:The only reason that I want it in the window is because on my computers in order to listen to it you have to download it to the desktop, cause if you just click open, then the sound isn't their. I was trying to make it simplier for everyone to use.
The key is you are trying to make it simple based on how you use a browser.

Invalid markup (and embed IS invalid markup) will cause people using assistive browsing technologies problems. Since the exact user here is one that is likely to be using those technologies, your attempts to make it "simple" for you to use may make it impossible for them to use.

Put another way, your browser lets you see the link, lets you open the window, and so on. If you are blind or visually impared, you might not be able to see the new window. (and imagine the frustration with a window you cant see that plays an annoying captcha sound on repeat that you can't easily close!!). Even if they see the new window, and could close it, they might not be able to work the controls for the sound itself, forcing them to reload multiple times to "get it right".

Don't use embed. Do exactly what yahoo and tons of other sites do: Offer a clickable link, which allows them to open the sound.

By the way, the behavior of it opening automatically or not is seperate from that link. You apparently do not have a browser helper program associated with whatever format the sound is in (wav? mp3?). On my linux box, my browser has audio files associated with xmms, so clicking on those links DOES play the sound (no download prompt).

Posted: Tue Jun 06, 2006 7:57 pm
by tecktalkcm0391
Well is their a way to save the audio file to a directory?

Like something like this:

Code: Select all

var $data_directory = "./audio_data";

function saveData()
  {
    $filename = md5($this->hash_salt . $_SERVER['REMOTE_ADDR']);
    $fp = fopen($this->data_directory . "/" . $filename, "w+");
    fwrite($fp, md5( $this->hash_salt . strtolower($this->code) )  );
    fclose($fp);
  }

And then delete it after so many mintues using something like a cron job?

Like this:

Code: Select all

if ($handle = @opendir($this->data_directory)) {
      while (($filename = readdir($handle)) !== false) {
        if(time() - filemtime($this->data_directory . "/" . $filename) > $this->prune_minimum_age * 60) {
          @unlink($this->data_directory . "/" . $filename);
        } 
      }
      closedir($handle);
    }

Posted: Wed Jun 07, 2006 5:18 am
by bokehman
tecktalkcm0391 wrote:Well is their a way to save the audio file to a directory?
What's the point? The audio file is unique and is served to the client on the fly. It only takes a second to assemble and this must be done however you handle it.

All you are doing is taking something that was very simple and turning it into a monster.