Mercurial > hg > nginx
annotate src/http/modules/ngx_http_image_filter_module.c @ 3440:88741ec7731a stable-0.7
merge r3294, r3305:
Fix a bug introduced in r2032: After a child process has read a terminate
message from a channel, the process tries to read the channel again.
The kernel (at least FreeBSD) may preempt the process and sends a SIGIO
signal to a master process. The master process sends a new terminate message,
the kernel switches again to the the child process, and the child process
reads the messages instead of an EAGAIN error. And this may repeat over
and over. Being that the child process can not exit the cycle and test
the termination flag set by the message handler.
The fix disallow the master process to send a new terminate message on
SIGIO signal reception. It may send the message only on SIGALARM signal.
author | Igor Sysoev <igor@sysoev.ru> |
---|---|
date | Mon, 01 Feb 2010 15:49:36 +0000 |
parents | 8b2d478de54b |
children | d87088142876 |
rev | line source |
---|---|
2788 | 1 |
2 /* | |
3 * Copyright (C) Igor Sysoev | |
4 */ | |
5 | |
6 | |
7 #include <ngx_config.h> | |
8 #include <ngx_core.h> | |
9 #include <ngx_http.h> | |
2819
43fe53832da7
handle big responses for "size" and "test" image_filters
Igor Sysoev <igor@sysoev.ru>
parents:
2795
diff
changeset
|
10 |
43fe53832da7
handle big responses for "size" and "test" image_filters
Igor Sysoev <igor@sysoev.ru>
parents:
2795
diff
changeset
|
11 #include <gd.h> |
2788 | 12 |
13 | |
14 #define NGX_HTTP_IMAGE_OFF 0 | |
15 #define NGX_HTTP_IMAGE_TEST 1 | |
16 #define NGX_HTTP_IMAGE_SIZE 2 | |
17 #define NGX_HTTP_IMAGE_RESIZE 3 | |
18 #define NGX_HTTP_IMAGE_CROP 4 | |
19 | |
20 | |
21 #define NGX_HTTP_IMAGE_START 0 | |
22 #define NGX_HTTP_IMAGE_READ 1 | |
23 #define NGX_HTTP_IMAGE_PROCESS 2 | |
2819
43fe53832da7
handle big responses for "size" and "test" image_filters
Igor Sysoev <igor@sysoev.ru>
parents:
2795
diff
changeset
|
24 #define NGX_HTTP_IMAGE_PASS 3 |
43fe53832da7
handle big responses for "size" and "test" image_filters
Igor Sysoev <igor@sysoev.ru>
parents:
2795
diff
changeset
|
25 #define NGX_HTTP_IMAGE_DONE 4 |
2788 | 26 |
27 | |
28 #define NGX_HTTP_IMAGE_NONE 0 | |
29 #define NGX_HTTP_IMAGE_JPEG 1 | |
30 #define NGX_HTTP_IMAGE_GIF 2 | |
31 #define NGX_HTTP_IMAGE_PNG 3 | |
32 | |
33 | |
34 #define NGX_HTTP_IMAGE_BUFFERED 0x08 | |
35 | |
36 | |
37 typedef struct { | |
38 ngx_uint_t filter; | |
39 ngx_uint_t width; | |
40 ngx_uint_t height; | |
2848 | 41 ngx_int_t jpeg_quality; |
2788 | 42 |
3244
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
43 ngx_flag_t transparency; |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
44 |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
45 ngx_http_complex_value_t *wcv; |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
46 ngx_http_complex_value_t *hcv; |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
47 |
2788 | 48 size_t buffer_size; |
49 } ngx_http_image_filter_conf_t; | |
50 | |
51 | |
52 typedef struct { | |
53 u_char *image; | |
54 u_char *last; | |
55 | |
56 size_t length; | |
57 | |
58 ngx_uint_t width; | |
59 ngx_uint_t height; | |
60 | |
3244
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
61 ngx_uint_t max_width; |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
62 ngx_uint_t max_height; |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
63 |
2788 | 64 ngx_uint_t phase; |
65 ngx_uint_t type; | |
66 } ngx_http_image_filter_ctx_t; | |
67 | |
68 | |
2819
43fe53832da7
handle big responses for "size" and "test" image_filters
Igor Sysoev <igor@sysoev.ru>
parents:
2795
diff
changeset
|
69 static ngx_int_t ngx_http_image_send(ngx_http_request_t *r, |
43fe53832da7
handle big responses for "size" and "test" image_filters
Igor Sysoev <igor@sysoev.ru>
parents:
2795
diff
changeset
|
70 ngx_http_image_filter_ctx_t *ctx, ngx_chain_t *in); |
2788 | 71 static ngx_uint_t ngx_http_image_test(ngx_http_request_t *r, ngx_chain_t *in); |
72 static ngx_int_t ngx_http_image_read(ngx_http_request_t *r, ngx_chain_t *in); | |
73 static ngx_buf_t *ngx_http_image_process(ngx_http_request_t *r); | |
74 static ngx_buf_t *ngx_http_image_json(ngx_http_request_t *r, | |
75 ngx_http_image_filter_ctx_t *ctx); | |
76 static ngx_buf_t *ngx_http_image_asis(ngx_http_request_t *r, | |
77 ngx_http_image_filter_ctx_t *ctx); | |
78 static void ngx_http_image_length(ngx_http_request_t *r, ngx_buf_t *b); | |
79 static ngx_int_t ngx_http_image_size(ngx_http_request_t *r, | |
80 ngx_http_image_filter_ctx_t *ctx); | |
81 | |
82 static ngx_buf_t *ngx_http_image_resize(ngx_http_request_t *r, | |
83 ngx_http_image_filter_ctx_t *ctx); | |
84 static gdImagePtr ngx_http_image_source(ngx_http_request_t *r, | |
85 ngx_http_image_filter_ctx_t *ctx); | |
86 static gdImagePtr ngx_http_image_new(ngx_http_request_t *r, int w, int h, | |
87 int colors); | |
88 static u_char *ngx_http_image_out(ngx_http_request_t *r, ngx_uint_t type, | |
89 gdImagePtr img, int *size); | |
90 static void ngx_http_image_cleanup(void *data); | |
3244
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
91 static ngx_uint_t ngx_http_image_filter_get_value(ngx_http_request_t *r, |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
92 ngx_http_complex_value_t *cv, ngx_uint_t v); |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
93 static ngx_uint_t ngx_http_image_filter_value(ngx_str_t *value); |
2788 | 94 |
95 | |
96 static void *ngx_http_image_filter_create_conf(ngx_conf_t *cf); | |
97 static char *ngx_http_image_filter_merge_conf(ngx_conf_t *cf, void *parent, | |
98 void *child); | |
99 static char *ngx_http_image_filter(ngx_conf_t *cf, ngx_command_t *cmd, | |
100 void *conf); | |
101 static ngx_int_t ngx_http_image_filter_init(ngx_conf_t *cf); | |
102 | |
103 | |
104 static ngx_command_t ngx_http_image_filter_commands[] = { | |
105 | |
106 { ngx_string("image_filter"), | |
107 NGX_HTTP_LOC_CONF|NGX_CONF_TAKE13, | |
108 ngx_http_image_filter, | |
109 NGX_HTTP_LOC_CONF_OFFSET, | |
110 0, | |
111 NULL }, | |
112 | |
2848 | 113 { ngx_string("image_filter_jpeg_quality"), |
114 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, | |
115 ngx_conf_set_num_slot, | |
116 NGX_HTTP_LOC_CONF_OFFSET, | |
117 offsetof(ngx_http_image_filter_conf_t, jpeg_quality), | |
118 NULL }, | |
119 | |
3244
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
120 { ngx_string("image_filter_transparency"), |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
121 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
122 ngx_conf_set_flag_slot, |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
123 NGX_HTTP_LOC_CONF_OFFSET, |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
124 offsetof(ngx_http_image_filter_conf_t, transparency), |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
125 NULL }, |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
126 |
2788 | 127 { ngx_string("image_filter_buffer"), |
128 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, | |
129 ngx_conf_set_size_slot, | |
130 NGX_HTTP_LOC_CONF_OFFSET, | |
131 offsetof(ngx_http_image_filter_conf_t, buffer_size), | |
132 NULL }, | |
133 | |
134 ngx_null_command | |
135 }; | |
136 | |
137 | |
138 static ngx_http_module_t ngx_http_image_filter_module_ctx = { | |
139 NULL, /* preconfiguration */ | |
140 ngx_http_image_filter_init, /* postconfiguration */ | |
141 | |
142 NULL, /* create main configuration */ | |
143 NULL, /* init main configuration */ | |
144 | |
145 NULL, /* create server configuration */ | |
146 NULL, /* merge server configuration */ | |
147 | |
148 ngx_http_image_filter_create_conf, /* create location configuration */ | |
149 ngx_http_image_filter_merge_conf /* merge location configuration */ | |
150 }; | |
151 | |
152 | |
153 ngx_module_t ngx_http_image_filter_module = { | |
154 NGX_MODULE_V1, | |
155 &ngx_http_image_filter_module_ctx, /* module context */ | |
156 ngx_http_image_filter_commands, /* module directives */ | |
157 NGX_HTTP_MODULE, /* module type */ | |
158 NULL, /* init master */ | |
159 NULL, /* init module */ | |
160 NULL, /* init process */ | |
161 NULL, /* init thread */ | |
162 NULL, /* exit thread */ | |
163 NULL, /* exit process */ | |
164 NULL, /* exit master */ | |
165 NGX_MODULE_V1_PADDING | |
166 }; | |
167 | |
168 | |
169 static ngx_http_output_header_filter_pt ngx_http_next_header_filter; | |
170 static ngx_http_output_body_filter_pt ngx_http_next_body_filter; | |
171 | |
172 | |
173 static ngx_str_t ngx_http_image_types[] = { | |
174 ngx_string("image/jpeg"), | |
175 ngx_string("image/gif"), | |
176 ngx_string("image/png") | |
177 }; | |
178 | |
179 | |
180 static ngx_int_t | |
181 ngx_http_image_header_filter(ngx_http_request_t *r) | |
182 { | |
183 off_t len; | |
184 ngx_http_image_filter_ctx_t *ctx; | |
185 ngx_http_image_filter_conf_t *conf; | |
186 | |
187 if (r->headers_out.status == NGX_HTTP_NOT_MODIFIED) { | |
188 return ngx_http_next_header_filter(r); | |
189 } | |
190 | |
2834
0449d289256c
test finalized image filter context before testing image_filter off
Igor Sysoev <igor@sysoev.ru>
parents:
2821
diff
changeset
|
191 ctx = ngx_http_get_module_ctx(r, ngx_http_image_filter_module); |
0449d289256c
test finalized image filter context before testing image_filter off
Igor Sysoev <igor@sysoev.ru>
parents:
2821
diff
changeset
|
192 |
0449d289256c
test finalized image filter context before testing image_filter off
Igor Sysoev <igor@sysoev.ru>
parents:
2821
diff
changeset
|
193 if (ctx) { |
0449d289256c
test finalized image filter context before testing image_filter off
Igor Sysoev <igor@sysoev.ru>
parents:
2821
diff
changeset
|
194 ngx_http_set_ctx(r, NULL, ngx_http_image_filter_module); |
0449d289256c
test finalized image filter context before testing image_filter off
Igor Sysoev <igor@sysoev.ru>
parents:
2821
diff
changeset
|
195 return ngx_http_next_header_filter(r); |
0449d289256c
test finalized image filter context before testing image_filter off
Igor Sysoev <igor@sysoev.ru>
parents:
2821
diff
changeset
|
196 } |
0449d289256c
test finalized image filter context before testing image_filter off
Igor Sysoev <igor@sysoev.ru>
parents:
2821
diff
changeset
|
197 |
2788 | 198 conf = ngx_http_get_module_loc_conf(r, ngx_http_image_filter_module); |
199 | |
200 if (conf->filter == NGX_HTTP_IMAGE_OFF) { | |
201 return ngx_http_next_header_filter(r); | |
202 } | |
203 | |
204 if (r->headers_out.content_type.len | |
205 >= sizeof("multipart/x-mixed-replace") - 1 | |
206 && ngx_strncasecmp(r->headers_out.content_type.data, | |
207 (u_char *) "multipart/x-mixed-replace", | |
208 sizeof("multipart/x-mixed-replace") - 1) | |
209 == 0) | |
210 { | |
211 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, | |
212 "image filter: multipart/x-mixed-replace response"); | |
213 | |
214 return NGX_ERROR; | |
215 } | |
216 | |
217 ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_image_filter_ctx_t)); | |
218 if (ctx == NULL) { | |
219 return NGX_ERROR; | |
220 } | |
221 | |
222 ngx_http_set_ctx(r, ctx, ngx_http_image_filter_module); | |
223 | |
224 len = r->headers_out.content_length_n; | |
225 | |
2795
d82d08314f78
fix building ngx_http_image_filter_module on 64-bit platforms
Igor Sysoev <igor@sysoev.ru>
parents:
2788
diff
changeset
|
226 if (len != -1 && len > (off_t) conf->buffer_size) { |
2788 | 227 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, |
228 "image filter: too big response: %O", len); | |
229 | |
230 return NGX_ERROR; | |
231 } | |
232 | |
233 if (len == -1) { | |
234 ctx->length = conf->buffer_size; | |
235 | |
236 } else { | |
237 ctx->length = (size_t) len; | |
238 } | |
239 | |
240 if (r->headers_out.refresh) { | |
241 r->headers_out.refresh->hash = 0; | |
242 } | |
243 | |
244 r->main_filter_need_in_memory = 1; | |
245 r->allow_ranges = 0; | |
246 | |
247 return NGX_OK; | |
248 } | |
249 | |
250 | |
251 static ngx_int_t | |
252 ngx_http_image_body_filter(ngx_http_request_t *r, ngx_chain_t *in) | |
253 { | |
254 ngx_int_t rc; | |
255 ngx_str_t *ct; | |
256 ngx_chain_t out; | |
257 ngx_http_image_filter_ctx_t *ctx; | |
258 ngx_http_image_filter_conf_t *conf; | |
259 | |
260 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "image filter"); | |
261 | |
262 if (in == NULL) { | |
263 return ngx_http_next_body_filter(r, in); | |
264 } | |
265 | |
266 ctx = ngx_http_get_module_ctx(r, ngx_http_image_filter_module); | |
267 | |
268 if (ctx == NULL) { | |
269 return ngx_http_next_body_filter(r, in); | |
270 } | |
271 | |
272 switch (ctx->phase) { | |
273 | |
274 case NGX_HTTP_IMAGE_START: | |
275 | |
276 ctx->type = ngx_http_image_test(r, in); | |
277 | |
278 conf = ngx_http_get_module_loc_conf(r, ngx_http_image_filter_module); | |
279 | |
280 if (ctx->type == NGX_HTTP_IMAGE_NONE) { | |
281 | |
282 if (conf->filter == NGX_HTTP_IMAGE_SIZE) { | |
283 out.buf = ngx_http_image_json(r, NULL); | |
284 | |
285 if (out.buf) { | |
286 out.next = NULL; | |
2819
43fe53832da7
handle big responses for "size" and "test" image_filters
Igor Sysoev <igor@sysoev.ru>
parents:
2795
diff
changeset
|
287 ctx->phase = NGX_HTTP_IMAGE_DONE; |
2788 | 288 |
2819
43fe53832da7
handle big responses for "size" and "test" image_filters
Igor Sysoev <igor@sysoev.ru>
parents:
2795
diff
changeset
|
289 return ngx_http_image_send(r, ctx, &out); |
2788 | 290 } |
291 } | |
292 | |
293 return ngx_http_filter_finalize_request(r, | |
2821
26e06e009ced
allow to pass image filter errors via the same location where the filter is set
Igor Sysoev <igor@sysoev.ru>
parents:
2819
diff
changeset
|
294 &ngx_http_image_filter_module, |
2788 | 295 NGX_HTTP_UNSUPPORTED_MEDIA_TYPE); |
296 } | |
297 | |
298 /* override content type */ | |
299 | |
300 ct = &ngx_http_image_types[ctx->type - 1]; | |
301 r->headers_out.content_type_len = ct->len; | |
302 r->headers_out.content_type = *ct; | |
2882
896db5a09bd2
reset content_type hash value, this fixes a bug when XSLT responses
Igor Sysoev <igor@sysoev.ru>
parents:
2848
diff
changeset
|
303 r->headers_out.content_type_lowcase = NULL; |
2788 | 304 |
305 if (conf->filter == NGX_HTTP_IMAGE_TEST) { | |
2819
43fe53832da7
handle big responses for "size" and "test" image_filters
Igor Sysoev <igor@sysoev.ru>
parents:
2795
diff
changeset
|
306 ctx->phase = NGX_HTTP_IMAGE_PASS; |
43fe53832da7
handle big responses for "size" and "test" image_filters
Igor Sysoev <igor@sysoev.ru>
parents:
2795
diff
changeset
|
307 |
43fe53832da7
handle big responses for "size" and "test" image_filters
Igor Sysoev <igor@sysoev.ru>
parents:
2795
diff
changeset
|
308 return ngx_http_image_send(r, ctx, in); |
2788 | 309 } |
310 | |
311 ctx->phase = NGX_HTTP_IMAGE_READ; | |
312 | |
313 /* fall through */ | |
314 | |
315 case NGX_HTTP_IMAGE_READ: | |
316 | |
317 rc = ngx_http_image_read(r, in); | |
318 | |
319 if (rc == NGX_AGAIN) { | |
320 return NGX_OK; | |
321 } | |
322 | |
323 if (rc == NGX_ERROR) { | |
324 return ngx_http_filter_finalize_request(r, | |
2821
26e06e009ced
allow to pass image filter errors via the same location where the filter is set
Igor Sysoev <igor@sysoev.ru>
parents:
2819
diff
changeset
|
325 &ngx_http_image_filter_module, |
2788 | 326 NGX_HTTP_UNSUPPORTED_MEDIA_TYPE); |
327 } | |
328 | |
329 /* fall through */ | |
330 | |
331 case NGX_HTTP_IMAGE_PROCESS: | |
332 | |
333 out.buf = ngx_http_image_process(r); | |
334 | |
335 if (out.buf == NULL) { | |
336 return ngx_http_filter_finalize_request(r, | |
2821
26e06e009ced
allow to pass image filter errors via the same location where the filter is set
Igor Sysoev <igor@sysoev.ru>
parents:
2819
diff
changeset
|
337 &ngx_http_image_filter_module, |
2788 | 338 NGX_HTTP_UNSUPPORTED_MEDIA_TYPE); |
339 } | |
340 | |
341 out.next = NULL; | |
2819
43fe53832da7
handle big responses for "size" and "test" image_filters
Igor Sysoev <igor@sysoev.ru>
parents:
2795
diff
changeset
|
342 ctx->phase = NGX_HTTP_IMAGE_PASS; |
43fe53832da7
handle big responses for "size" and "test" image_filters
Igor Sysoev <igor@sysoev.ru>
parents:
2795
diff
changeset
|
343 |
43fe53832da7
handle big responses for "size" and "test" image_filters
Igor Sysoev <igor@sysoev.ru>
parents:
2795
diff
changeset
|
344 return ngx_http_image_send(r, ctx, &out); |
2788 | 345 |
2819
43fe53832da7
handle big responses for "size" and "test" image_filters
Igor Sysoev <igor@sysoev.ru>
parents:
2795
diff
changeset
|
346 case NGX_HTTP_IMAGE_PASS: |
43fe53832da7
handle big responses for "size" and "test" image_filters
Igor Sysoev <igor@sysoev.ru>
parents:
2795
diff
changeset
|
347 |
43fe53832da7
handle big responses for "size" and "test" image_filters
Igor Sysoev <igor@sysoev.ru>
parents:
2795
diff
changeset
|
348 return ngx_http_next_body_filter(r, in); |
2788 | 349 |
350 default: /* NGX_HTTP_IMAGE_DONE */ | |
351 | |
2819
43fe53832da7
handle big responses for "size" and "test" image_filters
Igor Sysoev <igor@sysoev.ru>
parents:
2795
diff
changeset
|
352 rc = ngx_http_next_body_filter(r, NULL); |
43fe53832da7
handle big responses for "size" and "test" image_filters
Igor Sysoev <igor@sysoev.ru>
parents:
2795
diff
changeset
|
353 |
43fe53832da7
handle big responses for "size" and "test" image_filters
Igor Sysoev <igor@sysoev.ru>
parents:
2795
diff
changeset
|
354 /* NGX_ERROR resets any pending data */ |
43fe53832da7
handle big responses for "size" and "test" image_filters
Igor Sysoev <igor@sysoev.ru>
parents:
2795
diff
changeset
|
355 return (rc == NGX_OK) ? NGX_ERROR : rc; |
2788 | 356 } |
2819
43fe53832da7
handle big responses for "size" and "test" image_filters
Igor Sysoev <igor@sysoev.ru>
parents:
2795
diff
changeset
|
357 } |
2788 | 358 |
2819
43fe53832da7
handle big responses for "size" and "test" image_filters
Igor Sysoev <igor@sysoev.ru>
parents:
2795
diff
changeset
|
359 |
43fe53832da7
handle big responses for "size" and "test" image_filters
Igor Sysoev <igor@sysoev.ru>
parents:
2795
diff
changeset
|
360 static ngx_int_t |
43fe53832da7
handle big responses for "size" and "test" image_filters
Igor Sysoev <igor@sysoev.ru>
parents:
2795
diff
changeset
|
361 ngx_http_image_send(ngx_http_request_t *r, ngx_http_image_filter_ctx_t *ctx, |
43fe53832da7
handle big responses for "size" and "test" image_filters
Igor Sysoev <igor@sysoev.ru>
parents:
2795
diff
changeset
|
362 ngx_chain_t *in) |
43fe53832da7
handle big responses for "size" and "test" image_filters
Igor Sysoev <igor@sysoev.ru>
parents:
2795
diff
changeset
|
363 { |
43fe53832da7
handle big responses for "size" and "test" image_filters
Igor Sysoev <igor@sysoev.ru>
parents:
2795
diff
changeset
|
364 ngx_int_t rc; |
2788 | 365 |
366 rc = ngx_http_next_header_filter(r); | |
367 | |
368 if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) { | |
2819
43fe53832da7
handle big responses for "size" and "test" image_filters
Igor Sysoev <igor@sysoev.ru>
parents:
2795
diff
changeset
|
369 return NGX_ERROR; |
2788 | 370 } |
371 | |
2819
43fe53832da7
handle big responses for "size" and "test" image_filters
Igor Sysoev <igor@sysoev.ru>
parents:
2795
diff
changeset
|
372 rc = ngx_http_next_body_filter(r, in); |
43fe53832da7
handle big responses for "size" and "test" image_filters
Igor Sysoev <igor@sysoev.ru>
parents:
2795
diff
changeset
|
373 |
43fe53832da7
handle big responses for "size" and "test" image_filters
Igor Sysoev <igor@sysoev.ru>
parents:
2795
diff
changeset
|
374 if (ctx->phase == NGX_HTTP_IMAGE_DONE) { |
43fe53832da7
handle big responses for "size" and "test" image_filters
Igor Sysoev <igor@sysoev.ru>
parents:
2795
diff
changeset
|
375 /* NGX_ERROR resets any pending data */ |
43fe53832da7
handle big responses for "size" and "test" image_filters
Igor Sysoev <igor@sysoev.ru>
parents:
2795
diff
changeset
|
376 return (rc == NGX_OK) ? NGX_ERROR : rc; |
43fe53832da7
handle big responses for "size" and "test" image_filters
Igor Sysoev <igor@sysoev.ru>
parents:
2795
diff
changeset
|
377 } |
43fe53832da7
handle big responses for "size" and "test" image_filters
Igor Sysoev <igor@sysoev.ru>
parents:
2795
diff
changeset
|
378 |
43fe53832da7
handle big responses for "size" and "test" image_filters
Igor Sysoev <igor@sysoev.ru>
parents:
2795
diff
changeset
|
379 return rc; |
2788 | 380 } |
381 | |
382 | |
383 static ngx_uint_t | |
384 ngx_http_image_test(ngx_http_request_t *r, ngx_chain_t *in) | |
385 { | |
386 u_char *p; | |
387 | |
388 p = in->buf->pos; | |
389 | |
390 if (in->buf->last - p < 16) { | |
391 return NGX_HTTP_IMAGE_NONE; | |
392 } | |
393 | |
394 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | |
395 "image filter: \"%c%c\"", p[0], p[1]); | |
396 | |
397 if (p[0] == 0xff && p[1] == 0xd8) { | |
398 | |
399 /* JPEG */ | |
400 | |
401 return NGX_HTTP_IMAGE_JPEG; | |
402 | |
403 } else if (p[0] == 'G' && p[1] == 'I' && p[2] == 'F' && p[3] == '8' | |
2943 | 404 && p[5] == 'a') |
2788 | 405 { |
2943 | 406 if (p[4] == '9' || p[4] == '7') { |
407 /* GIF */ | |
408 return NGX_HTTP_IMAGE_GIF; | |
409 } | |
2788 | 410 |
411 } else if (p[0] == 0x89 && p[1] == 'P' && p[2] == 'N' && p[3] == 'G' | |
412 && p[4] == 0x0d && p[5] == 0x0a && p[6] == 0x1a && p[7] == 0x0a) | |
413 { | |
414 /* PNG */ | |
415 | |
416 return NGX_HTTP_IMAGE_PNG; | |
417 } | |
418 | |
419 return NGX_HTTP_IMAGE_NONE; | |
420 } | |
421 | |
422 | |
423 static ngx_int_t | |
424 ngx_http_image_read(ngx_http_request_t *r, ngx_chain_t *in) | |
425 { | |
426 u_char *p; | |
427 size_t size, rest; | |
428 ngx_buf_t *b; | |
429 ngx_chain_t *cl; | |
430 ngx_http_image_filter_ctx_t *ctx; | |
431 | |
432 ctx = ngx_http_get_module_ctx(r, ngx_http_image_filter_module); | |
433 | |
434 if (ctx->image == NULL) { | |
435 ctx->image = ngx_palloc(r->pool, ctx->length); | |
436 if (ctx->image == NULL) { | |
437 return NGX_ERROR; | |
438 } | |
439 | |
440 ctx->last = ctx->image; | |
441 } | |
442 | |
443 p = ctx->last; | |
444 | |
445 for (cl = in; cl; cl = cl->next) { | |
446 | |
447 b = cl->buf; | |
448 size = b->last - b->pos; | |
449 | |
450 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | |
451 "image buf: %uz", size); | |
452 | |
453 rest = ctx->image + ctx->length - p; | |
454 size = (rest < size) ? rest : size; | |
455 | |
456 p = ngx_cpymem(p, b->pos, size); | |
457 b->pos += size; | |
458 | |
459 if (b->last_buf) { | |
460 ctx->last = p; | |
461 return NGX_OK; | |
462 } | |
463 } | |
464 | |
465 ctx->last = p; | |
466 r->connection->buffered |= NGX_HTTP_IMAGE_BUFFERED; | |
467 | |
468 return NGX_AGAIN; | |
469 } | |
470 | |
471 | |
472 static ngx_buf_t * | |
473 ngx_http_image_process(ngx_http_request_t *r) | |
474 { | |
475 ngx_int_t rc; | |
476 ngx_http_image_filter_ctx_t *ctx; | |
477 ngx_http_image_filter_conf_t *conf; | |
478 | |
479 r->connection->buffered &= ~NGX_HTTP_IMAGE_BUFFERED; | |
480 | |
481 ctx = ngx_http_get_module_ctx(r, ngx_http_image_filter_module); | |
482 | |
483 rc = ngx_http_image_size(r, ctx); | |
484 | |
485 conf = ngx_http_get_module_loc_conf(r, ngx_http_image_filter_module); | |
486 | |
487 if (conf->filter == NGX_HTTP_IMAGE_SIZE) { | |
3244
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
488 return ngx_http_image_json(r, rc == NGX_OK ? ctx : NULL); |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
489 } |
2788 | 490 |
3244
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
491 ctx->max_width = ngx_http_image_filter_get_value(r, conf->wcv, conf->width); |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
492 if (ctx->max_width == 0) { |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
493 return NULL; |
2788 | 494 } |
495 | |
3244
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
496 ctx->max_height = ngx_http_image_filter_get_value(r, conf->hcv, |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
497 conf->height); |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
498 if (ctx->max_height == 0) { |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
499 return NULL; |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
500 } |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
501 |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
502 if (rc == NGX_OK |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
503 && ctx->width <= ctx->max_width |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
504 && ctx->height <= ctx->max_height) |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
505 { |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
506 return ngx_http_image_asis(r, ctx); |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
507 } |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
508 |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
509 return ngx_http_image_resize(r, ctx); |
2788 | 510 } |
511 | |
512 | |
513 static ngx_buf_t * | |
514 ngx_http_image_json(ngx_http_request_t *r, ngx_http_image_filter_ctx_t *ctx) | |
515 { | |
516 size_t len; | |
517 ngx_buf_t *b; | |
518 | |
519 b = ngx_pcalloc(r->pool, sizeof(ngx_buf_t)); | |
520 if (b == NULL) { | |
521 return NULL; | |
522 } | |
523 | |
524 b->memory = 1; | |
525 b->last_buf = 1; | |
526 | |
527 ngx_http_clean_header(r); | |
528 | |
529 r->headers_out.status = NGX_HTTP_OK; | |
530 r->headers_out.content_type.len = sizeof("text/plain") - 1; | |
531 r->headers_out.content_type.data = (u_char *) "text/plain"; | |
2882
896db5a09bd2
reset content_type hash value, this fixes a bug when XSLT responses
Igor Sysoev <igor@sysoev.ru>
parents:
2848
diff
changeset
|
532 r->headers_out.content_type_lowcase = NULL; |
2788 | 533 |
534 if (ctx == NULL) { | |
535 b->pos = (u_char *) "{}" CRLF; | |
536 b->last = b->pos + sizeof("{}" CRLF) - 1; | |
537 | |
538 ngx_http_image_length(r, b); | |
539 | |
540 return b; | |
541 } | |
542 | |
543 len = sizeof("{ \"img\" : " | |
544 "{ \"width\": , \"height\": , \"type\": \"jpeg\" } }" CRLF) - 1 | |
545 + 2 * NGX_SIZE_T_LEN; | |
546 | |
547 b->pos = ngx_pnalloc(r->pool, len); | |
548 if (b->pos == NULL) { | |
549 return NULL; | |
550 } | |
551 | |
552 b->last = ngx_sprintf(b->pos, | |
553 "{ \"img\" : " | |
554 "{ \"width\": %uz," | |
555 " \"height\": %uz," | |
556 " \"type\": \"%s\" } }" CRLF, | |
557 ctx->width, ctx->height, | |
558 ngx_http_image_types[ctx->type - 1].data + 6); | |
559 | |
560 ngx_http_image_length(r, b); | |
561 | |
562 return b; | |
563 } | |
564 | |
565 | |
566 static ngx_buf_t * | |
567 ngx_http_image_asis(ngx_http_request_t *r, ngx_http_image_filter_ctx_t *ctx) | |
568 { | |
569 ngx_buf_t *b; | |
570 | |
571 b = ngx_pcalloc(r->pool, sizeof(ngx_buf_t)); | |
572 if (b == NULL) { | |
573 return NULL; | |
574 } | |
575 | |
576 b->pos = ctx->image; | |
577 b->last = ctx->last; | |
578 b->memory = 1; | |
579 b->last_buf = 1; | |
580 | |
581 ngx_http_image_length(r, b); | |
582 | |
583 return b; | |
584 } | |
585 | |
586 | |
587 static void | |
588 ngx_http_image_length(ngx_http_request_t *r, ngx_buf_t *b) | |
589 { | |
590 r->headers_out.content_length_n = b->last - b->pos; | |
591 | |
592 if (r->headers_out.content_length) { | |
593 r->headers_out.content_length->hash = 0; | |
594 } | |
595 | |
596 r->headers_out.content_length = NULL; | |
597 } | |
598 | |
599 | |
600 static ngx_int_t | |
601 ngx_http_image_size(ngx_http_request_t *r, ngx_http_image_filter_ctx_t *ctx) | |
602 { | |
603 u_char *p, *last; | |
604 ngx_uint_t width, height; | |
605 | |
606 p = ctx->image; | |
607 | |
608 switch (ctx->type) { | |
609 | |
610 case NGX_HTTP_IMAGE_JPEG: | |
611 | |
612 p += 2; | |
613 last = ctx->image + ctx->length - 10; | |
614 | |
615 while (p < last) { | |
616 | |
617 if (p[0] == 0xff && p[1] != 0xff) { | |
618 | |
619 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | |
620 "JPEG: %02xd %02xd", *p, *(p + 1)); | |
621 | |
622 p++; | |
623 | |
624 if (*p == 0xc0 || *p == 0xc1 || *p == 0xc2 || *p == 0xc3 | |
625 || *p == 0xc9 || *p == 0xca || *p == 0xcb) | |
626 { | |
627 goto found; | |
628 } | |
629 | |
630 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | |
631 "JPEG: %02xd %02xd", p[1], p[2]); | |
632 | |
633 p += p[1] * 256 + p[2]; | |
634 | |
635 continue; | |
636 } | |
637 | |
638 p++; | |
639 } | |
640 | |
641 return NGX_DECLINED; | |
642 | |
643 found: | |
644 | |
645 width = p[6] * 256 + p[7]; | |
646 height = p[4] * 256 + p[5]; | |
647 | |
648 break; | |
649 | |
650 case NGX_HTTP_IMAGE_GIF: | |
651 | |
652 if (ctx->length < 10) { | |
653 return NGX_DECLINED; | |
654 } | |
655 | |
656 width = p[7] * 256 + p[6]; | |
657 height = p[9] * 256 + p[8]; | |
658 | |
659 break; | |
660 | |
661 case NGX_HTTP_IMAGE_PNG: | |
662 | |
663 if (ctx->length < 24) { | |
664 return NGX_DECLINED; | |
665 } | |
666 | |
667 width = p[18] * 256 + p[19]; | |
668 height = p[22] * 256 + p[23]; | |
669 | |
670 break; | |
671 | |
672 default: | |
673 | |
674 return NGX_DECLINED; | |
675 } | |
676 | |
677 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | |
678 "image size: %d x %d", width, height); | |
679 | |
680 ctx->width = width; | |
681 ctx->height = height; | |
682 | |
683 return NGX_OK; | |
684 } | |
685 | |
686 | |
687 static ngx_buf_t * | |
688 ngx_http_image_resize(ngx_http_request_t *r, ngx_http_image_filter_ctx_t *ctx) | |
689 { | |
3244
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
690 int sx, sy, dx, dy, ox, oy, size, |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
691 colors, palette, transparent, |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
692 red, green, blue; |
2788 | 693 u_char *out; |
694 ngx_buf_t *b; | |
695 ngx_uint_t resize; | |
696 gdImagePtr src, dst; | |
697 ngx_pool_cleanup_t *cln; | |
698 ngx_http_image_filter_conf_t *conf; | |
699 | |
700 src = ngx_http_image_source(r, ctx); | |
701 | |
702 if (src == NULL) { | |
703 return NULL; | |
704 } | |
705 | |
706 sx = gdImageSX(src); | |
707 sy = gdImageSY(src); | |
708 | |
709 conf = ngx_http_get_module_loc_conf(r, ngx_http_image_filter_module); | |
710 | |
3244
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
711 if ((ngx_uint_t) sx <= ctx->max_width |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
712 && (ngx_uint_t) sy <= ctx->max_height) |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
713 { |
2788 | 714 gdImageDestroy(src); |
715 return ngx_http_image_asis(r, ctx); | |
716 } | |
717 | |
718 colors = gdImageColorsTotal(src); | |
3244
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
719 |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
720 if (colors && conf->transparency) { |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
721 transparent = gdImageGetTransparent(src); |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
722 |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
723 if (transparent != -1) { |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
724 palette = colors; |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
725 red = gdImageRed(src, transparent); |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
726 green = gdImageGreen(src, transparent); |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
727 blue = gdImageBlue(src, transparent); |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
728 |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
729 goto transparent; |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
730 } |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
731 } |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
732 |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
733 palette = 0; |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
734 transparent = -1; |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
735 red = 0; |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
736 green = 0; |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
737 blue = 0; |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
738 |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
739 transparent: |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
740 |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
741 gdImageColorTransparent(src, -1); |
2788 | 742 |
743 dx = sx; | |
744 dy = sy; | |
745 | |
746 if (conf->filter == NGX_HTTP_IMAGE_RESIZE) { | |
747 | |
3244
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
748 if ((ngx_uint_t) dx > ctx->max_width) { |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
749 dy = dy * ctx->max_width / dx; |
2788 | 750 dy = dy ? dy : 1; |
3244
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
751 dx = ctx->max_width; |
2788 | 752 } |
753 | |
3244
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
754 if ((ngx_uint_t) dy > ctx->max_height) { |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
755 dx = dx * ctx->max_height / dy; |
2788 | 756 dx = dx ? dx : 1; |
3244
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
757 dy = ctx->max_height; |
2788 | 758 } |
759 | |
760 resize = 1; | |
761 | |
762 } else { /* NGX_HTTP_IMAGE_CROP */ | |
763 | |
764 resize = 0; | |
765 | |
3244
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
766 if ((ngx_uint_t) (dx * 100 / dy) |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
767 < ctx->max_width * 100 / ctx->max_height) |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
768 { |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
769 if ((ngx_uint_t) dx > ctx->max_width) { |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
770 dy = dy * ctx->max_width / dx; |
2788 | 771 dy = dy ? dy : 1; |
3244
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
772 dx = ctx->max_width; |
2788 | 773 resize = 1; |
774 } | |
775 | |
776 } else { | |
3244
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
777 if ((ngx_uint_t) dy > ctx->max_height) { |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
778 dx = dx * ctx->max_height / dy; |
2788 | 779 dx = dx ? dx : 1; |
3244
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
780 dy = ctx->max_height; |
2788 | 781 resize = 1; |
782 } | |
783 } | |
784 } | |
785 | |
786 if (resize) { | |
3244
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
787 dst = ngx_http_image_new(r, dx, dy, palette); |
2788 | 788 if (dst == NULL) { |
789 gdImageDestroy(src); | |
790 return NULL; | |
791 } | |
792 | |
3244
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
793 if (colors == 0) { |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
794 gdImageSaveAlpha(dst, 1); |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
795 gdImageAlphaBlending(dst, 0); |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
796 } |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
797 |
2788 | 798 gdImageCopyResampled(dst, src, 0, 0, 0, 0, dx, dy, sx, sy); |
799 | |
3244
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
800 if (colors) { |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
801 gdImageTrueColorToPalette(dst, 1, 256); |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
802 } |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
803 |
2788 | 804 gdImageDestroy(src); |
805 | |
806 } else { | |
807 dst = src; | |
808 } | |
809 | |
810 if (conf->filter == NGX_HTTP_IMAGE_CROP) { | |
811 | |
812 src = dst; | |
813 | |
3244
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
814 if ((ngx_uint_t) dx > ctx->max_width) { |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
815 ox = dx - ctx->max_width; |
2788 | 816 |
817 } else { | |
818 ox = 0; | |
819 } | |
820 | |
3244
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
821 if ((ngx_uint_t) dy > ctx->max_height) { |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
822 oy = dy - ctx->max_height; |
2788 | 823 |
824 } else { | |
825 oy = 0; | |
826 } | |
827 | |
828 if (ox || oy) { | |
829 | |
830 dst = ngx_http_image_new(r, dx - ox, dy - oy, colors); | |
831 | |
832 if (dst == NULL) { | |
833 gdImageDestroy(src); | |
834 return NULL; | |
835 } | |
836 | |
837 ox /= 2; | |
838 oy /= 2; | |
839 | |
840 ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | |
841 "image crop: %d x %d @ %d x %d", | |
842 dx, dy, ox, oy); | |
843 | |
3244
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
844 if (colors == 0) { |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
845 gdImageSaveAlpha(dst, 1); |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
846 gdImageAlphaBlending(dst, 0); |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
847 } |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
848 |
2788 | 849 gdImageCopy(dst, src, 0, 0, ox, oy, dx - ox, dy - oy); |
850 | |
3244
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
851 if (colors) { |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
852 gdImageTrueColorToPalette(dst, 1, 256); |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
853 } |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
854 |
2788 | 855 gdImageDestroy(src); |
856 } | |
857 } | |
858 | |
3244
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
859 if (transparent != -1 && colors) { |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
860 gdImageColorTransparent(dst, gdImageColorExact(dst, red, green, blue)); |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
861 } |
2788 | 862 |
863 out = ngx_http_image_out(r, ctx->type, dst, &size); | |
864 | |
865 ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | |
866 "image: %d x %d %d", sx, sy, colors); | |
867 | |
868 gdImageDestroy(dst); | |
869 ngx_pfree(r->pool, ctx->image); | |
870 | |
871 if (out == NULL) { | |
872 return NULL; | |
873 } | |
874 | |
875 cln = ngx_pool_cleanup_add(r->pool, 0); | |
876 if (cln == NULL) { | |
877 gdFree(out); | |
878 return NULL; | |
879 } | |
880 | |
881 b = ngx_pcalloc(r->pool, sizeof(ngx_buf_t)); | |
882 if (b == NULL) { | |
883 gdFree(out); | |
884 return NULL; | |
885 } | |
886 | |
887 cln->handler = ngx_http_image_cleanup; | |
888 cln->data = out; | |
889 | |
890 b->pos = out; | |
891 b->last = out + size; | |
892 b->memory = 1; | |
893 b->last_buf = 1; | |
894 | |
895 ngx_http_image_length(r, b); | |
896 | |
897 return b; | |
898 } | |
899 | |
900 | |
901 static gdImagePtr | |
902 ngx_http_image_source(ngx_http_request_t *r, ngx_http_image_filter_ctx_t *ctx) | |
903 { | |
904 char *failed; | |
905 gdImagePtr img; | |
906 | |
907 img = NULL; | |
908 | |
909 switch (ctx->type) { | |
910 | |
911 case NGX_HTTP_IMAGE_JPEG: | |
912 img = gdImageCreateFromJpegPtr(ctx->length, ctx->image); | |
913 failed = "gdImageCreateFromJpegPtr() failed"; | |
914 break; | |
915 | |
916 case NGX_HTTP_IMAGE_GIF: | |
917 img = gdImageCreateFromGifPtr(ctx->length, ctx->image); | |
918 failed = "gdImageCreateFromGifPtr() failed"; | |
919 break; | |
920 | |
921 case NGX_HTTP_IMAGE_PNG: | |
922 img = gdImageCreateFromPngPtr(ctx->length, ctx->image); | |
923 failed = "gdImageCreateFromPngPtr() failed"; | |
924 break; | |
925 | |
926 default: | |
927 failed = "unknown image type"; | |
928 break; | |
929 } | |
930 | |
931 if (img == NULL) { | |
932 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, failed); | |
933 } | |
934 | |
935 return img; | |
936 } | |
937 | |
938 | |
939 static gdImagePtr | |
940 ngx_http_image_new(ngx_http_request_t *r, int w, int h, int colors) | |
941 { | |
942 gdImagePtr img; | |
943 | |
944 if (colors == 0) { | |
945 img = gdImageCreateTrueColor(w, h); | |
946 | |
947 if (img == NULL) { | |
948 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, | |
949 "gdImageCreateTrueColor() failed"); | |
950 return NULL; | |
951 } | |
952 | |
953 } else { | |
954 img = gdImageCreate(w, h); | |
955 | |
956 if (img == NULL) { | |
957 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, | |
958 "gdImageCreate() failed"); | |
959 return NULL; | |
960 } | |
961 } | |
962 | |
963 return img; | |
964 } | |
965 | |
966 | |
967 static u_char * | |
968 ngx_http_image_out(ngx_http_request_t *r, ngx_uint_t type, gdImagePtr img, | |
969 int *size) | |
970 { | |
2848 | 971 char *failed; |
972 u_char *out; | |
973 ngx_http_image_filter_conf_t *conf; | |
2788 | 974 |
975 out = NULL; | |
976 | |
977 switch (type) { | |
978 | |
979 case NGX_HTTP_IMAGE_JPEG: | |
2848 | 980 conf = ngx_http_get_module_loc_conf(r, ngx_http_image_filter_module); |
981 out = gdImageJpegPtr(img, size, conf->jpeg_quality); | |
2788 | 982 failed = "gdImageJpegPtr() failed"; |
983 break; | |
984 | |
985 case NGX_HTTP_IMAGE_GIF: | |
986 out = gdImageGifPtr(img, size); | |
987 failed = "gdImageGifPtr() failed"; | |
988 break; | |
989 | |
990 case NGX_HTTP_IMAGE_PNG: | |
991 out = gdImagePngPtr(img, size); | |
992 failed = "gdImagePngPtr() failed"; | |
993 break; | |
994 | |
995 default: | |
996 failed = "unknown image type"; | |
997 break; | |
998 } | |
999 | |
1000 if (out == NULL) { | |
1001 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, failed); | |
1002 } | |
1003 | |
1004 return out; | |
1005 } | |
1006 | |
1007 | |
1008 static void | |
1009 ngx_http_image_cleanup(void *data) | |
1010 { | |
1011 gdFree(data); | |
1012 } | |
1013 | |
1014 | |
3244
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
1015 static ngx_uint_t |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
1016 ngx_http_image_filter_get_value(ngx_http_request_t *r, |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
1017 ngx_http_complex_value_t *cv, ngx_uint_t v) |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
1018 { |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
1019 ngx_str_t val; |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
1020 |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
1021 if (cv == NULL) { |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
1022 return v; |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
1023 } |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
1024 |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
1025 if (ngx_http_complex_value(r, cv, &val) != NGX_OK) { |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
1026 return 0; |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
1027 } |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
1028 |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
1029 return ngx_http_image_filter_value(&val); |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
1030 } |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
1031 |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
1032 |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
1033 static ngx_uint_t |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
1034 ngx_http_image_filter_value(ngx_str_t *value) |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
1035 { |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
1036 ngx_int_t n; |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
1037 |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
1038 if (value->len == 1 && value->data[0] == '-') { |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
1039 return (ngx_uint_t) -1; |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
1040 } |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
1041 |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
1042 n = ngx_atoi(value->data, value->len); |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
1043 |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
1044 if (n > 0) { |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
1045 return (ngx_uint_t) n; |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
1046 } |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
1047 |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
1048 return 0; |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
1049 } |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
1050 |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
1051 |
2788 | 1052 static void * |
1053 ngx_http_image_filter_create_conf(ngx_conf_t *cf) | |
1054 { | |
1055 ngx_http_image_filter_conf_t *conf; | |
1056 | |
1057 conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_image_filter_conf_t)); | |
1058 if (conf == NULL) { | |
3237
2efa8d2fcde1
merge r2903, r2911, r2912, r3002:
Igor Sysoev <igor@sysoev.ru>
parents:
2943
diff
changeset
|
1059 return NULL; |
2788 | 1060 } |
1061 | |
1062 conf->filter = NGX_CONF_UNSET_UINT; | |
2848 | 1063 conf->jpeg_quality = NGX_CONF_UNSET; |
3244
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
1064 conf->transparency = NGX_CONF_UNSET; |
2788 | 1065 conf->buffer_size = NGX_CONF_UNSET_SIZE; |
1066 | |
1067 return conf; | |
1068 } | |
1069 | |
1070 | |
1071 static char * | |
1072 ngx_http_image_filter_merge_conf(ngx_conf_t *cf, void *parent, void *child) | |
1073 { | |
1074 ngx_http_image_filter_conf_t *prev = parent; | |
1075 ngx_http_image_filter_conf_t *conf = child; | |
1076 | |
1077 if (conf->filter == NGX_CONF_UNSET_UINT) { | |
1078 | |
1079 if (prev->filter == NGX_CONF_UNSET_UINT) { | |
1080 conf->filter = NGX_HTTP_IMAGE_OFF; | |
1081 | |
1082 } else { | |
1083 conf->filter = prev->filter; | |
1084 conf->width = prev->width; | |
1085 conf->height = prev->height; | |
3244
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
1086 conf->wcv = prev->wcv; |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
1087 conf->hcv = prev->hcv; |
2788 | 1088 } |
1089 } | |
1090 | |
2848 | 1091 /* 75 is libjpeg default quality */ |
1092 ngx_conf_merge_value(conf->jpeg_quality, prev->jpeg_quality, 75); | |
1093 | |
3244
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
1094 ngx_conf_merge_value(conf->transparency, prev->transparency, 1); |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
1095 |
2788 | 1096 ngx_conf_merge_size_value(conf->buffer_size, prev->buffer_size, |
1097 1 * 1024 * 1024); | |
1098 | |
1099 return NGX_CONF_OK; | |
1100 } | |
1101 | |
1102 | |
1103 static char * | |
1104 ngx_http_image_filter(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) | |
1105 { | |
1106 ngx_http_image_filter_conf_t *imcf = conf; | |
1107 | |
3244
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
1108 ngx_str_t *value; |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
1109 ngx_int_t n; |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
1110 ngx_uint_t i; |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
1111 ngx_http_complex_value_t cv; |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
1112 ngx_http_compile_complex_value_t ccv; |
2788 | 1113 |
1114 value = cf->args->elts; | |
1115 | |
1116 i = 1; | |
1117 | |
1118 if (cf->args->nelts == 2) { | |
1119 if (ngx_strcmp(value[i].data, "off") == 0) { | |
1120 imcf->filter = NGX_HTTP_IMAGE_OFF; | |
1121 | |
1122 } else if (ngx_strcmp(value[i].data, "test") == 0) { | |
1123 imcf->filter = NGX_HTTP_IMAGE_TEST; | |
1124 | |
1125 } else if (ngx_strcmp(value[i].data, "size") == 0) { | |
1126 imcf->filter = NGX_HTTP_IMAGE_SIZE; | |
1127 | |
1128 } else { | |
1129 goto failed; | |
1130 } | |
1131 | |
1132 return NGX_CONF_OK; | |
1133 } | |
1134 | |
1135 if (ngx_strcmp(value[i].data, "resize") == 0) { | |
1136 imcf->filter = NGX_HTTP_IMAGE_RESIZE; | |
1137 | |
1138 } else if (ngx_strcmp(value[i].data, "crop") == 0) { | |
1139 imcf->filter = NGX_HTTP_IMAGE_CROP; | |
1140 | |
1141 } else { | |
1142 goto failed; | |
1143 } | |
1144 | |
3244
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
1145 ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t)); |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
1146 |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
1147 ccv.cf = cf; |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
1148 ccv.value = &value[++i]; |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
1149 ccv.complex_value = &cv; |
2788 | 1150 |
3244
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
1151 if (ngx_http_compile_complex_value(&ccv) != NGX_OK) { |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
1152 return NGX_CONF_ERROR; |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
1153 } |
2788 | 1154 |
3244
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
1155 if (cv.lengths == NULL) { |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
1156 n = ngx_http_image_filter_value(&value[i]); |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
1157 |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
1158 if (n == 0) { |
2788 | 1159 goto failed; |
1160 } | |
1161 | |
1162 imcf->width = (ngx_uint_t) n; | |
3244
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
1163 |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
1164 } else { |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
1165 imcf->wcv = ngx_palloc(cf->pool, sizeof(ngx_http_complex_value_t)); |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
1166 if (imcf->wcv == NULL) { |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
1167 return NGX_CONF_ERROR; |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
1168 } |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
1169 |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
1170 *imcf->wcv = cv; |
2788 | 1171 } |
1172 | |
3244
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
1173 ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t)); |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
1174 |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
1175 ccv.cf = cf; |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
1176 ccv.value = &value[++i]; |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
1177 ccv.complex_value = &cv; |
2788 | 1178 |
3244
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
1179 if (ngx_http_compile_complex_value(&ccv) != NGX_OK) { |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
1180 return NGX_CONF_ERROR; |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
1181 } |
2788 | 1182 |
3244
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
1183 if (cv.lengths == NULL) { |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
1184 n = ngx_http_image_filter_value(&value[i]); |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
1185 |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
1186 if (n == 0) { |
2788 | 1187 goto failed; |
1188 } | |
1189 | |
1190 imcf->height = (ngx_uint_t) n; | |
3244
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
1191 |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
1192 } else { |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
1193 imcf->hcv = ngx_palloc(cf->pool, sizeof(ngx_http_complex_value_t)); |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
1194 if (imcf->hcv == NULL) { |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
1195 return NGX_CONF_ERROR; |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
1196 } |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
1197 |
8b2d478de54b
merge r2999, r3118, r3134, r3135:
Igor Sysoev <igor@sysoev.ru>
parents:
3237
diff
changeset
|
1198 *imcf->hcv = cv; |
2788 | 1199 } |
1200 | |
1201 return NGX_CONF_OK; | |
1202 | |
1203 failed: | |
1204 | |
1205 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid parameter \"%V\"", | |
1206 &value[i]); | |
1207 | |
1208 return NGX_CONF_ERROR; | |
1209 } | |
1210 | |
1211 | |
1212 static ngx_int_t | |
1213 ngx_http_image_filter_init(ngx_conf_t *cf) | |
1214 { | |
1215 ngx_http_next_header_filter = ngx_http_top_header_filter; | |
1216 ngx_http_top_header_filter = ngx_http_image_header_filter; | |
1217 | |
1218 ngx_http_next_body_filter = ngx_http_top_body_filter; | |
1219 ngx_http_top_body_filter = ngx_http_image_body_filter; | |
1220 | |
1221 return NGX_OK; | |
1222 } |