def parse_url(url, allow_defaults=True):
    """Return a tuple (`host`, `port`, `ssl`) from the URL specified in the
    `url` parameter.

    The returned `ssl` item is a boolean indicating the use of SSL, and is
    recognized from the URL scheme (http vs. https). If none of these schemes
    is specified in the URL, the returned value defaults to False
    (non-SSL/http).

    The returned `port` item is the port number, as an integer. If there is
    no port number specified in the URL, the returned value defaults to 5988
    for non-SSL/http, and to 5989 for SSL/https.

    The returned `host` item is the host portion of the URL, as a string.
    The host portion may be specified in the URL as a short or long host name,
    dotted IPv4 address, or bracketed IPv6 address with or without zone index
    (aka scope ID). An IPv6 address is converted from the RFC6874 URI syntax
    to the RFC4007 text representation syntax before being returned, by
    removing the brackets and converting the zone index (if present) from
    "-eth0" to "%eth0".

    Examples for valid URLs can be found in the test program
    `tests/unittest/pywbem/test_cim_http.py`.

    Parameters:

      url:

      allow_defaults - If `True` (default) allow defaults for scheme and
        port. If `False`, raise exception for invalid or missing scheme or
        port.

    Returns:

      tuple of (`host`, `port`, `ssl`)

    Raises:

      ValueError: Exception raised if allow_defaults = False and either
        scheme or port are invalid or missing
    """

    default_ssl = False             # default SSL use (for no or unknown scheme)

    # Look for scheme.
    matches = re.match(r"^(https?)://(.*)$", url, re.I)
    _scheme = None
    if matches:
        _scheme = matches.group(1).lower()
        hostport = matches.group(2)
        ssl = (_scheme == 'https')
    else:
        if not allow_defaults:
            raise ValueError(
                _format("URL {0!A} invalid scheme component", url))
        # The URL specified no scheme (or a scheme other than the expected
        # schemes, but we don't check)
        ssl = default_ssl
        hostport = url

    # Remove trailing path segments, if any.
    # Having URL components other than just slashes (e.g. '#' or '?') is not
    # allowed (but we don't check).
    result = hostport.find("/")
    if result >= 0:
        hostport = hostport[0:result]

    # Look for port.
    # This regexp also works for (colon-separated) IPv6 addresses, because they
    # must be bracketed in a URL.
    matches = re.search(r":([0-9]+)$", hostport)
    if matches:
        host = hostport[0:matches.start(0)]
        port = int(matches.group(1))
    else:
        if not allow_defaults:
            raise ValueError(
                _format("URL {0!A} invalid host/port component", url))
        host = hostport
        port = DEFAULT_PORT_HTTPS if ssl else DEFAULT_PORT_HTTP

    # Reformat IPv6 addresses from RFC6874 URI syntax to RFC4007 text
    # representation syntax:
    #   - Remove the brackets.
    #   - Convert the zone index (aka scope ID) from "-eth0" to "%eth0".
    # Note on the regexp below: The first group needs the '?' after '.+' to
    # become non-greedy; in greedy mode, the optional second group would never
    # be matched.
    matches = re.match(r"^\[(.+?)(?:-(.+))?\]$", host)
    if matches:
        # It is an IPv6 address
        host = matches.group(1)
        if matches.group(2) is not None:
            # The zone index is present
            host += "%" + matches.group(2)

    return host, port, ssl
Return a tuple (`host`, `port`, `ssl`) from the URL specified in the
    `url` parameter.

    The returned `ssl` item is a boolean indicating the use of SSL, and is
    recognized from the URL scheme (http vs. https). If none of these schemes
    is specified in the URL, the returned value defaults to False
    (non-SSL/http).

    The returned `port` item is the port number, as an integer. If there is
    no port number specified in the URL, the returned value defaults to 5988
    for non-SSL/http, and to 5989 for SSL/https.

    The returned `host` item is the host portion of the URL, as a string.
    The host portion may be specified in the URL as a short or long host name,
    dotted IPv4 address, or bracketed IPv6 address with or without zone index
    (aka scope ID). An IPv6 address is converted from the RFC6874 URI syntax
    to the RFC4007 text representation syntax before being returned, by
    removing the brackets and converting the zone index (if present) from
    "-eth0" to "%eth0".

    Examples for valid URLs can be found in the test program
    `tests/unittest/pywbem/test_cim_http.py`.

    Parameters:

      url:

      allow_defaults - If `True` (default) allow defaults for scheme and
        port. If `False`, raise exception for invalid or missing scheme or
        port.

    Returns:

      tuple of (`host`, `port`, `ssl`)

    Raises:

      ValueError: Exception raised if allow_defaults = False and either
        scheme or port are invalid or missing