sash
sash

Reputation: 85

Php complex validation logic

I need to validate an input from text area. It is complex and i'm unable to figure out how i can do it best? Can you guys help?

Input from the text area are basically host names or ips. The input can be of any of the following formats:

x.x.x.x (single IP)
x.x.x.x-x.x.x.x (range of IPs)
x.x.x.x/x.x.x.x (IP and mask)
x.x.x.x/xx (IP and CIDR)
URL (with or without http:// and https:// prefixes)
domain name in format: xxxxxxx.xxx

Also multiple values can be given, like: 192.168.1.1 192.168.1.2/192.168.1.4

I am able to get the lines of textbox using the following code:

$text = trim($targets);
$textAr = explode("\n", $text);
$textAr = array_filter($textAr, 'trim');

foreach ($textAr as $line) {


} 

I am unable to proceed further. Please help.

Thanks, Dave

Upvotes: 1

Views: 243

Answers (1)

Michael
Michael

Reputation: 3141

If you don't mind being slightly loose on your validation, you can do something simple such as this:

function filter_fn($input)
{
    $input = trim($input);
    $regex_ip = '/^([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3})$/';
    $regex_range = '/^([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3})-([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3})$/';
    $regex_cidr = '/^([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\/[0-9]{1,2})$/';
    $regex_sub = '/^([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\/[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3})$/';

    if (filter_var($input, FILTER_VALIDATE_REGEXP, array('options' => array('regexp' => $regex_ip)))) {
        return $input;
    }

    if (preg_match($regex_range, $input)) {
        return $input;
    }

    if (preg_match($regex_cidr, $input)) {
         return $input;
    }

    if (preg_match($regex_sub, $input)) {
        return $input;
    }

    if (filter_var($input, FILTER_VALIDATE_URL)) {
        return $input;
    }

    if (filter_var('http://'.$input, FILTER_VALIDATE_URL)) {
        return $input;
    }

    return false;
}

$textAr = explode("\n", $text);
$textAr = array_filter($textAr, 'trim');
foreach ($textAr as $line) {
    $success = filter_var($line, FILTER_CALLBACK, array('options' => 'filter_fn'));
    if (!$success) {
        // It failed.
    } else {
        // It worked.
    }
} 

Note that in my example, I used both preg_match and filter_var with FILTER_VALIDATE_REGEXP. Both are identical in this case, so that first filter_var could have just as easily been replaced with:

preg_match($regex_ip, $input)

Or, even:

filter_var($input, FILTER_VALIDATE_IP)

Upvotes: 2

Related Questions