Mercurial > hg > nginx-vendor-current
comparison src/http/modules/ngx_http_image_filter_module.c @ 510:24b676623d4f NGINX_0_8_7
nginx 0.8.7
*) Change: minimum supported OpenSSL version is 0.9.7.
*) Change: the "ask" parameter of the "ssl_verify_client" directive was
changed to the "optional" parameter and now it checks a client
certificate if it was offered.
Thanks to Brice Figureau.
*) Feature: the $ssl_client_verify variable.
Thanks to Brice Figureau.
*) Feature: the "ssl_crl" directive.
Thanks to Brice Figureau.
*) Feature: the "proxy" parameter of the "geo" directive.
*) Feature: the "image_filter" directive supports variables for setting
size.
*) Bugfix: the $ssl_client_cert variable usage corrupted memory; the
bug had appeared in 0.7.7.
Thanks to Sergey Zhuravlev.
*) Bugfix: "proxy_pass_header" and "fastcgi_pass_header" directives did
not pass to a client the "X-Accel-Redirect", "X-Accel-Limit-Rate",
"X-Accel-Buffering", and "X-Accel-Charset" lines from backend
response header.
Thanks to Maxim Dounin.
*) Bugfix: in handling "Last-Modified" and "Accept-Ranges" backend
response header lines; the bug had appeared in 0.7.44.
Thanks to Maxim Dounin.
*) Bugfix: the "[alert] zero size buf" error if subrequest returns an
empty response; the bug had appeared in 0.8.5.
author | Igor Sysoev <http://sysoev.ru> |
---|---|
date | Mon, 27 Jul 2009 00:00:00 +0400 |
parents | 207ae3ff0444 |
children | 0161f3197817 |
comparison
equal
deleted
inserted
replaced
509:41f4e459ace8 | 510:24b676623d4f |
---|---|
38 ngx_uint_t filter; | 38 ngx_uint_t filter; |
39 ngx_uint_t width; | 39 ngx_uint_t width; |
40 ngx_uint_t height; | 40 ngx_uint_t height; |
41 ngx_int_t jpeg_quality; | 41 ngx_int_t jpeg_quality; |
42 | 42 |
43 ngx_http_complex_value_t *wcv; | |
44 ngx_http_complex_value_t *hcv; | |
45 | |
43 size_t buffer_size; | 46 size_t buffer_size; |
44 } ngx_http_image_filter_conf_t; | 47 } ngx_http_image_filter_conf_t; |
45 | 48 |
46 | 49 |
47 typedef struct { | 50 typedef struct { |
50 | 53 |
51 size_t length; | 54 size_t length; |
52 | 55 |
53 ngx_uint_t width; | 56 ngx_uint_t width; |
54 ngx_uint_t height; | 57 ngx_uint_t height; |
58 | |
59 ngx_uint_t max_width; | |
60 ngx_uint_t max_height; | |
55 | 61 |
56 ngx_uint_t phase; | 62 ngx_uint_t phase; |
57 ngx_uint_t type; | 63 ngx_uint_t type; |
58 } ngx_http_image_filter_ctx_t; | 64 } ngx_http_image_filter_ctx_t; |
59 | 65 |
78 static gdImagePtr ngx_http_image_new(ngx_http_request_t *r, int w, int h, | 84 static gdImagePtr ngx_http_image_new(ngx_http_request_t *r, int w, int h, |
79 int colors); | 85 int colors); |
80 static u_char *ngx_http_image_out(ngx_http_request_t *r, ngx_uint_t type, | 86 static u_char *ngx_http_image_out(ngx_http_request_t *r, ngx_uint_t type, |
81 gdImagePtr img, int *size); | 87 gdImagePtr img, int *size); |
82 static void ngx_http_image_cleanup(void *data); | 88 static void ngx_http_image_cleanup(void *data); |
89 static ngx_uint_t ngx_http_image_filter_get_value(ngx_http_request_t *r, | |
90 ngx_http_complex_value_t *cv, ngx_uint_t v); | |
91 static ngx_uint_t ngx_http_image_filter_value(ngx_str_t *value); | |
83 | 92 |
84 | 93 |
85 static void *ngx_http_image_filter_create_conf(ngx_conf_t *cf); | 94 static void *ngx_http_image_filter_create_conf(ngx_conf_t *cf); |
86 static char *ngx_http_image_filter_merge_conf(ngx_conf_t *cf, void *parent, | 95 static char *ngx_http_image_filter_merge_conf(ngx_conf_t *cf, void *parent, |
87 void *child); | 96 void *child); |
452 | 461 |
453 | 462 |
454 static ngx_buf_t * | 463 static ngx_buf_t * |
455 ngx_http_image_process(ngx_http_request_t *r) | 464 ngx_http_image_process(ngx_http_request_t *r) |
456 { | 465 { |
457 ngx_buf_t *b; | |
458 ngx_int_t rc; | 466 ngx_int_t rc; |
459 ngx_http_image_filter_ctx_t *ctx; | 467 ngx_http_image_filter_ctx_t *ctx; |
460 ngx_http_image_filter_conf_t *conf; | 468 ngx_http_image_filter_conf_t *conf; |
461 | 469 |
462 r->connection->buffered &= ~NGX_HTTP_IMAGE_BUFFERED; | 470 r->connection->buffered &= ~NGX_HTTP_IMAGE_BUFFERED; |
466 rc = ngx_http_image_size(r, ctx); | 474 rc = ngx_http_image_size(r, ctx); |
467 | 475 |
468 conf = ngx_http_get_module_loc_conf(r, ngx_http_image_filter_module); | 476 conf = ngx_http_get_module_loc_conf(r, ngx_http_image_filter_module); |
469 | 477 |
470 if (conf->filter == NGX_HTTP_IMAGE_SIZE) { | 478 if (conf->filter == NGX_HTTP_IMAGE_SIZE) { |
471 | 479 return ngx_http_image_json(r, rc == NGX_OK ? ctx : NULL); |
472 b = ngx_http_image_json(r, rc == NGX_OK ? ctx : NULL); | 480 } |
473 | 481 |
474 } else if (rc == NGX_OK | 482 ctx->max_width = ngx_http_image_filter_get_value(r, conf->wcv, conf->width); |
475 && ctx->width <= conf->width | 483 if (ctx->max_width == 0) { |
476 && ctx->height <= conf->height) | 484 return NULL; |
485 } | |
486 | |
487 ctx->max_height = ngx_http_image_filter_get_value(r, conf->hcv, | |
488 conf->height); | |
489 if (ctx->max_height == 0) { | |
490 return NULL; | |
491 } | |
492 | |
493 if (rc == NGX_OK | |
494 && ctx->width <= ctx->max_width | |
495 && ctx->height <= ctx->max_height) | |
477 { | 496 { |
478 b = ngx_http_image_asis(r, ctx); | 497 return ngx_http_image_asis(r, ctx); |
479 | 498 } |
480 } else { | 499 |
481 b = ngx_http_image_resize(r, ctx); | 500 return ngx_http_image_resize(r, ctx); |
482 } | |
483 | |
484 return b; | |
485 } | 501 } |
486 | 502 |
487 | 503 |
488 static ngx_buf_t * | 504 static ngx_buf_t * |
489 ngx_http_image_json(ngx_http_request_t *r, ngx_http_image_filter_ctx_t *ctx) | 505 ngx_http_image_json(ngx_http_request_t *r, ngx_http_image_filter_ctx_t *ctx) |
680 sx = gdImageSX(src); | 696 sx = gdImageSX(src); |
681 sy = gdImageSY(src); | 697 sy = gdImageSY(src); |
682 | 698 |
683 conf = ngx_http_get_module_loc_conf(r, ngx_http_image_filter_module); | 699 conf = ngx_http_get_module_loc_conf(r, ngx_http_image_filter_module); |
684 | 700 |
685 if ((ngx_uint_t) sx <= conf->width && (ngx_uint_t) sy <= conf->height) { | 701 if ((ngx_uint_t) sx <= ctx->max_width |
702 && (ngx_uint_t) sy <= ctx->max_height) | |
703 { | |
686 gdImageDestroy(src); | 704 gdImageDestroy(src); |
687 return ngx_http_image_asis(r, ctx); | 705 return ngx_http_image_asis(r, ctx); |
688 } | 706 } |
689 | 707 |
690 colors = gdImageColorsTotal(src); | 708 colors = gdImageColorsTotal(src); |
693 dx = sx; | 711 dx = sx; |
694 dy = sy; | 712 dy = sy; |
695 | 713 |
696 if (conf->filter == NGX_HTTP_IMAGE_RESIZE) { | 714 if (conf->filter == NGX_HTTP_IMAGE_RESIZE) { |
697 | 715 |
698 if ((ngx_uint_t) dx > conf->width) { | 716 if ((ngx_uint_t) dx > ctx->max_width) { |
699 dy = dy * conf->width / dx; | 717 dy = dy * ctx->max_width / dx; |
700 dy = dy ? dy : 1; | 718 dy = dy ? dy : 1; |
701 dx = conf->width; | 719 dx = ctx->max_width; |
702 } | 720 } |
703 | 721 |
704 if ((ngx_uint_t) dy > conf->height) { | 722 if ((ngx_uint_t) dy > ctx->max_height) { |
705 dx = dx * conf->height / dy; | 723 dx = dx * ctx->max_height / dy; |
706 dx = dx ? dx : 1; | 724 dx = dx ? dx : 1; |
707 dy = conf->height; | 725 dy = ctx->max_height; |
708 } | 726 } |
709 | 727 |
710 resize = 1; | 728 resize = 1; |
711 | 729 |
712 } else { /* NGX_HTTP_IMAGE_CROP */ | 730 } else { /* NGX_HTTP_IMAGE_CROP */ |
713 | 731 |
714 resize = 0; | 732 resize = 0; |
715 | 733 |
716 if ((ngx_uint_t) (dx * 100 / dy) < conf->width * 100 / conf->height) { | 734 if ((ngx_uint_t) (dx * 100 / dy) |
717 | 735 < ctx->max_width * 100 / ctx->max_height) |
718 if ((ngx_uint_t) dx > conf->width) { | 736 { |
719 dy = dy * conf->width / dx; | 737 if ((ngx_uint_t) dx > ctx->max_width) { |
738 dy = dy * ctx->max_width / dx; | |
720 dy = dy ? dy : 1; | 739 dy = dy ? dy : 1; |
721 dx = conf->width; | 740 dx = ctx->max_width; |
722 resize = 1; | 741 resize = 1; |
723 } | 742 } |
724 | 743 |
725 } else { | 744 } else { |
726 if ((ngx_uint_t) dy > conf->height) { | 745 if ((ngx_uint_t) dy > ctx->max_height) { |
727 dx = dx * conf->height / dy; | 746 dx = dx * ctx->max_height / dy; |
728 dx = dx ? dx : 1; | 747 dx = dx ? dx : 1; |
729 dy = conf->height; | 748 dy = ctx->max_height; |
730 resize = 1; | 749 resize = 1; |
731 } | 750 } |
732 } | 751 } |
733 } | 752 } |
734 | 753 |
749 | 768 |
750 if (conf->filter == NGX_HTTP_IMAGE_CROP) { | 769 if (conf->filter == NGX_HTTP_IMAGE_CROP) { |
751 | 770 |
752 src = dst; | 771 src = dst; |
753 | 772 |
754 if ((ngx_uint_t) dx > conf->width) { | 773 if ((ngx_uint_t) dx > ctx->max_width) { |
755 ox = dx - conf->width; | 774 ox = dx - ctx->max_width; |
756 | 775 |
757 } else { | 776 } else { |
758 ox = 0; | 777 ox = 0; |
759 } | 778 } |
760 | 779 |
761 if ((ngx_uint_t) dy > conf->height) { | 780 if ((ngx_uint_t) dy > ctx->max_height) { |
762 oy = dy - conf->height; | 781 oy = dy - ctx->max_height; |
763 | 782 |
764 } else { | 783 } else { |
765 oy = 0; | 784 oy = 0; |
766 } | 785 } |
767 | 786 |
939 { | 958 { |
940 gdFree(data); | 959 gdFree(data); |
941 } | 960 } |
942 | 961 |
943 | 962 |
963 static ngx_uint_t | |
964 ngx_http_image_filter_get_value(ngx_http_request_t *r, | |
965 ngx_http_complex_value_t *cv, ngx_uint_t v) | |
966 { | |
967 ngx_str_t val; | |
968 | |
969 if (cv == NULL) { | |
970 return v; | |
971 } | |
972 | |
973 if (ngx_http_complex_value(r, cv, &val) != NGX_OK) { | |
974 return 0; | |
975 } | |
976 | |
977 return ngx_http_image_filter_value(&val); | |
978 } | |
979 | |
980 | |
981 static ngx_uint_t | |
982 ngx_http_image_filter_value(ngx_str_t *value) | |
983 { | |
984 ngx_int_t n; | |
985 | |
986 if (value->len == 1 && value->data[0] == '-') { | |
987 return (ngx_uint_t) -1; | |
988 } | |
989 | |
990 n = ngx_atoi(value->data, value->len); | |
991 | |
992 if (n > 0) { | |
993 return (ngx_uint_t) n; | |
994 } | |
995 | |
996 return 0; | |
997 } | |
998 | |
999 | |
944 static void * | 1000 static void * |
945 ngx_http_image_filter_create_conf(ngx_conf_t *cf) | 1001 ngx_http_image_filter_create_conf(ngx_conf_t *cf) |
946 { | 1002 { |
947 ngx_http_image_filter_conf_t *conf; | 1003 ngx_http_image_filter_conf_t *conf; |
948 | 1004 |
972 | 1028 |
973 } else { | 1029 } else { |
974 conf->filter = prev->filter; | 1030 conf->filter = prev->filter; |
975 conf->width = prev->width; | 1031 conf->width = prev->width; |
976 conf->height = prev->height; | 1032 conf->height = prev->height; |
1033 conf->wcv = prev->wcv; | |
1034 conf->hcv = prev->hcv; | |
977 } | 1035 } |
978 } | 1036 } |
979 | 1037 |
980 /* 75 is libjpeg default quality */ | 1038 /* 75 is libjpeg default quality */ |
981 ngx_conf_merge_value(conf->jpeg_quality, prev->jpeg_quality, 75); | 1039 ngx_conf_merge_value(conf->jpeg_quality, prev->jpeg_quality, 75); |
990 static char * | 1048 static char * |
991 ngx_http_image_filter(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) | 1049 ngx_http_image_filter(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) |
992 { | 1050 { |
993 ngx_http_image_filter_conf_t *imcf = conf; | 1051 ngx_http_image_filter_conf_t *imcf = conf; |
994 | 1052 |
995 ngx_str_t *value; | 1053 ngx_str_t *value; |
996 ngx_int_t n; | 1054 ngx_int_t n; |
997 ngx_uint_t i; | 1055 ngx_uint_t i; |
1056 ngx_http_complex_value_t cv; | |
1057 ngx_http_compile_complex_value_t ccv; | |
998 | 1058 |
999 value = cf->args->elts; | 1059 value = cf->args->elts; |
1000 | 1060 |
1001 i = 1; | 1061 i = 1; |
1002 | 1062 |
1025 | 1085 |
1026 } else { | 1086 } else { |
1027 goto failed; | 1087 goto failed; |
1028 } | 1088 } |
1029 | 1089 |
1030 i++; | 1090 ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t)); |
1031 | 1091 |
1032 if (value[i].len == 1 && value[i].data[0] == '-') { | 1092 ccv.cf = cf; |
1033 imcf->width = (ngx_uint_t) -1; | 1093 ccv.value = &value[++i]; |
1094 ccv.complex_value = &cv; | |
1095 | |
1096 if (ngx_http_compile_complex_value(&ccv) != NGX_OK) { | |
1097 return NGX_CONF_ERROR; | |
1098 } | |
1099 | |
1100 if (cv.lengths == NULL) { | |
1101 n = ngx_http_image_filter_value(&value[i]); | |
1102 | |
1103 if (n == 0) { | |
1104 goto failed; | |
1105 } | |
1106 | |
1107 imcf->width = (ngx_uint_t) n; | |
1034 | 1108 |
1035 } else { | 1109 } else { |
1036 n = ngx_atoi(value[i].data, value[i].len); | 1110 imcf->wcv = ngx_palloc(cf->pool, sizeof(ngx_http_complex_value_t)); |
1037 if (n == NGX_ERROR) { | 1111 if (imcf->wcv == NULL) { |
1112 return NGX_CONF_ERROR; | |
1113 } | |
1114 | |
1115 *imcf->wcv = cv; | |
1116 } | |
1117 | |
1118 ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t)); | |
1119 | |
1120 ccv.cf = cf; | |
1121 ccv.value = &value[++i]; | |
1122 ccv.complex_value = &cv; | |
1123 | |
1124 if (ngx_http_compile_complex_value(&ccv) != NGX_OK) { | |
1125 return NGX_CONF_ERROR; | |
1126 } | |
1127 | |
1128 if (cv.lengths == NULL) { | |
1129 n = ngx_http_image_filter_value(&value[i]); | |
1130 | |
1131 if (n == 0) { | |
1038 goto failed; | 1132 goto failed; |
1039 } | 1133 } |
1040 | 1134 |
1041 imcf->width = (ngx_uint_t) n; | 1135 imcf->height = (ngx_uint_t) n; |
1042 } | |
1043 | |
1044 i++; | |
1045 | |
1046 if (value[i].len == 1 && value[i].data[0] == '-') { | |
1047 imcf->height = (ngx_uint_t) -1; | |
1048 | 1136 |
1049 } else { | 1137 } else { |
1050 n = ngx_atoi(value[i].data, value[i].len); | 1138 imcf->hcv = ngx_palloc(cf->pool, sizeof(ngx_http_complex_value_t)); |
1051 if (n == NGX_ERROR) { | 1139 if (imcf->hcv == NULL) { |
1052 goto failed; | 1140 return NGX_CONF_ERROR; |
1053 } | 1141 } |
1054 | 1142 |
1055 imcf->height = (ngx_uint_t) n; | 1143 *imcf->hcv = cv; |
1056 } | 1144 } |
1057 | 1145 |
1058 return NGX_CONF_OK; | 1146 return NGX_CONF_OK; |
1059 | 1147 |
1060 failed: | 1148 failed: |