static ssize_t
ngx_http_validate_host(ngx_http_request_t *r, u_char **host, size_t len,
    ngx_uint_t alloc)
{
    u_char  *h, ch;
    size_t   i, dot_pos, host_len;

    enum {
        sw_usual = 0,
        sw_literal,
        sw_rest
    } state;

    dot_pos = len;
    host_len = len;

    h = *host;

    state = sw_usual;

    for (i = 0; i < len; i++) {
        ch = h[i];

        switch (ch) {

        case '.':
            if (dot_pos == i - 1) {
                return 0;
            }
            dot_pos = i;
            break;

        case ':':
            if (state == sw_usual) {
                host_len = i;
                state = sw_rest;
            }
            break;

        case '[':
            if (i == 0) {
                state = sw_literal;
            }
            break;

        case ']':
            if (state == sw_literal) {
                host_len = i + 1;
                state = sw_rest;
            }
            break;

        case '\0':
            return 0;

        default:

            if (ngx_path_separator(ch)) {
                return 0;
            }

            if (ch >= 'A' && ch <= 'Z') {
                alloc = 1;
            }

            break;
        }
    }

    if (dot_pos == host_len - 1) {
        host_len--;
    }

    if (alloc) {
        *host = ngx_pnalloc(r->pool, host_len);
        if (*host == NULL) {
            return -1;
        }

        ngx_strlow(*host, h, host_len);
    }

    return host_len;
}