This project is something I did a while ago but never got around to releasing. It shows the core code for adding image captcha capabilities to your servers. It is pretty raw code, so only the basics are support (200x64 images) in a limited number of formats. The code can be extended to do a lot more though.
The way the image captcha system works in Silkroad is pretty straightforward. After you send 0x6101 to login, the Silkroad server pulls a pre-generated captcha from an image pool (or just generates one on the fly). This image is then packed into a smaller buffer (sort of like RLE compression or something) and then compressed with ZLib and sent along with a mini-header in the 0x2322 packet to the client.
When the client receives the 0x2322 packet, it will unpack the image and rebuild the image's pixels. From there it will display the image in the image slot on the login window. In the past, I have released code to save the image code from the packet, but there was nothing ever to build one and send the packet. That is what this project completes.
There are many ways to generate image captchas. One of the easiest methods I was playing with was using PHP and ImageMagick. For example, I wrote a simple script using online references that allows image captchas similar to Silkroad's but with many more characters. Here is one example: [Only registered and activated users can see links. Click Here To Register...]. You may replace the 'str' parameter to see others. This page is on a free host, so it might go down time to time.
Since you generate the captcha string, you can also store it with the resulting image so you know which image is associated with which captcha! You can either store it in the filename or if you do it at runtime, you can just store it into the connection's context data ( i.e. String current_captcha = "blah"; ).
Given you have 200 x 64 pixels worth of space, you can also implement more custom captchas. The captcha packet supports up to 512 bytes of input, so you can actually write: multiple choice questions, fill in the blank, or free answer styled captchas. There might be support for larger images as well, but I never looked into that. The code would have to be changed quite a bit to support that as well.
index.php (The demo image captcha page. Your host must support a modern PHP and ImageMagick and any dependencies)
To interface with web page output, you'd simply use something like cURL in C++ or the web classes in .Net. You'd query the page with a post and save the result image data and then process it in your server. How you process it will depend on any image processing library you are using.
That's about it really, the code requires my [Only registered and activated users can see links. Click Here To Register...] as well. Included is the project as well as the ZLib helper DLL required for easily using ZLib in C#. Everything else instruction wise is in the readme.
The hardest part that hasn't really been covered is using your own images. Basically, you need to get a 200 x 64 array of pixels that represents the image. Once you do that, no matter what original format the image was in, you should be able to use the code. I can't really offer any help with this task, so if you are going to make use of this project, you will have to work through it with your setup.
The way the image captcha system works in Silkroad is pretty straightforward. After you send 0x6101 to login, the Silkroad server pulls a pre-generated captcha from an image pool (or just generates one on the fly). This image is then packed into a smaller buffer (sort of like RLE compression or something) and then compressed with ZLib and sent along with a mini-header in the 0x2322 packet to the client.
When the client receives the 0x2322 packet, it will unpack the image and rebuild the image's pixels. From there it will display the image in the image slot on the login window. In the past, I have released code to save the image code from the packet, but there was nothing ever to build one and send the packet. That is what this project completes.
There are many ways to generate image captchas. One of the easiest methods I was playing with was using PHP and ImageMagick. For example, I wrote a simple script using online references that allows image captchas similar to Silkroad's but with many more characters. Here is one example: [Only registered and activated users can see links. Click Here To Register...]. You may replace the 'str' parameter to see others. This page is on a free host, so it might go down time to time.
Since you generate the captcha string, you can also store it with the resulting image so you know which image is associated with which captcha! You can either store it in the filename or if you do it at runtime, you can just store it into the connection's context data ( i.e. String current_captcha = "blah"; ).
Given you have 200 x 64 pixels worth of space, you can also implement more custom captchas. The captcha packet supports up to 512 bytes of input, so you can actually write: multiple choice questions, fill in the blank, or free answer styled captchas. There might be support for larger images as well, but I never looked into that. The code would have to be changed quite a bit to support that as well.
index.php (The demo image captcha page. Your host must support a modern PHP and ImageMagick and any dependencies)
Code:
<?php
$font = 'cour.ttf';
$str = $_REQUEST['str'];
header("Content-type: image/png");
$im = imagecreatetruecolor( 200, 64 );
imagealphablending($im, false);
imagesavealpha($im, true);
$background = imagecolorallocate( $im, 0, 0, 0 );
$foreground = imagecolorallocate( $im, 255, 255, 255 );
imagefilltoborder( $im, 0, 0, $background, $background );
$pixels_per_char = 200 / strlen( $str );
$chars = str_split( $str );
$offset = 0;
foreach( $chars as $char )
{
imagechar( $im, 5, $offset + rand( 0, $pixels_per_char - imagefontwidth( 5 ) ), rand( 0, 64 - imagefontheight( 5 ) ), $char, $foreground );
$offset += $pixels_per_char;
}
for( $ctr = 0; $ctr < 500; ++$ctr )
{
imagesetpixel( $im, mt_rand() % 200, mt_rand() % 64, $foreground );
}
for( $ctr = 0; $ctr < 3; ++$ctr )
{
imageline( $im, mt_rand() % 50, mt_rand() % 64, 150 + mt_rand() % 50, mt_rand() % 64, $foreground );
}
for( $ctr = 0; $ctr < 3; ++$ctr )
{
imageline( $im, mt_rand() % 200, mt_rand() % 16, mt_rand() % 200, 48 + mt_rand() % 16, $foreground );
}
imagepng( $im );
imagedestroy( $im );
die;
?>
That's about it really, the code requires my [Only registered and activated users can see links. Click Here To Register...] as well. Included is the project as well as the ZLib helper DLL required for easily using ZLib in C#. Everything else instruction wise is in the readme.
The hardest part that hasn't really been covered is using your own images. Basically, you need to get a 200 x 64 array of pixels that represents the image. Once you do that, no matter what original format the image was in, you should be able to use the code. I can't really offer any help with this task, so if you are going to make use of this project, you will have to work through it with your setup.