Example #1
0
File: pairs.py Project: xmnr/atk
def containsName(pairs, name, normalize=True):
    """
    Returns True if the name appears in a iterable of (name, value) pairs. If
    normalize is true, uses case insensitive comparison.
    """

    if normalize: name = normalizeHeaderName(name)
    for pairName, _ in pairs:
        if name == (
            normalizeHeaderName(pairName) if normalize else pairName
        ):
            return True
    return False
Example #2
0
File: pairs.py Project: xmnr/atk
def dedupPairs(pairs, normalize=True):
    """
    Returns a dictionary mapping (optionally normalized) names to a tuple of values
    associated with it. Values in the tuple will appear in the same order as
    they were in the original pairs. Normalizing is for headers and will is
    case insensitive.
    """

    dict = {}
    for name, value in pairs:
        if normalize: name = normalizeHeaderName(name)
        dict[name] = dict.get(name, tuple()) + (value, )

    return dict
Example #3
0
File: pairs.py Project: xmnr/atk
def searchPairs(
        pairs, name=None, value=None, nameMatch=EQ_MATCH, valueMatch=IN_MATCH,
        n=None, reverse=False
    ):
    """
    Iterates through (name, value) pairs, where name and value are strings, and
    compares them to the name and value provided in the arguments. Yields the
    index for every matching pair.

    Examples:

    for cookie in searchPairs(pairs, name="Set-Cookie"): ...
    for injection in searchPairs(loggedPairs, value="<php", valueMatch=IN_MATCH): ...
    matchingPairs = derefPairs(pairs, searchPairs(...))

    If you supply a name and a value, they must both match. If you don't supply
    one, it is ignored and not considered when matching. The type of match is
    controlled by the nameMatch and valueMatch arguments. EQ_MATCH is the
    default, and tests the equality of the supplied name or value and a pair's
    name or value; NEQ_MATCH tests their inequality;
    IN_MATCH test whether the value in the argument occurs anywhere in
    the pair's respective element; and NZ_MATCH is a case insensitive 
    match for names, for use when searching headers.

    You can limit the number of records returned by supplying an integer to n,
    and switch the search direction (to go from the last pair to the first)
    by passing True to reverse.
    """

    if name is None and value is None:
        raise ValueError("At least one of (name, value) must be a string.")
    if name is not None and not isinstance(name, str):
        raise TypeError("name must be a string.")
    if value is not None and not isinstance(value, str):
        raise TypeError("value must be a string.")
    if n is None: pass
    elif not isinstance(n, int):
        raise TypeError("n must be an integer.")
    elif n < 0:
        raise ValueError("n must be positive integer.")

    if name is not None and nameMatch == NZ_MATCH:
        name = normalizeHeaderName(name)

    # These lamdas implement the (programmable) logic specified  by the
    # nameMatch/valueMatch arguments, and by the presence/absense of
    # name/value, respectively. None is an error condition.
    nameMatches = \
        (lambda n: name == normalizeHeaderName(n)) if nameMatch == NZ_MATCH else \
        (lambda n: name == n) if nameMatch == EQ_MATCH else \
        (lambda n: name != n) if nameMatch == NEQ_MATCH else \
        (lambda n: name in n) if nameMatch == IN_MATCH else \
        None
    valueMatches = \
        (lambda v: value in v) if valueMatch == IN_MATCH else \
        (lambda v: value == v) if valueMatch == EQ_MATCH else \
        (lambda v: value != v) if valueMatch == NEQ_MATCH else \
        None
    pairMatches = \
        (lambda n, v: nameMatches(n)) if value is None else \
        (lambda n, v: valueMatches(v)) if name is None else \
        (lambda n, v: nameMatches(n) and valueMatches(v))
    if None in (nameMatches, valueMatches):
        raise ValueError(
            "Could not comply with matching directives. Please check your arguments."
        )
        # bad nameMatch or valueMatch argument

    for index, p in (
        zip(xrange(len(pairs)), pairs) if not reverse else \
        zip(xrange(len(pairs)-1, 0-1, -1), pairs[::-1])
    ):
        if n is not None and n <= 0: break

        if not isinstance(p, tuple):
            raise TypeError("pairs must be contain tuples.")
        if len(p) != 2:
            raise ValueError("pairs must be in the form (name, value).")
        if not (isinstance(p[0], str) and isinstance(p[1], str)):
            raise TypeError("pairs must be made up of strings.")

        if pairMatches(*p):
            if n is not None: n -= 1
            yield index