# HG changeset patch # User Valentin Bartenev # Date 1418405142 -10800 # Node ID 99751fe3bc3b285801b434f7f707d87fa42b093e # Parent 33c08d7e2915e6960fc1319726cc4e967d4e94e7 Autoindex: implemented XML output format. diff -r 33c08d7e2915 -r 99751fe3bc3b src/http/modules/ngx_http_autoindex_module.c --- a/src/http/modules/ngx_http_autoindex_module.c Fri Dec 12 20:25:35 2014 +0300 +++ b/src/http/modules/ngx_http_autoindex_module.c Fri Dec 12 20:25:42 2014 +0300 @@ -48,6 +48,7 @@ #define NGX_HTTP_AUTOINDEX_HTML 0 #define NGX_HTTP_AUTOINDEX_JSON 1 #define NGX_HTTP_AUTOINDEX_JSONP 2 +#define NGX_HTTP_AUTOINDEX_XML 3 #define NGX_HTTP_AUTOINDEX_PREALLOCATE 50 @@ -60,6 +61,8 @@ ngx_array_t *entries, ngx_str_t *callback); static ngx_int_t ngx_http_autoindex_jsonp_callback(ngx_http_request_t *r, ngx_str_t *callback); +static ngx_buf_t *ngx_http_autoindex_xml(ngx_http_request_t *r, + ngx_array_t *entries); static int ngx_libc_cdecl ngx_http_autoindex_cmp_entries(const void *one, const void *two); @@ -76,6 +79,7 @@ { ngx_string("html"), NGX_HTTP_AUTOINDEX_HTML }, { ngx_string("json"), NGX_HTTP_AUTOINDEX_JSON }, { ngx_string("jsonp"), NGX_HTTP_AUTOINDEX_JSONP }, + { ngx_string("xml"), NGX_HTTP_AUTOINDEX_XML }, { ngx_null_string, 0 } }; @@ -259,6 +263,11 @@ ngx_str_set(&r->headers_out.content_type, "application/javascript"); break; + case NGX_HTTP_AUTOINDEX_XML: + ngx_str_set(&r->headers_out.content_type, "text/xml"); + ngx_str_set(&r->headers_out.charset, "utf-8"); + break; + default: /* NGX_HTTP_AUTOINDEX_HTML */ ngx_str_set(&r->headers_out.content_type, "text/html"); break; @@ -388,6 +397,10 @@ b = ngx_http_autoindex_json(r, &entries, &callback); break; + case NGX_HTTP_AUTOINDEX_XML: + b = ngx_http_autoindex_xml(r, &entries); + break; + default: /* NGX_HTTP_AUTOINDEX_HTML */ b = ngx_http_autoindex_html(r, &entries); break; @@ -821,6 +834,98 @@ } +static ngx_buf_t * +ngx_http_autoindex_xml(ngx_http_request_t *r, ngx_array_t *entries) +{ + size_t len; + ngx_tm_t tm; + ngx_buf_t *b; + ngx_str_t type; + ngx_uint_t i; + ngx_http_autoindex_entry_t *entry; + + static u_char head[] = "" CRLF "" CRLF; + static u_char tail[] = "" CRLF; + + len = sizeof(head) - 1 + sizeof(tail) - 1; + + entry = entries->elts; + + for (i = 0; i < entries->nelts; i++) { + entry[i].escape = ngx_escape_html(NULL, entry[i].name.data, + entry[i].name.len); + + len += sizeof("" CRLF) - 1 + + entry[i].name.len + entry[i].escape + + sizeof(" mtime=\"1986-12-31T10:00:00Z\"") - 1; + + if (entry[i].file) { + len += sizeof(" size=\"\"") - 1 + NGX_OFF_T_LEN; + } + } + + b = ngx_create_temp_buf(r->pool, len); + if (b == NULL) { + return NULL; + } + + b->last = ngx_cpymem(b->last, head, sizeof(head) - 1); + + for (i = 0; i < entries->nelts; i++) { + *b->last++ = '<'; + + if (entry[i].dir) { + ngx_str_set(&type, "directory"); + + } else if (entry[i].file) { + ngx_str_set(&type, "file"); + + } else { + ngx_str_set(&type, "other"); + } + + b->last = ngx_cpymem(b->last, type.data, type.len); + + b->last = ngx_cpymem(b->last, " mtime=\"", sizeof(" mtime=\"") - 1); + + ngx_gmtime(entry[i].mtime, &tm); + + b->last = ngx_sprintf(b->last, "%4d-%02d-%02dT%02d:%02d:%02dZ", + tm.ngx_tm_year, tm.ngx_tm_mon, + tm.ngx_tm_mday, tm.ngx_tm_hour, + tm.ngx_tm_min, tm.ngx_tm_sec); + + if (entry[i].file) { + b->last = ngx_cpymem(b->last, "\" size=\"", + sizeof("\" size=\"") - 1); + b->last = ngx_sprintf(b->last, "%O", entry[i].size); + } + + *b->last++ = '"'; *b->last++ = '>'; + + if (entry[i].escape) { + b->last = (u_char *) ngx_escape_html(b->last, entry[i].name.data, + entry[i].name.len); + } else { + b->last = ngx_cpymem(b->last, entry[i].name.data, + entry[i].name.len); + } + + *b->last++ = '<'; *b->last++ = '/'; + + b->last = ngx_cpymem(b->last, type.data, type.len); + + *b->last++ = '>'; + + *b->last++ = CR; *b->last++ = LF; + } + + b->last = ngx_cpymem(b->last, tail, sizeof(tail) - 1); + + return b; +} + + static int ngx_libc_cdecl ngx_http_autoindex_cmp_entries(const void *one, const void *two) {