def process_attributes(cas_response):
    """Handles processing the attributes of a CAS3 SAML 1.1(?) response.

    I've seen three different types:
    1) The <cas:authenticationSuccess> element has several <cas:attribute>
       children, each of which has a 'name' and 'value' attribute.
    2) The <cas:authenticationSuccess> element has one <cas:attributes> child,
       which has several <cas:attribute> children, each of which has sibling
       <cas:name> and <cas:value> children
    3) The <cas:authenticationSuccess> element has several children, of the
       form <cas:{attribute name}>{attribute value}</cas:{attribute_name}>

    This should returns a dict version of the attributes, no matter what form
    they take (or, god forbid, a mix for some reason)

    TODO this needs testing for every case still!
    """
    out = {}
    nsmap = {'cas': 'http://www.yale.edu/tp/cas'}
    loose_attributes = cas_response.findall('*/cas:attribute', nsmap)
    for attribute in loose_attributes:
        key = None
        value = None
        key_elt = attribute.find('cas:name', nsmap)
        value_elt = attribute.find('cas:value', nsmap)
        if key_elt and value_elt:
            key = key_elt.text
            value = value_elt.text
        if attribute.attrib:
            key = attribute.attrib['name']
            value = attribute.attrib['value']
        if key and value:
            out[key] = value
    named_attributes = cas_response.xpath(
        '*/cas:attributes/*[not(cas:attribute)]', namespaces=nsmap)
    for attribute in named_attributes:
        key = attribute.tag.split('}')[-1]
        value = attribute.text
        if key and value:
            out[key] = value
    return out
