# HG changeset patch # User Igor Sysoev # Date 1281297600 -14400 # Node ID 3436cf38d59e5d8a3ac57414535a6bd7effa5936 # Parent ad310549c5d4a121f64a2f4167d445c86caf031e nginx 0.8.49 *) Feature: the "image_filter_jpeg_quality" directive supports variables. *) Bugfix: a segmentation fault might occur in a worker process, if the $geoip_region_name variables was used; the bug had appeared in 0.8.48. *) Bugfix: errors intercepted by error_page were cached only for next request; the bug had appeared in 0.8.48. diff --git a/CHANGES b/CHANGES --- a/CHANGES +++ b/CHANGES @@ -1,4 +1,17 @@ +Changes with nginx 0.8.49 09 Aug 2010 + + *) Feature: the "image_filter_jpeg_quality" directive supports + variables. + + *) Bugfix: a segmentation fault might occur in a worker process, if the + $geoip_region_name variables was used; the bug had appeared in + 0.8.48. + + *) Bugfix: errors intercepted by error_page were cached only for next + request; the bug had appeared in 0.8.48. + + Changes with nginx 0.8.48 03 Aug 2010 *) Change: now the "server_name" directive default value is an empty diff --git a/CHANGES.ru b/CHANGES.ru --- a/CHANGES.ru +++ b/CHANGES.ru @@ -1,4 +1,17 @@ +Изменения в nginx 0.8.49 09.08.2010 + + *) Добавление: директива image_filter_jpeg_quality поддерживает + переменные. + + *) Исправление: при использовании переменной $geoip_region_name в + рабочем процессе мог произойти segmentation fault; ошибка появилась + в 0.8.48. + + *) Исправление: ошибки, перехваченные error_page, кэшировались только + до следующего запроса; ошибка появилась в 0.8.48. + + Изменения в nginx 0.8.48 03.08.2010 *) Изменение: теперь по умолчанию директива server_name имеет значение diff --git a/src/core/nginx.h b/src/core/nginx.h --- a/src/core/nginx.h +++ b/src/core/nginx.h @@ -8,8 +8,8 @@ #define _NGINX_H_INCLUDED_ -#define nginx_version 8048 -#define NGINX_VERSION "0.8.48" +#define nginx_version 8049 +#define NGINX_VERSION "0.8.49" #define NGINX_VER "nginx/" NGINX_VERSION #define NGINX_VAR "NGINX" diff --git a/src/http/modules/ngx_http_geoip_module.c b/src/http/modules/ngx_http_geoip_module.c --- a/src/http/modules/ngx_http_geoip_module.c +++ b/src/http/modules/ngx_http_geoip_module.c @@ -231,7 +231,6 @@ ngx_http_geoip_city_variable(ngx_http_re len = ngx_strlen(val); v->data = ngx_pnalloc(r->pool, len); - if (v->data == NULL) { GeoIPRecord_delete(gr); return NGX_ERROR; @@ -275,11 +274,15 @@ ngx_http_geoip_region_name_variable(ngx_ val = GeoIP_region_name_by_code(gr->country_code, gr->region); + GeoIPRecord_delete(gr); + + if (val == NULL) { + goto not_found; + } + len = ngx_strlen(val); v->data = ngx_pnalloc(r->pool, len); - if (v->data == NULL) { - GeoIPRecord_delete(gr); return NGX_ERROR; } @@ -290,8 +293,6 @@ ngx_http_geoip_region_name_variable(ngx_ v->no_cacheable = 0; v->not_found = 0; - GeoIPRecord_delete(gr); - return NGX_OK; not_found: diff --git a/src/http/modules/ngx_http_image_filter_module.c b/src/http/modules/ngx_http_image_filter_module.c --- a/src/http/modules/ngx_http_image_filter_module.c +++ b/src/http/modules/ngx_http_image_filter_module.c @@ -38,12 +38,13 @@ typedef struct { ngx_uint_t filter; ngx_uint_t width; ngx_uint_t height; - ngx_int_t jpeg_quality; + ngx_uint_t jpeg_quality; ngx_flag_t transparency; ngx_http_complex_value_t *wcv; ngx_http_complex_value_t *hcv; + ngx_http_complex_value_t *jqcv; size_t buffer_size; } ngx_http_image_filter_conf_t; @@ -99,6 +100,8 @@ static char *ngx_http_image_filter_merge void *child); static char *ngx_http_image_filter(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); +static char *ngx_http_image_filter_jpeg_quality(ngx_conf_t *cf, + ngx_command_t *cmd, void *conf); static ngx_int_t ngx_http_image_filter_init(ngx_conf_t *cf); @@ -113,9 +116,9 @@ static ngx_command_t ngx_http_image_fil { ngx_string("image_filter_jpeg_quality"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, - ngx_conf_set_num_slot, + ngx_http_image_filter_jpeg_quality, NGX_HTTP_LOC_CONF_OFFSET, - offsetof(ngx_http_image_filter_conf_t, jpeg_quality), + 0, NULL }, { ngx_string("image_filter_transparency"), @@ -989,6 +992,7 @@ ngx_http_image_out(ngx_http_request_t *r { char *failed; u_char *out; + ngx_int_t jq; ngx_http_image_filter_conf_t *conf; out = NULL; @@ -997,7 +1001,13 @@ ngx_http_image_out(ngx_http_request_t *r case NGX_HTTP_IMAGE_JPEG: conf = ngx_http_get_module_loc_conf(r, ngx_http_image_filter_module); - out = gdImageJpegPtr(img, size, conf->jpeg_quality); + + jq = ngx_http_image_filter_get_value(r, conf->jqcv, conf->jpeg_quality); + if (jq <= 0) { + return NULL; + } + + out = gdImageJpegPtr(img, size, jq); failed = "gdImageJpegPtr() failed"; break; @@ -1079,7 +1089,7 @@ ngx_http_image_filter_create_conf(ngx_co } conf->filter = NGX_CONF_UNSET_UINT; - conf->jpeg_quality = NGX_CONF_UNSET; + conf->jpeg_quality = NGX_CONF_UNSET_UINT; conf->transparency = NGX_CONF_UNSET; conf->buffer_size = NGX_CONF_UNSET_SIZE; @@ -1108,7 +1118,11 @@ ngx_http_image_filter_merge_conf(ngx_con } /* 75 is libjpeg default quality */ - ngx_conf_merge_value(conf->jpeg_quality, prev->jpeg_quality, 75); + ngx_conf_merge_uint_value(conf->jpeg_quality, prev->jpeg_quality, 75); + + if (conf->jqcv == NULL) { + conf->jqcv = prev->jqcv; + } ngx_conf_merge_value(conf->transparency, prev->transparency, 1); @@ -1228,6 +1242,53 @@ failed: } +static char * +ngx_http_image_filter_jpeg_quality(ngx_conf_t *cf, ngx_command_t *cmd, + void *conf) +{ + ngx_http_image_filter_conf_t *imcf = conf; + + ngx_str_t *value; + ngx_int_t n; + ngx_http_complex_value_t cv; + ngx_http_compile_complex_value_t ccv; + + value = cf->args->elts; + + ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t)); + + ccv.cf = cf; + ccv.value = &value[1]; + ccv.complex_value = &cv; + + if (ngx_http_compile_complex_value(&ccv) != NGX_OK) { + return NGX_CONF_ERROR; + } + + if (cv.lengths == NULL) { + n = ngx_http_image_filter_value(&value[1]); + + if (n <= 0) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "invalid parameter \"%V\"", &value[1]); + return NGX_CONF_ERROR; + } + + imcf->jpeg_quality = (ngx_uint_t) n; + + } else { + imcf->jqcv = ngx_palloc(cf->pool, sizeof(ngx_http_complex_value_t)); + if (imcf->jqcv == NULL) { + return NGX_CONF_ERROR; + } + + *imcf->jqcv = cv; + } + + return NGX_CONF_OK; +} + + static ngx_int_t ngx_http_image_filter_init(ngx_conf_t *cf) { diff --git a/src/http/modules/perl/nginx.pm b/src/http/modules/perl/nginx.pm --- a/src/http/modules/perl/nginx.pm +++ b/src/http/modules/perl/nginx.pm @@ -48,7 +48,7 @@ our @EXPORT = qw( HTTP_INSUFFICIENT_STORAGE ); -our $VERSION = '0.8.48'; +our $VERSION = '0.8.49'; require XSLoader; XSLoader::load('nginx', $VERSION); diff --git a/src/http/ngx_http_file_cache.c b/src/http/ngx_http_file_cache.c --- a/src/http/ngx_http_file_cache.c +++ b/src/http/ngx_http_file_cache.c @@ -581,6 +581,7 @@ ngx_http_file_cache_exists(ngx_http_file fcn->uses = 1; fcn->count = 1; + fcn->updating = 0; renew: @@ -927,10 +928,13 @@ ngx_http_file_cache_free(ngx_http_cache_ } if (c->error) { - fcn->valid_sec = c->valid_sec; - fcn->valid_msec = c->valid_msec; fcn->error = c->error; + if (c->valid_sec) { + fcn->valid_sec = c->valid_sec; + fcn->valid_msec = c->valid_msec; + } + } else if (!fcn->exists && fcn->count == 0 && c->min_uses == 1) { ngx_queue_remove(&fcn->queue); ngx_rbtree_delete(&cache->sh->rbtree, &fcn->node); @@ -1426,6 +1430,7 @@ ngx_http_file_cache_add(ngx_http_file_ca fcn->valid_msec = c->valid_msec; fcn->error = 0; fcn->exists = 1; + fcn->updating = 0; fcn->uniq = c->uniq; fcn->valid_sec = c->valid_sec; fcn->body_start = c->body_start;