Reading Exif data with PHP

Within most photos from digital cameras besides the actual image, there’s a little ”information block” call EXIF data. If you have the correct PHP extension installed on your server – the one called ”exif” – it’s pretty easy to read the EXIF data and display them, as you like.

First, let’s check if the extension is available?

1
2
3
4
5
6
$load_ext = get_loaded_extensions();
if (!in_array(exif, $load_ext)) {
echo "Exif is NOT available";
} else {
echo "Exif extension is available.";
};

If you have the extension available, reading the data is a simple matter:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
$nikonFile   = './aarhus_demo_photo.jpg';
$exifNikon   = getExifData($nikonFile);
 
$olympusFile = './zanzibar_demo_photo.jpg';
$exifOlympus = getExifData($olympusFile);
 
echo "<h2>Olympus EXIF data</h2>";
echo "<pre>";
print_r($exifOlympus);
echo "</pre>";
 
echo "<h2>Nikon EXIF data</h2>";
echo "<pre>";
print_r($exifNikon);
echo "</pre>";
 
function getExifData($file) {
$exif = exif_read_data($file, 0, true);
return $exif;
}

As you may notice, there’s a photo from an Olympus camera and a Nikon camera as an example. The data available from each photo isn’t quite the same. Most generic fields are available, but some fields are camera specific (or maker specific).

See the example above in action (source). The two images are from Aarhus (Nikon) and Zanzibar (Olympus). You can read more on EXIF in Wikipedia.

Simple benchmarks in PHP

If you’re doing some basic profiling of your PHP scripts, the build-in microtime function can help you make some simple benchmarking fast. Here’s a rough example to show you how it could be used. The doSomething function is the function we want to benchmark.

1
2
3
4
5
6
7
8
9
10
11
12
13
$time = microtime();
$time = explode(' ', $time);
$time = $time[1] + $time[0];
$start = $time;
 
doSomething();
 
$time = microtime();
$time = explode(' ', $time);
$time = $time[1] + $time[0];
$finish = $time;
$total_time = round(($finish - $start), 6);
if ($debug) print ("<p>Processing took approximately $total_time seconds</p>");

The above example is pretty rough. If you want to see a slightly more complete benchmark example, I do have it available (with source too).

Create a random password with PHP

Some websites require access control, and sometimes you may need to generate a password for a user. Here’s a simple function that can do just that.

The $base-variable contains the characters allowed in the password. The supplied string may be changed, but the selected charaters should exist on all keyboards (as far as I know). When calling the function, you can specify the lenght of the password you want. Simple, right?

1
2
3
4
5
6
7
8
9
10
function makePassword($desiredLenght = 8) {
$password = '';
$base = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
 
for($i=0;$i<$desiredLenght;$i++) {
$password .= $base[(rand(0, (strlen($base)-1)))];
}
 
return $password;
}

Cracking the Cryptex with PHP

In the book “the Davinci Code” there was a fun little device called a cryptex.. A Cryptex has 6 dials with 6  letters on each, and only one combination producing a word will open it. The most straight forward way to crack it would be to try every combination one by one, but there’s a substantial number of combinations and we know only those which a valid words is a candidate.

With PHP, a few nested loops and the aspell interface available, cracking the code is simple matter:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
$pspell_link = pspell_new("da"); // Bring in the dictionarry
 
$array1 = Array("K", "M", "A", "D", "T", "J");  // First dial
$array2 = Array("B", "H", "R", "W", "Y", "E");
$array3 = Array("S","O","L","F","V","C");
$array4 = Array("X","T","N","U","Z","P");
$array5 = Array("E","D","Z","T","G","I");
$array6 = Array("N","G","L","D","Q","K");
 
foreach ($array1 as $a1) {
foreach ($array2 as $a2) {
foreach ($array3 as $a3) {
foreach ($array4 as $a4) {
foreach ($array5 as $a5) {
foreach ($array6 as $a6) {
$word = $a1 . $a2 . $a3 . $a4 . $a5 . $a6;
if (pspell_check($pspell_link,$word)) { // is the word in the dictionary?
echo $word;
echo "<br>";
}
}
}
}
}
}
}
 
exit();

This script prints out a list of all valid (Danish) words, that can occur with the given combination of letters.

A binary clock in PHP

There are some odd functions hidden in PHP. One of them is the decbin function, which makes it easy to convert between decimal and binary numbers.

If you’re bore don a rain day, you could use this function to make a simple binary clock, here’s a few lines to get you started:

echo "Hours: ".decbin(date("H"))."<br>";
echo " Minutes:".decbin(date("i"))."<br>";
echo " Seconds:".decbin(date("s"));

See the binary clock output (and the source of the page).

Checking requirements for PHP Applications

A great strength in PHP is that it’s so accessible, that almost anyone can get access to a PHP site and often will download “applications” for their site such as discussion boards, photo galleries and others. While it may easy to download such applications, it often happens that the people trying to get things to work, doesn’t read the requirements section of the install.txt
or readme.txt file, and thus never get the application running and doesn’t understand what the problem was and how to fix it. This is a brief guide with some tips on how to improve usability in this area.

First things first

Instead of relying on the user to read and check all steps in a text file, you should provide the install/setup file as a PHP-file, which is called through the browser. By doing this, you put the user in a familiar environment, and enables you to use all the power of PHP to guide the user through the requirements and install procedure. Assuming you think that’s a
bright idea, let see what you can do in such a setup-file.

Checking for the correct PHP version

First, if your Application requires a certain version of PHP, you should check if it’s available.

  • There’s a php function called phpversion() which will return a string with the current version number as a string.
  • PHP has a constant defined called PHP_VERSION. It contains the same string as the phpversion function returns.

If your application requires a certain version of PHP, there’s also a function called version_compare(),
which can help you check for a specific php-version or at least a certain version (ie. 4.4.0 or newer).

You use the function like this:

1
2
3
4
5
if (version_compare(php_version(), "4.4.0", "&gt;=")) {
// you're on 4.4.0 or later
} else {
// you're not
}

Checking for available extensions (compiled into PHP)

There’s function called get_loaded_extensions. It returns all the extensions compiled into PHP,
and if you need a certain extension, you can use this, to see if it’s available.

1
2
3
4
5
6
7
$load_ext = get_loaded_extensions();
 
if (in_array("soap", $load_ext)) {
echo "SOAP is available";
} else {
echo "SOAP is NOT available";
}

The extensions also have different version numbers, and if you need a certain version number to get your application to work, we can use the phpversion function from above to do this. The function can take an extension name as parameter, and will return not the PHP version, but the version of the extension instead:

1
2
3
4
5
$load_ext = get_loaded_extensions();
 
if (in_array("soap", $load_ext)) {
echo "soap extension available in version: " . phpverion("soap") . "&lt;br&gt;n";
}

If you do need a specific (or “at least”) version of the extension, you should do the check as in the above example, where at least a certain PHP version was required.

Checking for Zend Platform

If you’re running with Zend Platform enabled, it adds some extra features, which might be neat to use (if available) such as caching or error reporting. Since most PHP environments doesn’t have Zend available, we should check for the availablility before using the functions. One way of doing this is by using the “function_exists” function in PHP. It returns a boolean (true/false) answer.

1
2
3
if (function_exists("monitor_custom_event")) {
monitor_custom_event(........)
}

(the monitor_custom_event()-function is specific to Zend Platform – if available, we can use it.)

Checking for include files availablity

Some libraries are not compiled into PHP but written as PHP scripts themselves. Examples include MagpieRSS, CakePHP, Zend Framework and others. Checking if they are avaible without causing PHP to throw an error or at least warning message is a little tricky.

Here’s one way to do it. Turn off all error reporting, try to include the file, turn on error reporting and then check the list of included files to see if it was included:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$fileToInclude = 'SomeFile.inc';$initial_setting = error_reporting(0);
include($fileToInclude);
error_reporting($initial_setting);
$files = get_included_files();
$available = false;
$pattern = "/" . $fileToInclude . "$/";
 
foreach ($files as $file) {
if (preg_match($pattern, $file)) { $available = true; };
echo "$file n";
}
 
echo "The file \"$fileToInclude\" is ";
if (!$available) { echo "not "; };
echo "available";

Do be careful before applying this technique. First you should always be very careful
before toying with the error reporting (you don’t fix errors by turning off error reporting),
and second, while this technique works, it’s not lightweight, so it should only be used in
setup and configuration scripts.

Wrapping it up

Using PHP itself, to check if the requirements posed by your application are satisfied,
should be quite easy. Often however PHP applications seem to rely too much on text files to provide important information. In PHP all the tools and handles you need to check the requirements are available, and with HTML-producing PHP, you can easily provide links and guidance t the user, to help them get any missing pieces, to successfully install you application; so do that please.

Cracking Cryptex of the DaVinci code with PHP

In the book “the Davinci Code” there was a fun little device called a cryptex.. A Cryptex has 6 dials with 6 letters on each, and only one combination producing a word will open it. The most straight forward way to crack it would be to try every combination one by one, but there’s a substantial number of combinations and we know only those which a valid words is a candidate.

With PHP, a few nested loops and the aspell interface available, cracking the code is simple matter:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
$pspell_link = pspell_new("da"); // Bring in the dictionarry
 
$array1 = Array("K", "M", "A", "D", "T", "J");  // First dial
$array2 = Array("B", "H", "R", "W", "Y", "E");
$array3 = Array("S","O","L","F","V","C");
$array4 = Array("X","T","N","U","Z","P");
$array5 = Array("E","D","Z","T","G","I");
$array6 = Array("N","G","L","D","Q","K");
 
foreach ($array1 as $a1) {
	foreach ($array2 as $a2) {
		foreach ($array3 as $a3) {
			foreach ($array4 as $a4) {
				foreach ($array5 as $a5) {
					foreach ($array6 as $a6) {
						$word = $a1 . $a2 . $a3 . $a4 . $a5 . $a6;
						if (pspell_check($pspell_link,$word)) { // is the word in the dictionary?
							echo $word;
							echo "<br />";
						}
					}
				}
			}
		}
	}
}
 
exit();

This script prints out a list of all valid (Danish) words, that can occur with the given combination of letters.

Zend Framework – Ready or not?

We are a fairly large PHP shop at work running some of the largest Danish websites. In a fairly new project, it was suggested that we considered using the Zend Framework to fast track development and piggy back upon some of the components provided by the framework. We looked at it, and said no – at least for now.
Continue reading Zend Framework – Ready or not?