Archive for 'PHP'

Creating a basic captcha with Imagick

I hate captcha systems, truly, madly, deeply. But spammers force us to create and use them.
Writing captcha systems can be very easy. You need a randomly generated image, a hard to read font, and finally basic server side coding knowledge. I use PHP cos it’s well documented and extremely easy to use, but you can use any other server side language you want. On which ImageMagick can be used of course.
So, let’s list what we want to do:

  • Create a random string
  • Display it as an image
  • Check whether the user entered the string correctly

That’s all.

Creating random string with PHP
This is the easiest. PHP already has a function which creates new random string each second. Yup, that’s the time() function. But the created string has only numbers. To fix that, we encrypt it with some sort of built-in encryption function. That can be md5, sha1, anything. I use md5 now cos that’s which popped in my mind on the first place.
The second thing we want to solve is to not make the user to enter 32 characters, but only 5. Again, PHP’s string manipulation knowledge comes handy, I use substr(). So let’s see our code:

$rand = md5(time());
$str = substr($rand, 0 , 5);

That simple. We now have a 5 characters long completely random string.
 

Pushing the random string in an image, using IMagick
 
If you followed my IMagick related posts, you should know that annotating an image with IMagick is simpler than confusing a snail with a mirror. The only difference is that now we’ll have in the image our random string, not a fixed variable’s value. Yeah, that’s dynamic image.
I’ll also use a hard to read font, because using DirectX even a 5-year-old can create a captcha reading software if we use a common font.
You may ask how will the server side code which checks whether the captcha is correct or not will know the user entered the correct code or not. That’s solved with sessions. We start our session in the image generator script, and set the shortened version of our random string in a session variable.
So, when the image is loaded in your HTML, the session variable will get the 5 character long random string as value. The session variable will be checked on the page which checks the user input, if matches the value which was entered by the user, we know it’s human. No, we hope it’s a human.
So, the code to generate the dynamic captcha image:

session_start();
$rand = md5(time());
$str = substr($rand, 0 , 5);
$_SESSION['captcha'] = $str;

$font = '/path/to/your/hard2read/font.ttf';

$image = new Imagick();
$draw = new ImagickDraw();
$pixel = new ImagickPixel( 'white' );
$image->newImage(100, 27, $pixel);
$draw->setFont($font);
$draw->setFontSize( 25 );
$draw->line( $x, $y, $x1, $y1 );
$image->annotateImage($draw, 10, 20, 0, $str);
$image->setImageFormat('png');
header('Content-type: image/png');
echo $image;
a captcha image created with IMagick

We save the above code as captcha.php and try to load it. If everything went well, we should see an image like the one on the left.
 
The HTML form for our captcha
 
If you can’t do this by your own, you shouldn’t mess with captcha verification. But just for the sake of the example:

captcha image

Now the server side script which checks the user input. I write something very basic, don’t validate or sanitize anything. When you write your own user input verifier code, you should validate every single bit of your users’ input, don’t trust em!

session_start();
/*Check if every field has been filled in*/
if (!empty($_POST['uname']) && !empty($_POST['upass']) && !empty($_POST['captcha'])){

/*Check if the CAPTCHA image value matches the user input*/
    if ($_SESSION['captcha'] != $_POST['captcha']){
        echo 'You failed the CAPTCHA verification. Try again.';
    }else{
         echo 'Congrats! Everything is cool!';
    }

}else{
echo 'You missed to fill in some fields. Try again.';
}

And we’re done.

To play with the example you can do it here.
To download the files which were created through this post, click here.

Vertical text with Imagick

Creating vertical text over an image is extremely simple with Imagick. The text created with Imagick can be used for example as a watermark over an image or any other thing you can think of.

It’s very important to understand that the created object is just an image and that you can not have any text before the below code block and which will be sent to browser output. This includes white-space, page brake or any type of text.

The vertical text is obtained with annotateImage() since it’s 4th parameter of the function is to set the degree of the text. 0 degrees is horizontal text, 90 degrees is vertical text, that simple.

Let’s see the code:

$image = new Imagick();
$draw = new ImagickDraw();
$pixel = new ImagickPixel( 'white' );
$image->newImage(25, 150, $pixel);
$draw->setFontSize( 20 );
$image->annotateImage($draw, 0, 0, 90, 'Devoracles.com');
$image->setImageFormat('png');
header('Content-type: image/png');
echo $image;

The above’s result is what you see below.

As you see it’s extremely simple to create vertical text with Imagick, either if you’re a novice or a pro.

If you have any related question, feel free to ask.

Managing PDF files with Imagick

Many doesn’t know, but with Imagick anyone can manage PDF files. As far as I know you can’t create one, but this function can be extremely useful to create a screenshot of a PDF file on the server’s side.

First of all, the PDF file you just created has to be loaded in Imagick, either the whole document or only one page from it, then you can output it as any type of image, let’s see how to do it:

$pdf = new imagick( 'your.pdf' );
$pdf->setImageFormat( "gif" );
header( "Content-Type: image/gif" );
echo $pdf;

Be aware that you can not output anything else before this code block neither a whitespace or text. Nothing. Also, you can specify any image format you wish as Imagick can output almost any image format.

Look at the above code block. The first line says:

$pdf = new imagick( 'your.pdf' );

If you would like to select a specific page to output from the PDF, just specify the page number as it follows:

/*This would select the cover page: */
$pdf = new imagick( 'your.pdf[0]' );

/*and this the actual 1st page: */
$pdf = new imagick( 'your.pdf[1]' );

Now you should get the idea, if you don’t, feel free to question me.

The last thing I show you is how to create a thumbnail of a PDF. There is no too much difference, the only one is that before outputting the image we resize it using thumbnailImage():

$pdf = new imagick( 'your.pdf' );
$pdf->setImageFormat( "gif" );
$im->thumbnailImage( 200, NULL );
header( "Content-Type: image/gif" );
echo $pdf;

I used ‘NULL’ to preserve the image’s aspect ratio.

As always, if anything is unclear, feel free to question me.

MySQLi or MySQL, this is the question

As of PHP5, a new improved version of MySQL connector is available. It’s called MySQLi, which stands for “MySQL Improved”. I had to think a lot about what the “i” stands for, but it seems that the guys (or gals) who developed the extension has the same, endless imagination as the PHP developers has.

So, a few words about MySQLi. The first improvement is that it’s object oriented (OO) so it’s extremely easy to use in OO PHP codes. It can be used in the traditional way too, but its real power hides in the OO.
In the standard MySQL queries every should be escaped using mysql_real_escape_string(). This can be a tiny drawback as every single bit in a script will reduce execution time. On the other hand, MySQLi escapes every variable from a query automatically.
Did you try to connect to the MySQL server on secure connection ever? You can’t. It doesn’t support it. With MySQLi you can use secure connection to connect, this means for you increased security.

So, what’s the verdict? MySQLi or MySQL

I say, if you have time and you want to write an OO application, choose MySQLi. This if you develop new application from scratch and you have time to figure out how to use it.
To switch an existent well-designed application on the other hand I don’t recommend MySQLi. While the performance of MySQLi is way better than MySQL’s in some situations, running common queries with MySQLi will not increase your application’s performance.

How to save the images processed with Imagick as file

Scenario: You created with Imagick a cool thumbnail, and now you want to send it to a buffer other than the browser window. We already saw that it’s possible to process images on-the-fly, for example you have a 1024*768 wide image and you want to show its thumbnail version without having a thumbnail for the respective image. So what we do now is the exact opposite: we load the image in Imagick, process it, then save as a file. Probably this is the most encountered situation when processing images.

Let’s see the code, then I explain it step by step, as usual:

$im = new Imagick('/path/to/your/image.jpg');
$im->thumbnailImage( 100, null );
$fp =fopen('/path/to/the_new/thumbnail.jpg', 'w');
@fwrite($fp, $im);
@fclose($fp);

Now the explanation:

  1. st line: we loaded the image in Imagick, it’s now ready to be processed
  2. nd line: this time we create a thumbnail, store it in memory/cache: the X axis to be 100 pixels and preserve aspect ratio by setting the second parameter to ‘null’
  3. rd line: create a new file, you specify the path. The file shouldn’t exist, but all the directories Yes! W means we open the file for write
  4. th line: we write the Imagick object’s ($im) content in the open file
  5. th line: and finally, we close the file

That was all. We saved again the world.

As always, if you have questions regarding the post, drop a comment and will try to answer as soon as possible.

Filter your variables easily but like a pro!

How painful input validation is! Think about all the possible threats, combination of threats… think with the users’ mind. It’s a pain. And usually who can write scripts which filters effectively the user inputs is considered a pro, without hesitation. Just because it’s hard to do it.
Take the following scenario: you have a text-field which accepts text as user comment. You don’t want to let the user to use HTML in the comment box, and definitely not to allow the user to put javascript in the comment.
So how do you sanitize the string you get? It’s a long and hard way. You would use RegExp to exclude some entities then some php inbuilt functions to encode the remaining or even better to strip tags.
I show you an easier way:

filter_var(’<script>alert('Hello');</script>', FILTER_SANITIZE_STRING);

Done, the <script> tags will be stripped so the string will arrive in the database as alert(’Hello World’).
There are many available filters, just to mention the most interesting ones:

  • FILTER_SANITIZE_EMAIL — it sanitizes email address, strips characters which are not in conformance with the applicable RFC (link)
  • FILTER_SANITIZE_URL — whether the URL from the variable is in conformance with the applicable RFC (link)
  • FILTER_VALIDATE_IP — whether if the input is an IP address or not

I recommend using the filter_var() function and its filters for two obvious reasons: it saves you a lot of headaches and saves you time. Even though the filter_var function was introduced only in php 5.2 the function is extremely useful and gives another reason for you of why to upgrade to php5 ;)

For a complete reference please check php.net.

Additional tweaks to tighten php

Believe me or not, the resource limiting of PHP can also be an enormous security factor.
Take this scenario: Mr. John Hacker managed somehow to upload to your server a script, let’s say an IRC bot which eats up computing power and RAM. Your server became inaccessible due to the running script, who your regular users blame? You, of course, who else?
Php has some very neat settings you can tweak in order to limit its memory usage, to expose what version of php you are using or not, and others.
Let’s start from the beginning:
asp_tags and short_open_tags, whether to allow the use of asp-like tags like “<%” and short open tags like “<?” instead of “<?php”. I usually set these to off, for one reason: I usually know I set them to off thus I’m not trying to use them in the scripts, but others don’t know. If they manage to upload a script containing these tags it will be much likely useless for them as PHP won’t do anything with them.
expose_php if set to on, will append to the server signature the PHP version you are using. If you didn’t upgrade yet to the latest php, you should set it to off, else it’s up to you what you do. I like to set it off, let’s not allow others what version the server runs.
memory_limit, this is a nice one and you should tweak it to extreme. You can set how much memory would you like to allocate for PHP. If your scripts are not memory eaters, this should be a low value, if they are, a higher value. You can also disable the directive by setting a value of -1, but be aware that with -1, PHP can use as much memory as it wants. I learned that the golden middle is 32, try first that value and if everything is running well, leave at that value.
register_globals, the black sheep :|. Whether to register the $_ENV, $_GET, $_POST, $_SERVER and $_COOKIE variables as global variables. This is covered in too much articles already, i won’t explain why to set it OFF. If you rely on it, stop doing so, learn how to not rely on it or give up coding, period.
file_uploads and upload_max_filesize, whether to allow or not file uploads, and if you allow, what’s the maximum filesize you would like to accept via the HTTP request. The file upload is pretty useless to have it enabled if you don’t use file upload scripts, so if you are not using disable it. Why let Mr. John Hacker to put file-upload scripts on your server?

And these were all the settings I wanted to cover in this post. Consider using them, think carefully before allowing something and before setting something, always.
Here are the settings I recommend:

asp_tags = Off
short_open_tags = Off
expose_php = Off
memory_limit = 32M
register_globals = Off
file_uploads = Off
upload_max_filesize = 2M

Again, much likely others would do it in another way, that’s my way, feel free to use it or not :)

Create thumbnails on-the-fly using Imagick

OK, this will be simple. I said it’s simple, more simpler than anyone can expect. Let’s see the overcomplicated code:

<?php
$im = new Imagick( 'path/to/your/image.jpg' );
$im->thumbnailImage( 200, null );
header( "Content-Type: image/jpg" );
echo $im;
?>

That was all. Yup.
OK, now step by step:

  1. We instruct Imagick to work with the file from the parameter.
  2. Ask nicely Imagick to create a thumbnail: width should be 200px and no fixed height. That’s good, cos Imagick will automatically preserve the aspect ratio, so, bye-bye ugly thumbnails
  3. Set the correct Content-type header
  4. echo() the Imagick object which contains the image data, namely $im

That’s all. We saved the world again…

If something is not clear, the comments are open, just ask and will try to answer as soon as possible.

Watermarking images using Imagick

This is a perfect day to show all how easy is to use php’s imagick library to watermark an image.
What you need is to have imagick installed and working correctly, a font you will use to write your website’s name on the image and of course an image you will put the text on.

I will explain each step but for those who don’t want to read, here’s the script:

<?php
$img	= 'path/to/your/image.jpg';
$text	= 'devoracles.com';
$font	= 'path/to/your/yourfont.ttf'
$font_size	= '20';
$watermark	= array();
$image = new Imagick($img);
$image->setImageFormat("jpg");
$draw = new ImagickDraw();
$draw->setGravity(Imagick::GRAVITY_CENTER);
$draw->setFont($font);
$draw->setFontSize($font_size);
$textColor = new ImagickPixel("black");
$draw->setFillColor($textColor);
$im = new imagick();
$properties = $im->queryFontMetrics($draw,$text);
$watermark['w'] = intval($properties["textWidth"] + 5);
$watermark['h'] = intval($properties["textHeight"] + 5);
$im->newImage($watermark['w'],$watermark['h'],new ImagickPixel("transparent"));
$im->setImageFormat("jpg");
$im->annotateImage($draw, 0, 0, 0, $text);
$watermark = $im->clone();
$watermark->setImageBackgroundColor($textColor);
$watermark->shadowImage(80, 2, 2, 2);
$watermark->compositeImage($im, Imagick::COMPOSITE_OVER, 0, 0);
$image->compositeImage($watermark, Imagick::COMPOSITE_OVER, 0, 0);
header("Content-Type: image/jpg");
echo $image;
?>

And the result is:

Watermark with Imagick

Watermark with Imagick


That was all, now a bit of explanation for almost all the lines. The first steps, as you see was to set up some variables which will be used in the script, I think the variable names talk for themselves so I don’t have to explain them. Do I?
Next, I instructed imagick to read the image which will be worked with and specified the type of the image, in the above case a “jpg”.

$image = new Imagick($img);
$image->setImageFormat("jpg");

By the way, if you want to write a script you will pass through all your images, thus all the images are watermarked, first assure that the image you work with is from your server, read, no one can use your script to watermark images on another server. The second thing, you can get the image’s extension using mime_content_type(’path/to/your/image.jpg’). Not the best method I admit, but it’s simple and effective.
Let’s proceed further. I fired up a new class, ImagickDraw(), this will let Imagick know what font to use and also the text’s properties like font size, font color, etc. “Imagick::GRAVITY_CENTER” basically means to center the text on it’s, say, layer. You can play with it and try to set other parameters too, like “Imagick::GRAVITY_SOUTH” which means to place the text on the bottom of the layer, “Imagick::GRAVITY_WEST” to put it on the left side, you get the point.

$draw = new ImagickDraw();
$draw->setGravity(Imagick::GRAVITY_CENTER);
$draw->setFont($font);
$draw->setFontSize($f_size);
$textColor = new ImagickPixel("black");
$draw->setFillColor($textColor);

We get then the parameters of the text we want to put on the image and we add an additional 5 pixels to it, both horizontal and vertical axis. The 5 pixels will be needed later to have place for the drop-down shadow of the text. Then we simply create the canvas and with annotateImage() we put the text on the image.

$im = new imagick();
$properties = $im->queryFontMetrics($draw,$text);
$watermark['w'] = intval($properties["textWidth"] + 5);
$watermark['h'] = intval($properties["textHeight"] + 5);
$im->newImage($watermark['w'],$watermark['h'],new ImagickPixel(”transparent”));
$im->setImageFormat(”jpg”);
$im->annotateImage($draw, 0, 0, 0, $text);

OK, now let’s play a bit with the shadow. First we clone the $im object, which is basically the text we’ll put on the image. The color of the image will be the same as the text’s. And now the interesting stuff: shadowImage(). This will create the drop-down shadow and the parameters tells Imagick how to create that shadow. The usage is:

shadowImage ( float $opacity , float $sigma , int $x , int $y )

So the first parameter sets how opaque the shadow has to be, the last two sets where to drop that shadow. Don’t ask me the second what does, i have no idea :D
OK, lastly let’s put our shadow on the image with compositeImage().

$watermark = $im->clone();
$watermark->setImageBackgroundColor($textColor);
$watermark->shadowImage(80, 2, 2, 2);
$watermark->compositeImage($im, Imagick::COMPOSITE_OVER, 0, 0);

The last steps are to put the watermark on the image, set the correct content-type header image/jpg in our case and echo the data. Why do we have to set the content-type header? Well, if I’m not mistaken, this is a php script and the browsers, if not overridden expects text/html, which in our case is not good at all.

$image->compositeImage($watermark, Imagick::COMPOSITE_OVER, 0, 0);
header("Content-Type: image/jpg");
echo $image;

That’s all. It was a bit complicated, but I’d rate its difficulty as ‘medium’ but it’s extremely useful in many cases. This is not JavaScript, so the watermark will be in place whatever the user does. If you are at least a bit familiar with object oriented PHP, I say give it a go and try it.

If something is not clear, the comments are open, just ask and will try to answer as soon as possible.

Migrating from php4 to php5? Pros and cons

You think it’s hard? You think you will brake codes?
Why? Probably cos everyone told you so. I tell you something else: You have nothing to fear of.

Maybe the title is a bit unrelated to the post as I can’t seem to find a valid and justified con against it.
Anyway, some thing you should know: PHP 5 was released cos it contains dozens of fixes, upgrades. It wasn’t released cos the team which manages the project had a godly touch or they were drunk and when they woke up all they knew was they have to release a new PHP. No. There was a very good reason, and just for the matter of the argument, when something is free anyway, why wouldn’t you upgrade to a better, improved version? Huh?

The guy who I work with day-by-day, and probably my best friend as well, will say “don’t fix what is not broken”. I say, if something contains bugs, isn’t that thing broken?

So, as I said, you have nothing to fear of, much likely your code will work on the new platform as well, sincerely, when I upgraded to PHP 5 none of my scripts stopped working and there are a few hundred of separate scripts, but just to be sure, let’s check some things.

First of all, i don’t know if you know or not, there are some reserved words you can’t define in your scripts as variables or constants. That’s clear I guess, the “why don’t” has a simple answer… well, two: the first is, cos this is what the developers of PHP said, secondly cos why would you want to define a constant which was previously defined in the PHP core as a function. For example, “echo”, would you redefine it as a constant? I hope you wouldn’t. Also, the same applies to reserved words like “FALSE”, “TRUE”, “NULL”, etc. as these are reserved constants. Have a look on php.net on the reserved keywords list, well, table (link). Also, someone asked me of why “parent” and “self” throws errors when using them in scripts as (re)defined constants. Well, they are inbuilt classes, simple.
Another major change is that array_merge() accepts only arrays. This should be obvious anyway but as of PHP5 it returns NULL. There are some other changes as well, php.net has a more comprehensive list here (link).

And probably that was all you feared of. Really. :)