0)
list ($ip1bin, $ip2bin) = array($ip2bin, $ip1bin); // swap contents of ip1 <= ip2
$rangesubnets = array();
$netsize = 0;
do {
// at loop start, $ip1 is guaranteed strictly less than $ip2 (important for edge case trapping and preventing accidental binary wrapround)
// which means the assignments $ip1 += 1 and $ip2 -= 1 will always be "binary-wrapround-safe"
// step #1 if start ip (as shifted) ends in any '1's, then it must have a single cidr to itself (any cidr would include the '0' below it)
if (substr($ip1bin, -1, 1) == '1') {
// the start ip must be in a separate one-IP cidr range
$new_subnet_ip = substr($ip1bin, $netsize, $bits - $netsize) . str_repeat('0', $netsize);
$rangesubnets[$new_subnet_ip] = $bits - $netsize;
$n = strrpos($ip1bin, '0'); //can't be all 1's
$ip1bin = ($n == 0 ? '' : substr($ip1bin, 0, $n)) . '1' . str_repeat('0', $bits - $n - 1); // BINARY VERSION OF $ip1 += 1
}
// step #2, if end ip (as shifted) ends in any zeros then that must have a cidr to itself (as cidr cant span the 1->0 gap)
if (substr($ip2bin, -1, 1) == '0') {
// the end ip must be in a separate one-IP cidr range
$new_subnet_ip = substr($ip2bin, $netsize, $bits - $netsize) . str_repeat('0', $netsize);
$rangesubnets[$new_subnet_ip] = $bits - $netsize;
$n = strrpos($ip2bin, '1'); //can't be all 0's
$ip2bin = ($n == 0 ? '' : substr($ip2bin, 0, $n)) . '0' . str_repeat('1', $bits - $n - 1); // BINARY VERSION OF $ip2 -= 1
// already checked for the edge case where end = start+1 and start ends in 0x1, above, so it's safe
}
// this is the only edge case arising from increment/decrement.
// it happens if the range at start of loop is exactly 2 adjacent ips, that spanned the 1->0 gap. (we will have enumerated both by now)
if (strcmp($ip2bin, $ip1bin) < 0)
continue;
// step #3 the start and end ip MUST now end in '0's and '1's respectively
// so we have a non-trivial range AND the last N bits are no longer important for CIDR purposes.
$shift = $bits - max(strrpos($ip1bin, '0'), strrpos($ip2bin, '1')); // num of low bits which are '0' in ip1 and '1' in ip2
$ip1bin = str_repeat('0', $shift) . substr($ip1bin, 0, $bits - $shift);
$ip2bin = str_repeat('0', $shift) . substr($ip2bin, 0, $bits - $shift);
$netsize += $shift;
if ($ip1bin === $ip2bin) {
// we're done.
$new_subnet_ip = substr($ip1bin, $netsize, $bits - $netsize) . str_repeat('0', $netsize);
$rangesubnets[$new_subnet_ip] = $bits - $netsize;
continue;
}
// at this point there's still a remaining range, and either startip ends with '1', or endip ends with '0'. So repeat cycle.
} while (strcmp($ip1bin, $ip2bin) < 0);
// subnets are ordered by bit size. Re sort by IP ("naturally") and convert back to IPv4/IPv6
ksort($rangesubnets, SORT_STRING);
$out = array();
foreach ($rangesubnets as $ip => $netmask) {
if ($proto == 'ipv4') {
$i = str_split($ip, 8);
$out[] = implode('.', array( bindec($i[0]),bindec($i[1]),bindec($i[2]),bindec($i[3]))) . '/' . $netmask;
} else
$out[] = Net_IPv6::compress(Net_IPv6::_bin2Ip($ip)) . '/' . $netmask;
}
return $out;
}
# Set php Memory Limit to 256M. This is required to process the MaxMind IP Database
ini_set('memory_limit', '256M');
function pfb_update_check($header_url, $list_url, $url_format) {
global $pfb;
if ($url_format == "rsync" || $url_format == "html") {
$log = "[ {$header_url} ]\n Skipping timestamp query\n";
pfb_logger("{$log}","1");
return TRUE;
}
switch ($url_format) {
case "gz":
case "gz_2":
case "gz_lg":
case "et":
$type = '.gz';
break;
case "zip":
case "xlsx":
$type = '.zip';
break;
case "txt":
$type = '.orig';
break;
case "html":
case "block":
$type = '.raw';
break;
}
$log = "[ {$header_url} ]\n";
pfb_logger("{$log}","1");
$host = @parse_url($list_url);
$local_file = "{$pfb['origdir']}/{$header_url}{$type}";
if (file_exists($local_file)) {
// Determine if URL is Remote or Local
if ($host['host'] == "127.0.0.1" || $host['host'] == $pfb['iplocal'] || empty($host['host'])) {
$remote_tds = gmdate ("D, d M Y H:i:s T", filemtime($local_file));
} else {
$remote_tds = @implode(preg_grep("/Last-Modified/", get_headers($list_url)));
$remote_tds = preg_replace("/^Last-Modified: /","", $remote_tds);
}
$log = " Remote timestamp: {$remote_tds}\n";
pfb_logger("{$log}","1");
$local_tds = gmdate ("D, d M Y H:i:s T", filemtime($local_file));
$log = " Local timestamp: {$local_tds}\n";
pfb_logger("{$log}","1");
if ("{$remote_tds}" != "{$local_tds}") {
return TRUE;
} else {
$log = " Remote file unchanged. Download Terminated\n";
pfb_logger("{$log}","1");
return FALSE;
}
} else {
return TRUE;
}
}
if ($argv[1] == 'update') {
sync_package_pfblockerng("cron");
}
if ($argv[1] == 'uc') {
pfblockerng_uc_countries();
pfblockerng_get_countries();
}
if ($argv[1] == 'gc') {
pfblockerng_get_countries();
}
if ($argv[1] == 'cron') {
$hour = date('H');
$dow = date('N');
# Start hour of the 'Once a day' Schedule
$pfb['dailystart'] = $config['installedpackages']['pfblockerng']['config'][0]['pfb_dailystart'];
# Start hour of the Scheduler
if ($config['installedpackages']['pfblockerng']['config'][0]['pfb_hour'] != "") {
$pfb['hour'] = $config['installedpackages']['pfblockerng']['config'][0]['pfb_hour'];
} else {
$pfb['hour'] = "1";
}
$updates = 0;
# 2 Hour Schedule Converter
$shour = intval(substr($pfb['hour'], 0, 2));
$sch2 = strval($shour);
for ($i=0; $i<11; $i++) {
$shour += 2;
if ($shour > 24)
$shour -= 24;
$sch2 .= "," . strval($shour);
}
# 3 Hour Schedule Converter
$shour = intval(substr($pfb['hour'], 0, 2));
$sch3 = strval($shour);
for ($i=0; $i<7; $i++) {
$shour += 3;
if ($shour > 24)
$shour -= 24;
$sch3 .= "," . strval($shour);
}
# 4 Hour Schedule Converter
$shour = intval(substr($pfb['hour'], 0, 2));
$sch4 = strval($shour);
for ($i=0; $i<5; $i++) {
$shour += 4;
if ($shour > 24)
$shour -= 24;
$sch4 .= "," . strval($shour);
}
# 6 Hour Schedule Converter
$shour = intval(substr($pfb['hour'], 0, 2));
$sch6 = strval($shour);
for ($i=0; $i<3; $i++) {
$shour += 6;
if ($shour > 24)
$shour -= 24;
$sch6 .= "," . strval($shour);
}
# 8 Hour Schedule Converter
$shour = intval(substr($pfb['hour'], 0, 2));
$sch8 = strval($shour);
for ($i=0; $i<2; $i++) {
$shour += 8;
if ($shour > 24)
$shour -= 24;
$sch8 .= "," . strval($shour);
}
# 12 Hour Schedule Converter
$shour = intval(substr($pfb['hour'], 0, 2));
$sch12 = strval($shour) . ",";
$shour += 12;
if ($shour > 24)
$shour -= 24;
$sch12 .= strval($shour);
$e_sch2 = explode(",", $sch2);
$e_sch3 = explode(",", $sch3);
$e_sch4 = explode(",", $sch4);
$e_sch6 = explode(",", $sch6);
$e_sch8 = explode(",", $sch8);
$e_sch12 = explode(",", $sch12);
$log = " CRON PROCESS START [ NOW ]\n";
pfb_logger("{$log}","1");
$list_type = array ("pfblockernglistsv4" => "_v4", "pfblockernglistsv6" => "_v6");
foreach ($list_type as $ip_type => $vtype) {
if ($config['installedpackages'][$ip_type]['config'] != "") {
foreach ($config['installedpackages'][$ip_type]['config'] as $list) {
if (is_array($list['row']) && $list['action'] != "Disabled") {
foreach ($list['row'] as $row) {
if ($row['url'] != "" && $row['state'] != "Disabled") {
if ($vtype == "_v4") {
$header_url = "{$row['header']}";
} else {
$header_url = "{$row['header']}_v6";
}
# Determine Folder Location for Alias (return array $pfbarr)
pfb_determine_list_detail($list['action']);
$pfbfolder = $pfbarr['folder'];
$list_cron = $list['cron'];
$list_url = $row['url'];
$header_dow = $list['dow'];
$url_format = $row['format'];
// Bypass update if state is defined as "Hold" and list file exists
if (file_exists($pfbfolder . '/' . $header_url . '.txt') && $row['state'] == "Hold") {
continue;
}
# Check if List file exists, if not found run Update
if (!file_exists($pfbfolder . '/' . $header_url . '.txt')) {
$log = " Updates Found\n";
pfb_logger("{$log}","1");
$updates++;
continue;
}
switch ($list_cron) {
case "01hour":
if (pfb_update_check($header_url, $list_url, $url_format)) {
$log = " Updates Found\n";
pfb_logger("{$log}","1");
unlink_if_exists($pfbfolder . '/' . $header_url . '.txt');
$updates++;
}
break;
case "02hours":
if (in_array($hour, $e_sch2)) {
if (pfb_update_check($header_url, $list_url, $url_format)) {
$log = " Updates Found\n";
pfb_logger("{$log}","1");
unlink_if_exists($pfbfolder . '/' . $header_url . '.txt');
$updates++;
}
}
break;
case "03hours":
if (in_array($hour, $e_sch3)) {
if (pfb_update_check($header_url, $list_url, $url_format)) {
$log = " Updates Found\n";
pfb_logger("{$log}","1");
unlink_if_exists($pfbfolder . '/' . $header_url . '.txt');
$updates++;
}
}
break;
case "04hours":
if (in_array($hour, $e_sch4)) {
if (pfb_update_check($header_url, $list_url, $url_format)) {
$log = " Updates Found\n";
pfb_logger("{$log}","1");
unlink_if_exists($pfbfolder . '/' . $header_url . '.txt');
$updates++;
}
}
break;
case "06hours":
if (in_array($hour, $e_sch6)) {
if (pfb_update_check($header_url, $list_url, $url_format)) {
$log = " Updates Found\n";
pfb_logger("{$log}","1");
unlink_if_exists($pfbfolder . '/' . $header_url . '.txt');
$updates++;
}
}
break;
case "08hours":
if (in_array($hour, $e_sch8)) {
if (pfb_update_check($header_url, $list_url, $url_format)) {
$log = " Updates Found\n";
pfb_logger("{$log}","1");
unlink_if_exists($pfbfolder . '/' . $header_url . '.txt');
$updates++;
}
}
break;
case "12hours":
if (in_array($hour, $e_sch12)) {
if (pfb_update_check($header_url, $list_url, $url_format)) {
$log = " Updates Found\n";
pfb_logger("{$log}","1");
unlink_if_exists($pfbfolder . '/' . $header_url . '.txt');
$updates++;
}
}
break;
case "EveryDay":
if ($hour == $pfb['dailystart']) {
if (pfb_update_check($header_url, $list_url, $url_format)) {
$log = " Updates Found\n";
pfb_logger("{$log}","1");
unlink_if_exists($pfbfolder . '/' . $header_url . '.txt');
$updates++;
}
}
break;
case "Weekly":
if ($hour == $pfb['dailystart'] && $dow == $header_dow) {
if (pfb_update_check($header_url, $list_url, $url_format)) {
$log = " Updates Found\n";
pfb_logger("{$log}","1");
unlink_if_exists($pfbfolder . '/' . $header_url . '.txt');
$updates++;
}
}
break;
default: {
}
break;
}
}
}
}
}
}
}
if ($updates > 0) {
sync_package_pfblockerng("cron");
} else {
$log = "\n No Updates required. \n\n";
pfb_logger("{$log}","1");
}
$log = " CRON PROCESS ENDED [ NOW ]\n";
pfb_logger("{$log}","1");
# Call Log Mgmt Function
// If Update GUI 'Manual view' is selected. Last output will be missed. So sleep for 5 secs.
sleep(5);
pfb_log_mgmt();
}
function pfblockerng_uc_countries() {
global $g,$pfb;
pfb_global();
$maxmind_cont = "{$pfb['dbdir']}/country_continent.csv";
$maxmind_cc4 = "{$pfb['dbdir']}/GeoIPCountryWhois.csv";
$maxmind_cc6 = "{$pfb['dbdir']}/GeoIPv6.csv";
# Create Folders if not Exist
$folder_array = array ("{$pfb['dbdir']}","{$pfb['logdir']}","{$pfb['ccdir']}");
foreach ($folder_array as $folder) {
safe_mkdir ("{$folder}",0755);
}
$now = date("m/d/y G:i:s", time());
$log = "Country Code Update Start - [ NOW ]\n\n";
print "Country Code Update Start - [ $now ]\n\n";
pfb_logger("{$log}","3");
if (!file_exists($maxmind_cont) || !file_exists($maxmind_cc4) || !file_exists($maxmind_cc6)) {
$log = " [ MAXMIND UPDATE FAIL, CSV Missing, using Previous Country Code Database \n";
print $log;
pfb_logger("{$log}","3");
return;
}
# Save Date/Time Stamp to MaxMind version file
$maxmind_ver = "MaxMind GeoLite Date/Time Stamps \n\n";
$remote_tds = @implode(preg_grep("/Last-Modified/", get_headers("http://geolite.maxmind.com/download/geoip/database/GeoIPCountryCSV.zip")));
$maxmind_ver .= "MaxMind_v4 \t" . $remote_tds . "\n";
$local_tds = @gmdate ("D, d M Y H:i:s T", filemtime($maxmind_cc4));
$maxmind_ver .= "Local_v4 \tLast-Modified: " . $local_tds . "\n\n";
$remote_tds = @implode(preg_grep("/Last-Modified/", get_headers("http://geolite.maxmind.com/download/geoip/database/GeoIPv6.csv.gz")));
$maxmind_ver .= "MaxMind_v6 \t" . $remote_tds . "\n";
$local_tds = @gmdate ("D, d M Y H:i:s T", filemtime($maxmind_cc6));
$maxmind_ver .= "Local_v6 \tLast-Modified: " . $local_tds . "\n";
$maxmind_ver .= "\nThese Timestamps should *match* \n";
@file_put_contents("{$pfb['logdir']}/maxmind_ver", $maxmind_ver);
// Collect ISO Codes for Each Continent
$log = "Processing Continent Data \n";
print $log;
pfb_logger("{$log}","3");
$cont_array = array ( array($AF),array($AS),array($EU),array($NA),array($OC),array($SA));
$csv = array_map('str_getcsv', @file($maxmind_cont));
if (isset($csv)) {
foreach ($csv as $cc) {
$cc_key = $cc[0];
$cont_key = $cc[1];
switch ($cont_key) {
case "AF":
$cont_array[0]['continent'] = "Africa";
$cont_array[0]['iso'] .= "{$cc_key},";
$cont_array[0]['file4'] = "{$pfb['ccdir']}/Africa_v4.txt";
$cont_array[0]['file6'] = "{$pfb['ccdir']}/Africa_v6.txt";
break;
case "AS":
$cont_array[1]['continent'] = "Asia";
$cont_array[1]['iso'] .= "{$cc_key},";
$cont_array[1]['file4'] = "{$pfb['ccdir']}/Asia_v4.txt";
$cont_array[1]['file6'] = "{$pfb['ccdir']}/Asia_v6.txt";
break;
case "EU":
$cont_array[2]['continent'] = "Europe";
$cont_array[2]['iso'] .= "{$cc_key},";
$cont_array[2]['file4'] = "{$pfb['ccdir']}/Europe_v4.txt";
$cont_array[2]['file6'] = "{$pfb['ccdir']}/Europe_v6.txt";
break;
case "NA":
$cont_array[3]['continent'] = "North America";
$cont_array[3]['iso'] .= "{$cc_key},";
$cont_array[3]['file4'] = "{$pfb['ccdir']}/North_America_v4.txt";
$cont_array[3]['file6'] = "{$pfb['ccdir']}/North_America_v6.txt";
break;
case "OC":
$cont_array[4]['continent'] = "Oceania";
$cont_array[4]['iso'] .= "{$cc_key},";
$cont_array[4]['file4'] = "{$pfb['ccdir']}/Oceania_v4.txt";
$cont_array[4]['file6'] = "{$pfb['ccdir']}/Oceania_v6.txt";
break;
case "SA":
$cont_array[5]['continent'] = "South America";
$cont_array[5]['iso'] .= "{$cc_key},";
$cont_array[5]['file4'] = "{$pfb['ccdir']}/South_America_v4.txt";
$cont_array[5]['file6'] = "{$pfb['ccdir']}/South_America_v6.txt";
break;
}
}
}
unset($csv);
// Collect Country ISO Data IPv4 and Sort to Continent Array
$log = "Processing ISO IPv4 Continent/Country Data \n";
print $log;
pfb_logger("{$log}","3");
$csv2 = array_map('str_getcsv', @file($maxmind_cc4));
if (isset($csv2)) {
foreach ($csv2 as $cc) {
$ip1_key = $cc[0];
$ip2_key = $cc[1];
$var1_key = $cc[2];
$var2_key = $cc[3];
$cc_key = $cc[4];
$country_key = $cc[5];
$a_cidr = implode(",", ip_range_to_subnet_array_temp($cc[0],$cc[1]));
$counter = 0;
foreach ($cont_array as $iso) {
if (preg_match("/\b$cc_key\b/", $iso['iso'])) {
$cont_array[$counter][$cc_key]['ip4'] .= $a_cidr . ",";
$cont_array[$counter][$cc_key]['country'] = $country_key;
continue;
}
$counter++;
}
}
}
unset($csv2);
// Build Continent IPv4 CIDR Files
$counter = 0;
foreach ($cont_array as $iso) {
$header = "";
$pfb_file = "";
$iso_key = "";
$header .= "# Generated from MaxMind Inc. on: " . date("m/d/y G:i:s", time()) . "\n";
$header .= "# Continent IPv4: " . $cont_array[$counter]['continent'] . "\n";
$pfb_file = $cont_array[$counter]['file4'];
$iso_key = array_keys($iso);
foreach ($iso_key as $key) {
if (preg_match("/[A-Z]{2}/", $key)) {
$header .= "# Country: " . $iso[$key]['country'] . "\n";
$header .= "# ISO Code: " . $key . "\n";
$header .= "# Total Networks: " . substr_count($iso[$key]['ip4'], ",") . "\n";
$header .= str_replace(",", "\n", $iso[$key]['ip4']);
$iso[$key]['ip4'] = "";
}
}
$counter++;
@file_put_contents($pfb_file, $header, LOCK_EX);
}
// Collect Country ISO Data IPv6 and Sort to Continent Array
$log = "Processing ISO IPv6 Continent/Country Data \n";
print $log;
pfb_logger("{$log}","3");
$csv3 = array_map('str_getcsv', @file($maxmind_cc6));
if (isset($csv3)) {
foreach ($csv3 as $cc) {
$ip1_key = $cc[0];
$ip2_key = $cc[1];
$var1_key = $cc[2];
$var2_key = $cc[3];
$cc_key = $cc[4];
$country_key = $cc[5];
$a_cidr = implode(",", ip_range_to_subnet_array_temp($cc[0],$cc[1]));
$counter = 0;
foreach ($cont_array as $iso) {
if (preg_match("/\b$cc_key\b/", $iso['iso'])) {
$cont_array[$counter][$cc_key]['ip6'] .= $a_cidr . ",";
continue;
}
$counter++;
}
}
}
unset ($csv3);
// Build Continent IPv6 Files
$counter = 0;
foreach ($cont_array as $iso) {
$header = "";
$pfb_file = "";
$iso_key = "";
$header .= "# Generated from MaxMind Inc. on: " . date("m/d/y G:i:s", time()) . "\n";
$header .= "# Continent IPv6: " . $cont_array[$counter]['continent'] . "\n";
$pfb_file = $cont_array[$counter]['file6'];
$iso_key = array_keys($iso);
foreach ($iso_key as $key) {
if (preg_match("/[A-Z]{2}/", $key)) {
$header .= "# Country: " . $iso[$key]['country'] . "\n";
$header .= "# ISO Code: " . $key . "\n";
$header .= "# Total Networks: " . substr_count($iso[$key]['ip6'], ",") . "\n";
$header .= str_replace(",", "\n", $iso[$key]['ip6']);
$iso[$key]['ip6'] = "";
}
}
$counter++;
@file_put_contents($pfb_file, $header, LOCK_EX);
}
unset($cont_array);
}
function pfblockerng_get_countries() {
global $g,$pfb;
pfb_global();
# These arrays are used to collect the ';
$roptions4[] = $Country . '-' . $ISOCode . ' ('. $total4 .') ' . ' ' . $ISOCode . '';
// Save ISO IPv4 Data
@file_put_contents($pfb['ccdir'] . '/' . $ISOCode . '_v4.txt',$pfb_v4,LOCK_EX);
// Clear Variables and Restart Continent Collection process
$total4 = 0;
$pfb_v4 = "";
$pfb['complete'] = FALSE;
}
if (preg_match("/Country:\s(.*)/",$line, $matches)) { $Country = $matches[1];}
if (preg_match("/ISO Code:\s(.*)/",$line, $matches)) { $ISOCode = $matches[1];}
} elseif (!preg_match("/#/",$line)) {
$total4++;
if (!empty($line))
$pfb_v4 .= $line . "\n";
$pfb['complete'] = TRUE;
}
}
unset ($ips, $convert);
// Sort IPv4 Countries Alphabetically and Build XML