Mercurial > hg > nginx
comparison src/http/modules/ngx_http_xslt_filter_module.c @ 2153:6476e445d6ce
xsl:output's media-type and encoding support
author | Igor Sysoev <igor@sysoev.ru> |
---|---|
date | Tue, 05 Aug 2008 14:24:16 +0000 |
parents | b23e83f5b182 |
children | 4f48a2765da0 |
comparison
equal
deleted
inserted
replaced
2152:b23e83f5b182 | 2153:6476e445d6ce |
---|---|
33 } ngx_http_xslt_sheet_t; | 33 } ngx_http_xslt_sheet_t; |
34 | 34 |
35 | 35 |
36 typedef struct { | 36 typedef struct { |
37 xmlDtdPtr dtd; | 37 xmlDtdPtr dtd; |
38 ngx_array_t sheets; /* ngx_http_xslt_sheet_t */ | 38 ngx_array_t sheets; /* ngx_http_xslt_sheet_t */ |
39 ngx_hash_t types; | 39 ngx_hash_t types; |
40 ngx_array_t *types_keys; | 40 ngx_array_t *types_keys; |
41 } ngx_http_xslt_filter_conf_t; | 41 } ngx_http_xslt_filter_conf_t; |
42 | 42 |
43 | 43 |
45 xmlDocPtr doc; | 45 xmlDocPtr doc; |
46 xmlParserCtxtPtr ctxt; | 46 xmlParserCtxtPtr ctxt; |
47 xmlSAXHandler *sax; | 47 xmlSAXHandler *sax; |
48 ngx_http_request_t *request; | 48 ngx_http_request_t *request; |
49 ngx_array_t params; | 49 ngx_array_t params; |
50 unsigned done:1; | 50 |
51 unsigned html:1; | 51 ngx_uint_t done; /* unsigned done:1; */ |
52 } ngx_http_xslt_filter_ctx_t; | 52 } ngx_http_xslt_filter_ctx_t; |
53 | 53 |
54 | 54 |
55 static ngx_int_t ngx_http_xslt_send(ngx_http_request_t *r, | 55 static ngx_int_t ngx_http_xslt_send(ngx_http_request_t *r, |
56 ngx_http_xslt_filter_ctx_t *ctx, ngx_buf_t *b); | 56 ngx_http_xslt_filter_ctx_t *ctx, ngx_buf_t *b); |
107 | 107 |
108 static ngx_buf_t *ngx_http_xslt_apply_stylesheet(ngx_http_request_t *r, | 108 static ngx_buf_t *ngx_http_xslt_apply_stylesheet(ngx_http_request_t *r, |
109 ngx_http_xslt_filter_ctx_t *ctx); | 109 ngx_http_xslt_filter_ctx_t *ctx); |
110 static ngx_int_t ngx_http_xslt_params(ngx_http_request_t *r, | 110 static ngx_int_t ngx_http_xslt_params(ngx_http_request_t *r, |
111 ngx_http_xslt_filter_ctx_t *ctx, ngx_array_t *params); | 111 ngx_http_xslt_filter_ctx_t *ctx, ngx_array_t *params); |
112 static u_char *ngx_http_xslt_content_type(xsltStylesheetPtr s); | |
113 static u_char *ngx_http_xslt_encoding(xsltStylesheetPtr s); | |
112 static void ngx_http_xslt_cleanup(void *data); | 114 static void ngx_http_xslt_cleanup(void *data); |
113 | 115 |
114 static char *ngx_http_xslt_entities(ngx_conf_t *cf, ngx_command_t *cmd, | 116 static char *ngx_http_xslt_entities(ngx_conf_t *cf, ngx_command_t *cmd, |
115 void *conf); | 117 void *conf); |
116 static char *ngx_http_xslt_stylesheet(ngx_conf_t *cf, ngx_command_t *cmd, | 118 static char *ngx_http_xslt_stylesheet(ngx_conf_t *cf, ngx_command_t *cmd, |
314 ngx_free(b->pos); | 316 ngx_free(b->pos); |
315 return ngx_http_special_response_handler(r, | 317 return ngx_http_special_response_handler(r, |
316 NGX_HTTP_INTERNAL_SERVER_ERROR); | 318 NGX_HTTP_INTERNAL_SERVER_ERROR); |
317 } | 319 } |
318 | 320 |
319 if (ctx->html) { | |
320 r->headers_out.content_type_len = sizeof("text/html") - 1; | |
321 r->headers_out.content_type.len = sizeof("text/html") - 1; | |
322 r->headers_out.content_type.data = (u_char *) "text/html"; | |
323 } | |
324 | |
325 r->headers_out.content_length_n = b->last - b->pos; | 321 r->headers_out.content_length_n = b->last - b->pos; |
326 | 322 |
327 if (r->headers_out.content_length) { | 323 if (r->headers_out.content_length) { |
328 r->headers_out.content_length->hash = 0; | 324 r->headers_out.content_length->hash = 0; |
329 r->headers_out.content_length = NULL; | 325 r->headers_out.content_length = NULL; |
728 | 724 |
729 static ngx_buf_t * | 725 static ngx_buf_t * |
730 ngx_http_xslt_apply_stylesheet(ngx_http_request_t *r, | 726 ngx_http_xslt_apply_stylesheet(ngx_http_request_t *r, |
731 ngx_http_xslt_filter_ctx_t *ctx) | 727 ngx_http_xslt_filter_ctx_t *ctx) |
732 { | 728 { |
733 int len, rc; | 729 int len, rc, doc_type; |
730 u_char *type, *encoding; | |
734 ngx_buf_t *b; | 731 ngx_buf_t *b; |
735 ngx_uint_t i; | 732 ngx_uint_t i; |
736 xmlChar *buf; | 733 xmlChar *buf; |
737 xmlDocPtr doc, res; | 734 xmlDocPtr doc, res; |
738 ngx_http_xslt_sheet_t *sheet; | 735 ngx_http_xslt_sheet_t *sheet; |
772 | 769 |
773 /* reset array elements */ | 770 /* reset array elements */ |
774 ctx->params.nelts = 0; | 771 ctx->params.nelts = 0; |
775 } | 772 } |
776 | 773 |
777 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | 774 /* there must be at least one stylesheet */ |
778 "xslt filter doc type: %d", doc->type); | 775 |
779 | 776 type = ngx_http_xslt_content_type(sheet[i - 1].stylesheet); |
780 ctx->html = (doc->type == XML_HTML_DOCUMENT_NODE) ? 1 : 0; | 777 encoding = ngx_http_xslt_encoding(sheet[i - 1].stylesheet); |
778 doc_type = doc->type; | |
779 | |
780 ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | |
781 "xslt filter type: %d t:%s e:%s", | |
782 doc_type, type ? type : (u_char *) "(null)", | |
783 encoding ? encoding : (u_char *) "(null)"); | |
781 | 784 |
782 rc = xsltSaveResultToString(&buf, &len, doc, sheet[i - 1].stylesheet); | 785 rc = xsltSaveResultToString(&buf, &len, doc, sheet[i - 1].stylesheet); |
783 | 786 |
784 xmlFreeDoc(doc); | 787 xmlFreeDoc(doc); |
785 | 788 |
803 | 806 |
804 b->pos = buf; | 807 b->pos = buf; |
805 b->last = buf + len; | 808 b->last = buf + len; |
806 b->memory = 1; | 809 b->memory = 1; |
807 b->last_buf = 1; | 810 b->last_buf = 1; |
811 | |
812 if (type) { | |
813 len = ngx_strlen(type); | |
814 | |
815 r->headers_out.content_type_len = len; | |
816 r->headers_out.content_type.len = len; | |
817 r->headers_out.content_type.data = type; | |
818 | |
819 } else if (doc_type == XML_HTML_DOCUMENT_NODE) { | |
820 | |
821 r->headers_out.content_type_len = sizeof("text/html") - 1; | |
822 r->headers_out.content_type.len = sizeof("text/html") - 1; | |
823 r->headers_out.content_type.data = (u_char *) "text/html"; | |
824 } | |
825 | |
826 if (encoding) { | |
827 r->headers_out.charset.len = ngx_strlen(encoding); | |
828 r->headers_out.charset.data = encoding; | |
829 } | |
808 | 830 |
809 return b; | 831 return b; |
810 } | 832 } |
811 | 833 |
812 | 834 |
902 | 924 |
903 return NGX_OK; | 925 return NGX_OK; |
904 } | 926 } |
905 | 927 |
906 | 928 |
929 static u_char * | |
930 ngx_http_xslt_content_type(xsltStylesheetPtr s) | |
931 { | |
932 u_char *type; | |
933 | |
934 if (s->mediaType) { | |
935 return s->mediaType; | |
936 } | |
937 | |
938 for (s = s->imports; s; s = s->next) { | |
939 | |
940 type = ngx_http_xslt_content_type(s); | |
941 | |
942 if (type) { | |
943 return type; | |
944 } | |
945 } | |
946 | |
947 return NULL; | |
948 } | |
949 | |
950 | |
951 static u_char * | |
952 ngx_http_xslt_encoding(xsltStylesheetPtr s) | |
953 { | |
954 u_char *encoding; | |
955 | |
956 if (s->encoding) { | |
957 return s->encoding; | |
958 } | |
959 | |
960 for (s = s->imports; s; s = s->next) { | |
961 | |
962 encoding = ngx_http_xslt_encoding(s); | |
963 | |
964 if (encoding) { | |
965 return encoding; | |
966 } | |
967 } | |
968 | |
969 return NULL; | |
970 } | |
971 | |
972 | |
907 static void | 973 static void |
908 ngx_http_xslt_cleanup(void *data) | 974 ngx_http_xslt_cleanup(void *data) |
909 { | 975 { |
910 ngx_free(data); | 976 ngx_free(data); |
911 } | 977 } |