8

I try to create a captcha code image with php gd :

$im = imagecreatetruecolor(100, 25);
$white = imagecolorallocate($im, 255, 255, 255);
$black = imagecolorallocate($im, 0, 0, 0);
imagefilledrectangle($im, 0, 0, 399, 29, $white);
$imgstring=$_GET['captcha'];
$font = 'RAVIE.TTF';
imagettftext($im, 15, 0, 10, 20, $black, $font, $imgstring);
header('Content-Type: image/png');
imagepng($im);
imagedestroy($im);

The GET value is send with ajax like this:

var randstring;
function Captcha() {
    randstring = Math.round((Math.pow(36, length + 1) - Math.random() * Math.pow(36, 5))).toString(36).slice(1);

            $.ajax({
                url: 'test_image.php',
                data: {'captcha' : randstring},
                method: 'GET',
                success: function (data){
                    console.log(data);
                },
                error: function (){
                    alert('Error');
                    return false;
                }   

            });
        }

HTML:

<img src="test_image.php">

Though it gives no errors , the image is not generated . Yes, the request reach the php script , i already checked , but something blocks image from being generated...

UPDATE Actually the image is generated, and also the ajax request is sent. But on the test_image.php script , $_GET['captcha'] ( the request ) is not recognized so it will just output a blank string in that image , though the image is there , but without a string .

Petru Lebada
  • 2,167
  • 8
  • 38
  • 59
  • so if you load test_image.php directly you can see the image there? – nowhere Oct 13 '15 at 13:12
  • the $_GET string is not recognized , so the image has no string , but it exist on the page , and the ajax request is also sent , if instead of $_GET['captcha'] i put a random static string , the image will have that string – Petru Lebada Oct 13 '15 at 13:24
  • Have you tried to skip ajax by trying something like : . If it works you can still update randomnr with a random value from js. – nowhere Oct 13 '15 at 13:26
  • ah i see now your update... – nowhere Oct 13 '15 at 13:27
  • what's the point of the captcha then ? if i just put the string in url , where every bot can simply copy+paste it – Petru Lebada Oct 13 '15 at 13:29
  • to be fair whatever you generate with javascript is clearly available to everybody.. sending it via ajax won't hide your generated code ;) By the way i was just wondering if it works in that way. Can you see the image + code if you surf directly to URL/test_image.php?captcha=randomnr ? – nowhere Oct 13 '15 at 13:30
  • to explain better my previous comment: ie: if you want to hide the captcha code you should generate it with php when you load the form page and save it in a session variable. After the form is submitted you compare the code that was inserted with what you have in your session. – nowhere Oct 13 '15 at 13:34
  • yes it works like this ... it may be something wrong with my ajax request... but i can't figure out... – Petru Lebada Oct 13 '15 at 13:34
  • @nowhere , i know but i have my own reasons for using js , though i know the danger i expose to – Petru Lebada Oct 13 '15 at 13:35
  • Maybe font problems? – gre_gor Oct 13 '15 at 13:37
  • @gre_gor , no .. that's for sure – Petru Lebada Oct 13 '15 at 13:37

5 Answers5

4

You want to load the content of your image using AJAX but do not want to put URL in img tag for security reason. So, in that case, you should fetch base64 encoded data of the image and use it inside your img src.

Use following code for your php file:

<?php

// Start output buffering
ob_start();
$im = imagecreatetruecolor(100, 25);
$white = imagecolorallocate($im, 255, 255, 255);
$black = imagecolorallocate($im, 0, 0, 0);
imagefilledrectangle($im, 0, 0, 399, 29, $white);
$imgstring=$_GET['captcha'];
$font = 'RAVIE.TTF';
imagettftext($im, 15, 0, 10, 20, $black, $font, $imgstring);
imagepng($im);
imagedestroy($im);

// Get Image content a variable
$captchaImageData=ob_get_contents();
// Clean the output buffer
ob_end_clean();

//Base64 Encode
$encodedData = base64_encode($captchaImageData);

echo $encodedData;
?>

You Javascript code will be following:

function Captcha() {
    var randstring = Math.round((Math.pow(36, length + 1) - Math.random() * Math.pow(36, 5))).toString(36).slice(1);

    $.ajax({
        url: 'test_image.php',
        data: {'captcha' : randstring},
        method: 'GET',
        beforeSend: function(data) {
            $('captchaImage').attr('src','laoding.gif');
        },
        success: function (data){
            // data is base64_encoded data of your image
            // load it in your img suorce
            $('captchaImage').attr('src','data:image/png;base64,'+data);
        },
        error: function (){
            alert('Error');
            $('captchaImage').attr('src','error.jpg');
        }   

    });
}

You HTML element will be updated with an ID. Also put some sort of loading gif/animation until image is loaded.

<img src="loading.gif" id="captchaImage">

Now calling Captcha() funciton in javascript will always load a new captcha image. Put appropriate loading.gif and error.jpg images

ksg91
  • 1,279
  • 14
  • 34
0

Can you try this in your js code? Instead of loading the image via ajax we can try just to append the code to the src value of the image:

randstring = Math.round((Math.pow(36, length + 1) - Math.random() * Math.pow(36, 5))).toString(36).slice(1);

$("#image").attr('src',$("#image").attr('src') + "?captcha="+randstring );

HTML

<img id="image" src="test_image.php">
nowhere
  • 1,558
  • 1
  • 12
  • 31
  • i can tell you by now that is working , but is not what i 'm looking for ... if i'll send it with ajax, it won't be so easy to access it , especially for spam bots – Petru Lebada Oct 13 '15 at 13:40
  • @PetruLebada ok i ll update the answer then.. by they way your code can be either safe on the js side or not safe: fixing the ajax request won't be making it any safer since with both solutions the randstring variable still contains your code. – nowhere Oct 13 '15 at 13:45
  • can you give me some examples on how can my captcha code can be accessed ? – Petru Lebada Oct 13 '15 at 13:54
  • @PetruLebada the point here is that both solutions are safe enough from bots since they are made to scan the page and submit data usually for the most used protection systems. Since your solution was made ad hoc for your site unless someone creates a bot on purpose to attack it, it should be safe enough. I don't know now if bots go around checking also js variables to discover a captcha code but i doubt it. – nowhere Oct 13 '15 at 14:33
  • And even if they can somehow read your code in my experience having a couple hidden input fields (which aren't supposed to be submitted) are usually enough to block any bot that might find a way to force your captcha code. – nowhere Oct 13 '15 at 14:35
0

try to replace the get param with a test variable: $imgstring='this is some text';

Does this show an image with the text.

btw. this is not a very good way for a captcha, all bots could easily read the ajax request. Would be better to generate the captcha by the test_image.php file and store the random string in session for example.

UPDATE

So if you really want to use ajax you can´t do it the way you do. You need to use base64 encode to show the picure via ajax. javascript:

$.ajax({
url: 'test_image.php',
data: {'captcha' : randstring},
method: 'GET',
success: function (data){
console.log(data);
$('#mycaptcha').attr('src','data:image/png;base64,'+data);
},error: function (){alert('Error');return false;}   
});

....

Captcha();

PHP:

imagettftext($im, 15, 0, 10, 20, $black, $font, $imgstring);
ob_start();
imagepng($im);
$imgdata=ob_get_contents();
ob_end_clean();
imagedestroy($im);
echo base64_encode($imgdata);

html: [img id="mycaptcha"]

cant post html brackets .. use <>

FlorianR.
  • 66
  • 4
  • yes like this is working , and yes i know with php is safer , but i need to use js , and i don't know if spam bots can access the ajax request ... – Petru Lebada Oct 13 '15 at 13:42
0

You write:

<img src="test_image.php" id="img">

but do not passing any parameters there. Of course your PHP script does not see any $_GET['captcha']. Your AJAX is being called but does not affectes to img due to is not relaed to it.

Try:

var c = Math.round((Math.pow(36, length + 1) - Math.random() * Math.pow(36, 5))).toString(36).slice(1);
$("#img").attr("src", "test_image.php?captcha=" + c);

This will send your string in GET query.

If you want to call it on some button click ("Refresh captcha" for example), call this code on its onclick event.

Dan Spirit
  • 327
  • 1
  • 8
0

Check your server log. Maybe imagettftext cannot open the specified font file.

Try to copy the font file to the same directory as the php script.

Then:

putenv('GDFONTPATH=' . realpath('.'));
$im = imagecreatetruecolor(100, 25);
$white = imagecolorallocate($im, 255, 255, 0);
$black = imagecolorallocate($im, 0, 0, 0);
imagefilledrectangle($im, 0, 0, 399, 29, $white);
$imgstring=$_GET['captcha'];
$font = 'RAVIE.TTF';
imagettftext($im, 15, 0, 10, 20, $black, $font, $imgstring);
header('Content-Type: image/png');
imagepng($im);
imagedestroy($im);
exit;
Peter
  • 6,509
  • 4
  • 30
  • 34