Habe es gefunden, danke. :) Ich poste mal nur noch mal meine letzte Version, da ich nicht glaube, dass ich ohne gegebenen Anlass noch was dran machen werde (sorry). Ich glaube, ich verstehe die eigentliche Problemstellung auch nicht so richtig, weil es nicht so sehr mein Bereich ist.
Vielleicht hilft es aber trotzdem irgendwem:
<?php
/**
*
*/
class Algo
{
/**
* @var array
*/
private $masks;
/**
* @var array
*/
private $maskKeys;
/**
* @param array $masks
*/
public function __construct(array $masks)
{
$this->masks = $this->rearrangeMasks($masks);
$this->maskKeys = array_keys($this->masks);
ksort($this->maskKeys);
}
/**
* @param array $a
* @return array
*/
private function rearrangeMasks(array $a)
{
$new = array();
foreach ($a as $item) {
list($ipv4, $cidr) = explode('/', $item);
$iplong = ip2long($ipv4);
$iplong >>= 32 - $cidr;
if (!isset($new[$cidr])) {
$new[$cidr] = array();
}
$new[$cidr][$iplong] = true;
}
return $new;
}
/**
* @param string $ipv4
* @return bool
*/
public function isMatch($ipv4)
{
$iplong = ip2long($ipv4);
foreach ($this->maskKeys as $i) {
if (isset($this->masks[$i][$iplong >> 32 - $i])) {
return true;
}
}
return false;
}
}
/**
*
*/
class AlgoTest extends PHPUnit_Framework_TestCase
{
/**
* @param string $bin
* @return string
*/
private function ipFromBin($bin)
{
$parts = explode('.', $bin);
return implode('.', array_map('bindec', $parts));
}
/**
* @param string $bin
* @return string
*/
private function maskFromBin($bin)
{
list($tmp, $cidr) = explode('/', $bin);
return $this->ipFromBin($tmp) . '/' . $cidr;
}
/**
* @param array $masks
* @param array $assertions
*/
private function runAssertions(array $masks, array $assertions)
{
$algo = new Algo($masks);
foreach ($assertions as $assertion) {
list($ipv4, $expected) = $assertion;
$this->assertSame($expected, $algo->isMatch($ipv4), implode(', ', $masks) . ' : ' . $ipv4);
}
}
/**
*
*/
public function testMain()
{
$masks = array(
'192.168.11.12/24',
'62.10.11.12/32',
'128.10.11.12/8',
'96.50.51.52/16'
);
$assertions = array(
array('192.168.128.0', false),
array('192.168.11.255', true),
array('62.10.11.255', false),
array('62.10.11.12', true),
array('128.255.255.255', true),
array('129.255.255.255', false),
array('96.50.255.255', true),
array('97.50.51.52', false)
);
$this->runAssertions($masks, $assertions);
$masks = array(
// 192.168.1.188/27 xxxxxxxx xxxxxxxx xxxxxxxx xxx-----
$this->maskFromBin('11000000.10101000.00000001.10111100/27')
);
$assertions = array(
array($this->ipFromBin('11000000.10101000.00000001.10111111'), true),
array($this->ipFromBin('11000000.10101000.00000001.10100000'), true),
array($this->ipFromBin('11000000.10101000.00000001.10011111'), false),
array($this->ipFromBin('11000000.10101000.00000001.10000000'), false)
);
$this->runAssertions($masks, $assertions);
$masks = array(
// 192.168.1.188/1 x------- -------- -------- --------
$this->maskFromBin('11000000.10101000.00000001.10111100/1')
);
$assertions = array(
array($this->ipFromBin('11111111.11111111.11111111.11111111'), true),
array($this->ipFromBin('01000000.10101000.00000001.10011111'), false)
);
$this->runAssertions($masks, $assertions);
$masks = array(
// xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx
$this->maskFromBin('11111111.11111111.11111111.11111111/32'),
// xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx
$this->maskFromBin('00000000.00000000.00000000.00000000/32')
);
$assertions = array(
array($this->ipFromBin('11111111.11111111.11111111.11111111'), true),
array($this->ipFromBin('00000000.00000000.00000000.00000000'), true),
array($this->ipFromBin('11111111.11111111.11111111.11111110'), false),
array($this->ipFromBin('00000000.00000000.00000000.00000001'), false)
);
$this->runAssertions($masks, $assertions);
$masks = array(
// xxxxxxxx xxxx---- -------- --------
$this->maskFromBin('11111111.11110000.00000000.00000000/12')
);
$assertions = array(
array($this->ipFromBin('11111111.11110000.11111111.11111111'), true),
array($this->ipFromBin('11111111.00001111.11111111.11111111'), false)
);
$this->runAssertions($masks, $assertions);
}
}