File contents
            
            import string
class IPv4:
    """ Simple class for IPv4 parsing, used as quick conversion if its really sure we
        get valid and complete 4-tuples. (in our case from REMOTE_ADDR and friends)
        It has much lesser overhead then the IPv4CIDR class below
    """
    def __init__(self,ipstr):
        # ipstr in the form 'a.b.c.d'
        self.maskbits=32L
        self.mask=4294967295L
        # constants since this is a host address
        ipl=map(long,ipstr.split('.',3))
        # sum them up
        self.ip=min(reduce(lambda x,y:(x<<8L)+y,ipl),4294967294L)
    def __str__(self):
        ip=self.ip
        s=[]
        while ip:
            ip,r=divmod(ip,256)
            s.insert(0,str(r))
        s=(['0','0','0','0']+s)[-4:]
        if self.maskbits<32:
            return(string.join(s,'.')+'/'+str(self.maskbits))
        return(string.join(s,'.'))
    def __repr__(self):
        return("IPv4('%s')" % self)
    
    def __getitem__(self,key):
        if key:
            raise IndexError('list index out of range')
        else: return self
    def __eq__(self,other):
        return((other.ip & other.mask) == (self.ip & other.mask))
                    
class IPv4CIDR(IPv4):
    """ Helper class for IPv4 handling. Uses CIDR (classless interdomain routing) notation
        for subnets (or supernets, respectively)
        It should only trow exceptions during instantiation and only if something is completely
        wrong.
        Use:  a=IPv4CIDR('192.168.15.5')
              n1=IPv4CIDR('192.168.15.0/24')
              n2=IPv4CIDR('172.16.0.0/18')
              a == n1 -> returns true (1)
              a == n2 -> returns false (0)
              a in [n1,n2] -> returns true (1) because a is in subnet n1               
    """
    def __init__(self,ipstr):
        # ipstr in CIDR notation: ip/hostbits
        # if /hostbits are ommited, /32 is assumed
        # we have to check for the magic star first
        if ipstr:
            if ipstr[-1]=='*':
                ipstr=(ipstr[:-1]+'0.'*(4-ipstr.count('.')))[:-1]+'/'+str(ipstr.count('.')*8)
            ips,masks=(ipstr.split('/')+['32',])[:2]
            self.maskbits=min(long(masks),32L)
            self.mask=min(4294967296L-(1L<<(32-self.maskbits)),4294967295L)
            ipl=map(long,ips.split('.',3))
            # now a bit magic... 
            self.ip=min(reduce(lambda x,y:(x<<8L)+y,ipl[:-1]+[0L,]*(4-len(ipl))+ipl[-1:]),4294967294L)
            # and voil� - we have ip and mask with simple bound-checking
        else:
            self.mask=0
            self.maskbits=0
            self.ip=0
    def __repr__(self):
        return("IPv4CIDR('%s')" % self)
    def __eq__(self,other):
        # we check which might be the host (or smaller subnet)
        if self.maskbits>other.maskbits:
            return((other.ip & other.mask) == ((self.ip & self.mask) & other.mask))
        else:
            return((self.ip & self.mask) == ((other.ip & other.mask) & self.mask))