## ------------------------------------------------------------------------
## iSiLK - A python-based graphical user interface for SiLK
## ------------------------------------------------------------------------
## Copyright (c) 2007-2008 Carnegie Mellon University. All Rights Reserved.
## ------------------------------------------------------------------------
## Authors: Andrew Kompanek (ajk@cert.org)
## ------------------------------------------------------------------------
## GNU General Public License (GPL) Rights pursuant to Version 2, June 1991
## Government Purpose License Rights (GPLR) pursuant to DFARS 252.225-7013
## ------------------------------------------------------------------------
## See the LICENSE file included in this distribution
## ------------------------------------------------------------------------

import re, sys
import config.silk as config

def _validate_octet(val):    
    if val == "x":
        return val
    else:
        return validate_list_arg(val, 0, 255)
  
def _validate_range(val, minval=0, maxval=65535):
    if not val.find("-") >= 0:
        e = re.compile("^(\d+)$")
        m = e.match(val)
        if not m: 
            if val == '':
                raise Exception("A value must be specified after a comma")
            else:
                raise Exception("%s is not a positive integer" % val)

        if int(val) < minval or int(val) > maxval:
            raise Exception("%s is out of range" % val)
        return int(val)
    else:
        e = re.compile("^(\d*)\-(\d*)$")
        m = e.match(val)
        if not m: 
            raise Exception("Bad range value: %s" % val)
        if m.groups()[0] != "":
            start = int (m.groups()[0])
        else:
            start=minval
        if m.groups()[1] != "":
            end = int (m.groups()[1])
        else:
            end = maxval
        if start > end or start < minval or end > maxval: 
            raise Exception("Illegal range %d-%d (not between %d and %d)" 
                             % (start, end, minval, maxval))
        return (start,end)

def validate_list_arg(val, minval=0, maxval=65535):
    items = val.split(",")
    retval = []
    for i in items: 
        retval.append(_validate_range(i, minval, maxval))
    return retval
    
def check_list_membership(range_str, val, minval, maxval):
    validate_list_arg(range_str, minval, maxval)
    print "Changing against range_str = %s" % range_str
    items = range_str.split(",")
    val = int(val)
    retval = []
    for i in items: 
        val_range = _validate_range(i, minval, maxval)
        print "Checking against %s" % str(val_range)
        if type(val_range) == int:
            if val == val_range: return True
        else:
            (start,end) = val_range
            if (val >= start and val <= end): return True
    return False

def _list_arg_to_string(l):
    retval = ""
    first = True
    for i in l: 
        if not first: retval += ","
        first = False
        if type(i) == int: 
            retval += ("%d" % i)
        else:
            retval += ("%d-%d" % (i[0], i[1]))
    return retval
    
def parse_flags_arg(val):
    ''' Parse into a dictionary with boolean for flags in mask. '''
    valid_flags = "FSRPAUEC"
    flags = {}
    validate_flags_arg(val)
    if val == "": return flags
    (l,r) = val.split("/")
    for i in range(0,8):
        if valid_flags[i] in r:
            flags[valid_flags[i]] = (valid_flags[i] in l)
    return flags
    
def validate_flags_arg(val):
    if val == "": return
    if val.find("/") == -1:
        raise Exception("Invalid TCP flag filter")
    (l, r) = val.split("/")
    left = set(l)
    right = set(r)
    if len(l) != len(left) or len(r) != len(right):
        raise Exception("Include each TCP flag only once.")
    valid_flags =  set("FSRPAUEC")
    if len(left.intersection(valid_flags)) != len(left):
        raise Exception("Unexpected TCP flag on left")
    if len(right.intersection(valid_flags)) != len(right):
        raise Exception("Unexpected TCP flag on right")
    if len(left.intersection(right)) != len(left):
        raise Exception("Flag specified in set must be included in the mask.")
    return
    
def validate_volume_arg(val):
    if val =="": return
    return validate_list_arg(val, 0, sys.maxint)
    
def validate_port_arg(val):
    if val == "": return    
    return validate_list_arg(val, 0,65535)

def validate_proto_arg(val):
    if val == "": return    
    return validate_list_arg(val, 0,255)
    
def validate_icmp_type_arg(val):
    if val == "": return    
    return validate_list_arg(val, 0,255)    

def validate_icmp_code_arg(val):
    if val == "": return    
    return validate_list_arg(val, 0,255)

def validate_bin_size_arg(val):
    if val == "": return
    try:
        val = int(val)
    except:
        raise Exception("Invalid bin size argument: %d" % val)

def validate_ip_arg(val):
    if "/" in val:
        (val,bits) = val.split("/")
    if val == "":
        return    
    items = val.split(".")
    if not len(items) == 4:
        raise Exception("Invalid IP address filter: %s" % val) 
    retval = []
    for i in items: 
        try:
            octet = _validate_octet(i)
        except Exception, e:
            raise Exception("Illegal octet pattern: %s (%s)" % (i,e))
        retval.append(octet)
    return retval
    
    
    
