uint32_t
ngx_utf8_decode(u_char **p, size_t n)
{
    size_t    len;
    uint32_t  u, i, valid;
    u = **p;
    if (u > 0xf0) {
        u &= 0x07;
        valid = 0xffff;
        len = 3;
    } else if (u > 0xe0) {
        u &= 0x0f;
        valid = 0x7ff;
        len = 2;
    } else if (u > 0xc0) {
        u &= 0x1f;
        valid = 0x7f;
        len = 1;
    } else {
        (*p)++;
        return 0xffffffff;
    }
    if (n - 1 < len) {
        return 0xfffffffe;
    }
    (*p)++;
    while (len) {
        i = *(*p)++;
        if (i < 0x80) {
            return 0xffffffff;
        }
        u = (u << 6) | (i & 0x3f);
        len--;
    }
    if (u > valid) {
        return u;
    }
    return 0xffffffff;
}
['static ngx_int_t\nngx_http_autoindex_handler(ngx_http_request_t *r)\n{\n    u_char                         *last, *filename, scale;\n    off_t                           length;\n    size_t                          len, utf_len, allocated, root;\n    ngx_tm_t                        tm;\n    ngx_err_t                       err;\n    ngx_buf_t                      *b;\n    ngx_int_t                       rc, size;\n    ngx_str_t                       path;\n    ngx_dir_t                       dir;\n    ngx_uint_t                      i, level;\n    ngx_pool_t                     *pool;\n    ngx_time_t                     *tp;\n    ngx_chain_t                     out;\n    ngx_array_t                     entries;\n    ngx_http_autoindex_entry_t     *entry;\n    ngx_http_autoindex_loc_conf_t  *alcf;\n    static char  *months[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",\n                               "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };\n    if (r->uri.data[r->uri.len - 1] != \'/\') {\n        return NGX_DECLINED;\n    }\n    if (r->zero_in_uri) {\n        return NGX_DECLINED;\n    }\n    if (!(r->method & (NGX_HTTP_GET|NGX_HTTP_HEAD))) {\n        return NGX_DECLINED;\n    }\n    alcf = ngx_http_get_module_loc_conf(r, ngx_http_autoindex_module);\n    if (!alcf->enable) {\n        return NGX_DECLINED;\n    }\n    last = ngx_http_map_uri_to_path(r, &path, &root,\n                                    NGX_HTTP_AUTOINDEX_PREALLOCATE);\n    if (last == NULL) {\n        return NGX_HTTP_INTERNAL_SERVER_ERROR;\n    }\n    allocated = path.len;\n    path.len = last - path.data;\n    if (path.len > 1) {\n        path.len--;\n    }\n    path.data[path.len] = \'\\0\';\n    ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,\n                   "http autoindex: \\"%s\\"", path.data);\n    if (ngx_open_dir(&path, &dir) == NGX_ERROR) {\n        err = ngx_errno;\n        if (err == NGX_ENOENT\n            || err == NGX_ENOTDIR\n            || err == NGX_ENAMETOOLONG)\n        {\n            level = NGX_LOG_ERR;\n            rc = NGX_HTTP_NOT_FOUND;\n        } else if (err == NGX_EACCES) {\n            level = NGX_LOG_ERR;\n            rc = NGX_HTTP_FORBIDDEN;\n        } else {\n            level = NGX_LOG_CRIT;\n            rc = NGX_HTTP_INTERNAL_SERVER_ERROR;\n        }\n        ngx_log_error(level, r->connection->log, err,\n                      ngx_open_dir_n " \\"%s\\" failed", path.data);\n        return rc;\n    }\n#if (NGX_SUPPRESS_WARN)\n    ngx_memzero(&entries, sizeof(ngx_array_t));\n#endif\n    pool = r->pool;\n    if (ngx_array_init(&entries, pool, 40, sizeof(ngx_http_autoindex_entry_t))\n        != NGX_OK)\n    {\n        return ngx_http_autoindex_error(r, &dir, &path);\n    }\n    r->headers_out.status = NGX_HTTP_OK;\n    r->headers_out.content_type_len = sizeof("text/html") - 1;\n    r->headers_out.content_type.len = sizeof("text/html") - 1;\n    r->headers_out.content_type.data = (u_char *) "text/html";\n    rc = ngx_http_send_header(r);\n    if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) {\n        if (ngx_close_dir(&dir) == NGX_ERROR) {\n            ngx_log_error(NGX_LOG_ALERT, r->connection->log, ngx_errno,\n                          ngx_close_dir_n " \\"%V\\" failed", &path);\n        }\n        return rc;\n    }\n    filename = path.data;\n    filename[path.len] = \'/\';\n    for ( ;; ) {\n        ngx_set_errno(0);\n        if (ngx_read_dir(&dir) == NGX_ERROR) {\n            err = ngx_errno;\n            if (err != NGX_ENOMOREFILES) {\n                ngx_log_error(NGX_LOG_CRIT, r->connection->log, err,\n                              ngx_read_dir_n " \\"%V\\" failed", &path);\n                return ngx_http_autoindex_error(r, &dir, &path);\n            }\n            break;\n        }\n        ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,\n                       "http autoindex file: \\"%s\\"", ngx_de_name(&dir));\n        len = ngx_de_namelen(&dir);\n        if (ngx_de_name(&dir)[0] == \'.\') {\n            continue;\n        }\n        if (!dir.valid_info) {\n            if (path.len + 1 + len + 1 > allocated) {\n                allocated = path.len + 1 + len + 1\n                                     + NGX_HTTP_AUTOINDEX_PREALLOCATE;\n                filename = ngx_pnalloc(pool, allocated);\n                if (filename == NULL) {\n                    return ngx_http_autoindex_error(r, &dir, &path);\n                }\n                last = ngx_cpystrn(filename, path.data, path.len + 1);\n                *last++ = \'/\';\n            }\n            ngx_cpystrn(last, ngx_de_name(&dir), len + 1);\n            if (ngx_de_info(filename, &dir) == NGX_FILE_ERROR) {\n                err = ngx_errno;\n                if (err != NGX_ENOENT) {\n                    ngx_log_error(NGX_LOG_CRIT, r->connection->log, err,\n                                  ngx_de_info_n " \\"%s\\" failed", filename);\n                    if (err == NGX_EACCES) {\n                        continue;\n                    }\n                    return ngx_http_autoindex_error(r, &dir, &path);\n                }\n                if (ngx_de_link_info(filename, &dir) == NGX_FILE_ERROR) {\n                    ngx_log_error(NGX_LOG_CRIT, r->connection->log, ngx_errno,\n                                  ngx_de_link_info_n " \\"%s\\" failed",\n                                  filename);\n                    return ngx_http_autoindex_error(r, &dir, &path);\n                }\n            }\n        }\n        entry = ngx_array_push(&entries);\n        if (entry == NULL) {\n            return ngx_http_autoindex_error(r, &dir, &path);\n        }\n        entry->name.len = len;\n        entry->name.data = ngx_pnalloc(pool, len + 1);\n        if (entry->name.data == NULL) {\n            return ngx_http_autoindex_error(r, &dir, &path);\n        }\n        ngx_cpystrn(entry->name.data, ngx_de_name(&dir), len + 1);\n        entry->escape = 2 * ngx_escape_uri(NULL, ngx_de_name(&dir), len,\n                                           NGX_ESCAPE_HTML);\n        if (r->utf8) {\n            entry->utf_len = ngx_utf8_length(entry->name.data, entry->name.len);\n        } else {\n            entry->utf_len = len;\n        }\n        entry->dir = ngx_de_is_dir(&dir);\n        entry->mtime = ngx_de_mtime(&dir);\n        entry->size = ngx_de_size(&dir);\n    }\n    if (ngx_close_dir(&dir) == NGX_ERROR) {\n        ngx_log_error(NGX_LOG_ALERT, r->connection->log, ngx_errno,\n                      ngx_close_dir_n " \\"%s\\" failed", &path);\n    }\n    len = sizeof(title) - 1\n          + r->uri.len\n          + sizeof(header) - 1\n          + r->uri.len\n          + sizeof("</h1>") - 1\n          + sizeof("<hr><pre><a href=\\"../\\">../</a>" CRLF) - 1\n          + sizeof("</pre><hr>") - 1\n          + sizeof(tail) - 1;\n    entry = entries.elts;\n    for (i = 0; i < entries.nelts; i++) {\n        len += sizeof("<a href=\\"") - 1\n            + entry[i].name.len + entry[i].escape\n            + 1\n            + sizeof("\\">") - 1\n            + entry[i].name.len - entry[i].utf_len\n            + NGX_HTTP_AUTOINDEX_NAME_LEN + sizeof("&gt;") - 2\n            + sizeof("</a>") - 1\n            + sizeof(" 28-Sep-1970 12:00 ") - 1\n            + 20\n            + 2;\n    }\n    b = ngx_create_temp_buf(r->pool, len);\n    if (b == NULL) {\n        return NGX_HTTP_INTERNAL_SERVER_ERROR;\n    }\n    if (entries.nelts > 1) {\n        ngx_qsort(entry, (size_t) entries.nelts,\n                  sizeof(ngx_http_autoindex_entry_t),\n                  ngx_http_autoindex_cmp_entries);\n    }\n    b->last = ngx_cpymem(b->last, title, sizeof(title) - 1);\n    b->last = ngx_cpymem(b->last, r->uri.data, r->uri.len);\n    b->last = ngx_cpymem(b->last, header, sizeof(header) - 1);\n    b->last = ngx_cpymem(b->last, r->uri.data, r->uri.len);\n    b->last = ngx_cpymem(b->last, "</h1>", sizeof("</h1>") - 1);\n    b->last = ngx_cpymem(b->last, "<hr><pre><a href=\\"../\\">../</a>" CRLF,\n                         sizeof("<hr><pre><a href=\\"../\\">../</a>" CRLF) - 1);\n    tp = ngx_timeofday();\n    for (i = 0; i < entries.nelts; i++) {\n        b->last = ngx_cpymem(b->last, "<a href=\\"", sizeof("<a href=\\"") - 1);\n        if (entry[i].escape) {\n            ngx_escape_uri(b->last, entry[i].name.data, entry[i].name.len,\n                           NGX_ESCAPE_HTML);\n            b->last += entry[i].name.len + entry[i].escape;\n        } else {\n            b->last = ngx_cpymem(b->last, entry[i].name.data,\n                                 entry[i].name.len);\n        }\n        if (entry[i].dir) {\n            *b->last++ = \'/\';\n        }\n        *b->last++ = \'"\';\n        *b->last++ = \'>\';\n        len = entry[i].utf_len;\n        if (entry[i].name.len != len) {\n            if (len > NGX_HTTP_AUTOINDEX_NAME_LEN) {\n                utf_len = NGX_HTTP_AUTOINDEX_NAME_LEN - 3 + 1;\n            } else {\n                utf_len = NGX_HTTP_AUTOINDEX_NAME_LEN + 1;\n            }\n            b->last = ngx_utf8_cpystrn(b->last, entry[i].name.data,\n                                       utf_len, entry[i].name.len + 1);\n            last = b->last;\n        } else {\n            b->last = ngx_cpystrn(b->last, entry[i].name.data,\n                                  NGX_HTTP_AUTOINDEX_NAME_LEN + 1);\n            last = b->last - 3;\n        }\n        if (len > NGX_HTTP_AUTOINDEX_NAME_LEN) {\n            b->last = ngx_cpymem(last, "..&gt;</a>", sizeof("..&gt;</a>") - 1);\n        } else {\n            if (entry[i].dir && NGX_HTTP_AUTOINDEX_NAME_LEN - len > 0) {\n                *b->last++ = \'/\';\n                len++;\n            }\n            b->last = ngx_cpymem(b->last, "</a>", sizeof("</a>") - 1);\n            ngx_memset(b->last, \' \', NGX_HTTP_AUTOINDEX_NAME_LEN - len);\n            b->last += NGX_HTTP_AUTOINDEX_NAME_LEN - len;\n        }\n        *b->last++ = \' \';\n        ngx_gmtime(entry[i].mtime + tp->gmtoff * 60 * alcf->localtime, &tm);\n        b->last = ngx_sprintf(b->last, "%02d-%s-%d %02d:%02d ",\n                              tm.ngx_tm_mday,\n                              months[tm.ngx_tm_mon - 1],\n                              tm.ngx_tm_year,\n                              tm.ngx_tm_hour,\n                              tm.ngx_tm_min);\n        if (alcf->exact_size) {\n            if (entry[i].dir) {\n                b->last = ngx_cpymem(b->last,  "                  -",\n                                     sizeof("                  -") - 1);\n            } else {\n                b->last = ngx_sprintf(b->last, "%19O", entry[i].size);\n            }\n        } else {\n            if (entry[i].dir) {\n                b->last = ngx_cpymem(b->last,  "      -",\n                                     sizeof("      -") - 1);\n            } else {\n                length = entry[i].size;\n                if (length > 1024 * 1024 * 1024 - 1) {\n                    size = (ngx_int_t) (length / (1024 * 1024 * 1024));\n                    if ((length % (1024 * 1024 * 1024))\n                                                > (1024 * 1024 * 1024 / 2 - 1))\n                    {\n                        size++;\n                    }\n                    scale = \'G\';\n                } else if (length > 1024 * 1024 - 1) {\n                    size = (ngx_int_t) (length / (1024 * 1024));\n                    if ((length % (1024 * 1024)) > (1024 * 1024 / 2 - 1)) {\n                        size++;\n                    }\n                    scale = \'M\';\n                } else if (length > 9999) {\n                    size = (ngx_int_t) (length / 1024);\n                    if (length % 1024 > 511) {\n                        size++;\n                    }\n                    scale = \'K\';\n                } else {\n                    size = (ngx_int_t) length;\n                    scale = \'\\0\';\n                }\n                if (scale) {\n                    b->last = ngx_sprintf(b->last, "%6i%c", size, scale);\n                } else {\n                    b->last = ngx_sprintf(b->last, " %6i", size);\n                }\n            }\n        }\n        *b->last++ = CR;\n        *b->last++ = LF;\n    }\n    b->last = ngx_cpymem(b->last, "</pre><hr>", sizeof("</pre><hr>") - 1);\n    b->last = ngx_cpymem(b->last, tail, sizeof(tail) - 1);\n    if (r == r->main) {\n        b->last_buf = 1;\n    }\n    b->last_in_chain = 1;\n    out.buf = b;\n    out.next = NULL;\n    return ngx_http_output_filter(r, &out);\n}', 'size_t\nngx_utf8_length(u_char *p, size_t n)\n{\n    u_char  c, *last;\n    size_t  len;\n    last = p + n;\n    for (len = 0; p < last; len++) {\n        c = *p;\n        if (c < 0x80) {\n            p++;\n            continue;\n        }\n        if (ngx_utf8_decode(&p, n) > 0x10ffff) {\n            return n;\n        }\n    }\n    return len;\n}', 'uint32_t\nngx_utf8_decode(u_char **p, size_t n)\n{\n    size_t    len;\n    uint32_t  u, i, valid;\n    u = **p;\n    if (u > 0xf0) {\n        u &= 0x07;\n        valid = 0xffff;\n        len = 3;\n    } else if (u > 0xe0) {\n        u &= 0x0f;\n        valid = 0x7ff;\n        len = 2;\n    } else if (u > 0xc0) {\n        u &= 0x1f;\n        valid = 0x7f;\n        len = 1;\n    } else {\n        (*p)++;\n        return 0xffffffff;\n    }\n    if (n - 1 < len) {\n        return 0xfffffffe;\n    }\n    (*p)++;\n    while (len) {\n        i = *(*p)++;\n        if (i < 0x80) {\n            return 0xffffffff;\n        }\n        u = (u << 6) | (i & 0x3f);\n        len--;\n    }\n    if (u > valid) {\n        return u;\n    }\n    return 0xffffffff;\n}']