Mercurial > hg > nginx
comparison src/http/modules/ngx_http_autoindex_module.c @ 5945:99751fe3bc3b
Autoindex: implemented XML output format.
author | Valentin Bartenev <vbart@nginx.com> |
---|---|
date | Fri, 12 Dec 2014 20:25:42 +0300 |
parents | 33c08d7e2915 |
children | 044cb349fd3c |
comparison
equal
deleted
inserted
replaced
5944:33c08d7e2915 | 5945:99751fe3bc3b |
---|---|
46 | 46 |
47 | 47 |
48 #define NGX_HTTP_AUTOINDEX_HTML 0 | 48 #define NGX_HTTP_AUTOINDEX_HTML 0 |
49 #define NGX_HTTP_AUTOINDEX_JSON 1 | 49 #define NGX_HTTP_AUTOINDEX_JSON 1 |
50 #define NGX_HTTP_AUTOINDEX_JSONP 2 | 50 #define NGX_HTTP_AUTOINDEX_JSONP 2 |
51 #define NGX_HTTP_AUTOINDEX_XML 3 | |
51 | 52 |
52 #define NGX_HTTP_AUTOINDEX_PREALLOCATE 50 | 53 #define NGX_HTTP_AUTOINDEX_PREALLOCATE 50 |
53 | 54 |
54 #define NGX_HTTP_AUTOINDEX_NAME_LEN 50 | 55 #define NGX_HTTP_AUTOINDEX_NAME_LEN 50 |
55 | 56 |
58 ngx_array_t *entries); | 59 ngx_array_t *entries); |
59 static ngx_buf_t *ngx_http_autoindex_json(ngx_http_request_t *r, | 60 static ngx_buf_t *ngx_http_autoindex_json(ngx_http_request_t *r, |
60 ngx_array_t *entries, ngx_str_t *callback); | 61 ngx_array_t *entries, ngx_str_t *callback); |
61 static ngx_int_t ngx_http_autoindex_jsonp_callback(ngx_http_request_t *r, | 62 static ngx_int_t ngx_http_autoindex_jsonp_callback(ngx_http_request_t *r, |
62 ngx_str_t *callback); | 63 ngx_str_t *callback); |
64 static ngx_buf_t *ngx_http_autoindex_xml(ngx_http_request_t *r, | |
65 ngx_array_t *entries); | |
63 | 66 |
64 static int ngx_libc_cdecl ngx_http_autoindex_cmp_entries(const void *one, | 67 static int ngx_libc_cdecl ngx_http_autoindex_cmp_entries(const void *one, |
65 const void *two); | 68 const void *two); |
66 static ngx_int_t ngx_http_autoindex_error(ngx_http_request_t *r, | 69 static ngx_int_t ngx_http_autoindex_error(ngx_http_request_t *r, |
67 ngx_dir_t *dir, ngx_str_t *name); | 70 ngx_dir_t *dir, ngx_str_t *name); |
74 | 77 |
75 static ngx_conf_enum_t ngx_http_autoindex_format[] = { | 78 static ngx_conf_enum_t ngx_http_autoindex_format[] = { |
76 { ngx_string("html"), NGX_HTTP_AUTOINDEX_HTML }, | 79 { ngx_string("html"), NGX_HTTP_AUTOINDEX_HTML }, |
77 { ngx_string("json"), NGX_HTTP_AUTOINDEX_JSON }, | 80 { ngx_string("json"), NGX_HTTP_AUTOINDEX_JSON }, |
78 { ngx_string("jsonp"), NGX_HTTP_AUTOINDEX_JSONP }, | 81 { ngx_string("jsonp"), NGX_HTTP_AUTOINDEX_JSONP }, |
82 { ngx_string("xml"), NGX_HTTP_AUTOINDEX_XML }, | |
79 { ngx_null_string, 0 } | 83 { ngx_null_string, 0 } |
80 }; | 84 }; |
81 | 85 |
82 | 86 |
83 static ngx_command_t ngx_http_autoindex_commands[] = { | 87 static ngx_command_t ngx_http_autoindex_commands[] = { |
257 | 261 |
258 case NGX_HTTP_AUTOINDEX_JSONP: | 262 case NGX_HTTP_AUTOINDEX_JSONP: |
259 ngx_str_set(&r->headers_out.content_type, "application/javascript"); | 263 ngx_str_set(&r->headers_out.content_type, "application/javascript"); |
260 break; | 264 break; |
261 | 265 |
266 case NGX_HTTP_AUTOINDEX_XML: | |
267 ngx_str_set(&r->headers_out.content_type, "text/xml"); | |
268 ngx_str_set(&r->headers_out.charset, "utf-8"); | |
269 break; | |
270 | |
262 default: /* NGX_HTTP_AUTOINDEX_HTML */ | 271 default: /* NGX_HTTP_AUTOINDEX_HTML */ |
263 ngx_str_set(&r->headers_out.content_type, "text/html"); | 272 ngx_str_set(&r->headers_out.content_type, "text/html"); |
264 break; | 273 break; |
265 } | 274 } |
266 | 275 |
384 b = ngx_http_autoindex_json(r, &entries, NULL); | 393 b = ngx_http_autoindex_json(r, &entries, NULL); |
385 break; | 394 break; |
386 | 395 |
387 case NGX_HTTP_AUTOINDEX_JSONP: | 396 case NGX_HTTP_AUTOINDEX_JSONP: |
388 b = ngx_http_autoindex_json(r, &entries, &callback); | 397 b = ngx_http_autoindex_json(r, &entries, &callback); |
398 break; | |
399 | |
400 case NGX_HTTP_AUTOINDEX_XML: | |
401 b = ngx_http_autoindex_xml(r, &entries); | |
389 break; | 402 break; |
390 | 403 |
391 default: /* NGX_HTTP_AUTOINDEX_HTML */ | 404 default: /* NGX_HTTP_AUTOINDEX_HTML */ |
392 b = ngx_http_autoindex_html(r, &entries); | 405 b = ngx_http_autoindex_html(r, &entries); |
393 break; | 406 break; |
819 | 832 |
820 return NGX_OK; | 833 return NGX_OK; |
821 } | 834 } |
822 | 835 |
823 | 836 |
837 static ngx_buf_t * | |
838 ngx_http_autoindex_xml(ngx_http_request_t *r, ngx_array_t *entries) | |
839 { | |
840 size_t len; | |
841 ngx_tm_t tm; | |
842 ngx_buf_t *b; | |
843 ngx_str_t type; | |
844 ngx_uint_t i; | |
845 ngx_http_autoindex_entry_t *entry; | |
846 | |
847 static u_char head[] = "<?xml version=\"1.0\"?>" CRLF "<list>" CRLF; | |
848 static u_char tail[] = "</list>" CRLF; | |
849 | |
850 len = sizeof(head) - 1 + sizeof(tail) - 1; | |
851 | |
852 entry = entries->elts; | |
853 | |
854 for (i = 0; i < entries->nelts; i++) { | |
855 entry[i].escape = ngx_escape_html(NULL, entry[i].name.data, | |
856 entry[i].name.len); | |
857 | |
858 len += sizeof("<directory></directory>" CRLF) - 1 | |
859 + entry[i].name.len + entry[i].escape | |
860 + sizeof(" mtime=\"1986-12-31T10:00:00Z\"") - 1; | |
861 | |
862 if (entry[i].file) { | |
863 len += sizeof(" size=\"\"") - 1 + NGX_OFF_T_LEN; | |
864 } | |
865 } | |
866 | |
867 b = ngx_create_temp_buf(r->pool, len); | |
868 if (b == NULL) { | |
869 return NULL; | |
870 } | |
871 | |
872 b->last = ngx_cpymem(b->last, head, sizeof(head) - 1); | |
873 | |
874 for (i = 0; i < entries->nelts; i++) { | |
875 *b->last++ = '<'; | |
876 | |
877 if (entry[i].dir) { | |
878 ngx_str_set(&type, "directory"); | |
879 | |
880 } else if (entry[i].file) { | |
881 ngx_str_set(&type, "file"); | |
882 | |
883 } else { | |
884 ngx_str_set(&type, "other"); | |
885 } | |
886 | |
887 b->last = ngx_cpymem(b->last, type.data, type.len); | |
888 | |
889 b->last = ngx_cpymem(b->last, " mtime=\"", sizeof(" mtime=\"") - 1); | |
890 | |
891 ngx_gmtime(entry[i].mtime, &tm); | |
892 | |
893 b->last = ngx_sprintf(b->last, "%4d-%02d-%02dT%02d:%02d:%02dZ", | |
894 tm.ngx_tm_year, tm.ngx_tm_mon, | |
895 tm.ngx_tm_mday, tm.ngx_tm_hour, | |
896 tm.ngx_tm_min, tm.ngx_tm_sec); | |
897 | |
898 if (entry[i].file) { | |
899 b->last = ngx_cpymem(b->last, "\" size=\"", | |
900 sizeof("\" size=\"") - 1); | |
901 b->last = ngx_sprintf(b->last, "%O", entry[i].size); | |
902 } | |
903 | |
904 *b->last++ = '"'; *b->last++ = '>'; | |
905 | |
906 if (entry[i].escape) { | |
907 b->last = (u_char *) ngx_escape_html(b->last, entry[i].name.data, | |
908 entry[i].name.len); | |
909 } else { | |
910 b->last = ngx_cpymem(b->last, entry[i].name.data, | |
911 entry[i].name.len); | |
912 } | |
913 | |
914 *b->last++ = '<'; *b->last++ = '/'; | |
915 | |
916 b->last = ngx_cpymem(b->last, type.data, type.len); | |
917 | |
918 *b->last++ = '>'; | |
919 | |
920 *b->last++ = CR; *b->last++ = LF; | |
921 } | |
922 | |
923 b->last = ngx_cpymem(b->last, tail, sizeof(tail) - 1); | |
924 | |
925 return b; | |
926 } | |
927 | |
928 | |
824 static int ngx_libc_cdecl | 929 static int ngx_libc_cdecl |
825 ngx_http_autoindex_cmp_entries(const void *one, const void *two) | 930 ngx_http_autoindex_cmp_entries(const void *one, const void *two) |
826 { | 931 { |
827 ngx_http_autoindex_entry_t *first = (ngx_http_autoindex_entry_t *) one; | 932 ngx_http_autoindex_entry_t *first = (ngx_http_autoindex_entry_t *) one; |
828 ngx_http_autoindex_entry_t *second = (ngx_http_autoindex_entry_t *) two; | 933 ngx_http_autoindex_entry_t *second = (ngx_http_autoindex_entry_t *) two; |