PHP IP To Location

1 March, 2010 | PHP | No comments

Converting an IP address into some useful location information can be useful if you want to find out where sites are hosted or customise content to users depending on their location.

All this code is freely available over at github.

There are several ways to do this, all of which have their advantages and disadvantages, but sticking with one can cause rewriting a lot of code in the future. So rather than pick one and stick with it I decided to use dependency injection to allow different classes to be used that convert IP addresses to locations in different ways. The first task is to create an abstract class that will be used to construct the rest of the IP location classes. Each class that extends this abstract class will contain a method called getIpLocation() that will convert an IP address into a location, and a method that will update the data source for the location lookup. Rather than lump all of the classes into a single directory I have created a directory called Service, into which all of the different classes that lookup IP addresses will be kept.

Read more »

Written by Philip Norton.

parse_url Warning Bug In Wordpress 2.9.2

23 February, 2010 | Wordpress | 2 comments

Whilst setting up a new Wordpress install for a site development I found an odd little issue that would only occur in certain circumstances. My current development platform consists of an Apache server on which I create a virtual host for every development site I need. However, rather than setting a DNS entry for each address I just listen to diferent ports. In this particular instance I used the port 59419.

When the install was complete I was presented with the following error at the top of every admin page.

Warning: parse_url(http://10.0.0.1:594191?ver=20091217) [function.parse-url]: Unable to parse URL in \www\wp-includes\script-loader.php on line 542

For some reason Wordpress was adding a "1" to the end of the port number, which was causing the URL to throw a warning message when calling parse_url() as the port number can't be higher than about 65535 (depending on the system). This normally wouldn't cause an issue on most setups, but in this case it increased the port number just high enough to throw this error.

Although the warning is issued on line 542 of wp-includes\script-loader.php, I actually tracked the offending code down to line 438 in the same file. Here it is, along with the comment above it:

// Register "meta" stylesheet for admin colors. All colors-* style sheets should have the same version string. $styles->add( 'colors', true, array(), $colors_version );

The true value is normally a CSS filename, but this one is needed to set some initial conditions for the rest of the admin styles. So when this is appended to the base path it is converted to 1, which is what normally happens when you echo a true boolean value in PHP. To solve this issue I just replaced this true value with a string consisting of a slash.

$styles->add( 'colors', '/', array(), $colors_version );

This has no effect on the functionality of this code. Removing this line completely will cause the admin area to lose all colours and images.

Although this is a very minor bug, it must have caused an issue on someone's system at some point in the past. So I put this fix here in case anyone else has had the same issue.

Written by Philip Norton.

Selectively Turn Off Drupal Caching

19 February, 2010 | Drupal | No comments

It is sometimes necessary to turn off caching on certain pages on a Drupal site. This might be when trying to do something out of the ordinary, like write information to a file, or randomly generate a section of a template. The following code can be used to turn off caching just on the front page of the site.

function theme_preprocess(&$vars, $hook) {     if ($vars['is_front'] == true) {         $GLOBALS['conf']['cache'] = false;     } }

Adding false to the cache item of the conf globals array at run time will turn off the cache. This is within an if statement that checks to see if the current page is the Drupal front page so it will only be used on the front page.

This is a pretty simple solution, but it should be used with great care. Remember that you are turning off the cache and this will definitely have an effect on the performance of the site. Be sure of what you are doing when you turn off the cache!

Written by Philip Norton.

Using JQuery To Open External Links In A New Window

19 February, 2010 | JQuery | No comments

Opening external links in a new window can be useful, but adding target="_blank" can be a real chore. Not only that, but if you are trying to validate the page to XHTML strict then the target attribute will cause errors to appear as it is not defined in XHTML.

An easy solution to this issue is to add the following JQuery to your site. It will look for any links that start with http and do not contain the current domain and add a new click event to them that causes a new window to be opened. This will exclude most links straight away as they will most likely be relative.

$("a[href^='http']:not([href*='example.com'])").click(function(){  window.open(this.href);  return false; }).attr("title", "Opens in a new window");

This code will also add a new title to each link, replacing any that already exist, just remove the call to attr() at the end of the block to stop this. If you are using this on your site then make sure you put this into a dom ready block, and also that you change the example.com to be your own domain name.

Written by Philip Norton.

Using Authentication And file_get_contents()

15 February, 2010 | PHP | 5 comments

Using file_get_contents() to fetch the contents of a file is quite a common practice. This might be just to get the contents of a text file or to get the ImageCache module in Drupal to pre-cache images. The file_get_contents() function can get a local or remote file and is usually run like this.

$data = file_get_contents($url);

However, when trying to use this function to communicate with an authenticated server you will see the following error appearing.

Warning: file_get_contents(http://www.example.com/test.php): failed to open stream: HTTP request failed! HTTP/1.1 401 Authorization Required in test.php on line 4

To get around this issue you will need to pass a third parameter to the file_get_contents() function that causes the function to use a context. This context will pass an additional Authorization header to the server and is created through a function called stream_context_create(). Here is all the code you need to use file_get_contents() in an authenticated manner.

$username = 'username'; $password = 'password';   $context = stream_context_create(array(     'http' => array(         'header'  => "Authorization: Basic " . base64_encode("$username:$password")     ) )); $data = file_get_contents($url, false, $context);

The second parameter is for the addition of a flag and is skipped here by using a null value, but false is also applicable. For more information about what flags are available see the file_get_contents() page on the PHP manual.

Written by Philip Norton.