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: