Category: Coding

Generate a random public IP address in PHP

The requirements

Valid IP addresses are in the form xxx.xxx.xxx.xxx, where xxx is a number from 0-255. RFC 1918 specfies that the 10.0.0.0-10.255.255.255, 172.16.0.0-172.31.255.255 and 192.168.0.0-192.168.255.255 address ranges are restricted for use in private internets only.

I needed a PHP function that would generate a random IP address excluding the IP ranges restricted by RFC 1918. The following is what I came up with.

The code

For the sake of clarity, the code is more verbose then necessary. Remove line breaks and add ternary operators to your liking for production.

/**
 * Returns a random valid public IP address. For the definition of a 
 * public IP address see http://www.faqs.org/rfcs/rfc1918.html
 * @return string The IP address
 */
function random_valid_public_ip() {
  // Generate a random IP
  $ip =
      mt_rand(0, 255) . '.' .
      mt_rand(0, 255) . '.' .
      mt_rand(0, 255) . '.' .
      mt_rand(0, 255);

  // Return the IP if it is a valid IP, generate another IP if not
  if (
      !ip_in_range($ip, '10.0.0.0', '10.255.255.255') &&
      !ip_in_range($ip, '172.16.0.0', '172.31.255.255') &&
      !ip_in_range($ip, '192.168.0.0', '192.168.255.255')
  ) {
    return $ip;
  } else {
    return random_valid_public_ip();
  }
}

/**
 * Returns true if the IP address supplied is within the range from 
 * $start to $end inclusive
 * @param string $ip The IP address to be checked
 * @param string $start The start IP address
 * @param string $end The end IP address
 * @return boolean 
 */
function ip_in_range($ip, $start, $end) {
  // Split the IP addresses into their component octets
  $i = explode('.', $ip);
  $s = explode('.', $start);
  $e = explode('.', $end);

  // Return false if the IP is in the restricted range
  return in_array($i[0], range($s[0], $e[0])) &&
      in_array($i[1], range($s[1], $e[1])) &&
      in_array($i[2], range($s[2], $e[2])) &&
      in_array($i[3], range($s[3], $e[3]));
}

Tweaking .htaccess for website performance on DreamHost

Add expires headers

# Add Proper MIME-Type for Favicon
AddType image/x-icon .ico

# Expires headers
ExpiresActive on
# Set default to 3 days
ExpiresDefault A259200
# Set static content to 2 weeks
<FilesMatch "\.(gif|jpe?g|png|css|js|ico)$">
ExpiresDefault "access plus 2 weeks"
</FilesMatch>

Turn off Etags

# Turn of Etags
Header unset ETag
FileETag None

Enable Gzip

# Enable Gzip
<IfModule mod_deflate.c>
AddOutputFilterByType DEFLATE text/text text/html text/plain text/xml text/css application/x-javascript application/javascript
</IfModule>

Installing PHP and PHPUnit on Windows 7

Download PHP

Windows downloads of PHP are available here. If you are not sure of which version to get, check out this Stack Overflow page. I used the VC9 thread safe PHP 5.3.10 download.

Install PHP

Once you’ve downloaded the installer, run it and install PHP in C:\php\ (or wherever you like, only remember this path for later). Choose your webserver (or none if you don’t have a webserver installed) and select any additional components as needed, including PEAR.

Once PHP is installed open a command prompt. Check that PHP is set up correctly by running
php -v

It should give you output something like
PHP 5.3.10 (cli) (built: Feb 2 2012 20:27:51)
Copyright (c) 1997-2012 The PHP Group
Zend Engine v2.3.0, Copyright (c) 1998-2012 Zend Technologies

If you don’t get this output something has gone wrong with the PHP install or in the modification of your environment variables. Get this fixed before proceeding with the guide.

Install PEAR

In the command prompt, switch to the directory that you installed PHP to by running
cd C:\php\

Then install PEAR by running
go-pear

Press Enter to accept the default when it asks you “Are you installing a system-wide PEAR or a local copy?”
Press Enter again to accept the file layout.
Press Enter to finish.

Install PHPUnit

Run the following commands (they may take a while to update, be patient):
pear channel-update pear.php.net
pear upgrade-all
pear channel-discover pear.phpunit.de
pear channel-discover components.ez.no
pear channel-discover pear.symfony-project.com
pear update-channels

To install PHPUnit, run
pear install --alldeps --force phpunit/PHPUnit

To test that PHPUnit was successfully installed, run
phpunit -v

If all is fine, it should print out something like PHPUnit 3.6.10 by Sebastian Bergmann followed by the help contents.

Problems?

If you get a problem with PEAR refusing to install the dependencies for PHPUnit, try running this command: pear clear-cache. If the underlying problem is this error SECURITY ERROR: Will not write to C:\php\...rest.cacheid as it is symlinked to C:\php\...rest.cacheid - Possible symlink attack then clearing the cache should fix it.

If you get stuck with no helpful error messages while installing PHPUnit, check the PHP error log. To locate it, open your php.ini file (c:\php\php.ini) and look for a line like error_log="C:\Windows\temp\php-errors.log". Open the log file at the location specified and look at the bottom of the log for any recent errors. Copy the error message and Google for solutions.

HTML Purifier

The problem

I want to allow users to input HTML-formatted text, but I only want them to use certain tags and never any JavaScript. Sometimes users will copy and paste WYSIWYG formatted HTML, with it’s associated CSS classes and inline style rules – but I don’t want that to mess up my site design.

A simplistic approach is to attempt to use regular expressions to filter out unwanted HTML tags, but this becomes tedious and is always fraught with risk because it is notoriously difficult to anticipate and catch all the possible permutations of HTML tags and their attributes.

A more successful approach is to use a psuedo markup language like bbCode or WikiText, but both of these require users to learn another markup language, which is likely to deter users from posting.

Is there a better alternative?

Yes there is! HTML Purifier is a standards-compliant HTML filter library written in PHP. HTML Purifier will not only remove all malicious code (better known as XSS) with a thoroughly audited, secure yet permissive whitelist, it will also make sure your documents are standards compliant, something only achievable with a comprehensive knowledge of W3C’s specifications.

HTML Purifier works by decomposing the whole document into tokens and removing non-whitelisted elements, checking the well-formedness and nesting of tags, and validating all attributes according to their RFCs.

Why HTML Purifier

I’ve used HTML Purifier because it

  • uses a whitelist (e.g. allow only b, p, br, ul, ol and li tags)
  • outputs valid XHTML
  • protects againts XSS
  • can remove attibutes and classes from tags without removing the tags

Before and after

An example of HTML that a user may enter:

<P style="MARGIN: 0cm 0cm 0pt; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto" class=MsoNormal><st1:Lorem w:st="on"><st1:place w:st="on"><B>LOREM IPSUM</B></st1:place></st1:Lorem><B>LOREM IPSUM</B></P>
<P style="MARGIN: 0cm 0cm 0pt; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto" class=MsoNormal><st1:place w:st="on"><st1:PlaceName w:st="on">Lorem</st1:PlaceName> <st1:PlaceType w:st="on">Ipsum</st1:PlaceType></st1:place>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque at augue vitae nisl sodales interdum. <st1:City w:st="on"><st1:place w:st="on">Lorem </st1:place></st1:City> Pellentesque erat enim, ullamcorper eget vehicula feugiat, auctor non nunc. Quisque vel molestie eros. Cras erat nulla, faucibus eget pretium at, cursus eu enim. <st1:place w:st="on"><st1:PlaceType w:st="on">lorem</st1:PlaceType> <st1:PlaceType w:st="on">Ipsum</st1:PlaceType></st1:place> Integer et eros lorem, eget pharetra justo. Maecenas accumsan eleifend leo, a ullamcorper justo venenatis ut. Vestibulum bibendum diam vel turpis lobortis bibendum.</P>
<P style="MARGIN: 0cm 0cm 0pt; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto" class=MsoNormal><B>Lorem / Ipsum</B> </P>

After it has been passed through the filter:

<p><b>LOREM IPSUM</b><b>LOREM IPSUM</b></p>
<p>Lorem Ipsum Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque at augue vitae nisl sodales interdum. Lorem Pellentesque erat enim, ullamcorper eget vehicula feugiat, auctor non nunc. Quisque vel molestie eros. Cras erat nulla, faucibus eget pretium at, cursus eu enim. lorem Ipsum Integer et eros lorem, eget pharetra justo. Maecenas accumsan eleifend leo, a ullamcorper justo venenatis ut. Vestibulum bibendum diam vel turpis lobortis bibendum.</P>
<p><b>Lorem / Ipsum</b></p>

This is the code used to achieve the before/after example:

require_once '/path_to/HTMLPurifier/HTMLPurifier.auto.php';
$config = HTMLPurifier_Config::createDefault();
$config->set('HTML.AllowedElements', 'b,i,p,br,ul,ol,li');
$config->set('Attr.AllowedClasses', '');
$config->set('HTML.AllowedAttributes', '');
$config->set('AutoFormat.RemoveEmpty', true);
$purifier = new HTMLPurifier($config);

$remarks = 'the text to be filtered';
$remarks = preg_replace('/<\?xml[^>]+\/>/im', '', $remarks);
$remarks_cleaned = $purifier->purify($remarks);

The only other line of code here doing work apart from the HTML Purifier is the regex to remove <?xml ... ?> namespace tags from MS Word.