Detecting if an IP address is in a certain range in PHP

First published on the Cu.be blog : link

If you ever need to detect whether an IP address (letโ€™s say 192.168.0.2) is inside a certain IP range/subnet (letโ€™s say 192.168.0.0/24), you can use the following code in PHP :

/**
 * Check IPv4 address is within a range
 *
 * @param string $ip A valid IPv4 address (xxx.xxx.xxx.xxx)
 * @param string $subnet A valid IPv4 subnet (xxx.xxx.xxx.xxx)
 * @param string $mask A valid IPv4 subnet mask (a number from 0-32)
 * @return boolean True if the address is within the range, false if it isn't
 */
function ip4_in_network($ip, $subnet, $mask)
{
    if ($mask <= 0) {
        return false;
    }
    $ip_bin_string = sprintf("%032b", ip2long($ip));
    $net_bin_string = sprintf("%032b", ip2long($subnet));
    return (substr_compare($ip_bin_string, $net_bin_string, 0, $mask) === 0);
}


For IPv6, the code is slightly more complicated:

/**
 * Check IPv6 address is within a range
 *
 * @param string $ip A valid IPv6 address
 * @param string $subnet A valid IPv6 subnet
 * @param string $mask A valid IPv6 subnet mask (a number from 0-128)
 * @return boolean True if the address is within the range, false if it isn't
 */
function ip6_in_network($ip, $subnet, $mask)
{
    $subnet = inet_pton($subnet);
    $ip = inet_pton($ip);

    // thanks to MW on http://stackoverflow.com/questions/7951061/matching-ipv6-address-to-a-cidr-subnet
    $binMask = str_repeat("f", $mask / 4);
    switch ($mask % 4) {
        case 0:
            break;
        case 1:
            $binMask .= "8";
            break;
        case 2:
            $binMask .= "c";
            break;
        case 3:
            $binMask .= "e";
            break;
    }
    $binMask = str_pad($binMask, 32, '0');
    $binMask = pack("H*", $binMask);

    return ($ip & $binMask) == $subnet;
}

PHPCompatibility is ready for PHP 7.0

It took a while to get it finished, but I finally managed to finish writing the changes for PHPCompatibility to include PHP 7.0 support.

Thanks to financial support from the cool people at WPEngine, the complete set of sniffs for PHP 7.0 is now available on Github through the usual link.

As always, tests include both forward and backward compatibility. It is advisable to run PHPCompatibility on PHP 7.0, as some sniffs can not be run on older versions. You can use the ‘–runtime-set testVersion 5.x’ parameter (replacing the x with the number of your chosing) to test your code for older versions.

The sniff includes support for all of these changes :

  • Deprecated functionality :
    • PHP4 style constructors
    • password_hash salt option
  • Older version check (using –runtime-set testVersion)
    • scalar type declaration
    • return type declaration
    • null coalescing operator
    • spaceship operator
    • constant arrays in define
    • anonymous classes
    • unserialize filter variable
    • IntlChar class
    • Group use declaration
    • intdiv function
    • session_start options
    • preg_replace_callback_array function
    • random_bytes and random_int functions
  • Backward incompatibilities
    • Empty list assignments
    • global keyword with variable variables no longer allowed
    • Function parenthesis warning
    • Negative bitshifts
    • Removed functions call_user_method, call_user_method_array, mcrypt_generic_end, mcrypt_ecb(), mcrypt_cbc, mcrypt_cfb, mcrypt_ofb, datefmt_set_timezone_id, IntlDateFormatter::setTimeZoneID, set_magic_quotes_runtime, magic_quotes_runtime, set_socket_blocking, imagepsbbox, imagepsencodefont, imagepsextendfont, imagepsfreefont, imagepsloadfont, imagepsslantfont, imagepstext
    • Removed INI directives always_populate_raw_post_data, asp_tags and xsl.security_prefs
    • New objects assigned by reference removed
    • New reserved keywords bool, int, float, string, NULL, TRUE, FALSE, resource, object, mixed and numeric
    • Functions with multiple parameters with same name not allowed
    • Switch statements with multiple defaults not allowed
    • $HTTP_RAW_POST_DATA removed
    • mktime and gmmktime no longer support is_dst parameter
    • preg_replace no longer supports \e
  • Several new built-in functions, classes, interfaces and exceptions
  • Many new global constants
  • Many removed extensions
  • Loosening reserved word restrictions (in some places)

A happy 20 years !

In honor of the 20th anniversary of PHP, I thought I’d write a short story about my years in PHP.

I discovered PHP in 1997 after I started experimenting with Linux and we started a university team of the Distributed.net RC5 challenge. We had a so-called personal key proxy running and wanted to generate some personal statistics. I decided to learn this relatively new language called PHP, which was at version 2.0FI at the time, which served to create some basic stats. Afterwards we used the Perl-based PPStats, but I soon found it too slow and too messy to deal with, so I rewrote it in PHP.

GNet
My first major PHP adventure was a personal project called GNet, a search engine submission system (back in the days when most search engines didn’t crawl the web and if they did, they did so slowly and inefficiently). The system I built was both web-based as well as Windows-based. The web-based version was built in PHP 3.0, the Windows version was not a standalone system, but rather plugged into the web-based version to fetch the latest engine list, parameter lists, etc using some custom API (well there were no ‘standard’ APIs at the time anyway). This was an actual client-server based application with PHP running on the server side, back in 1999 ๐Ÿ™‚

phpAds(New) / OpenX
The end of the 90s was also the boom of the online advertising industry. And having a system like GNet meant I could actually show some ads and try to make a little money. There was a system called phpAds, written by Tobias Ratschiller. After version 1.4 arrived, Tobias seemed to have vanished and although I had created a number of bug fixes, nobody was able to put them into the official phpAds project, which was being run from Tobias’ website.
So I merged all the existing patches with mine, added some functionality, and released phpAdsNew 1.4.9, the new part indicating that this was the new release. The new would remain part of its name until 2007, when the project was renamed to OpenAds (it has since been renamed to OpenX and recently to Revive Adserver). Over the course of 2 years, I rewrote the core of the system and added features, until in 2002 I gladly handed it over to someone else to maintain.
Although I never made much money with the ads, the project was fun, I got to see the fruits of my labour being used by thousands of companies and I learned a lot running it.

Consultancy
The next few years I spent building mostly control panels and online ordering systems (for our own domain name, hosting and colocation business) and small websites and webapps.
In 2006 I started working for a number of Belgian companies as a freelance PHP developer. I worked for Internet Architects, Telenet, NMBS (Belgian railways) and a few more, before finally starting a dedicated PHP development company called Cu.be Solutions.

Open Source
Although phpAdsNew/OpenX was an open source project from the start, I had been out of touch with actual open source work for a while when I started working on PHPCompatibility a few years ago. I’m happy to see a lot of people using it.
But my contribution is so small compared to the massive amounts of code so many have contributed to the PHP core, frameworks, CMS systems, testing tools, and so much more.

The community
Open Source makes PHP great, absolutely. But it’s the PHP community that makes it all worth it ten-fold. In the past 8 years I’ve met the most amazing people from all around the world, each with their own distinct tastes, opinions, abilities, mindset, and so on… with one single thing binding them together : they’re all using this tool Rasmus Lerdorf built 20 years ago, this tool that has taken the web by storm and has been the undisputed number 1 web language for a long time, a language I will gladly use for another 20 ๐Ÿ˜‰

Happy happy birthday PHP ! Onwards to the next 20 !

PHPConsistent : a new tool to verify your calls and documentation quality

Back in 2009 and 2010 I wrote about a PHPUnit patch I wrote to automatically verify parameter types in function calls. The feature never made it into PHPUnit and honestly it didn’t really fit into the feature set either. Although I still plan on releasing it as a PHPUnit extension that you can easily load, I’ve since been using it outside of PHPUnit, not just on tests, but on any PHP code.

Introducing PHPConsistent

PHPConsistent will verify your code using both dynamic and static analysis.

The goal is to improve code quality of your code and the libraries you use by :

  • Verifying your code is making calls using the right parameters and parameter types
  • Verifying if the in-line documentation (docblock) of the called functions/methods is accurate

It will compare :

  • Parameter types specified in the docblock <-> types of parameters passed upon calling the function/method
  • Number of parameters specified in the docblock <-> number of parameters actually present in the function/method definition
  • Names of parameters specified in the docblock <-> names of parameters actually present in the function/method definition

Sample output

Invalid type calling SomeClass->GiveMeAnArray : parameter 3 ($somearray) should be of type array but got boolean instead : library/App.php (line 5)
Parameter names in function definition and docblock don't match when calling JustAnotherFunction : parameter 2 ($inputFilename) should be called $inputFile according to docblock : application/Bootstrap.php (line 214)
Parameter count in function definition and docblock don't match when calling OneMoreFunction : function has 6 but should be 5 according to docblock : application/Bootstrap.php (line 215)

Performance

Keep in mind that PHPConsistent relies on Xdebug’s trace functionality, making it quite slow. It also needs to analyze the output of that trace, making it even slower. So it’s definitely not something you want to run on a production environment !

Want to know more ?

Check out the PHPConsistent Github page

PHPCompatibility update

Update (Nov 3, 2013) : changed the parameters to reflect the new changes in PHP_CodeSniffer

Just a quick post about the updates made to PHPCompatibility.

I did a talk on PHP 5.4/5.5 at Zendcon, not just about what’s new and why you should upgrade, but also about the way PHPCompatibility can ease the pain. I received very good feedback, as well as very interesting questions. As a result, I added a feature I’ve wanted to add for a long time : the option to specify which PHP version to check for.

Here’s the caveat : it requires a change to PHP_CodeSniffer. I’m hoping that change will be accepted soon. From that point onwards, if you have the latest PHP_CodeSniffer (you might want to get it from Github).

So then you will be able to do :

phpcs --standard=PHPCompatibility --runtime-set testVersion 5.4 <path-of-your-php-files>

You can also test for backwards compatibility of your code by specifying versions like 5.2, which causes it to check whether you’re using functions or keywords not known to this older version. Quite nice if you’re coding on PHP 5.5, but your system engineer tells you half way through the project the project will have to be deployed on 5.2.

Important note : if you want to test backwards compatibility, it’s best to run on the latest PHP version available (5.5 right now), for the simple reason that if you have, for example, the keyword ‘yield’ in your code, PHP_CodeSniffer can only recognize it when you’re running PHP 5.5. It can only tell you it’s not available in previous versions if it actually knows what it is.

Expect more compatibility tools soon, as I have some more ideas, such as how to automatically figure out whether and where you’re still relying on register_globals and magic quotes ๐Ÿ˜‰

Technical and business stuff for the open-minded

Want to discuss a problem or a business idea with me ? Schedule a free 30min session here

By continuing to use the site, you agree to the use of cookies. more information

The cookie settings on this website are set to "allow cookies" to give you the best browsing experience possible. If you continue to use this website without changing your cookie settings or you click "Accept" below then you are consenting to this.

Close