karadayi
karadayi

Reputation: 2269

PHP check with foreach if array exist inside a txt file and return boolean

I know it is basic code but somewhere is a mistake that I can not figure out after hours. Inside the blocklist.txt are several lines of IP's which should check if is existing or give boolean true or false out. I do not get the boolean true out even if it matches.

function blocklist($ip) {
    $blocked = false;
    $ipList = file('blocklist.txt', FILE_SKIP_EMPTY_LINES) // ip in array
        or exit("Unable to open blocklist file");

    foreach ($ipList as $entry) {
        if(strpos($entry, $ip)) { // check if ip exist in array
            $blocked = true; // set true
            break; 
        }
        echo $blocked ? 'true' : 'false';
    }
    return $blocked;
}

function getUserIP() {
    $ip = '';
    if (getenv('HTTP_CLIENT_IP'))
        $ip = getenv('HTTP_CLIENT_IP');
    else if(getenv('HTTP_X_FORWARDED_FOR'))
        $ip = getenv('HTTP_X_FORWARDED_FOR');
    else
        $ip = 'UNKNOWN';
    return $ip;
}

blocklist.txt content

123.45.67.89
464.93.47.37
95.83.46.359
237.8.54.849

Upvotes: 0

Views: 101

Answers (2)

mickmackusa
mickmackusa

Reputation: 47934

I don't think it makes sense to break your file contents into an array, make iterated trim() calls to remove the whitespace from each element, then scan the new prepared array for an identical value match.

Is there a good reason not to do this? A single function call will be much more efficient/direct.

function blocklist($ip){
    if(!$ipList=file_get_contents('blocklist.txt')){
        exit("Unable to open blocklist file");
    }
    return preg_match('/\b\Q'.$ip.'\E\b/',$ipList) ? true : false;
}

Here's a demo with a static $ipList string:

function blocklist($ip){
    $ipList='123.45.67.89
464.93.47.12
464.93.47.123
95.83.46.359
237.8.54.849';
    //                  vv-----------vv-Word Boundaries to ensure no extra digits are matched
    return preg_match('/\b\Q'.$ip.'\E\b/',$ipList) ? true : false;
    //                    ^^-------^^-Interpret $ip string literally, so dots are not "any character" (only important in extreme fringe cases)
}

var_export(blocklist('464.93.47.123'));  // true
var_export(blocklist('464.93.1.123'));  // false

Otherwise if you have your heart set on processing an array, perform a single loop with an early exit possibility (not a array_map() then an in_array():

function blocklist($ip){
    $ipList = file('blocklist.txt', FILE_SKIP_EMPTY_LINES) // ip in array
              or exit("Unable to open blocklist file");
    foreach ($ipList as $entry) {
        if($ip===trim($entry)) { // check if ip value is element value
            return true; // set true and early exit
        }
    }
    return false;
}

Also, the other function can be refined to use a simpler / shorter syntax:

function getUserIP() {
    if (getenv('HTTP_CLIENT_IP')) return getenv('HTTP_CLIENT_IP');
    if (getenv('HTTP_X_FORWARDED_FOR')) return getenv('HTTP_X_FORWARDED_FOR');
    return 'UNKNOWN';
}

Upvotes: 0

Aman Maurya
Aman Maurya

Reputation: 1325

When you parse IP from blocklist.txt in $ipList variable then extra space is added to every IP,so I removed the whitespace from every value in $ipList using

array_map('trim',$ipList)

function blocklist($ip) {
    //remove white space from input array
    $ip = trim($ip);
    $blocked = false;
    $ipList = file('blocklist.txt', FILE_SKIP_EMPTY_LINES) // ip in array
        or exit("Unable to open blocklist file");
    //remove the white space from each value 
    $ipList = array_map('trim',$ipList);
    //Check if IP exist in the array list 
    if(in_array($ip,$ipList)){
        return true;
    }else{
        return false;
    }
}

function getUserIP() {
    $ip = '';
    if (getenv('HTTP_CLIENT_IP'))
        $ip = getenv('HTTP_CLIENT_IP');
    else if(getenv('HTTP_X_FORWARDED_FOR'))
        $ip = getenv('HTTP_X_FORWARDED_FOR');
    else
        $ip = 'UNKNOWN';
    return $ip;
}

var_dump(blocklist('123.45.67.89')); //output true

Upvotes: 1

Related Questions