Validate a tree splitted URI in format returned by
    uri_tree_normalize(), raising an exception in case something invalid
    is detected - that is RFC 3986 is not respected - and returning the
    unmodified uri_tree otherwise.

    This function must be called on something similar to the return value
    of uri_tree_normalize() - and not uri_tree_decode() or directly
    uri_split_tree() - to have a meaningful action.

    The following deviations from RFC 3986 - and also design choice - are
    allowed and no exception will be raised in the following cases.

    - IPv4address can contain decimal / octal / hexadecimal representation
      of individual bytes.
    - In a similar way h16 in IPv6address can be zero-prepended.
    - No percent encoding validation is performed, so that non pct-encoded
      sequences begining with an '%' will be leaved untouched later by the
      percent decoding algorithm.
    - This function will not attempt to classify path as path-absolute
      according to the presence of a non-empty authority; paths will always
      be allowed to begin with '//' because the implicit assertion that
      this URI has just been splitted by the Appendix B Regular Expression
      is made, so a (possibly empty) authority was present, and that when
      the intent of the caller is to join the URI it will take appropriate
      measures to guaranty RFC 3986 compliance, by unconditionally or if
      necessary adding an empty authority.

def uri_tree_validate(uri_tree):
    """
    Validate a tree splitted URI in format returned by
    uri_tree_normalize(), raising an exception in case something invalid
    is detected - that is RFC 3986 is not respected - and returning the
    unmodified uri_tree otherwise.

    This function must be called on something similar to the return value
    of uri_tree_normalize() - and not uri_tree_decode() or directly
    uri_split_tree() - to have a meaningful action.

    The following deviations from RFC 3986 - and also design choice - are
    allowed and no exception will be raised in the following cases.

    - IPv4address can contain decimal / octal / hexadecimal representation
      of individual bytes.
    - In a similar way h16 in IPv6address can be zero-prepended.
    - No percent encoding validation is performed, so that non pct-encoded
      sequences begining with an '%' will be leaved untouched later by the
      percent decoding algorithm.
    - This function will not attempt to classify path as path-absolute
      according to the presence of a non-empty authority; paths will always
      be allowed to begin with '//' because the implicit assertion that
      this URI has just been splitted by the Appendix B Regular Expression
      is made, so a (possibly empty) authority was present, and that when
      the intent of the caller is to join the URI it will take appropriate
      measures to guaranty RFC 3986 compliance, by unconditionally or if
      necessary adding an empty authority.
    """
    scheme, authority, path, query, fragment = uri_tree
    if scheme:
        if not valid_scheme(scheme):
            raise InvalidSchemeError, "Invalid scheme %r" % (scheme,)
    if authority:
        user, passwd, host, port = authority
        if user and not __all_in(user, USER_CHAR):
            raise InvalidUserError, "Invalid user %r" % (user,)
        if passwd and not __all_in(passwd, PASSWD_CHAR):
            raise InvalidPasswdError, "Invalid passwd %r" % (passwd,)
        if host:
            type_host = host_type(host)
            if type_host == HOST_REG_NAME:
                if not __all_in(host, REG_NAME_CHAR):
                    raise InvalidRegNameError, "Invalid reg-name %r" % (host,)
            elif type_host == HOST_IP_LITERAL:
                if not __valid_IPLiteral(host):
                    raise InvalidIPLiteralError, "Invalid IP-literal %r" % (host,)
        if port and not __all_in(port, DIGIT):
            raise InvalidPortError, "Invalid port %r" % (port,)
    if path:
        if not __all_in(path, PCHAR):
            raise InvalidPathError, "Invalid path %r - invalid character detected" % (path,)
        if authority and path[0] != '/':
            raise InvalidPathError, "Invalid path %r - non-absolute path can't be used with an authority" % (path,)
        if (not authority) and (not scheme) and (':' in path.split('/', 1)[0]):
            raise InvalidPathError, "Invalid path %r - path-noscheme can't have a ':' if no '/' before" % (path,)
    if query and (not __valid_query(query)):
        raise InvalidQueryError, "Invalid splitted query tuple %r" % (query,)
    if fragment and (not __all_in(fragment, QUEFRAG_CHAR)):
        raise InvalidFragmentError, "Invalid fragment %r" % (fragment,)
    return uri_tree