aboutsummaryrefslogtreecommitdiffstats
path: root/nginx/src/http/modules
diff options
context:
space:
mode:
Diffstat (limited to 'nginx/src/http/modules')
-rw-r--r--nginx/src/http/modules/ngx_http_access_module.c463
-rw-r--r--nginx/src/http/modules/ngx_http_addition_filter_module.c254
-rw-r--r--nginx/src/http/modules/ngx_http_auth_basic_module.c429
-rw-r--r--nginx/src/http/modules/ngx_http_auth_request_module.c444
-rw-r--r--nginx/src/http/modules/ngx_http_autoindex_module.c1056
-rw-r--r--nginx/src/http/modules/ngx_http_browser_module.c712
-rw-r--r--nginx/src/http/modules/ngx_http_charset_filter_module.c1685
-rw-r--r--nginx/src/http/modules/ngx_http_chunked_filter_module.c341
-rw-r--r--nginx/src/http/modules/ngx_http_dav_module.c1169
-rw-r--r--nginx/src/http/modules/ngx_http_degradation_module.c243
-rw-r--r--nginx/src/http/modules/ngx_http_empty_gif_module.c140
-rw-r--r--nginx/src/http/modules/ngx_http_fastcgi_module.c3762
-rw-r--r--nginx/src/http/modules/ngx_http_flv_module.c266
-rw-r--r--nginx/src/http/modules/ngx_http_geo_module.c1668
-rw-r--r--nginx/src/http/modules/ngx_http_geoip_module.c925
-rw-r--r--nginx/src/http/modules/ngx_http_grpc_module.c4707
-rw-r--r--nginx/src/http/modules/ngx_http_gunzip_filter_module.c687
-rw-r--r--nginx/src/http/modules/ngx_http_gzip_filter_module.c1273
-rw-r--r--nginx/src/http/modules/ngx_http_gzip_static_module.c331
-rw-r--r--nginx/src/http/modules/ngx_http_headers_filter_module.c867
-rw-r--r--nginx/src/http/modules/ngx_http_image_filter_module.c1675
-rw-r--r--nginx/src/http/modules/ngx_http_index_module.c540
-rw-r--r--nginx/src/http/modules/ngx_http_limit_conn_module.c670
-rw-r--r--nginx/src/http/modules/ngx_http_limit_req_module.c960
-rw-r--r--nginx/src/http/modules/ngx_http_log_module.c1909
-rw-r--r--nginx/src/http/modules/ngx_http_map_module.c589
-rw-r--r--nginx/src/http/modules/ngx_http_memcached_module.c721
-rw-r--r--nginx/src/http/modules/ngx_http_mirror_module.c264
-rw-r--r--nginx/src/http/modules/ngx_http_mp4_module.c3562
-rw-r--r--nginx/src/http/modules/ngx_http_not_modified_filter_module.c266
-rw-r--r--nginx/src/http/modules/ngx_http_proxy_module.c4348
-rw-r--r--nginx/src/http/modules/ngx_http_random_index_module.c317
-rw-r--r--nginx/src/http/modules/ngx_http_range_filter_module.c932
-rw-r--r--nginx/src/http/modules/ngx_http_realip_module.c623
-rw-r--r--nginx/src/http/modules/ngx_http_referer_module.c682
-rw-r--r--nginx/src/http/modules/ngx_http_rewrite_module.c1022
-rw-r--r--nginx/src/http/modules/ngx_http_scgi_module.c2008
-rw-r--r--nginx/src/http/modules/ngx_http_secure_link_module.c367
-rw-r--r--nginx/src/http/modules/ngx_http_slice_filter_module.c545
-rw-r--r--nginx/src/http/modules/ngx_http_split_clients_module.c246
-rw-r--r--nginx/src/http/modules/ngx_http_ssi_filter_module.c2933
-rw-r--r--nginx/src/http/modules/ngx_http_ssi_filter_module.h114
-rw-r--r--nginx/src/http/modules/ngx_http_ssl_module.c997
-rw-r--r--nginx/src/http/modules/ngx_http_ssl_module.h66
-rw-r--r--nginx/src/http/modules/ngx_http_static_module.c288
-rw-r--r--nginx/src/http/modules/ngx_http_stub_status_module.c236
-rw-r--r--nginx/src/http/modules/ngx_http_sub_filter_module.c1018
-rw-r--r--nginx/src/http/modules/ngx_http_try_files_module.c404
-rw-r--r--nginx/src/http/modules/ngx_http_upstream_hash_module.c680
-rw-r--r--nginx/src/http/modules/ngx_http_upstream_ip_hash_module.c272
-rw-r--r--nginx/src/http/modules/ngx_http_upstream_keepalive_module.c530
-rw-r--r--nginx/src/http/modules/ngx_http_upstream_least_conn_module.c314
-rw-r--r--nginx/src/http/modules/ngx_http_upstream_zone_module.c325
-rw-r--r--nginx/src/http/modules/ngx_http_userid_filter_module.c846
-rw-r--r--nginx/src/http/modules/ngx_http_uwsgi_module.c2397
-rw-r--r--nginx/src/http/modules/ngx_http_xslt_filter_module.c1158
-rw-r--r--nginx/src/http/modules/perl/Makefile.PL35
-rw-r--r--nginx/src/http/modules/perl/nginx.pm140
-rw-r--r--nginx/src/http/modules/perl/nginx.xs1041
-rw-r--r--nginx/src/http/modules/perl/ngx_http_perl_module.c1086
-rw-r--r--nginx/src/http/modules/perl/ngx_http_perl_module.h67
-rw-r--r--nginx/src/http/modules/perl/typemap3
62 files changed, 0 insertions, 58618 deletions
diff --git a/nginx/src/http/modules/ngx_http_access_module.c b/nginx/src/http/modules/ngx_http_access_module.c
deleted file mode 100644
index 7355de9..0000000
--- a/nginx/src/http/modules/ngx_http_access_module.c
+++ /dev/null
@@ -1,463 +0,0 @@
-
-/*
- * Copyright (C) Igor Sysoev
- * Copyright (C) Nginx, Inc.
- */
-
-
-#include <ngx_config.h>
-#include <ngx_core.h>
-#include <ngx_http.h>
-
-
-typedef struct {
- in_addr_t mask;
- in_addr_t addr;
- ngx_uint_t deny; /* unsigned deny:1; */
-} ngx_http_access_rule_t;
-
-#if (NGX_HAVE_INET6)
-
-typedef struct {
- struct in6_addr addr;
- struct in6_addr mask;
- ngx_uint_t deny; /* unsigned deny:1; */
-} ngx_http_access_rule6_t;
-
-#endif
-
-#if (NGX_HAVE_UNIX_DOMAIN)
-
-typedef struct {
- ngx_uint_t deny; /* unsigned deny:1; */
-} ngx_http_access_rule_un_t;
-
-#endif
-
-typedef struct {
- ngx_array_t *rules; /* array of ngx_http_access_rule_t */
-#if (NGX_HAVE_INET6)
- ngx_array_t *rules6; /* array of ngx_http_access_rule6_t */
-#endif
-#if (NGX_HAVE_UNIX_DOMAIN)
- ngx_array_t *rules_un; /* array of ngx_http_access_rule_un_t */
-#endif
-} ngx_http_access_loc_conf_t;
-
-
-static ngx_int_t ngx_http_access_handler(ngx_http_request_t *r);
-static ngx_int_t ngx_http_access_inet(ngx_http_request_t *r,
- ngx_http_access_loc_conf_t *alcf, in_addr_t addr);
-#if (NGX_HAVE_INET6)
-static ngx_int_t ngx_http_access_inet6(ngx_http_request_t *r,
- ngx_http_access_loc_conf_t *alcf, u_char *p);
-#endif
-#if (NGX_HAVE_UNIX_DOMAIN)
-static ngx_int_t ngx_http_access_unix(ngx_http_request_t *r,
- ngx_http_access_loc_conf_t *alcf);
-#endif
-static ngx_int_t ngx_http_access_found(ngx_http_request_t *r, ngx_uint_t deny);
-static char *ngx_http_access_rule(ngx_conf_t *cf, ngx_command_t *cmd,
- void *conf);
-static void *ngx_http_access_create_loc_conf(ngx_conf_t *cf);
-static char *ngx_http_access_merge_loc_conf(ngx_conf_t *cf,
- void *parent, void *child);
-static ngx_int_t ngx_http_access_init(ngx_conf_t *cf);
-
-
-static ngx_command_t ngx_http_access_commands[] = {
-
- { ngx_string("allow"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LMT_CONF
- |NGX_CONF_TAKE1,
- ngx_http_access_rule,
- NGX_HTTP_LOC_CONF_OFFSET,
- 0,
- NULL },
-
- { ngx_string("deny"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LMT_CONF
- |NGX_CONF_TAKE1,
- ngx_http_access_rule,
- NGX_HTTP_LOC_CONF_OFFSET,
- 0,
- NULL },
-
- ngx_null_command
-};
-
-
-
-static ngx_http_module_t ngx_http_access_module_ctx = {
- NULL, /* preconfiguration */
- ngx_http_access_init, /* postconfiguration */
-
- NULL, /* create main configuration */
- NULL, /* init main configuration */
-
- NULL, /* create server configuration */
- NULL, /* merge server configuration */
-
- ngx_http_access_create_loc_conf, /* create location configuration */
- ngx_http_access_merge_loc_conf /* merge location configuration */
-};
-
-
-ngx_module_t ngx_http_access_module = {
- NGX_MODULE_V1,
- &ngx_http_access_module_ctx, /* module context */
- ngx_http_access_commands, /* module directives */
- NGX_HTTP_MODULE, /* module type */
- NULL, /* init master */
- NULL, /* init module */
- NULL, /* init process */
- NULL, /* init thread */
- NULL, /* exit thread */
- NULL, /* exit process */
- NULL, /* exit master */
- NGX_MODULE_V1_PADDING
-};
-
-
-static ngx_int_t
-ngx_http_access_handler(ngx_http_request_t *r)
-{
- struct sockaddr_in *sin;
- ngx_http_access_loc_conf_t *alcf;
-#if (NGX_HAVE_INET6)
- u_char *p;
- in_addr_t addr;
- struct sockaddr_in6 *sin6;
-#endif
-
- alcf = ngx_http_get_module_loc_conf(r, ngx_http_access_module);
-
- switch (r->connection->sockaddr->sa_family) {
-
- case AF_INET:
- if (alcf->rules) {
- sin = (struct sockaddr_in *) r->connection->sockaddr;
- return ngx_http_access_inet(r, alcf, sin->sin_addr.s_addr);
- }
- break;
-
-#if (NGX_HAVE_INET6)
-
- case AF_INET6:
- sin6 = (struct sockaddr_in6 *) r->connection->sockaddr;
- p = sin6->sin6_addr.s6_addr;
-
- if (alcf->rules && IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
- addr = p[12] << 24;
- addr += p[13] << 16;
- addr += p[14] << 8;
- addr += p[15];
- return ngx_http_access_inet(r, alcf, htonl(addr));
- }
-
- if (alcf->rules6) {
- return ngx_http_access_inet6(r, alcf, p);
- }
-
- break;
-
-#endif
-
-#if (NGX_HAVE_UNIX_DOMAIN)
-
- case AF_UNIX:
- if (alcf->rules_un) {
- return ngx_http_access_unix(r, alcf);
- }
-
- break;
-
-#endif
- }
-
- return NGX_DECLINED;
-}
-
-
-static ngx_int_t
-ngx_http_access_inet(ngx_http_request_t *r, ngx_http_access_loc_conf_t *alcf,
- in_addr_t addr)
-{
- ngx_uint_t i;
- ngx_http_access_rule_t *rule;
-
- rule = alcf->rules->elts;
- for (i = 0; i < alcf->rules->nelts; i++) {
-
- ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "access: %08XD %08XD %08XD",
- addr, rule[i].mask, rule[i].addr);
-
- if ((addr & rule[i].mask) == rule[i].addr) {
- return ngx_http_access_found(r, rule[i].deny);
- }
- }
-
- return NGX_DECLINED;
-}
-
-
-#if (NGX_HAVE_INET6)
-
-static ngx_int_t
-ngx_http_access_inet6(ngx_http_request_t *r, ngx_http_access_loc_conf_t *alcf,
- u_char *p)
-{
- ngx_uint_t n;
- ngx_uint_t i;
- ngx_http_access_rule6_t *rule6;
-
- rule6 = alcf->rules6->elts;
- for (i = 0; i < alcf->rules6->nelts; i++) {
-
-#if (NGX_DEBUG)
- {
- size_t cl, ml, al;
- u_char ct[NGX_INET6_ADDRSTRLEN];
- u_char mt[NGX_INET6_ADDRSTRLEN];
- u_char at[NGX_INET6_ADDRSTRLEN];
-
- cl = ngx_inet6_ntop(p, ct, NGX_INET6_ADDRSTRLEN);
- ml = ngx_inet6_ntop(rule6[i].mask.s6_addr, mt, NGX_INET6_ADDRSTRLEN);
- al = ngx_inet6_ntop(rule6[i].addr.s6_addr, at, NGX_INET6_ADDRSTRLEN);
-
- ngx_log_debug6(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "access: %*s %*s %*s", cl, ct, ml, mt, al, at);
- }
-#endif
-
- for (n = 0; n < 16; n++) {
- if ((p[n] & rule6[i].mask.s6_addr[n]) != rule6[i].addr.s6_addr[n]) {
- goto next;
- }
- }
-
- return ngx_http_access_found(r, rule6[i].deny);
-
- next:
- continue;
- }
-
- return NGX_DECLINED;
-}
-
-#endif
-
-
-#if (NGX_HAVE_UNIX_DOMAIN)
-
-static ngx_int_t
-ngx_http_access_unix(ngx_http_request_t *r, ngx_http_access_loc_conf_t *alcf)
-{
- ngx_uint_t i;
- ngx_http_access_rule_un_t *rule_un;
-
- rule_un = alcf->rules_un->elts;
- for (i = 0; i < alcf->rules_un->nelts; i++) {
-
- /* TODO: check path */
- if (1) {
- return ngx_http_access_found(r, rule_un[i].deny);
- }
- }
-
- return NGX_DECLINED;
-}
-
-#endif
-
-
-static ngx_int_t
-ngx_http_access_found(ngx_http_request_t *r, ngx_uint_t deny)
-{
- ngx_http_core_loc_conf_t *clcf;
-
- if (deny) {
- clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
-
- if (clcf->satisfy == NGX_HTTP_SATISFY_ALL) {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "access forbidden by rule");
- }
-
- return NGX_HTTP_FORBIDDEN;
- }
-
- return NGX_OK;
-}
-
-
-static char *
-ngx_http_access_rule(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
-{
- ngx_http_access_loc_conf_t *alcf = conf;
-
- ngx_int_t rc;
- ngx_uint_t all;
- ngx_str_t *value;
- ngx_cidr_t cidr;
- ngx_http_access_rule_t *rule;
-#if (NGX_HAVE_INET6)
- ngx_http_access_rule6_t *rule6;
-#endif
-#if (NGX_HAVE_UNIX_DOMAIN)
- ngx_http_access_rule_un_t *rule_un;
-#endif
-
- all = 0;
- ngx_memzero(&cidr, sizeof(ngx_cidr_t));
-
- value = cf->args->elts;
-
- if (value[1].len == 3 && ngx_strcmp(value[1].data, "all") == 0) {
- all = 1;
-
-#if (NGX_HAVE_UNIX_DOMAIN)
- } else if (value[1].len == 5 && ngx_strcmp(value[1].data, "unix:") == 0) {
- cidr.family = AF_UNIX;
-#endif
-
- } else {
- rc = ngx_ptocidr(&value[1], &cidr);
-
- if (rc == NGX_ERROR) {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "invalid parameter \"%V\"", &value[1]);
- return NGX_CONF_ERROR;
- }
-
- if (rc == NGX_DONE) {
- ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
- "low address bits of %V are meaningless", &value[1]);
- }
- }
-
- if (cidr.family == AF_INET || all) {
-
- if (alcf->rules == NULL) {
- alcf->rules = ngx_array_create(cf->pool, 4,
- sizeof(ngx_http_access_rule_t));
- if (alcf->rules == NULL) {
- return NGX_CONF_ERROR;
- }
- }
-
- rule = ngx_array_push(alcf->rules);
- if (rule == NULL) {
- return NGX_CONF_ERROR;
- }
-
- rule->mask = cidr.u.in.mask;
- rule->addr = cidr.u.in.addr;
- rule->deny = (value[0].data[0] == 'd') ? 1 : 0;
- }
-
-#if (NGX_HAVE_INET6)
- if (cidr.family == AF_INET6 || all) {
-
- if (alcf->rules6 == NULL) {
- alcf->rules6 = ngx_array_create(cf->pool, 4,
- sizeof(ngx_http_access_rule6_t));
- if (alcf->rules6 == NULL) {
- return NGX_CONF_ERROR;
- }
- }
-
- rule6 = ngx_array_push(alcf->rules6);
- if (rule6 == NULL) {
- return NGX_CONF_ERROR;
- }
-
- rule6->mask = cidr.u.in6.mask;
- rule6->addr = cidr.u.in6.addr;
- rule6->deny = (value[0].data[0] == 'd') ? 1 : 0;
- }
-#endif
-
-#if (NGX_HAVE_UNIX_DOMAIN)
- if (cidr.family == AF_UNIX || all) {
-
- if (alcf->rules_un == NULL) {
- alcf->rules_un = ngx_array_create(cf->pool, 1,
- sizeof(ngx_http_access_rule_un_t));
- if (alcf->rules_un == NULL) {
- return NGX_CONF_ERROR;
- }
- }
-
- rule_un = ngx_array_push(alcf->rules_un);
- if (rule_un == NULL) {
- return NGX_CONF_ERROR;
- }
-
- rule_un->deny = (value[0].data[0] == 'd') ? 1 : 0;
- }
-#endif
-
- return NGX_CONF_OK;
-}
-
-
-static void *
-ngx_http_access_create_loc_conf(ngx_conf_t *cf)
-{
- ngx_http_access_loc_conf_t *conf;
-
- conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_access_loc_conf_t));
- if (conf == NULL) {
- return NULL;
- }
-
- return conf;
-}
-
-
-static char *
-ngx_http_access_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
-{
- ngx_http_access_loc_conf_t *prev = parent;
- ngx_http_access_loc_conf_t *conf = child;
-
- if (conf->rules == NULL
-#if (NGX_HAVE_INET6)
- && conf->rules6 == NULL
-#endif
-#if (NGX_HAVE_UNIX_DOMAIN)
- && conf->rules_un == NULL
-#endif
- ) {
- conf->rules = prev->rules;
-#if (NGX_HAVE_INET6)
- conf->rules6 = prev->rules6;
-#endif
-#if (NGX_HAVE_UNIX_DOMAIN)
- conf->rules_un = prev->rules_un;
-#endif
- }
-
- return NGX_CONF_OK;
-}
-
-
-static ngx_int_t
-ngx_http_access_init(ngx_conf_t *cf)
-{
- ngx_http_handler_pt *h;
- ngx_http_core_main_conf_t *cmcf;
-
- cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);
-
- h = ngx_array_push(&cmcf->phases[NGX_HTTP_ACCESS_PHASE].handlers);
- if (h == NULL) {
- return NGX_ERROR;
- }
-
- *h = ngx_http_access_handler;
-
- return NGX_OK;
-}
diff --git a/nginx/src/http/modules/ngx_http_addition_filter_module.c b/nginx/src/http/modules/ngx_http_addition_filter_module.c
deleted file mode 100644
index e546f0d..0000000
--- a/nginx/src/http/modules/ngx_http_addition_filter_module.c
+++ /dev/null
@@ -1,254 +0,0 @@
-
-/*
- * Copyright (C) Igor Sysoev
- * Copyright (C) Nginx, Inc.
- */
-
-
-#include <ngx_config.h>
-#include <ngx_core.h>
-#include <ngx_http.h>
-
-
-typedef struct {
- ngx_str_t before_body;
- ngx_str_t after_body;
-
- ngx_hash_t types;
- ngx_array_t *types_keys;
-} ngx_http_addition_conf_t;
-
-
-typedef struct {
- ngx_uint_t before_body_sent;
-} ngx_http_addition_ctx_t;
-
-
-static void *ngx_http_addition_create_conf(ngx_conf_t *cf);
-static char *ngx_http_addition_merge_conf(ngx_conf_t *cf, void *parent,
- void *child);
-static ngx_int_t ngx_http_addition_filter_init(ngx_conf_t *cf);
-
-
-static ngx_command_t ngx_http_addition_commands[] = {
-
- { ngx_string("add_before_body"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_str_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_addition_conf_t, before_body),
- NULL },
-
- { ngx_string("add_after_body"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_str_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_addition_conf_t, after_body),
- NULL },
-
- { ngx_string("addition_types"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
- ngx_http_types_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_addition_conf_t, types_keys),
- &ngx_http_html_default_types[0] },
-
- ngx_null_command
-};
-
-
-static ngx_http_module_t ngx_http_addition_filter_module_ctx = {
- NULL, /* preconfiguration */
- ngx_http_addition_filter_init, /* postconfiguration */
-
- NULL, /* create main configuration */
- NULL, /* init main configuration */
-
- NULL, /* create server configuration */
- NULL, /* merge server configuration */
-
- ngx_http_addition_create_conf, /* create location configuration */
- ngx_http_addition_merge_conf /* merge location configuration */
-};
-
-
-ngx_module_t ngx_http_addition_filter_module = {
- NGX_MODULE_V1,
- &ngx_http_addition_filter_module_ctx, /* module context */
- ngx_http_addition_commands, /* module directives */
- NGX_HTTP_MODULE, /* module type */
- NULL, /* init master */
- NULL, /* init module */
- NULL, /* init process */
- NULL, /* init thread */
- NULL, /* exit thread */
- NULL, /* exit process */
- NULL, /* exit master */
- NGX_MODULE_V1_PADDING
-};
-
-
-static ngx_http_output_header_filter_pt ngx_http_next_header_filter;
-static ngx_http_output_body_filter_pt ngx_http_next_body_filter;
-
-
-static ngx_int_t
-ngx_http_addition_header_filter(ngx_http_request_t *r)
-{
- ngx_http_addition_ctx_t *ctx;
- ngx_http_addition_conf_t *conf;
-
- if (r->headers_out.status != NGX_HTTP_OK || r != r->main) {
- return ngx_http_next_header_filter(r);
- }
-
- conf = ngx_http_get_module_loc_conf(r, ngx_http_addition_filter_module);
-
- if (conf->before_body.len == 0 && conf->after_body.len == 0) {
- return ngx_http_next_header_filter(r);
- }
-
- if (ngx_http_test_content_type(r, &conf->types) == NULL) {
- return ngx_http_next_header_filter(r);
- }
-
- ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_addition_ctx_t));
- if (ctx == NULL) {
- return NGX_ERROR;
- }
-
- ngx_http_set_ctx(r, ctx, ngx_http_addition_filter_module);
-
- ngx_http_clear_content_length(r);
- ngx_http_clear_accept_ranges(r);
- ngx_http_weak_etag(r);
-
- r->preserve_body = 1;
-
- return ngx_http_next_header_filter(r);
-}
-
-
-static ngx_int_t
-ngx_http_addition_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
-{
- ngx_int_t rc;
- ngx_uint_t last;
- ngx_chain_t *cl;
- ngx_http_request_t *sr;
- ngx_http_addition_ctx_t *ctx;
- ngx_http_addition_conf_t *conf;
-
- if (in == NULL || r->header_only) {
- return ngx_http_next_body_filter(r, in);
- }
-
- ctx = ngx_http_get_module_ctx(r, ngx_http_addition_filter_module);
-
- if (ctx == NULL) {
- return ngx_http_next_body_filter(r, in);
- }
-
- conf = ngx_http_get_module_loc_conf(r, ngx_http_addition_filter_module);
-
- if (!ctx->before_body_sent) {
- ctx->before_body_sent = 1;
-
- if (conf->before_body.len) {
- if (ngx_http_subrequest(r, &conf->before_body, NULL, &sr, NULL, 0)
- != NGX_OK)
- {
- return NGX_ERROR;
- }
- }
- }
-
- if (conf->after_body.len == 0) {
- ngx_http_set_ctx(r, NULL, ngx_http_addition_filter_module);
- return ngx_http_next_body_filter(r, in);
- }
-
- last = 0;
-
- for (cl = in; cl; cl = cl->next) {
- if (cl->buf->last_buf) {
- cl->buf->last_buf = 0;
- cl->buf->last_in_chain = 1;
- cl->buf->sync = 1;
- last = 1;
- }
- }
-
- rc = ngx_http_next_body_filter(r, in);
-
- if (rc == NGX_ERROR || !last || conf->after_body.len == 0) {
- return rc;
- }
-
- if (ngx_http_subrequest(r, &conf->after_body, NULL, &sr, NULL, 0)
- != NGX_OK)
- {
- return NGX_ERROR;
- }
-
- ngx_http_set_ctx(r, NULL, ngx_http_addition_filter_module);
-
- return ngx_http_send_special(r, NGX_HTTP_LAST);
-}
-
-
-static ngx_int_t
-ngx_http_addition_filter_init(ngx_conf_t *cf)
-{
- ngx_http_next_header_filter = ngx_http_top_header_filter;
- ngx_http_top_header_filter = ngx_http_addition_header_filter;
-
- ngx_http_next_body_filter = ngx_http_top_body_filter;
- ngx_http_top_body_filter = ngx_http_addition_body_filter;
-
- return NGX_OK;
-}
-
-
-static void *
-ngx_http_addition_create_conf(ngx_conf_t *cf)
-{
- ngx_http_addition_conf_t *conf;
-
- conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_addition_conf_t));
- if (conf == NULL) {
- return NULL;
- }
-
- /*
- * set by ngx_pcalloc():
- *
- * conf->before_body = { 0, NULL };
- * conf->after_body = { 0, NULL };
- * conf->types = { NULL };
- * conf->types_keys = NULL;
- */
-
- return conf;
-}
-
-
-static char *
-ngx_http_addition_merge_conf(ngx_conf_t *cf, void *parent, void *child)
-{
- ngx_http_addition_conf_t *prev = parent;
- ngx_http_addition_conf_t *conf = child;
-
- ngx_conf_merge_str_value(conf->before_body, prev->before_body, "");
- ngx_conf_merge_str_value(conf->after_body, prev->after_body, "");
-
- if (ngx_http_merge_types(cf, &conf->types_keys, &conf->types,
- &prev->types_keys, &prev->types,
- ngx_http_html_default_types)
- != NGX_OK)
- {
- return NGX_CONF_ERROR;
- }
-
- return NGX_CONF_OK;
-}
diff --git a/nginx/src/http/modules/ngx_http_auth_basic_module.c b/nginx/src/http/modules/ngx_http_auth_basic_module.c
deleted file mode 100644
index a6f9ec4..0000000
--- a/nginx/src/http/modules/ngx_http_auth_basic_module.c
+++ /dev/null
@@ -1,429 +0,0 @@
-
-/*
- * Copyright (C) Igor Sysoev
- * Copyright (C) Nginx, Inc.
- */
-
-
-#include <ngx_config.h>
-#include <ngx_core.h>
-#include <ngx_http.h>
-#include <ngx_crypt.h>
-
-
-#define NGX_HTTP_AUTH_BUF_SIZE 2048
-
-
-typedef struct {
- ngx_http_complex_value_t *realm;
- ngx_http_complex_value_t user_file;
-} ngx_http_auth_basic_loc_conf_t;
-
-
-static ngx_int_t ngx_http_auth_basic_handler(ngx_http_request_t *r);
-static ngx_int_t ngx_http_auth_basic_crypt_handler(ngx_http_request_t *r,
- ngx_str_t *passwd, ngx_str_t *realm);
-static ngx_int_t ngx_http_auth_basic_set_realm(ngx_http_request_t *r,
- ngx_str_t *realm);
-static void ngx_http_auth_basic_close(ngx_file_t *file);
-static void *ngx_http_auth_basic_create_loc_conf(ngx_conf_t *cf);
-static char *ngx_http_auth_basic_merge_loc_conf(ngx_conf_t *cf,
- void *parent, void *child);
-static ngx_int_t ngx_http_auth_basic_init(ngx_conf_t *cf);
-static char *ngx_http_auth_basic_user_file(ngx_conf_t *cf, ngx_command_t *cmd,
- void *conf);
-
-
-static ngx_command_t ngx_http_auth_basic_commands[] = {
-
- { ngx_string("auth_basic"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LMT_CONF
- |NGX_CONF_TAKE1,
- ngx_http_set_complex_value_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_auth_basic_loc_conf_t, realm),
- NULL },
-
- { ngx_string("auth_basic_user_file"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LMT_CONF
- |NGX_CONF_TAKE1,
- ngx_http_auth_basic_user_file,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_auth_basic_loc_conf_t, user_file),
- NULL },
-
- ngx_null_command
-};
-
-
-static ngx_http_module_t ngx_http_auth_basic_module_ctx = {
- NULL, /* preconfiguration */
- ngx_http_auth_basic_init, /* postconfiguration */
-
- NULL, /* create main configuration */
- NULL, /* init main configuration */
-
- NULL, /* create server configuration */
- NULL, /* merge server configuration */
-
- ngx_http_auth_basic_create_loc_conf, /* create location configuration */
- ngx_http_auth_basic_merge_loc_conf /* merge location configuration */
-};
-
-
-ngx_module_t ngx_http_auth_basic_module = {
- NGX_MODULE_V1,
- &ngx_http_auth_basic_module_ctx, /* module context */
- ngx_http_auth_basic_commands, /* module directives */
- NGX_HTTP_MODULE, /* module type */
- NULL, /* init master */
- NULL, /* init module */
- NULL, /* init process */
- NULL, /* init thread */
- NULL, /* exit thread */
- NULL, /* exit process */
- NULL, /* exit master */
- NGX_MODULE_V1_PADDING
-};
-
-
-static ngx_int_t
-ngx_http_auth_basic_handler(ngx_http_request_t *r)
-{
- off_t offset;
- ssize_t n;
- ngx_fd_t fd;
- ngx_int_t rc;
- ngx_err_t err;
- ngx_str_t pwd, realm, user_file;
- ngx_uint_t i, level, login, left, passwd;
- ngx_file_t file;
- ngx_http_auth_basic_loc_conf_t *alcf;
- u_char buf[NGX_HTTP_AUTH_BUF_SIZE];
- enum {
- sw_login,
- sw_passwd,
- sw_skip
- } state;
-
- alcf = ngx_http_get_module_loc_conf(r, ngx_http_auth_basic_module);
-
- if (alcf->realm == NULL || alcf->user_file.value.data == NULL) {
- return NGX_DECLINED;
- }
-
- if (ngx_http_complex_value(r, alcf->realm, &realm) != NGX_OK) {
- return NGX_ERROR;
- }
-
- if (realm.len == 3 && ngx_strncmp(realm.data, "off", 3) == 0) {
- return NGX_DECLINED;
- }
-
- rc = ngx_http_auth_basic_user(r);
-
- if (rc == NGX_DECLINED) {
-
- ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
- "no user/password was provided for basic authentication");
-
- return ngx_http_auth_basic_set_realm(r, &realm);
- }
-
- if (rc == NGX_ERROR) {
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
-
- if (ngx_http_complex_value(r, &alcf->user_file, &user_file) != NGX_OK) {
- return NGX_ERROR;
- }
-
- fd = ngx_open_file(user_file.data, NGX_FILE_RDONLY, NGX_FILE_OPEN, 0);
-
- if (fd == NGX_INVALID_FILE) {
- err = ngx_errno;
-
- if (err == NGX_ENOENT) {
- level = NGX_LOG_ERR;
- rc = NGX_HTTP_FORBIDDEN;
-
- } else {
- level = NGX_LOG_CRIT;
- rc = NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
-
- ngx_log_error(level, r->connection->log, err,
- ngx_open_file_n " \"%s\" failed", user_file.data);
-
- return rc;
- }
-
- ngx_memzero(&file, sizeof(ngx_file_t));
-
- file.fd = fd;
- file.name = user_file;
- file.log = r->connection->log;
-
- state = sw_login;
- passwd = 0;
- login = 0;
- left = 0;
- offset = 0;
-
- for ( ;; ) {
- i = left;
-
- n = ngx_read_file(&file, buf + left, NGX_HTTP_AUTH_BUF_SIZE - left,
- offset);
-
- if (n == NGX_ERROR) {
- ngx_http_auth_basic_close(&file);
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
-
- if (n == 0) {
- break;
- }
-
- for (i = left; i < left + n; i++) {
- switch (state) {
-
- case sw_login:
- if (login == 0) {
-
- if (buf[i] == '#' || buf[i] == CR) {
- state = sw_skip;
- break;
- }
-
- if (buf[i] == LF) {
- break;
- }
- }
-
- if (buf[i] != r->headers_in.user.data[login]) {
- state = sw_skip;
- break;
- }
-
- if (login == r->headers_in.user.len) {
- state = sw_passwd;
- passwd = i + 1;
- }
-
- login++;
-
- break;
-
- case sw_passwd:
- if (buf[i] == LF || buf[i] == CR || buf[i] == ':') {
- buf[i] = '\0';
-
- ngx_http_auth_basic_close(&file);
-
- pwd.len = i - passwd;
- pwd.data = &buf[passwd];
-
- return ngx_http_auth_basic_crypt_handler(r, &pwd, &realm);
- }
-
- break;
-
- case sw_skip:
- if (buf[i] == LF) {
- state = sw_login;
- login = 0;
- }
-
- break;
- }
- }
-
- if (state == sw_passwd) {
- left = left + n - passwd;
- ngx_memmove(buf, &buf[passwd], left);
- passwd = 0;
-
- } else {
- left = 0;
- }
-
- offset += n;
- }
-
- ngx_http_auth_basic_close(&file);
-
- if (state == sw_passwd) {
- pwd.len = i - passwd;
- pwd.data = ngx_pnalloc(r->pool, pwd.len + 1);
- if (pwd.data == NULL) {
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
-
- ngx_cpystrn(pwd.data, &buf[passwd], pwd.len + 1);
-
- return ngx_http_auth_basic_crypt_handler(r, &pwd, &realm);
- }
-
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "user \"%V\" was not found in \"%s\"",
- &r->headers_in.user, user_file.data);
-
- return ngx_http_auth_basic_set_realm(r, &realm);
-}
-
-
-static ngx_int_t
-ngx_http_auth_basic_crypt_handler(ngx_http_request_t *r, ngx_str_t *passwd,
- ngx_str_t *realm)
-{
- ngx_int_t rc;
- u_char *encrypted;
-
- rc = ngx_crypt(r->pool, r->headers_in.passwd.data, passwd->data,
- &encrypted);
-
- ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "rc: %i user: \"%V\" salt: \"%s\"",
- rc, &r->headers_in.user, passwd->data);
-
- if (rc != NGX_OK) {
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
-
- if (ngx_strcmp(encrypted, passwd->data) == 0) {
- return NGX_OK;
- }
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "encrypted: \"%s\"", encrypted);
-
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "user \"%V\": password mismatch",
- &r->headers_in.user);
-
- return ngx_http_auth_basic_set_realm(r, realm);
-}
-
-
-static ngx_int_t
-ngx_http_auth_basic_set_realm(ngx_http_request_t *r, ngx_str_t *realm)
-{
- size_t len;
- u_char *basic, *p;
-
- r->headers_out.www_authenticate = ngx_list_push(&r->headers_out.headers);
- if (r->headers_out.www_authenticate == NULL) {
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
-
- len = sizeof("Basic realm=\"\"") - 1 + realm->len;
-
- basic = ngx_pnalloc(r->pool, len);
- if (basic == NULL) {
- r->headers_out.www_authenticate->hash = 0;
- r->headers_out.www_authenticate = NULL;
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
-
- p = ngx_cpymem(basic, "Basic realm=\"", sizeof("Basic realm=\"") - 1);
- p = ngx_cpymem(p, realm->data, realm->len);
- *p = '"';
-
- r->headers_out.www_authenticate->hash = 1;
- ngx_str_set(&r->headers_out.www_authenticate->key, "WWW-Authenticate");
- r->headers_out.www_authenticate->value.data = basic;
- r->headers_out.www_authenticate->value.len = len;
-
- return NGX_HTTP_UNAUTHORIZED;
-}
-
-static void
-ngx_http_auth_basic_close(ngx_file_t *file)
-{
- if (ngx_close_file(file->fd) == NGX_FILE_ERROR) {
- ngx_log_error(NGX_LOG_ALERT, file->log, ngx_errno,
- ngx_close_file_n " \"%s\" failed", file->name.data);
- }
-}
-
-
-static void *
-ngx_http_auth_basic_create_loc_conf(ngx_conf_t *cf)
-{
- ngx_http_auth_basic_loc_conf_t *conf;
-
- conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_auth_basic_loc_conf_t));
- if (conf == NULL) {
- return NULL;
- }
-
- return conf;
-}
-
-
-static char *
-ngx_http_auth_basic_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
-{
- ngx_http_auth_basic_loc_conf_t *prev = parent;
- ngx_http_auth_basic_loc_conf_t *conf = child;
-
- if (conf->realm == NULL) {
- conf->realm = prev->realm;
- }
-
- if (conf->user_file.value.data == NULL) {
- conf->user_file = prev->user_file;
- }
-
- return NGX_CONF_OK;
-}
-
-
-static ngx_int_t
-ngx_http_auth_basic_init(ngx_conf_t *cf)
-{
- ngx_http_handler_pt *h;
- ngx_http_core_main_conf_t *cmcf;
-
- cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);
-
- h = ngx_array_push(&cmcf->phases[NGX_HTTP_ACCESS_PHASE].handlers);
- if (h == NULL) {
- return NGX_ERROR;
- }
-
- *h = ngx_http_auth_basic_handler;
-
- return NGX_OK;
-}
-
-
-static char *
-ngx_http_auth_basic_user_file(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
-{
- ngx_http_auth_basic_loc_conf_t *alcf = conf;
-
- ngx_str_t *value;
- ngx_http_compile_complex_value_t ccv;
-
- if (alcf->user_file.value.data) {
- return "is duplicate";
- }
-
- value = cf->args->elts;
-
- ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));
-
- ccv.cf = cf;
- ccv.value = &value[1];
- ccv.complex_value = &alcf->user_file;
- ccv.zero = 1;
- ccv.conf_prefix = 1;
-
- if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
- return NGX_CONF_ERROR;
- }
-
- return NGX_CONF_OK;
-}
diff --git a/nginx/src/http/modules/ngx_http_auth_request_module.c b/nginx/src/http/modules/ngx_http_auth_request_module.c
deleted file mode 100644
index bab79e4..0000000
--- a/nginx/src/http/modules/ngx_http_auth_request_module.c
+++ /dev/null
@@ -1,444 +0,0 @@
-
-/*
- * Copyright (C) Maxim Dounin
- * Copyright (C) Nginx, Inc.
- */
-
-
-#include <ngx_config.h>
-#include <ngx_core.h>
-#include <ngx_http.h>
-
-
-typedef struct {
- ngx_str_t uri;
- ngx_array_t *vars;
-} ngx_http_auth_request_conf_t;
-
-
-typedef struct {
- ngx_uint_t done;
- ngx_uint_t status;
- ngx_http_request_t *subrequest;
-} ngx_http_auth_request_ctx_t;
-
-
-typedef struct {
- ngx_int_t index;
- ngx_http_complex_value_t value;
- ngx_http_set_variable_pt set_handler;
-} ngx_http_auth_request_variable_t;
-
-
-static ngx_int_t ngx_http_auth_request_handler(ngx_http_request_t *r);
-static ngx_int_t ngx_http_auth_request_done(ngx_http_request_t *r,
- void *data, ngx_int_t rc);
-static ngx_int_t ngx_http_auth_request_set_variables(ngx_http_request_t *r,
- ngx_http_auth_request_conf_t *arcf, ngx_http_auth_request_ctx_t *ctx);
-static ngx_int_t ngx_http_auth_request_variable(ngx_http_request_t *r,
- ngx_http_variable_value_t *v, uintptr_t data);
-static void *ngx_http_auth_request_create_conf(ngx_conf_t *cf);
-static char *ngx_http_auth_request_merge_conf(ngx_conf_t *cf,
- void *parent, void *child);
-static ngx_int_t ngx_http_auth_request_init(ngx_conf_t *cf);
-static char *ngx_http_auth_request(ngx_conf_t *cf, ngx_command_t *cmd,
- void *conf);
-static char *ngx_http_auth_request_set(ngx_conf_t *cf, ngx_command_t *cmd,
- void *conf);
-
-
-static ngx_command_t ngx_http_auth_request_commands[] = {
-
- { ngx_string("auth_request"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_http_auth_request,
- NGX_HTTP_LOC_CONF_OFFSET,
- 0,
- NULL },
-
- { ngx_string("auth_request_set"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE2,
- ngx_http_auth_request_set,
- NGX_HTTP_LOC_CONF_OFFSET,
- 0,
- NULL },
-
- ngx_null_command
-};
-
-
-static ngx_http_module_t ngx_http_auth_request_module_ctx = {
- NULL, /* preconfiguration */
- ngx_http_auth_request_init, /* postconfiguration */
-
- NULL, /* create main configuration */
- NULL, /* init main configuration */
-
- NULL, /* create server configuration */
- NULL, /* merge server configuration */
-
- ngx_http_auth_request_create_conf, /* create location configuration */
- ngx_http_auth_request_merge_conf /* merge location configuration */
-};
-
-
-ngx_module_t ngx_http_auth_request_module = {
- NGX_MODULE_V1,
- &ngx_http_auth_request_module_ctx, /* module context */
- ngx_http_auth_request_commands, /* module directives */
- NGX_HTTP_MODULE, /* module type */
- NULL, /* init master */
- NULL, /* init module */
- NULL, /* init process */
- NULL, /* init thread */
- NULL, /* exit thread */
- NULL, /* exit process */
- NULL, /* exit master */
- NGX_MODULE_V1_PADDING
-};
-
-
-static ngx_int_t
-ngx_http_auth_request_handler(ngx_http_request_t *r)
-{
- ngx_table_elt_t *h, *ho;
- ngx_http_request_t *sr;
- ngx_http_post_subrequest_t *ps;
- ngx_http_auth_request_ctx_t *ctx;
- ngx_http_auth_request_conf_t *arcf;
-
- arcf = ngx_http_get_module_loc_conf(r, ngx_http_auth_request_module);
-
- if (arcf->uri.len == 0) {
- return NGX_DECLINED;
- }
-
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "auth request handler");
-
- ctx = ngx_http_get_module_ctx(r, ngx_http_auth_request_module);
-
- if (ctx != NULL) {
- if (!ctx->done) {
- return NGX_AGAIN;
- }
-
- /*
- * as soon as we are done - explicitly set variables to make
- * sure they will be available after internal redirects
- */
-
- if (ngx_http_auth_request_set_variables(r, arcf, ctx) != NGX_OK) {
- return NGX_ERROR;
- }
-
- /* return appropriate status */
-
- if (ctx->status == NGX_HTTP_FORBIDDEN) {
- return ctx->status;
- }
-
- if (ctx->status == NGX_HTTP_UNAUTHORIZED) {
- sr = ctx->subrequest;
-
- h = sr->headers_out.www_authenticate;
-
- if (!h && sr->upstream) {
- h = sr->upstream->headers_in.www_authenticate;
- }
-
- if (h) {
- ho = ngx_list_push(&r->headers_out.headers);
- if (ho == NULL) {
- return NGX_ERROR;
- }
-
- *ho = *h;
-
- r->headers_out.www_authenticate = ho;
- }
-
- return ctx->status;
- }
-
- if (ctx->status >= NGX_HTTP_OK
- && ctx->status < NGX_HTTP_SPECIAL_RESPONSE)
- {
- return NGX_OK;
- }
-
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "auth request unexpected status: %ui", ctx->status);
-
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
-
- ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_auth_request_ctx_t));
- if (ctx == NULL) {
- return NGX_ERROR;
- }
-
- ps = ngx_palloc(r->pool, sizeof(ngx_http_post_subrequest_t));
- if (ps == NULL) {
- return NGX_ERROR;
- }
-
- ps->handler = ngx_http_auth_request_done;
- ps->data = ctx;
-
- if (ngx_http_subrequest(r, &arcf->uri, NULL, &sr, ps,
- NGX_HTTP_SUBREQUEST_WAITED)
- != NGX_OK)
- {
- return NGX_ERROR;
- }
-
- /*
- * allocate fake request body to avoid attempts to read it and to make
- * sure real body file (if already read) won't be closed by upstream
- */
-
- sr->request_body = ngx_pcalloc(r->pool, sizeof(ngx_http_request_body_t));
- if (sr->request_body == NULL) {
- return NGX_ERROR;
- }
-
- sr->header_only = 1;
-
- ctx->subrequest = sr;
-
- ngx_http_set_ctx(r, ctx, ngx_http_auth_request_module);
-
- return NGX_AGAIN;
-}
-
-
-static ngx_int_t
-ngx_http_auth_request_done(ngx_http_request_t *r, void *data, ngx_int_t rc)
-{
- ngx_http_auth_request_ctx_t *ctx = data;
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "auth request done s:%ui", r->headers_out.status);
-
- ctx->done = 1;
- ctx->status = r->headers_out.status;
-
- return rc;
-}
-
-
-static ngx_int_t
-ngx_http_auth_request_set_variables(ngx_http_request_t *r,
- ngx_http_auth_request_conf_t *arcf, ngx_http_auth_request_ctx_t *ctx)
-{
- ngx_str_t val;
- ngx_http_variable_t *v;
- ngx_http_variable_value_t *vv;
- ngx_http_auth_request_variable_t *av, *last;
- ngx_http_core_main_conf_t *cmcf;
-
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "auth request set variables");
-
- if (arcf->vars == NULL) {
- return NGX_OK;
- }
-
- cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
- v = cmcf->variables.elts;
-
- av = arcf->vars->elts;
- last = av + arcf->vars->nelts;
-
- while (av < last) {
- /*
- * explicitly set new value to make sure it will be available after
- * internal redirects
- */
-
- vv = &r->variables[av->index];
-
- if (ngx_http_complex_value(ctx->subrequest, &av->value, &val)
- != NGX_OK)
- {
- return NGX_ERROR;
- }
-
- vv->valid = 1;
- vv->not_found = 0;
- vv->data = val.data;
- vv->len = val.len;
-
- if (av->set_handler) {
- /*
- * set_handler only available in cmcf->variables_keys, so we store
- * it explicitly
- */
-
- av->set_handler(r, vv, v[av->index].data);
- }
-
- av++;
- }
-
- return NGX_OK;
-}
-
-
-static ngx_int_t
-ngx_http_auth_request_variable(ngx_http_request_t *r,
- ngx_http_variable_value_t *v, uintptr_t data)
-{
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "auth request variable");
-
- v->not_found = 1;
-
- return NGX_OK;
-}
-
-
-static void *
-ngx_http_auth_request_create_conf(ngx_conf_t *cf)
-{
- ngx_http_auth_request_conf_t *conf;
-
- conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_auth_request_conf_t));
- if (conf == NULL) {
- return NULL;
- }
-
- /*
- * set by ngx_pcalloc():
- *
- * conf->uri = { 0, NULL };
- */
-
- conf->vars = NGX_CONF_UNSET_PTR;
-
- return conf;
-}
-
-
-static char *
-ngx_http_auth_request_merge_conf(ngx_conf_t *cf, void *parent, void *child)
-{
- ngx_http_auth_request_conf_t *prev = parent;
- ngx_http_auth_request_conf_t *conf = child;
-
- ngx_conf_merge_str_value(conf->uri, prev->uri, "");
- ngx_conf_merge_ptr_value(conf->vars, prev->vars, NULL);
-
- return NGX_CONF_OK;
-}
-
-
-static ngx_int_t
-ngx_http_auth_request_init(ngx_conf_t *cf)
-{
- ngx_http_handler_pt *h;
- ngx_http_core_main_conf_t *cmcf;
-
- cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);
-
- h = ngx_array_push(&cmcf->phases[NGX_HTTP_ACCESS_PHASE].handlers);
- if (h == NULL) {
- return NGX_ERROR;
- }
-
- *h = ngx_http_auth_request_handler;
-
- return NGX_OK;
-}
-
-
-static char *
-ngx_http_auth_request(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
-{
- ngx_http_auth_request_conf_t *arcf = conf;
-
- ngx_str_t *value;
-
- if (arcf->uri.data != NULL) {
- return "is duplicate";
- }
-
- value = cf->args->elts;
-
- if (ngx_strcmp(value[1].data, "off") == 0) {
- arcf->uri.len = 0;
- arcf->uri.data = (u_char *) "";
-
- return NGX_CONF_OK;
- }
-
- arcf->uri = value[1];
-
- return NGX_CONF_OK;
-}
-
-
-static char *
-ngx_http_auth_request_set(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
-{
- ngx_http_auth_request_conf_t *arcf = conf;
-
- ngx_str_t *value;
- ngx_http_variable_t *v;
- ngx_http_auth_request_variable_t *av;
- ngx_http_compile_complex_value_t ccv;
-
- value = cf->args->elts;
-
- if (value[1].data[0] != '$') {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "invalid variable name \"%V\"", &value[1]);
- return NGX_CONF_ERROR;
- }
-
- value[1].len--;
- value[1].data++;
-
- if (arcf->vars == NGX_CONF_UNSET_PTR) {
- arcf->vars = ngx_array_create(cf->pool, 1,
- sizeof(ngx_http_auth_request_variable_t));
- if (arcf->vars == NULL) {
- return NGX_CONF_ERROR;
- }
- }
-
- av = ngx_array_push(arcf->vars);
- if (av == NULL) {
- return NGX_CONF_ERROR;
- }
-
- v = ngx_http_add_variable(cf, &value[1], NGX_HTTP_VAR_CHANGEABLE);
- if (v == NULL) {
- return NGX_CONF_ERROR;
- }
-
- av->index = ngx_http_get_variable_index(cf, &value[1]);
- if (av->index == NGX_ERROR) {
- return NGX_CONF_ERROR;
- }
-
- if (v->get_handler == NULL) {
- v->get_handler = ngx_http_auth_request_variable;
- v->data = (uintptr_t) av;
- }
-
- av->set_handler = v->set_handler;
-
- ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));
-
- ccv.cf = cf;
- ccv.value = &value[2];
- ccv.complex_value = &av->value;
-
- if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
- return NGX_CONF_ERROR;
- }
-
- return NGX_CONF_OK;
-}
diff --git a/nginx/src/http/modules/ngx_http_autoindex_module.c b/nginx/src/http/modules/ngx_http_autoindex_module.c
deleted file mode 100644
index 94b91db..0000000
--- a/nginx/src/http/modules/ngx_http_autoindex_module.c
+++ /dev/null
@@ -1,1056 +0,0 @@
-
-/*
- * Copyright (C) Igor Sysoev
- * Copyright (C) Nginx, Inc.
- */
-
-
-#include <ngx_config.h>
-#include <ngx_core.h>
-#include <ngx_http.h>
-
-
-#if 0
-
-typedef struct {
- ngx_buf_t *buf;
- size_t size;
- ngx_pool_t *pool;
- size_t alloc_size;
- ngx_chain_t **last_out;
-} ngx_http_autoindex_ctx_t;
-
-#endif
-
-
-typedef struct {
- ngx_str_t name;
- size_t utf_len;
- size_t escape;
- size_t escape_html;
-
- unsigned dir:1;
- unsigned file:1;
-
- time_t mtime;
- off_t size;
-} ngx_http_autoindex_entry_t;
-
-
-typedef struct {
- ngx_flag_t enable;
- ngx_uint_t format;
- ngx_flag_t localtime;
- ngx_flag_t exact_size;
-} ngx_http_autoindex_loc_conf_t;
-
-
-#define NGX_HTTP_AUTOINDEX_HTML 0
-#define NGX_HTTP_AUTOINDEX_JSON 1
-#define NGX_HTTP_AUTOINDEX_JSONP 2
-#define NGX_HTTP_AUTOINDEX_XML 3
-
-#define NGX_HTTP_AUTOINDEX_PREALLOCATE 50
-
-#define NGX_HTTP_AUTOINDEX_NAME_LEN 50
-
-
-static ngx_buf_t *ngx_http_autoindex_html(ngx_http_request_t *r,
- ngx_array_t *entries);
-static ngx_buf_t *ngx_http_autoindex_json(ngx_http_request_t *r,
- ngx_array_t *entries, ngx_str_t *callback);
-static ngx_int_t ngx_http_autoindex_jsonp_callback(ngx_http_request_t *r,
- ngx_str_t *callback);
-static ngx_buf_t *ngx_http_autoindex_xml(ngx_http_request_t *r,
- ngx_array_t *entries);
-
-static int ngx_libc_cdecl ngx_http_autoindex_cmp_entries(const void *one,
- const void *two);
-static ngx_int_t ngx_http_autoindex_error(ngx_http_request_t *r,
- ngx_dir_t *dir, ngx_str_t *name);
-
-static ngx_int_t ngx_http_autoindex_init(ngx_conf_t *cf);
-static void *ngx_http_autoindex_create_loc_conf(ngx_conf_t *cf);
-static char *ngx_http_autoindex_merge_loc_conf(ngx_conf_t *cf,
- void *parent, void *child);
-
-
-static ngx_conf_enum_t ngx_http_autoindex_format[] = {
- { ngx_string("html"), NGX_HTTP_AUTOINDEX_HTML },
- { ngx_string("json"), NGX_HTTP_AUTOINDEX_JSON },
- { ngx_string("jsonp"), NGX_HTTP_AUTOINDEX_JSONP },
- { ngx_string("xml"), NGX_HTTP_AUTOINDEX_XML },
- { ngx_null_string, 0 }
-};
-
-
-static ngx_command_t ngx_http_autoindex_commands[] = {
-
- { ngx_string("autoindex"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
- ngx_conf_set_flag_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_autoindex_loc_conf_t, enable),
- NULL },
-
- { ngx_string("autoindex_format"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_enum_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_autoindex_loc_conf_t, format),
- &ngx_http_autoindex_format },
-
- { ngx_string("autoindex_localtime"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
- ngx_conf_set_flag_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_autoindex_loc_conf_t, localtime),
- NULL },
-
- { ngx_string("autoindex_exact_size"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
- ngx_conf_set_flag_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_autoindex_loc_conf_t, exact_size),
- NULL },
-
- ngx_null_command
-};
-
-
-static ngx_http_module_t ngx_http_autoindex_module_ctx = {
- NULL, /* preconfiguration */
- ngx_http_autoindex_init, /* postconfiguration */
-
- NULL, /* create main configuration */
- NULL, /* init main configuration */
-
- NULL, /* create server configuration */
- NULL, /* merge server configuration */
-
- ngx_http_autoindex_create_loc_conf, /* create location configuration */
- ngx_http_autoindex_merge_loc_conf /* merge location configuration */
-};
-
-
-ngx_module_t ngx_http_autoindex_module = {
- NGX_MODULE_V1,
- &ngx_http_autoindex_module_ctx, /* module context */
- ngx_http_autoindex_commands, /* module directives */
- NGX_HTTP_MODULE, /* module type */
- NULL, /* init master */
- NULL, /* init module */
- NULL, /* init process */
- NULL, /* init thread */
- NULL, /* exit thread */
- NULL, /* exit process */
- NULL, /* exit master */
- NGX_MODULE_V1_PADDING
-};
-
-
-static ngx_int_t
-ngx_http_autoindex_handler(ngx_http_request_t *r)
-{
- u_char *last, *filename;
- size_t len, allocated, root;
- ngx_err_t err;
- ngx_buf_t *b;
- ngx_int_t rc;
- ngx_str_t path, callback;
- ngx_dir_t dir;
- ngx_uint_t level, format;
- ngx_pool_t *pool;
- ngx_chain_t out;
- ngx_array_t entries;
- ngx_http_autoindex_entry_t *entry;
- ngx_http_autoindex_loc_conf_t *alcf;
-
- if (r->uri.data[r->uri.len - 1] != '/') {
- return NGX_DECLINED;
- }
-
- if (!(r->method & (NGX_HTTP_GET|NGX_HTTP_HEAD))) {
- return NGX_DECLINED;
- }
-
- alcf = ngx_http_get_module_loc_conf(r, ngx_http_autoindex_module);
-
- if (!alcf->enable) {
- return NGX_DECLINED;
- }
-
- rc = ngx_http_discard_request_body(r);
-
- if (rc != NGX_OK) {
- return rc;
- }
-
- /* NGX_DIR_MASK_LEN is lesser than NGX_HTTP_AUTOINDEX_PREALLOCATE */
-
- last = ngx_http_map_uri_to_path(r, &path, &root,
- NGX_HTTP_AUTOINDEX_PREALLOCATE);
- if (last == NULL) {
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
-
- allocated = path.len;
- path.len = last - path.data;
- if (path.len > 1) {
- path.len--;
- }
- path.data[path.len] = '\0';
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "http autoindex: \"%s\"", path.data);
-
- format = alcf->format;
-
- if (format == NGX_HTTP_AUTOINDEX_JSONP) {
- if (ngx_http_autoindex_jsonp_callback(r, &callback) != NGX_OK) {
- return NGX_HTTP_BAD_REQUEST;
- }
-
- if (callback.len == 0) {
- format = NGX_HTTP_AUTOINDEX_JSON;
- }
- }
-
- if (ngx_open_dir(&path, &dir) == NGX_ERROR) {
- err = ngx_errno;
-
- if (err == NGX_ENOENT
- || err == NGX_ENOTDIR
- || err == NGX_ENAMETOOLONG)
- {
- level = NGX_LOG_ERR;
- rc = NGX_HTTP_NOT_FOUND;
-
- } else if (err == NGX_EACCES) {
- level = NGX_LOG_ERR;
- rc = NGX_HTTP_FORBIDDEN;
-
- } else {
- level = NGX_LOG_CRIT;
- rc = NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
-
- ngx_log_error(level, r->connection->log, err,
- ngx_open_dir_n " \"%s\" failed", path.data);
-
- return rc;
- }
-
-#if (NGX_SUPPRESS_WARN)
-
- /* MSVC thinks 'entries' may be used without having been initialized */
- ngx_memzero(&entries, sizeof(ngx_array_t));
-
-#endif
-
- /* TODO: pool should be temporary pool */
- pool = r->pool;
-
- if (ngx_array_init(&entries, pool, 40, sizeof(ngx_http_autoindex_entry_t))
- != NGX_OK)
- {
- return ngx_http_autoindex_error(r, &dir, &path);
- }
-
- r->headers_out.status = NGX_HTTP_OK;
-
- switch (format) {
-
- case NGX_HTTP_AUTOINDEX_JSON:
- ngx_str_set(&r->headers_out.content_type, "application/json");
- break;
-
- case NGX_HTTP_AUTOINDEX_JSONP:
- ngx_str_set(&r->headers_out.content_type, "application/javascript");
- break;
-
- case NGX_HTTP_AUTOINDEX_XML:
- ngx_str_set(&r->headers_out.content_type, "text/xml");
- ngx_str_set(&r->headers_out.charset, "utf-8");
- break;
-
- default: /* NGX_HTTP_AUTOINDEX_HTML */
- ngx_str_set(&r->headers_out.content_type, "text/html");
- break;
- }
-
- r->headers_out.content_type_len = r->headers_out.content_type.len;
- r->headers_out.content_type_lowcase = NULL;
-
- rc = ngx_http_send_header(r);
-
- if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) {
- if (ngx_close_dir(&dir) == NGX_ERROR) {
- ngx_log_error(NGX_LOG_ALERT, r->connection->log, ngx_errno,
- ngx_close_dir_n " \"%V\" failed", &path);
- }
-
- return rc;
- }
-
- filename = path.data;
- filename[path.len] = '/';
-
- for ( ;; ) {
- ngx_set_errno(0);
-
- if (ngx_read_dir(&dir) == NGX_ERROR) {
- err = ngx_errno;
-
- if (err != NGX_ENOMOREFILES) {
- ngx_log_error(NGX_LOG_CRIT, r->connection->log, err,
- ngx_read_dir_n " \"%V\" failed", &path);
- return ngx_http_autoindex_error(r, &dir, &path);
- }
-
- break;
- }
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "http autoindex file: \"%s\"", ngx_de_name(&dir));
-
- len = ngx_de_namelen(&dir);
-
- if (ngx_de_name(&dir)[0] == '.') {
- continue;
- }
-
- if (!dir.valid_info) {
-
- /* 1 byte for '/' and 1 byte for terminating '\0' */
-
- if (path.len + 1 + len + 1 > allocated) {
- allocated = path.len + 1 + len + 1
- + NGX_HTTP_AUTOINDEX_PREALLOCATE;
-
- filename = ngx_pnalloc(pool, allocated);
- if (filename == NULL) {
- return ngx_http_autoindex_error(r, &dir, &path);
- }
-
- last = ngx_cpystrn(filename, path.data, path.len + 1);
- *last++ = '/';
- }
-
- ngx_cpystrn(last, ngx_de_name(&dir), len + 1);
-
- if (ngx_de_info(filename, &dir) == NGX_FILE_ERROR) {
- err = ngx_errno;
-
- if (err != NGX_ENOENT && err != NGX_ELOOP) {
- ngx_log_error(NGX_LOG_CRIT, r->connection->log, err,
- ngx_de_info_n " \"%s\" failed", filename);
-
- if (err == NGX_EACCES) {
- continue;
- }
-
- return ngx_http_autoindex_error(r, &dir, &path);
- }
-
- if (ngx_de_link_info(filename, &dir) == NGX_FILE_ERROR) {
- ngx_log_error(NGX_LOG_CRIT, r->connection->log, ngx_errno,
- ngx_de_link_info_n " \"%s\" failed",
- filename);
- return ngx_http_autoindex_error(r, &dir, &path);
- }
- }
- }
-
- entry = ngx_array_push(&entries);
- if (entry == NULL) {
- return ngx_http_autoindex_error(r, &dir, &path);
- }
-
- entry->name.len = len;
-
- entry->name.data = ngx_pnalloc(pool, len + 1);
- if (entry->name.data == NULL) {
- return ngx_http_autoindex_error(r, &dir, &path);
- }
-
- ngx_cpystrn(entry->name.data, ngx_de_name(&dir), len + 1);
-
- entry->dir = ngx_de_is_dir(&dir);
- entry->file = ngx_de_is_file(&dir);
- entry->mtime = ngx_de_mtime(&dir);
- entry->size = ngx_de_size(&dir);
- }
-
- if (ngx_close_dir(&dir) == NGX_ERROR) {
- ngx_log_error(NGX_LOG_ALERT, r->connection->log, ngx_errno,
- ngx_close_dir_n " \"%V\" failed", &path);
- }
-
- if (entries.nelts > 1) {
- ngx_qsort(entries.elts, (size_t) entries.nelts,
- sizeof(ngx_http_autoindex_entry_t),
- ngx_http_autoindex_cmp_entries);
- }
-
- switch (format) {
-
- case NGX_HTTP_AUTOINDEX_JSON:
- b = ngx_http_autoindex_json(r, &entries, NULL);
- break;
-
- case NGX_HTTP_AUTOINDEX_JSONP:
- b = ngx_http_autoindex_json(r, &entries, &callback);
- break;
-
- case NGX_HTTP_AUTOINDEX_XML:
- b = ngx_http_autoindex_xml(r, &entries);
- break;
-
- default: /* NGX_HTTP_AUTOINDEX_HTML */
- b = ngx_http_autoindex_html(r, &entries);
- break;
- }
-
- if (b == NULL) {
- return NGX_ERROR;
- }
-
- /* TODO: free temporary pool */
-
- if (r == r->main) {
- b->last_buf = 1;
- }
-
- b->last_in_chain = 1;
-
- out.buf = b;
- out.next = NULL;
-
- return ngx_http_output_filter(r, &out);
-}
-
-
-static ngx_buf_t *
-ngx_http_autoindex_html(ngx_http_request_t *r, ngx_array_t *entries)
-{
- u_char *last, scale;
- off_t length;
- size_t len, char_len, escape_html;
- ngx_tm_t tm;
- ngx_buf_t *b;
- ngx_int_t size;
- ngx_uint_t i, utf8;
- ngx_time_t *tp;
- ngx_http_autoindex_entry_t *entry;
- ngx_http_autoindex_loc_conf_t *alcf;
-
- static u_char title[] =
- "<html>" CRLF
- "<head><title>Index of "
- ;
-
- static u_char header[] =
- "</title></head>" CRLF
- "<body bgcolor=\"white\">" CRLF
- "<h1>Index of "
- ;
-
- static u_char tail[] =
- "</body>" CRLF
- "</html>" CRLF
- ;
-
- static char *months[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
- "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
-
- if (r->headers_out.charset.len == 5
- && ngx_strncasecmp(r->headers_out.charset.data, (u_char *) "utf-8", 5)
- == 0)
- {
- utf8 = 1;
-
- } else {
- utf8 = 0;
- }
-
- escape_html = ngx_escape_html(NULL, r->uri.data, r->uri.len);
-
- len = sizeof(title) - 1
- + r->uri.len + escape_html
- + sizeof(header) - 1
- + r->uri.len + escape_html
- + sizeof("</h1>") - 1
- + sizeof("<hr><pre><a href=\"../\">../</a>" CRLF) - 1
- + sizeof("</pre><hr>") - 1
- + sizeof(tail) - 1;
-
- entry = entries->elts;
- for (i = 0; i < entries->nelts; i++) {
- entry[i].escape = 2 * ngx_escape_uri(NULL, entry[i].name.data,
- entry[i].name.len,
- NGX_ESCAPE_URI_COMPONENT);
-
- entry[i].escape_html = ngx_escape_html(NULL, entry[i].name.data,
- entry[i].name.len);
-
- if (utf8) {
- entry[i].utf_len = ngx_utf8_length(entry[i].name.data,
- entry[i].name.len);
- } else {
- entry[i].utf_len = entry[i].name.len;
- }
-
- len += sizeof("<a href=\"") - 1
- + entry[i].name.len + entry[i].escape
- + 1 /* 1 is for "/" */
- + sizeof("\">") - 1
- + entry[i].name.len - entry[i].utf_len
- + entry[i].escape_html
- + NGX_HTTP_AUTOINDEX_NAME_LEN + sizeof("&gt;") - 2
- + sizeof("</a>") - 1
- + sizeof(" 28-Sep-1970 12:00 ") - 1
- + 20 /* the file size */
- + 2;
- }
-
- b = ngx_create_temp_buf(r->pool, len);
- if (b == NULL) {
- return NULL;
- }
-
- b->last = ngx_cpymem(b->last, title, sizeof(title) - 1);
-
- if (escape_html) {
- b->last = (u_char *) ngx_escape_html(b->last, r->uri.data, r->uri.len);
- b->last = ngx_cpymem(b->last, header, sizeof(header) - 1);
- b->last = (u_char *) ngx_escape_html(b->last, r->uri.data, r->uri.len);
-
- } else {
- b->last = ngx_cpymem(b->last, r->uri.data, r->uri.len);
- b->last = ngx_cpymem(b->last, header, sizeof(header) - 1);
- b->last = ngx_cpymem(b->last, r->uri.data, r->uri.len);
- }
-
- b->last = ngx_cpymem(b->last, "</h1>", sizeof("</h1>") - 1);
-
- b->last = ngx_cpymem(b->last, "<hr><pre><a href=\"../\">../</a>" CRLF,
- sizeof("<hr><pre><a href=\"../\">../</a>" CRLF) - 1);
-
- alcf = ngx_http_get_module_loc_conf(r, ngx_http_autoindex_module);
- tp = ngx_timeofday();
-
- for (i = 0; i < entries->nelts; i++) {
- b->last = ngx_cpymem(b->last, "<a href=\"", sizeof("<a href=\"") - 1);
-
- if (entry[i].escape) {
- ngx_escape_uri(b->last, entry[i].name.data, entry[i].name.len,
- NGX_ESCAPE_URI_COMPONENT);
-
- b->last += entry[i].name.len + entry[i].escape;
-
- } else {
- b->last = ngx_cpymem(b->last, entry[i].name.data,
- entry[i].name.len);
- }
-
- if (entry[i].dir) {
- *b->last++ = '/';
- }
-
- *b->last++ = '"';
- *b->last++ = '>';
-
- len = entry[i].utf_len;
-
- if (entry[i].name.len != len) {
- if (len > NGX_HTTP_AUTOINDEX_NAME_LEN) {
- char_len = NGX_HTTP_AUTOINDEX_NAME_LEN - 3 + 1;
-
- } else {
- char_len = NGX_HTTP_AUTOINDEX_NAME_LEN + 1;
- }
-
- last = b->last;
- b->last = ngx_utf8_cpystrn(b->last, entry[i].name.data,
- char_len, entry[i].name.len + 1);
-
- if (entry[i].escape_html) {
- b->last = (u_char *) ngx_escape_html(last, entry[i].name.data,
- b->last - last);
- }
-
- last = b->last;
-
- } else {
- if (entry[i].escape_html) {
- if (len > NGX_HTTP_AUTOINDEX_NAME_LEN) {
- char_len = NGX_HTTP_AUTOINDEX_NAME_LEN - 3;
-
- } else {
- char_len = len;
- }
-
- b->last = (u_char *) ngx_escape_html(b->last,
- entry[i].name.data, char_len);
- last = b->last;
-
- } else {
- b->last = ngx_cpystrn(b->last, entry[i].name.data,
- NGX_HTTP_AUTOINDEX_NAME_LEN + 1);
- last = b->last - 3;
- }
- }
-
- if (len > NGX_HTTP_AUTOINDEX_NAME_LEN) {
- b->last = ngx_cpymem(last, "..&gt;</a>", sizeof("..&gt;</a>") - 1);
-
- } else {
- if (entry[i].dir && NGX_HTTP_AUTOINDEX_NAME_LEN - len > 0) {
- *b->last++ = '/';
- len++;
- }
-
- b->last = ngx_cpymem(b->last, "</a>", sizeof("</a>") - 1);
-
- if (NGX_HTTP_AUTOINDEX_NAME_LEN - len > 0) {
- ngx_memset(b->last, ' ', NGX_HTTP_AUTOINDEX_NAME_LEN - len);
- b->last += NGX_HTTP_AUTOINDEX_NAME_LEN - len;
- }
- }
-
- *b->last++ = ' ';
-
- ngx_gmtime(entry[i].mtime + tp->gmtoff * 60 * alcf->localtime, &tm);
-
- b->last = ngx_sprintf(b->last, "%02d-%s-%d %02d:%02d ",
- tm.ngx_tm_mday,
- months[tm.ngx_tm_mon - 1],
- tm.ngx_tm_year,
- tm.ngx_tm_hour,
- tm.ngx_tm_min);
-
- if (alcf->exact_size) {
- if (entry[i].dir) {
- b->last = ngx_cpymem(b->last, " -",
- sizeof(" -") - 1);
- } else {
- b->last = ngx_sprintf(b->last, "%19O", entry[i].size);
- }
-
- } else {
- if (entry[i].dir) {
- b->last = ngx_cpymem(b->last, " -",
- sizeof(" -") - 1);
-
- } else {
- length = entry[i].size;
-
- if (length > 1024 * 1024 * 1024 - 1) {
- size = (ngx_int_t) (length / (1024 * 1024 * 1024));
- if ((length % (1024 * 1024 * 1024))
- > (1024 * 1024 * 1024 / 2 - 1))
- {
- size++;
- }
- scale = 'G';
-
- } else if (length > 1024 * 1024 - 1) {
- size = (ngx_int_t) (length / (1024 * 1024));
- if ((length % (1024 * 1024)) > (1024 * 1024 / 2 - 1)) {
- size++;
- }
- scale = 'M';
-
- } else if (length > 9999) {
- size = (ngx_int_t) (length / 1024);
- if (length % 1024 > 511) {
- size++;
- }
- scale = 'K';
-
- } else {
- size = (ngx_int_t) length;
- scale = '\0';
- }
-
- if (scale) {
- b->last = ngx_sprintf(b->last, "%6i%c", size, scale);
-
- } else {
- b->last = ngx_sprintf(b->last, " %6i", size);
- }
- }
- }
-
- *b->last++ = CR;
- *b->last++ = LF;
- }
-
- b->last = ngx_cpymem(b->last, "</pre><hr>", sizeof("</pre><hr>") - 1);
-
- b->last = ngx_cpymem(b->last, tail, sizeof(tail) - 1);
-
- return b;
-}
-
-
-static ngx_buf_t *
-ngx_http_autoindex_json(ngx_http_request_t *r, ngx_array_t *entries,
- ngx_str_t *callback)
-{
- size_t len;
- ngx_buf_t *b;
- ngx_uint_t i;
- ngx_http_autoindex_entry_t *entry;
-
- len = sizeof("[" CRLF CRLF "]") - 1;
-
- if (callback) {
- len += sizeof("/* callback */" CRLF "();") - 1 + callback->len;
- }
-
- entry = entries->elts;
-
- for (i = 0; i < entries->nelts; i++) {
- entry[i].escape = ngx_escape_json(NULL, entry[i].name.data,
- entry[i].name.len);
-
- len += sizeof("{ }," CRLF) - 1
- + sizeof("\"name\":\"\"") - 1
- + entry[i].name.len + entry[i].escape
- + sizeof(", \"type\":\"directory\"") - 1
- + sizeof(", \"mtime\":\"Wed, 31 Dec 1986 10:00:00 GMT\"") - 1;
-
- if (entry[i].file) {
- len += sizeof(", \"size\":") - 1 + NGX_OFF_T_LEN;
- }
- }
-
- b = ngx_create_temp_buf(r->pool, len);
- if (b == NULL) {
- return NULL;
- }
-
- if (callback) {
- b->last = ngx_cpymem(b->last, "/* callback */" CRLF,
- sizeof("/* callback */" CRLF) - 1);
-
- b->last = ngx_cpymem(b->last, callback->data, callback->len);
-
- *b->last++ = '(';
- }
-
- *b->last++ = '[';
-
- for (i = 0; i < entries->nelts; i++) {
- b->last = ngx_cpymem(b->last, CRLF "{ \"name\":\"",
- sizeof(CRLF "{ \"name\":\"") - 1);
-
- if (entry[i].escape) {
- b->last = (u_char *) ngx_escape_json(b->last, entry[i].name.data,
- entry[i].name.len);
- } else {
- b->last = ngx_cpymem(b->last, entry[i].name.data,
- entry[i].name.len);
- }
-
- b->last = ngx_cpymem(b->last, "\", \"type\":\"",
- sizeof("\", \"type\":\"") - 1);
-
- if (entry[i].dir) {
- b->last = ngx_cpymem(b->last, "directory", sizeof("directory") - 1);
-
- } else if (entry[i].file) {
- b->last = ngx_cpymem(b->last, "file", sizeof("file") - 1);
-
- } else {
- b->last = ngx_cpymem(b->last, "other", sizeof("other") - 1);
- }
-
- b->last = ngx_cpymem(b->last, "\", \"mtime\":\"",
- sizeof("\", \"mtime\":\"") - 1);
-
- b->last = ngx_http_time(b->last, entry[i].mtime);
-
- if (entry[i].file) {
- b->last = ngx_cpymem(b->last, "\", \"size\":",
- sizeof("\", \"size\":") - 1);
- b->last = ngx_sprintf(b->last, "%O", entry[i].size);
-
- } else {
- *b->last++ = '"';
- }
-
- b->last = ngx_cpymem(b->last, " },", sizeof(" },") - 1);
- }
-
- if (i > 0) {
- b->last--; /* strip last comma */
- }
-
- b->last = ngx_cpymem(b->last, CRLF "]", sizeof(CRLF "]") - 1);
-
- if (callback) {
- *b->last++ = ')'; *b->last++ = ';';
- }
-
- return b;
-}
-
-
-static ngx_int_t
-ngx_http_autoindex_jsonp_callback(ngx_http_request_t *r, ngx_str_t *callback)
-{
- u_char *p, c, ch;
- ngx_uint_t i;
-
- if (ngx_http_arg(r, (u_char *) "callback", 8, callback) != NGX_OK) {
- callback->len = 0;
- return NGX_OK;
- }
-
- if (callback->len > 128) {
- ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
- "client sent too long callback name: \"%V\"", callback);
- return NGX_DECLINED;
- }
-
- p = callback->data;
-
- for (i = 0; i < callback->len; i++) {
- ch = p[i];
-
- c = (u_char) (ch | 0x20);
- if (c >= 'a' && c <= 'z') {
- continue;
- }
-
- if ((ch >= '0' && ch <= '9') || ch == '_' || ch == '.') {
- continue;
- }
-
- ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
- "client sent invalid callback name: \"%V\"", callback);
-
- return NGX_DECLINED;
- }
-
- return NGX_OK;
-}
-
-
-static ngx_buf_t *
-ngx_http_autoindex_xml(ngx_http_request_t *r, ngx_array_t *entries)
-{
- size_t len;
- ngx_tm_t tm;
- ngx_buf_t *b;
- ngx_str_t type;
- ngx_uint_t i;
- ngx_http_autoindex_entry_t *entry;
-
- static u_char head[] = "<?xml version=\"1.0\"?>" CRLF "<list>" CRLF;
- static u_char tail[] = "</list>" CRLF;
-
- len = sizeof(head) - 1 + sizeof(tail) - 1;
-
- entry = entries->elts;
-
- for (i = 0; i < entries->nelts; i++) {
- entry[i].escape = ngx_escape_html(NULL, entry[i].name.data,
- entry[i].name.len);
-
- len += sizeof("<directory></directory>" CRLF) - 1
- + entry[i].name.len + entry[i].escape
- + sizeof(" mtime=\"1986-12-31T10:00:00Z\"") - 1;
-
- if (entry[i].file) {
- len += sizeof(" size=\"\"") - 1 + NGX_OFF_T_LEN;
- }
- }
-
- b = ngx_create_temp_buf(r->pool, len);
- if (b == NULL) {
- return NULL;
- }
-
- b->last = ngx_cpymem(b->last, head, sizeof(head) - 1);
-
- for (i = 0; i < entries->nelts; i++) {
- *b->last++ = '<';
-
- if (entry[i].dir) {
- ngx_str_set(&type, "directory");
-
- } else if (entry[i].file) {
- ngx_str_set(&type, "file");
-
- } else {
- ngx_str_set(&type, "other");
- }
-
- b->last = ngx_cpymem(b->last, type.data, type.len);
-
- b->last = ngx_cpymem(b->last, " mtime=\"", sizeof(" mtime=\"") - 1);
-
- ngx_gmtime(entry[i].mtime, &tm);
-
- b->last = ngx_sprintf(b->last, "%4d-%02d-%02dT%02d:%02d:%02dZ",
- tm.ngx_tm_year, tm.ngx_tm_mon,
- tm.ngx_tm_mday, tm.ngx_tm_hour,
- tm.ngx_tm_min, tm.ngx_tm_sec);
-
- if (entry[i].file) {
- b->last = ngx_cpymem(b->last, "\" size=\"",
- sizeof("\" size=\"") - 1);
- b->last = ngx_sprintf(b->last, "%O", entry[i].size);
- }
-
- *b->last++ = '"'; *b->last++ = '>';
-
- if (entry[i].escape) {
- b->last = (u_char *) ngx_escape_html(b->last, entry[i].name.data,
- entry[i].name.len);
- } else {
- b->last = ngx_cpymem(b->last, entry[i].name.data,
- entry[i].name.len);
- }
-
- *b->last++ = '<'; *b->last++ = '/';
-
- b->last = ngx_cpymem(b->last, type.data, type.len);
-
- *b->last++ = '>';
-
- *b->last++ = CR; *b->last++ = LF;
- }
-
- b->last = ngx_cpymem(b->last, tail, sizeof(tail) - 1);
-
- return b;
-}
-
-
-static int ngx_libc_cdecl
-ngx_http_autoindex_cmp_entries(const void *one, const void *two)
-{
- ngx_http_autoindex_entry_t *first = (ngx_http_autoindex_entry_t *) one;
- ngx_http_autoindex_entry_t *second = (ngx_http_autoindex_entry_t *) two;
-
- if (first->dir && !second->dir) {
- /* move the directories to the start */
- return -1;
- }
-
- if (!first->dir && second->dir) {
- /* move the directories to the start */
- return 1;
- }
-
- return (int) ngx_strcmp(first->name.data, second->name.data);
-}
-
-
-#if 0
-
-static ngx_buf_t *
-ngx_http_autoindex_alloc(ngx_http_autoindex_ctx_t *ctx, size_t size)
-{
- ngx_chain_t *cl;
-
- if (ctx->buf) {
-
- if ((size_t) (ctx->buf->end - ctx->buf->last) >= size) {
- return ctx->buf;
- }
-
- ctx->size += ctx->buf->last - ctx->buf->pos;
- }
-
- ctx->buf = ngx_create_temp_buf(ctx->pool, ctx->alloc_size);
- if (ctx->buf == NULL) {
- return NULL;
- }
-
- cl = ngx_alloc_chain_link(ctx->pool);
- if (cl == NULL) {
- return NULL;
- }
-
- cl->buf = ctx->buf;
- cl->next = NULL;
-
- *ctx->last_out = cl;
- ctx->last_out = &cl->next;
-
- return ctx->buf;
-}
-
-#endif
-
-
-static ngx_int_t
-ngx_http_autoindex_error(ngx_http_request_t *r, ngx_dir_t *dir, ngx_str_t *name)
-{
- if (ngx_close_dir(dir) == NGX_ERROR) {
- ngx_log_error(NGX_LOG_ALERT, r->connection->log, ngx_errno,
- ngx_close_dir_n " \"%V\" failed", name);
- }
-
- return r->header_sent ? NGX_ERROR : NGX_HTTP_INTERNAL_SERVER_ERROR;
-}
-
-
-static void *
-ngx_http_autoindex_create_loc_conf(ngx_conf_t *cf)
-{
- ngx_http_autoindex_loc_conf_t *conf;
-
- conf = ngx_palloc(cf->pool, sizeof(ngx_http_autoindex_loc_conf_t));
- if (conf == NULL) {
- return NULL;
- }
-
- conf->enable = NGX_CONF_UNSET;
- conf->format = NGX_CONF_UNSET_UINT;
- conf->localtime = NGX_CONF_UNSET;
- conf->exact_size = NGX_CONF_UNSET;
-
- return conf;
-}
-
-
-static char *
-ngx_http_autoindex_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
-{
- ngx_http_autoindex_loc_conf_t *prev = parent;
- ngx_http_autoindex_loc_conf_t *conf = child;
-
- ngx_conf_merge_value(conf->enable, prev->enable, 0);
- ngx_conf_merge_uint_value(conf->format, prev->format,
- NGX_HTTP_AUTOINDEX_HTML);
- ngx_conf_merge_value(conf->localtime, prev->localtime, 0);
- ngx_conf_merge_value(conf->exact_size, prev->exact_size, 1);
-
- return NGX_CONF_OK;
-}
-
-
-static ngx_int_t
-ngx_http_autoindex_init(ngx_conf_t *cf)
-{
- ngx_http_handler_pt *h;
- ngx_http_core_main_conf_t *cmcf;
-
- cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);
-
- h = ngx_array_push(&cmcf->phases[NGX_HTTP_CONTENT_PHASE].handlers);
- if (h == NULL) {
- return NGX_ERROR;
- }
-
- *h = ngx_http_autoindex_handler;
-
- return NGX_OK;
-}
diff --git a/nginx/src/http/modules/ngx_http_browser_module.c b/nginx/src/http/modules/ngx_http_browser_module.c
deleted file mode 100644
index f774254..0000000
--- a/nginx/src/http/modules/ngx_http_browser_module.c
+++ /dev/null
@@ -1,712 +0,0 @@
-
-/*
- * Copyright (C) Igor Sysoev
- * Copyright (C) Nginx, Inc.
- */
-
-
-#include <ngx_config.h>
-#include <ngx_core.h>
-#include <ngx_http.h>
-
-
-/*
- * The module can check browser versions conforming to the following formats:
- * X, X.X, X.X.X, and X.X.X.X. The maximum values of each format may be
- * 4000, 4000.99, 4000.99.99, and 4000.99.99.99.
- */
-
-
-#define NGX_HTTP_MODERN_BROWSER 0
-#define NGX_HTTP_ANCIENT_BROWSER 1
-
-
-typedef struct {
- u_char browser[12];
- size_t skip;
- size_t add;
- u_char name[12];
-} ngx_http_modern_browser_mask_t;
-
-
-typedef struct {
- ngx_uint_t version;
- size_t skip;
- size_t add;
- u_char name[12];
-} ngx_http_modern_browser_t;
-
-
-typedef struct {
- ngx_array_t *modern_browsers;
- ngx_array_t *ancient_browsers;
- ngx_http_variable_value_t *modern_browser_value;
- ngx_http_variable_value_t *ancient_browser_value;
-
- unsigned modern_unlisted_browsers:1;
- unsigned netscape4:1;
-} ngx_http_browser_conf_t;
-
-
-static ngx_int_t ngx_http_msie_variable(ngx_http_request_t *r,
- ngx_http_variable_value_t *v, uintptr_t data);
-static ngx_int_t ngx_http_browser_variable(ngx_http_request_t *r,
- ngx_http_variable_value_t *v, uintptr_t data);
-
-static ngx_uint_t ngx_http_browser(ngx_http_request_t *r,
- ngx_http_browser_conf_t *cf);
-
-static ngx_int_t ngx_http_browser_add_variables(ngx_conf_t *cf);
-static void *ngx_http_browser_create_conf(ngx_conf_t *cf);
-static char *ngx_http_browser_merge_conf(ngx_conf_t *cf, void *parent,
- void *child);
-static int ngx_libc_cdecl ngx_http_modern_browser_sort(const void *one,
- const void *two);
-static char *ngx_http_modern_browser(ngx_conf_t *cf, ngx_command_t *cmd,
- void *conf);
-static char *ngx_http_ancient_browser(ngx_conf_t *cf, ngx_command_t *cmd,
- void *conf);
-static char *ngx_http_modern_browser_value(ngx_conf_t *cf, ngx_command_t *cmd,
- void *conf);
-static char *ngx_http_ancient_browser_value(ngx_conf_t *cf, ngx_command_t *cmd,
- void *conf);
-
-
-static ngx_command_t ngx_http_browser_commands[] = {
-
- { ngx_string("modern_browser"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE12,
- ngx_http_modern_browser,
- NGX_HTTP_LOC_CONF_OFFSET,
- 0,
- NULL },
-
- { ngx_string("ancient_browser"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
- ngx_http_ancient_browser,
- NGX_HTTP_LOC_CONF_OFFSET,
- 0,
- NULL },
-
- { ngx_string("modern_browser_value"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_http_modern_browser_value,
- NGX_HTTP_LOC_CONF_OFFSET,
- 0,
- NULL },
-
- { ngx_string("ancient_browser_value"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_http_ancient_browser_value,
- NGX_HTTP_LOC_CONF_OFFSET,
- 0,
- NULL },
-
- ngx_null_command
-};
-
-
-static ngx_http_module_t ngx_http_browser_module_ctx = {
- ngx_http_browser_add_variables, /* preconfiguration */
- NULL, /* postconfiguration */
-
- NULL, /* create main configuration */
- NULL, /* init main configuration */
-
- NULL, /* create server configuration */
- NULL, /* merge server configuration */
-
- ngx_http_browser_create_conf, /* create location configuration */
- ngx_http_browser_merge_conf /* merge location configuration */
-};
-
-
-ngx_module_t ngx_http_browser_module = {
- NGX_MODULE_V1,
- &ngx_http_browser_module_ctx, /* module context */
- ngx_http_browser_commands, /* module directives */
- NGX_HTTP_MODULE, /* module type */
- NULL, /* init master */
- NULL, /* init module */
- NULL, /* init process */
- NULL, /* init thread */
- NULL, /* exit thread */
- NULL, /* exit process */
- NULL, /* exit master */
- NGX_MODULE_V1_PADDING
-};
-
-
-static ngx_http_modern_browser_mask_t ngx_http_modern_browser_masks[] = {
-
- /* Opera must be the first browser to check */
-
- /*
- * "Opera/7.50 (X11; FreeBSD i386; U) [en]"
- * "Mozilla/5.0 (X11; FreeBSD i386; U) Opera 7.50 [en]"
- * "Mozilla/4.0 (compatible; MSIE 6.0; X11; FreeBSD i386) Opera 7.50 [en]"
- * "Opera/8.0 (Windows NT 5.1; U; ru)"
- * "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; en) Opera 8.0"
- * "Opera/9.01 (X11; FreeBSD 6 i386; U; en)"
- */
-
- { "opera",
- 0,
- sizeof("Opera ") - 1,
- "Opera"},
-
- /* "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)" */
-
- { "msie",
- sizeof("Mozilla/4.0 (compatible; ") - 1,
- sizeof("MSIE ") - 1,
- "MSIE "},
-
- /*
- * "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.0.0) Gecko/20020610"
- * "Mozilla/5.0 (Windows; U; Windows NT 5.1; ru-RU; rv:1.5) Gecko/20031006"
- * "Mozilla/5.0 (Windows; U; Windows NT 5.1; ru-RU; rv:1.6) Gecko/20040206
- * Firefox/0.8"
- * "Mozilla/5.0 (Windows; U; Windows NT 5.1; ru-RU; rv:1.7.8)
- * Gecko/20050511 Firefox/1.0.4"
- * "Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.8.0.5) Gecko/20060729
- * Firefox/1.5.0.5"
- */
-
- { "gecko",
- sizeof("Mozilla/5.0 (") - 1,
- sizeof("rv:") - 1,
- "rv:"},
-
- /*
- * "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; ru-ru) AppleWebKit/125.2
- * (KHTML, like Gecko) Safari/125.7"
- * "Mozilla/5.0 (SymbianOS/9.1; U; en-us) AppleWebKit/413
- * (KHTML, like Gecko) Safari/413"
- * "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en) AppleWebKit/418
- * (KHTML, like Gecko) Safari/417.9.3"
- * "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; ru-ru) AppleWebKit/418.8
- * (KHTML, like Gecko) Safari/419.3"
- */
-
- { "safari",
- sizeof("Mozilla/5.0 (") - 1,
- sizeof("Safari/") - 1,
- "Safari/"},
-
- /*
- * "Mozilla/5.0 (compatible; Konqueror/3.1; Linux)"
- * "Mozilla/5.0 (compatible; Konqueror/3.4; Linux) KHTML/3.4.2 (like Gecko)"
- * "Mozilla/5.0 (compatible; Konqueror/3.5; FreeBSD) KHTML/3.5.1
- * (like Gecko)"
- */
-
- { "konqueror",
- sizeof("Mozilla/5.0 (compatible; ") - 1,
- sizeof("Konqueror/") - 1,
- "Konqueror/"},
-
- { "", 0, 0, "" }
-
-};
-
-
-static ngx_http_variable_t ngx_http_browser_vars[] = {
-
- { ngx_string("msie"), NULL, ngx_http_msie_variable,
- 0, NGX_HTTP_VAR_CHANGEABLE, 0 },
-
- { ngx_string("modern_browser"), NULL, ngx_http_browser_variable,
- NGX_HTTP_MODERN_BROWSER, NGX_HTTP_VAR_CHANGEABLE, 0 },
-
- { ngx_string("ancient_browser"), NULL, ngx_http_browser_variable,
- NGX_HTTP_ANCIENT_BROWSER, NGX_HTTP_VAR_CHANGEABLE, 0 },
-
- ngx_http_null_variable
-};
-
-
-static ngx_int_t
-ngx_http_browser_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v,
- uintptr_t data)
-{
- ngx_uint_t rc;
- ngx_http_browser_conf_t *cf;
-
- cf = ngx_http_get_module_loc_conf(r, ngx_http_browser_module);
-
- rc = ngx_http_browser(r, cf);
-
- if (data == NGX_HTTP_MODERN_BROWSER && rc == NGX_HTTP_MODERN_BROWSER) {
- *v = *cf->modern_browser_value;
- return NGX_OK;
- }
-
- if (data == NGX_HTTP_ANCIENT_BROWSER && rc == NGX_HTTP_ANCIENT_BROWSER) {
- *v = *cf->ancient_browser_value;
- return NGX_OK;
- }
-
- *v = ngx_http_variable_null_value;
- return NGX_OK;
-}
-
-
-static ngx_uint_t
-ngx_http_browser(ngx_http_request_t *r, ngx_http_browser_conf_t *cf)
-{
- size_t len;
- u_char *name, *ua, *last, c;
- ngx_str_t *ancient;
- ngx_uint_t i, version, ver, scale;
- ngx_http_modern_browser_t *modern;
-
- if (r->headers_in.user_agent == NULL) {
- if (cf->modern_unlisted_browsers) {
- return NGX_HTTP_MODERN_BROWSER;
- }
-
- return NGX_HTTP_ANCIENT_BROWSER;
- }
-
- ua = r->headers_in.user_agent->value.data;
- len = r->headers_in.user_agent->value.len;
- last = ua + len;
-
- if (cf->modern_browsers) {
- modern = cf->modern_browsers->elts;
-
- for (i = 0; i < cf->modern_browsers->nelts; i++) {
- name = ua + modern[i].skip;
-
- if (name >= last) {
- continue;
- }
-
- name = (u_char *) ngx_strstr(name, modern[i].name);
-
- if (name == NULL) {
- continue;
- }
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "browser: \"%s\"", name);
-
- name += modern[i].add;
-
- if (name >= last) {
- continue;
- }
-
- ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "version: \"%ui\" \"%s\"", modern[i].version, name);
-
- version = 0;
- ver = 0;
- scale = 1000000;
-
- while (name < last) {
-
- c = *name++;
-
- if (c >= '0' && c <= '9') {
- ver = ver * 10 + (c - '0');
- continue;
- }
-
- if (c == '.') {
- version += ver * scale;
-
- ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "version: \"%ui\" \"%ui\"",
- modern[i].version, version);
-
- if (version > modern[i].version) {
- return NGX_HTTP_MODERN_BROWSER;
- }
-
- ver = 0;
- scale /= 100;
- continue;
- }
-
- break;
- }
-
- version += ver * scale;
-
- ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "version: \"%ui\" \"%ui\"",
- modern[i].version, version);
-
- if (version >= modern[i].version) {
- return NGX_HTTP_MODERN_BROWSER;
- }
-
- return NGX_HTTP_ANCIENT_BROWSER;
- }
-
- if (!cf->modern_unlisted_browsers) {
- return NGX_HTTP_ANCIENT_BROWSER;
- }
- }
-
- if (cf->netscape4) {
- if (len > sizeof("Mozilla/4.72 ") - 1
- && ngx_strncmp(ua, "Mozilla/", sizeof("Mozilla/") - 1) == 0
- && ua[8] > '0' && ua[8] < '5')
- {
- return NGX_HTTP_ANCIENT_BROWSER;
- }
- }
-
- if (cf->ancient_browsers) {
- ancient = cf->ancient_browsers->elts;
-
- for (i = 0; i < cf->ancient_browsers->nelts; i++) {
- if (len >= ancient[i].len
- && ngx_strstr(ua, ancient[i].data) != NULL)
- {
- return NGX_HTTP_ANCIENT_BROWSER;
- }
- }
- }
-
- if (cf->modern_unlisted_browsers) {
- return NGX_HTTP_MODERN_BROWSER;
- }
-
- return NGX_HTTP_ANCIENT_BROWSER;
-}
-
-
-static ngx_int_t
-ngx_http_msie_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v,
- uintptr_t data)
-{
- if (r->headers_in.msie) {
- *v = ngx_http_variable_true_value;
- return NGX_OK;
- }
-
- *v = ngx_http_variable_null_value;
- return NGX_OK;
-}
-
-
-static ngx_int_t
-ngx_http_browser_add_variables(ngx_conf_t *cf)
-{
- ngx_http_variable_t *var, *v;
-
- for (v = ngx_http_browser_vars; v->name.len; v++) {
-
- var = ngx_http_add_variable(cf, &v->name, v->flags);
- if (var == NULL) {
- return NGX_ERROR;
- }
-
- var->get_handler = v->get_handler;
- var->data = v->data;
- }
-
- return NGX_OK;
-}
-
-
-static void *
-ngx_http_browser_create_conf(ngx_conf_t *cf)
-{
- ngx_http_browser_conf_t *conf;
-
- conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_browser_conf_t));
- if (conf == NULL) {
- return NULL;
- }
-
- /*
- * set by ngx_pcalloc():
- *
- * conf->modern_browsers = NULL;
- * conf->ancient_browsers = NULL;
- * conf->modern_browser_value = NULL;
- * conf->ancient_browser_value = NULL;
- *
- * conf->modern_unlisted_browsers = 0;
- * conf->netscape4 = 0;
- */
-
- return conf;
-}
-
-
-static char *
-ngx_http_browser_merge_conf(ngx_conf_t *cf, void *parent, void *child)
-{
- ngx_http_browser_conf_t *prev = parent;
- ngx_http_browser_conf_t *conf = child;
-
- ngx_uint_t i, n;
- ngx_http_modern_browser_t *browsers, *opera;
-
- /*
- * At the merge the skip field is used to store the browser slot,
- * it will be used in sorting and then will overwritten
- * with a real skip value. The zero value means Opera.
- */
-
- if (conf->modern_browsers == NULL && conf->modern_unlisted_browsers == 0) {
- conf->modern_browsers = prev->modern_browsers;
- conf->modern_unlisted_browsers = prev->modern_unlisted_browsers;
-
- } else if (conf->modern_browsers != NULL) {
- browsers = conf->modern_browsers->elts;
-
- for (i = 0; i < conf->modern_browsers->nelts; i++) {
- if (browsers[i].skip == 0) {
- goto found;
- }
- }
-
- /*
- * Opera may contain MSIE string, so if Opera was not enumerated
- * as modern browsers, then add it and set a unreachable version
- */
-
- opera = ngx_array_push(conf->modern_browsers);
- if (opera == NULL) {
- return NGX_CONF_ERROR;
- }
-
- opera->skip = 0;
- opera->version = 4001000000U;
-
- browsers = conf->modern_browsers->elts;
-
-found:
-
- ngx_qsort(browsers, (size_t) conf->modern_browsers->nelts,
- sizeof(ngx_http_modern_browser_t),
- ngx_http_modern_browser_sort);
-
- for (i = 0; i < conf->modern_browsers->nelts; i++) {
- n = browsers[i].skip;
-
- browsers[i].skip = ngx_http_modern_browser_masks[n].skip;
- browsers[i].add = ngx_http_modern_browser_masks[n].add;
- (void) ngx_cpystrn(browsers[i].name,
- ngx_http_modern_browser_masks[n].name, 12);
- }
- }
-
- if (conf->ancient_browsers == NULL && conf->netscape4 == 0) {
- conf->ancient_browsers = prev->ancient_browsers;
- conf->netscape4 = prev->netscape4;
- }
-
- if (conf->modern_browser_value == NULL) {
- conf->modern_browser_value = prev->modern_browser_value;
- }
-
- if (conf->modern_browser_value == NULL) {
- conf->modern_browser_value = &ngx_http_variable_true_value;
- }
-
- if (conf->ancient_browser_value == NULL) {
- conf->ancient_browser_value = prev->ancient_browser_value;
- }
-
- if (conf->ancient_browser_value == NULL) {
- conf->ancient_browser_value = &ngx_http_variable_true_value;
- }
-
- return NGX_CONF_OK;
-}
-
-
-static int ngx_libc_cdecl
-ngx_http_modern_browser_sort(const void *one, const void *two)
-{
- ngx_http_modern_browser_t *first = (ngx_http_modern_browser_t *) one;
- ngx_http_modern_browser_t *second = (ngx_http_modern_browser_t *) two;
-
- return (first->skip - second->skip);
-}
-
-
-static char *
-ngx_http_modern_browser(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
-{
- ngx_http_browser_conf_t *bcf = conf;
-
- u_char c;
- ngx_str_t *value;
- ngx_uint_t i, n, version, ver, scale;
- ngx_http_modern_browser_t *browser;
- ngx_http_modern_browser_mask_t *mask;
-
- value = cf->args->elts;
-
- if (cf->args->nelts == 2) {
- if (ngx_strcmp(value[1].data, "unlisted") == 0) {
- bcf->modern_unlisted_browsers = 1;
- return NGX_CONF_OK;
- }
-
- return NGX_CONF_ERROR;
- }
-
- if (bcf->modern_browsers == NULL) {
- bcf->modern_browsers = ngx_array_create(cf->pool, 5,
- sizeof(ngx_http_modern_browser_t));
- if (bcf->modern_browsers == NULL) {
- return NGX_CONF_ERROR;
- }
- }
-
- browser = ngx_array_push(bcf->modern_browsers);
- if (browser == NULL) {
- return NGX_CONF_ERROR;
- }
-
- mask = ngx_http_modern_browser_masks;
-
- for (n = 0; mask[n].browser[0] != '\0'; n++) {
- if (ngx_strcasecmp(mask[n].browser, value[1].data) == 0) {
- goto found;
- }
- }
-
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "unknown browser name \"%V\"", &value[1]);
-
- return NGX_CONF_ERROR;
-
-found:
-
- /*
- * at this stage the skip field is used to store the browser slot,
- * it will be used in sorting in merge stage and then will overwritten
- * with a real value
- */
-
- browser->skip = n;
-
- version = 0;
- ver = 0;
- scale = 1000000;
-
- for (i = 0; i < value[2].len; i++) {
-
- c = value[2].data[i];
-
- if (c >= '0' && c <= '9') {
- ver = ver * 10 + (c - '0');
- continue;
- }
-
- if (c == '.') {
- version += ver * scale;
- ver = 0;
- scale /= 100;
- continue;
- }
-
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "invalid browser version \"%V\"", &value[2]);
-
- return NGX_CONF_ERROR;
- }
-
- version += ver * scale;
-
- browser->version = version;
-
- return NGX_CONF_OK;
-}
-
-
-static char *
-ngx_http_ancient_browser(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
-{
- ngx_http_browser_conf_t *bcf = conf;
-
- ngx_str_t *value, *browser;
- ngx_uint_t i;
-
- value = cf->args->elts;
-
- for (i = 1; i < cf->args->nelts; i++) {
- if (ngx_strcmp(value[i].data, "netscape4") == 0) {
- bcf->netscape4 = 1;
- continue;
- }
-
- if (bcf->ancient_browsers == NULL) {
- bcf->ancient_browsers = ngx_array_create(cf->pool, 4,
- sizeof(ngx_str_t));
- if (bcf->ancient_browsers == NULL) {
- return NGX_CONF_ERROR;
- }
- }
-
- browser = ngx_array_push(bcf->ancient_browsers);
- if (browser == NULL) {
- return NGX_CONF_ERROR;
- }
-
- *browser = value[i];
- }
-
- return NGX_CONF_OK;
-}
-
-
-static char *
-ngx_http_modern_browser_value(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
-{
- ngx_http_browser_conf_t *bcf = conf;
-
- ngx_str_t *value;
-
- bcf->modern_browser_value = ngx_palloc(cf->pool,
- sizeof(ngx_http_variable_value_t));
- if (bcf->modern_browser_value == NULL) {
- return NGX_CONF_ERROR;
- }
-
- value = cf->args->elts;
-
- bcf->modern_browser_value->len = value[1].len;
- bcf->modern_browser_value->valid = 1;
- bcf->modern_browser_value->no_cacheable = 0;
- bcf->modern_browser_value->not_found = 0;
- bcf->modern_browser_value->data = value[1].data;
-
- return NGX_CONF_OK;
-}
-
-
-static char *
-ngx_http_ancient_browser_value(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
-{
- ngx_http_browser_conf_t *bcf = conf;
-
- ngx_str_t *value;
-
- bcf->ancient_browser_value = ngx_palloc(cf->pool,
- sizeof(ngx_http_variable_value_t));
- if (bcf->ancient_browser_value == NULL) {
- return NGX_CONF_ERROR;
- }
-
- value = cf->args->elts;
-
- bcf->ancient_browser_value->len = value[1].len;
- bcf->ancient_browser_value->valid = 1;
- bcf->ancient_browser_value->no_cacheable = 0;
- bcf->ancient_browser_value->not_found = 0;
- bcf->ancient_browser_value->data = value[1].data;
-
- return NGX_CONF_OK;
-}
diff --git a/nginx/src/http/modules/ngx_http_charset_filter_module.c b/nginx/src/http/modules/ngx_http_charset_filter_module.c
deleted file mode 100644
index e52b96e..0000000
--- a/nginx/src/http/modules/ngx_http_charset_filter_module.c
+++ /dev/null
@@ -1,1685 +0,0 @@
-
-/*
- * Copyright (C) Igor Sysoev
- * Copyright (C) Nginx, Inc.
- */
-
-
-#include <ngx_config.h>
-#include <ngx_core.h>
-#include <ngx_http.h>
-
-
-#define NGX_HTTP_CHARSET_OFF -2
-#define NGX_HTTP_NO_CHARSET -3
-#define NGX_HTTP_CHARSET_VAR 0x10000
-
-/* 1 byte length and up to 3 bytes for the UTF-8 encoding of the UCS-2 */
-#define NGX_UTF_LEN 4
-
-#define NGX_HTML_ENTITY_LEN (sizeof("&#1114111;") - 1)
-
-
-typedef struct {
- u_char **tables;
- ngx_str_t name;
-
- unsigned length:16;
- unsigned utf8:1;
-} ngx_http_charset_t;
-
-
-typedef struct {
- ngx_int_t src;
- ngx_int_t dst;
-} ngx_http_charset_recode_t;
-
-
-typedef struct {
- ngx_int_t src;
- ngx_int_t dst;
- u_char *src2dst;
- u_char *dst2src;
-} ngx_http_charset_tables_t;
-
-
-typedef struct {
- ngx_array_t charsets; /* ngx_http_charset_t */
- ngx_array_t tables; /* ngx_http_charset_tables_t */
- ngx_array_t recodes; /* ngx_http_charset_recode_t */
-} ngx_http_charset_main_conf_t;
-
-
-typedef struct {
- ngx_int_t charset;
- ngx_int_t source_charset;
- ngx_flag_t override_charset;
-
- ngx_hash_t types;
- ngx_array_t *types_keys;
-} ngx_http_charset_loc_conf_t;
-
-
-typedef struct {
- u_char *table;
- ngx_int_t charset;
- ngx_str_t charset_name;
-
- ngx_chain_t *busy;
- ngx_chain_t *free_bufs;
- ngx_chain_t *free_buffers;
-
- size_t saved_len;
- u_char saved[NGX_UTF_LEN];
-
- unsigned length:16;
- unsigned from_utf8:1;
- unsigned to_utf8:1;
-} ngx_http_charset_ctx_t;
-
-
-typedef struct {
- ngx_http_charset_tables_t *table;
- ngx_http_charset_t *charset;
- ngx_uint_t characters;
-} ngx_http_charset_conf_ctx_t;
-
-
-static ngx_int_t ngx_http_destination_charset(ngx_http_request_t *r,
- ngx_str_t *name);
-static ngx_int_t ngx_http_main_request_charset(ngx_http_request_t *r,
- ngx_str_t *name);
-static ngx_int_t ngx_http_source_charset(ngx_http_request_t *r,
- ngx_str_t *name);
-static ngx_int_t ngx_http_get_charset(ngx_http_request_t *r, ngx_str_t *name);
-static ngx_inline void ngx_http_set_charset(ngx_http_request_t *r,
- ngx_str_t *charset);
-static ngx_int_t ngx_http_charset_ctx(ngx_http_request_t *r,
- ngx_http_charset_t *charsets, ngx_int_t charset, ngx_int_t source_charset);
-static ngx_uint_t ngx_http_charset_recode(ngx_buf_t *b, u_char *table);
-static ngx_chain_t *ngx_http_charset_recode_from_utf8(ngx_pool_t *pool,
- ngx_buf_t *buf, ngx_http_charset_ctx_t *ctx);
-static ngx_chain_t *ngx_http_charset_recode_to_utf8(ngx_pool_t *pool,
- ngx_buf_t *buf, ngx_http_charset_ctx_t *ctx);
-
-static ngx_chain_t *ngx_http_charset_get_buf(ngx_pool_t *pool,
- ngx_http_charset_ctx_t *ctx);
-static ngx_chain_t *ngx_http_charset_get_buffer(ngx_pool_t *pool,
- ngx_http_charset_ctx_t *ctx, size_t size);
-
-static char *ngx_http_charset_map_block(ngx_conf_t *cf, ngx_command_t *cmd,
- void *conf);
-static char *ngx_http_charset_map(ngx_conf_t *cf, ngx_command_t *dummy,
- void *conf);
-
-static char *ngx_http_set_charset_slot(ngx_conf_t *cf, ngx_command_t *cmd,
- void *conf);
-static ngx_int_t ngx_http_add_charset(ngx_array_t *charsets, ngx_str_t *name);
-
-static void *ngx_http_charset_create_main_conf(ngx_conf_t *cf);
-static void *ngx_http_charset_create_loc_conf(ngx_conf_t *cf);
-static char *ngx_http_charset_merge_loc_conf(ngx_conf_t *cf,
- void *parent, void *child);
-static ngx_int_t ngx_http_charset_postconfiguration(ngx_conf_t *cf);
-
-
-static ngx_str_t ngx_http_charset_default_types[] = {
- ngx_string("text/html"),
- ngx_string("text/xml"),
- ngx_string("text/plain"),
- ngx_string("text/vnd.wap.wml"),
- ngx_string("application/javascript"),
- ngx_string("application/rss+xml"),
- ngx_null_string
-};
-
-
-static ngx_command_t ngx_http_charset_filter_commands[] = {
-
- { ngx_string("charset"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF
- |NGX_HTTP_LIF_CONF|NGX_CONF_TAKE1,
- ngx_http_set_charset_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_charset_loc_conf_t, charset),
- NULL },
-
- { ngx_string("source_charset"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF
- |NGX_HTTP_LIF_CONF|NGX_CONF_TAKE1,
- ngx_http_set_charset_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_charset_loc_conf_t, source_charset),
- NULL },
-
- { ngx_string("override_charset"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF
- |NGX_HTTP_LIF_CONF|NGX_CONF_FLAG,
- ngx_conf_set_flag_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_charset_loc_conf_t, override_charset),
- NULL },
-
- { ngx_string("charset_types"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
- ngx_http_types_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_charset_loc_conf_t, types_keys),
- &ngx_http_charset_default_types[0] },
-
- { ngx_string("charset_map"),
- NGX_HTTP_MAIN_CONF|NGX_CONF_BLOCK|NGX_CONF_TAKE2,
- ngx_http_charset_map_block,
- NGX_HTTP_MAIN_CONF_OFFSET,
- 0,
- NULL },
-
- ngx_null_command
-};
-
-
-static ngx_http_module_t ngx_http_charset_filter_module_ctx = {
- NULL, /* preconfiguration */
- ngx_http_charset_postconfiguration, /* postconfiguration */
-
- ngx_http_charset_create_main_conf, /* create main configuration */
- NULL, /* init main configuration */
-
- NULL, /* create server configuration */
- NULL, /* merge server configuration */
-
- ngx_http_charset_create_loc_conf, /* create location configuration */
- ngx_http_charset_merge_loc_conf /* merge location configuration */
-};
-
-
-ngx_module_t ngx_http_charset_filter_module = {
- NGX_MODULE_V1,
- &ngx_http_charset_filter_module_ctx, /* module context */
- ngx_http_charset_filter_commands, /* module directives */
- NGX_HTTP_MODULE, /* module type */
- NULL, /* init master */
- NULL, /* init module */
- NULL, /* init process */
- NULL, /* init thread */
- NULL, /* exit thread */
- NULL, /* exit process */
- NULL, /* exit master */
- NGX_MODULE_V1_PADDING
-};
-
-
-static ngx_http_output_header_filter_pt ngx_http_next_header_filter;
-static ngx_http_output_body_filter_pt ngx_http_next_body_filter;
-
-
-static ngx_int_t
-ngx_http_charset_header_filter(ngx_http_request_t *r)
-{
- ngx_int_t charset, source_charset;
- ngx_str_t dst, src;
- ngx_http_charset_t *charsets;
- ngx_http_charset_main_conf_t *mcf;
-
- if (r == r->main) {
- charset = ngx_http_destination_charset(r, &dst);
-
- } else {
- charset = ngx_http_main_request_charset(r, &dst);
- }
-
- if (charset == NGX_ERROR) {
- return NGX_ERROR;
- }
-
- if (charset == NGX_DECLINED) {
- return ngx_http_next_header_filter(r);
- }
-
- /* charset: charset index or NGX_HTTP_NO_CHARSET */
-
- source_charset = ngx_http_source_charset(r, &src);
-
- if (source_charset == NGX_ERROR) {
- return NGX_ERROR;
- }
-
- /*
- * source_charset: charset index, NGX_HTTP_NO_CHARSET,
- * or NGX_HTTP_CHARSET_OFF
- */
-
- ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "charset: \"%V\" > \"%V\"", &src, &dst);
-
- if (source_charset == NGX_HTTP_CHARSET_OFF) {
- ngx_http_set_charset(r, &dst);
-
- return ngx_http_next_header_filter(r);
- }
-
- if (charset == NGX_HTTP_NO_CHARSET
- || source_charset == NGX_HTTP_NO_CHARSET)
- {
- if (source_charset != charset
- || ngx_strncasecmp(dst.data, src.data, dst.len) != 0)
- {
- goto no_charset_map;
- }
-
- ngx_http_set_charset(r, &dst);
-
- return ngx_http_next_header_filter(r);
- }
-
- if (source_charset == charset) {
- r->headers_out.content_type.len = r->headers_out.content_type_len;
-
- ngx_http_set_charset(r, &dst);
-
- return ngx_http_next_header_filter(r);
- }
-
- /* source_charset != charset */
-
- if (r->headers_out.content_encoding
- && r->headers_out.content_encoding->value.len)
- {
- return ngx_http_next_header_filter(r);
- }
-
- mcf = ngx_http_get_module_main_conf(r, ngx_http_charset_filter_module);
- charsets = mcf->charsets.elts;
-
- if (charsets[source_charset].tables == NULL
- || charsets[source_charset].tables[charset] == NULL)
- {
- goto no_charset_map;
- }
-
- r->headers_out.content_type.len = r->headers_out.content_type_len;
-
- ngx_http_set_charset(r, &dst);
-
- return ngx_http_charset_ctx(r, charsets, charset, source_charset);
-
-no_charset_map:
-
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "no \"charset_map\" between the charsets \"%V\" and \"%V\"",
- &src, &dst);
-
- return ngx_http_next_header_filter(r);
-}
-
-
-static ngx_int_t
-ngx_http_destination_charset(ngx_http_request_t *r, ngx_str_t *name)
-{
- ngx_int_t charset;
- ngx_http_charset_t *charsets;
- ngx_http_variable_value_t *vv;
- ngx_http_charset_loc_conf_t *mlcf;
- ngx_http_charset_main_conf_t *mcf;
-
- if (r->headers_out.content_type.len == 0) {
- return NGX_DECLINED;
- }
-
- if (r->headers_out.override_charset
- && r->headers_out.override_charset->len)
- {
- *name = *r->headers_out.override_charset;
-
- charset = ngx_http_get_charset(r, name);
-
- if (charset != NGX_HTTP_NO_CHARSET) {
- return charset;
- }
-
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "unknown charset \"%V\" to override", name);
-
- return NGX_DECLINED;
- }
-
- mlcf = ngx_http_get_module_loc_conf(r, ngx_http_charset_filter_module);
- charset = mlcf->charset;
-
- if (charset == NGX_HTTP_CHARSET_OFF) {
- return NGX_DECLINED;
- }
-
- if (r->headers_out.charset.len) {
- if (mlcf->override_charset == 0) {
- return NGX_DECLINED;
- }
-
- } else {
- if (ngx_http_test_content_type(r, &mlcf->types) == NULL) {
- return NGX_DECLINED;
- }
- }
-
- if (charset < NGX_HTTP_CHARSET_VAR) {
- mcf = ngx_http_get_module_main_conf(r, ngx_http_charset_filter_module);
- charsets = mcf->charsets.elts;
- *name = charsets[charset].name;
- return charset;
- }
-
- vv = ngx_http_get_indexed_variable(r, charset - NGX_HTTP_CHARSET_VAR);
-
- if (vv == NULL || vv->not_found) {
- return NGX_ERROR;
- }
-
- name->len = vv->len;
- name->data = vv->data;
-
- return ngx_http_get_charset(r, name);
-}
-
-
-static ngx_int_t
-ngx_http_main_request_charset(ngx_http_request_t *r, ngx_str_t *src)
-{
- ngx_int_t charset;
- ngx_str_t *main_charset;
- ngx_http_charset_ctx_t *ctx;
-
- ctx = ngx_http_get_module_ctx(r->main, ngx_http_charset_filter_module);
-
- if (ctx) {
- *src = ctx->charset_name;
- return ctx->charset;
- }
-
- main_charset = &r->main->headers_out.charset;
-
- if (main_charset->len == 0) {
- return NGX_DECLINED;
- }
-
- ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_charset_ctx_t));
- if (ctx == NULL) {
- return NGX_ERROR;
- }
-
- ngx_http_set_ctx(r->main, ctx, ngx_http_charset_filter_module);
-
- charset = ngx_http_get_charset(r, main_charset);
-
- ctx->charset = charset;
- ctx->charset_name = *main_charset;
- *src = *main_charset;
-
- return charset;
-}
-
-
-static ngx_int_t
-ngx_http_source_charset(ngx_http_request_t *r, ngx_str_t *name)
-{
- ngx_int_t charset;
- ngx_http_charset_t *charsets;
- ngx_http_variable_value_t *vv;
- ngx_http_charset_loc_conf_t *lcf;
- ngx_http_charset_main_conf_t *mcf;
-
- if (r->headers_out.charset.len) {
- *name = r->headers_out.charset;
- return ngx_http_get_charset(r, name);
- }
-
- lcf = ngx_http_get_module_loc_conf(r, ngx_http_charset_filter_module);
-
- charset = lcf->source_charset;
-
- if (charset == NGX_HTTP_CHARSET_OFF) {
- name->len = 0;
- return charset;
- }
-
- if (charset < NGX_HTTP_CHARSET_VAR) {
- mcf = ngx_http_get_module_main_conf(r, ngx_http_charset_filter_module);
- charsets = mcf->charsets.elts;
- *name = charsets[charset].name;
- return charset;
- }
-
- vv = ngx_http_get_indexed_variable(r, charset - NGX_HTTP_CHARSET_VAR);
-
- if (vv == NULL || vv->not_found) {
- return NGX_ERROR;
- }
-
- name->len = vv->len;
- name->data = vv->data;
-
- return ngx_http_get_charset(r, name);
-}
-
-
-static ngx_int_t
-ngx_http_get_charset(ngx_http_request_t *r, ngx_str_t *name)
-{
- ngx_uint_t i, n;
- ngx_http_charset_t *charset;
- ngx_http_charset_main_conf_t *mcf;
-
- mcf = ngx_http_get_module_main_conf(r, ngx_http_charset_filter_module);
-
- charset = mcf->charsets.elts;
- n = mcf->charsets.nelts;
-
- for (i = 0; i < n; i++) {
- if (charset[i].name.len != name->len) {
- continue;
- }
-
- if (ngx_strncasecmp(charset[i].name.data, name->data, name->len) == 0) {
- return i;
- }
- }
-
- return NGX_HTTP_NO_CHARSET;
-}
-
-
-static ngx_inline void
-ngx_http_set_charset(ngx_http_request_t *r, ngx_str_t *charset)
-{
- if (r != r->main) {
- return;
- }
-
- if (r->headers_out.status == NGX_HTTP_MOVED_PERMANENTLY
- || r->headers_out.status == NGX_HTTP_MOVED_TEMPORARILY)
- {
- /*
- * do not set charset for the redirect because NN 4.x
- * use this charset instead of the next page charset
- */
-
- r->headers_out.charset.len = 0;
- return;
- }
-
- r->headers_out.charset = *charset;
-}
-
-
-static ngx_int_t
-ngx_http_charset_ctx(ngx_http_request_t *r, ngx_http_charset_t *charsets,
- ngx_int_t charset, ngx_int_t source_charset)
-{
- ngx_http_charset_ctx_t *ctx;
-
- ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_charset_ctx_t));
- if (ctx == NULL) {
- return NGX_ERROR;
- }
-
- ngx_http_set_ctx(r, ctx, ngx_http_charset_filter_module);
-
- ctx->table = charsets[source_charset].tables[charset];
- ctx->charset = charset;
- ctx->charset_name = charsets[charset].name;
- ctx->length = charsets[charset].length;
- ctx->from_utf8 = charsets[source_charset].utf8;
- ctx->to_utf8 = charsets[charset].utf8;
-
- r->filter_need_in_memory = 1;
-
- if ((ctx->to_utf8 || ctx->from_utf8) && r == r->main) {
- ngx_http_clear_content_length(r);
-
- } else {
- r->filter_need_temporary = 1;
- }
-
- return ngx_http_next_header_filter(r);
-}
-
-
-static ngx_int_t
-ngx_http_charset_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
-{
- ngx_int_t rc;
- ngx_buf_t *b;
- ngx_chain_t *cl, *out, **ll;
- ngx_http_charset_ctx_t *ctx;
-
- ctx = ngx_http_get_module_ctx(r, ngx_http_charset_filter_module);
-
- if (ctx == NULL || ctx->table == NULL) {
- return ngx_http_next_body_filter(r, in);
- }
-
- if ((ctx->to_utf8 || ctx->from_utf8) || ctx->busy) {
-
- out = NULL;
- ll = &out;
-
- for (cl = in; cl; cl = cl->next) {
- b = cl->buf;
-
- if (ngx_buf_size(b) == 0) {
-
- *ll = ngx_alloc_chain_link(r->pool);
- if (*ll == NULL) {
- return NGX_ERROR;
- }
-
- (*ll)->buf = b;
- (*ll)->next = NULL;
-
- ll = &(*ll)->next;
-
- continue;
- }
-
- if (ctx->to_utf8) {
- *ll = ngx_http_charset_recode_to_utf8(r->pool, b, ctx);
-
- } else {
- *ll = ngx_http_charset_recode_from_utf8(r->pool, b, ctx);
- }
-
- if (*ll == NULL) {
- return NGX_ERROR;
- }
-
- while (*ll) {
- ll = &(*ll)->next;
- }
- }
-
- rc = ngx_http_next_body_filter(r, out);
-
- if (out) {
- if (ctx->busy == NULL) {
- ctx->busy = out;
-
- } else {
- for (cl = ctx->busy; cl->next; cl = cl->next) { /* void */ }
- cl->next = out;
- }
- }
-
- while (ctx->busy) {
-
- cl = ctx->busy;
- b = cl->buf;
-
- if (ngx_buf_size(b) != 0) {
- break;
- }
-
- ctx->busy = cl->next;
-
- if (b->tag != (ngx_buf_tag_t) &ngx_http_charset_filter_module) {
- continue;
- }
-
- if (b->shadow) {
- b->shadow->pos = b->shadow->last;
- }
-
- if (b->pos) {
- cl->next = ctx->free_buffers;
- ctx->free_buffers = cl;
- continue;
- }
-
- cl->next = ctx->free_bufs;
- ctx->free_bufs = cl;
- }
-
- return rc;
- }
-
- for (cl = in; cl; cl = cl->next) {
- (void) ngx_http_charset_recode(cl->buf, ctx->table);
- }
-
- return ngx_http_next_body_filter(r, in);
-}
-
-
-static ngx_uint_t
-ngx_http_charset_recode(ngx_buf_t *b, u_char *table)
-{
- u_char *p, *last;
-
- last = b->last;
-
- for (p = b->pos; p < last; p++) {
-
- if (*p != table[*p]) {
- goto recode;
- }
- }
-
- return 0;
-
-recode:
-
- do {
- if (*p != table[*p]) {
- *p = table[*p];
- }
-
- p++;
-
- } while (p < last);
-
- b->in_file = 0;
-
- return 1;
-}
-
-
-static ngx_chain_t *
-ngx_http_charset_recode_from_utf8(ngx_pool_t *pool, ngx_buf_t *buf,
- ngx_http_charset_ctx_t *ctx)
-{
- size_t len, size;
- u_char c, *p, *src, *dst, *saved, **table;
- uint32_t n;
- ngx_buf_t *b;
- ngx_uint_t i;
- ngx_chain_t *out, *cl, **ll;
-
- src = buf->pos;
-
- if (ctx->saved_len == 0) {
-
- for ( /* void */ ; src < buf->last; src++) {
-
- if (*src < 0x80) {
- continue;
- }
-
- len = src - buf->pos;
-
- if (len > 512) {
- out = ngx_http_charset_get_buf(pool, ctx);
- if (out == NULL) {
- return NULL;
- }
-
- b = out->buf;
-
- b->temporary = buf->temporary;
- b->memory = buf->memory;
- b->mmap = buf->mmap;
- b->flush = buf->flush;
-
- b->pos = buf->pos;
- b->last = src;
-
- out->buf = b;
- out->next = NULL;
-
- size = buf->last - src;
-
- saved = src;
- n = ngx_utf8_decode(&saved, size);
-
- if (n == 0xfffffffe) {
- /* incomplete UTF-8 symbol */
-
- ngx_memcpy(ctx->saved, src, size);
- ctx->saved_len = size;
-
- b->shadow = buf;
-
- return out;
- }
-
- } else {
- out = NULL;
- size = len + buf->last - src;
- src = buf->pos;
- }
-
- if (size < NGX_HTML_ENTITY_LEN) {
- size += NGX_HTML_ENTITY_LEN;
- }
-
- cl = ngx_http_charset_get_buffer(pool, ctx, size);
- if (cl == NULL) {
- return NULL;
- }
-
- if (out) {
- out->next = cl;
-
- } else {
- out = cl;
- }
-
- b = cl->buf;
- dst = b->pos;
-
- goto recode;
- }
-
- out = ngx_alloc_chain_link(pool);
- if (out == NULL) {
- return NULL;
- }
-
- out->buf = buf;
- out->next = NULL;
-
- return out;
- }
-
- /* process incomplete UTF sequence from previous buffer */
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, pool->log, 0,
- "http charset utf saved: %z", ctx->saved_len);
-
- p = src;
-
- for (i = ctx->saved_len; i < NGX_UTF_LEN; i++) {
- ctx->saved[i] = *p++;
-
- if (p == buf->last) {
- break;
- }
- }
-
- saved = ctx->saved;
- n = ngx_utf8_decode(&saved, i);
-
- c = '\0';
-
- if (n < 0x10000) {
- table = (u_char **) ctx->table;
- p = table[n >> 8];
-
- if (p) {
- c = p[n & 0xff];
- }
-
- } else if (n == 0xfffffffe) {
-
- /* incomplete UTF-8 symbol */
-
- if (i < NGX_UTF_LEN) {
- out = ngx_http_charset_get_buf(pool, ctx);
- if (out == NULL) {
- return NULL;
- }
-
- b = out->buf;
-
- b->pos = buf->pos;
- b->last = buf->last;
- b->sync = 1;
- b->shadow = buf;
-
- ngx_memcpy(&ctx->saved[ctx->saved_len], src, i);
- ctx->saved_len += i;
-
- return out;
- }
- }
-
- size = buf->last - buf->pos;
-
- if (size < NGX_HTML_ENTITY_LEN) {
- size += NGX_HTML_ENTITY_LEN;
- }
-
- cl = ngx_http_charset_get_buffer(pool, ctx, size);
- if (cl == NULL) {
- return NULL;
- }
-
- out = cl;
-
- b = cl->buf;
- dst = b->pos;
-
- if (c) {
- *dst++ = c;
-
- } else if (n == 0xfffffffe) {
- *dst++ = '?';
-
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, pool->log, 0,
- "http charset invalid utf 0");
-
- saved = &ctx->saved[NGX_UTF_LEN];
-
- } else if (n > 0x10ffff) {
- *dst++ = '?';
-
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, pool->log, 0,
- "http charset invalid utf 1");
-
- } else {
- dst = ngx_sprintf(dst, "&#%uD;", n);
- }
-
- src += (saved - ctx->saved) - ctx->saved_len;
- ctx->saved_len = 0;
-
-recode:
-
- ll = &cl->next;
-
- table = (u_char **) ctx->table;
-
- while (src < buf->last) {
-
- if ((size_t) (b->end - dst) < NGX_HTML_ENTITY_LEN) {
- b->last = dst;
-
- size = buf->last - src + NGX_HTML_ENTITY_LEN;
-
- cl = ngx_http_charset_get_buffer(pool, ctx, size);
- if (cl == NULL) {
- return NULL;
- }
-
- *ll = cl;
- ll = &cl->next;
-
- b = cl->buf;
- dst = b->pos;
- }
-
- if (*src < 0x80) {
- *dst++ = *src++;
- continue;
- }
-
- len = buf->last - src;
-
- n = ngx_utf8_decode(&src, len);
-
- if (n < 0x10000) {
-
- p = table[n >> 8];
-
- if (p) {
- c = p[n & 0xff];
-
- if (c) {
- *dst++ = c;
- continue;
- }
- }
-
- dst = ngx_sprintf(dst, "&#%uD;", n);
-
- continue;
- }
-
- if (n == 0xfffffffe) {
- /* incomplete UTF-8 symbol */
-
- ngx_memcpy(ctx->saved, src, len);
- ctx->saved_len = len;
-
- if (b->pos == dst) {
- b->sync = 1;
- b->temporary = 0;
- }
-
- break;
- }
-
- if (n > 0x10ffff) {
- *dst++ = '?';
-
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, pool->log, 0,
- "http charset invalid utf 2");
-
- continue;
- }
-
- /* n > 0xffff */
-
- dst = ngx_sprintf(dst, "&#%uD;", n);
- }
-
- b->last = dst;
-
- b->last_buf = buf->last_buf;
- b->last_in_chain = buf->last_in_chain;
- b->flush = buf->flush;
-
- b->shadow = buf;
-
- return out;
-}
-
-
-static ngx_chain_t *
-ngx_http_charset_recode_to_utf8(ngx_pool_t *pool, ngx_buf_t *buf,
- ngx_http_charset_ctx_t *ctx)
-{
- size_t len, size;
- u_char *p, *src, *dst, *table;
- ngx_buf_t *b;
- ngx_chain_t *out, *cl, **ll;
-
- table = ctx->table;
-
- for (src = buf->pos; src < buf->last; src++) {
- if (table[*src * NGX_UTF_LEN] == '\1') {
- continue;
- }
-
- goto recode;
- }
-
- out = ngx_alloc_chain_link(pool);
- if (out == NULL) {
- return NULL;
- }
-
- out->buf = buf;
- out->next = NULL;
-
- return out;
-
-recode:
-
- /*
- * we assume that there are about half of characters to be recoded,
- * so we preallocate "size / 2 + size / 2 * ctx->length"
- */
-
- len = src - buf->pos;
-
- if (len > 512) {
- out = ngx_http_charset_get_buf(pool, ctx);
- if (out == NULL) {
- return NULL;
- }
-
- b = out->buf;
-
- b->temporary = buf->temporary;
- b->memory = buf->memory;
- b->mmap = buf->mmap;
- b->flush = buf->flush;
-
- b->pos = buf->pos;
- b->last = src;
-
- out->buf = b;
- out->next = NULL;
-
- size = buf->last - src;
- size = size / 2 + size / 2 * ctx->length;
-
- } else {
- out = NULL;
-
- size = buf->last - src;
- size = len + size / 2 + size / 2 * ctx->length;
-
- src = buf->pos;
- }
-
- cl = ngx_http_charset_get_buffer(pool, ctx, size);
- if (cl == NULL) {
- return NULL;
- }
-
- if (out) {
- out->next = cl;
-
- } else {
- out = cl;
- }
-
- ll = &cl->next;
-
- b = cl->buf;
- dst = b->pos;
-
- while (src < buf->last) {
-
- p = &table[*src++ * NGX_UTF_LEN];
- len = *p++;
-
- if ((size_t) (b->end - dst) < len) {
- b->last = dst;
-
- size = buf->last - src;
- size = len + size / 2 + size / 2 * ctx->length;
-
- cl = ngx_http_charset_get_buffer(pool, ctx, size);
- if (cl == NULL) {
- return NULL;
- }
-
- *ll = cl;
- ll = &cl->next;
-
- b = cl->buf;
- dst = b->pos;
- }
-
- while (len) {
- *dst++ = *p++;
- len--;
- }
- }
-
- b->last = dst;
-
- b->last_buf = buf->last_buf;
- b->last_in_chain = buf->last_in_chain;
- b->flush = buf->flush;
-
- b->shadow = buf;
-
- return out;
-}
-
-
-static ngx_chain_t *
-ngx_http_charset_get_buf(ngx_pool_t *pool, ngx_http_charset_ctx_t *ctx)
-{
- ngx_chain_t *cl;
-
- cl = ctx->free_bufs;
-
- if (cl) {
- ctx->free_bufs = cl->next;
-
- cl->buf->shadow = NULL;
- cl->next = NULL;
-
- return cl;
- }
-
- cl = ngx_alloc_chain_link(pool);
- if (cl == NULL) {
- return NULL;
- }
-
- cl->buf = ngx_calloc_buf(pool);
- if (cl->buf == NULL) {
- return NULL;
- }
-
- cl->next = NULL;
-
- cl->buf->tag = (ngx_buf_tag_t) &ngx_http_charset_filter_module;
-
- return cl;
-}
-
-
-static ngx_chain_t *
-ngx_http_charset_get_buffer(ngx_pool_t *pool, ngx_http_charset_ctx_t *ctx,
- size_t size)
-{
- ngx_buf_t *b;
- ngx_chain_t *cl, **ll;
-
- for (ll = &ctx->free_buffers, cl = ctx->free_buffers;
- cl;
- ll = &cl->next, cl = cl->next)
- {
- b = cl->buf;
-
- if ((size_t) (b->end - b->start) >= size) {
- *ll = cl->next;
- cl->next = NULL;
-
- b->pos = b->start;
- b->temporary = 1;
- b->shadow = NULL;
-
- return cl;
- }
- }
-
- cl = ngx_alloc_chain_link(pool);
- if (cl == NULL) {
- return NULL;
- }
-
- cl->buf = ngx_create_temp_buf(pool, size);
- if (cl->buf == NULL) {
- return NULL;
- }
-
- cl->next = NULL;
-
- cl->buf->temporary = 1;
- cl->buf->tag = (ngx_buf_tag_t) &ngx_http_charset_filter_module;
-
- return cl;
-}
-
-
-static char *
-ngx_http_charset_map_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
-{
- ngx_http_charset_main_conf_t *mcf = conf;
-
- char *rv;
- u_char *p, *dst2src, **pp;
- ngx_int_t src, dst;
- ngx_uint_t i, n;
- ngx_str_t *value;
- ngx_conf_t pvcf;
- ngx_http_charset_t *charset;
- ngx_http_charset_tables_t *table;
- ngx_http_charset_conf_ctx_t ctx;
-
- value = cf->args->elts;
-
- src = ngx_http_add_charset(&mcf->charsets, &value[1]);
- if (src == NGX_ERROR) {
- return NGX_CONF_ERROR;
- }
-
- dst = ngx_http_add_charset(&mcf->charsets, &value[2]);
- if (dst == NGX_ERROR) {
- return NGX_CONF_ERROR;
- }
-
- if (src == dst) {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "\"charset_map\" between the same charsets "
- "\"%V\" and \"%V\"", &value[1], &value[2]);
- return NGX_CONF_ERROR;
- }
-
- table = mcf->tables.elts;
- for (i = 0; i < mcf->tables.nelts; i++) {
- if ((src == table->src && dst == table->dst)
- || (src == table->dst && dst == table->src))
- {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "duplicate \"charset_map\" between "
- "\"%V\" and \"%V\"", &value[1], &value[2]);
- return NGX_CONF_ERROR;
- }
- }
-
- table = ngx_array_push(&mcf->tables);
- if (table == NULL) {
- return NGX_CONF_ERROR;
- }
-
- table->src = src;
- table->dst = dst;
-
- if (ngx_strcasecmp(value[2].data, (u_char *) "utf-8") == 0) {
- table->src2dst = ngx_pcalloc(cf->pool, 256 * NGX_UTF_LEN);
- if (table->src2dst == NULL) {
- return NGX_CONF_ERROR;
- }
-
- table->dst2src = ngx_pcalloc(cf->pool, 256 * sizeof(void *));
- if (table->dst2src == NULL) {
- return NGX_CONF_ERROR;
- }
-
- dst2src = ngx_pcalloc(cf->pool, 256);
- if (dst2src == NULL) {
- return NGX_CONF_ERROR;
- }
-
- pp = (u_char **) &table->dst2src[0];
- pp[0] = dst2src;
-
- for (i = 0; i < 128; i++) {
- p = &table->src2dst[i * NGX_UTF_LEN];
- p[0] = '\1';
- p[1] = (u_char) i;
- dst2src[i] = (u_char) i;
- }
-
- for (/* void */; i < 256; i++) {
- p = &table->src2dst[i * NGX_UTF_LEN];
- p[0] = '\1';
- p[1] = '?';
- }
-
- } else {
- table->src2dst = ngx_palloc(cf->pool, 256);
- if (table->src2dst == NULL) {
- return NGX_CONF_ERROR;
- }
-
- table->dst2src = ngx_palloc(cf->pool, 256);
- if (table->dst2src == NULL) {
- return NGX_CONF_ERROR;
- }
-
- for (i = 0; i < 128; i++) {
- table->src2dst[i] = (u_char) i;
- table->dst2src[i] = (u_char) i;
- }
-
- for (/* void */; i < 256; i++) {
- table->src2dst[i] = '?';
- table->dst2src[i] = '?';
- }
- }
-
- charset = mcf->charsets.elts;
-
- ctx.table = table;
- ctx.charset = &charset[dst];
- ctx.characters = 0;
-
- pvcf = *cf;
- cf->ctx = &ctx;
- cf->handler = ngx_http_charset_map;
- cf->handler_conf = conf;
-
- rv = ngx_conf_parse(cf, NULL);
-
- *cf = pvcf;
-
- if (ctx.characters) {
- n = ctx.charset->length;
- ctx.charset->length /= ctx.characters;
-
- if (((n * 10) / ctx.characters) % 10 > 4) {
- ctx.charset->length++;
- }
- }
-
- return rv;
-}
-
-
-static char *
-ngx_http_charset_map(ngx_conf_t *cf, ngx_command_t *dummy, void *conf)
-{
- u_char *p, *dst2src, **pp;
- uint32_t n;
- ngx_int_t src, dst;
- ngx_str_t *value;
- ngx_uint_t i;
- ngx_http_charset_tables_t *table;
- ngx_http_charset_conf_ctx_t *ctx;
-
- if (cf->args->nelts != 2) {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid parameters number");
- return NGX_CONF_ERROR;
- }
-
- value = cf->args->elts;
-
- src = ngx_hextoi(value[0].data, value[0].len);
- if (src == NGX_ERROR || src > 255) {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "invalid value \"%V\"", &value[0]);
- return NGX_CONF_ERROR;
- }
-
- ctx = cf->ctx;
- table = ctx->table;
-
- if (ctx->charset->utf8) {
- p = &table->src2dst[src * NGX_UTF_LEN];
-
- *p++ = (u_char) (value[1].len / 2);
-
- for (i = 0; i < value[1].len; i += 2) {
- dst = ngx_hextoi(&value[1].data[i], 2);
- if (dst == NGX_ERROR || dst > 255) {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "invalid value \"%V\"", &value[1]);
- return NGX_CONF_ERROR;
- }
-
- *p++ = (u_char) dst;
- }
-
- i /= 2;
-
- ctx->charset->length += i;
- ctx->characters++;
-
- p = &table->src2dst[src * NGX_UTF_LEN] + 1;
-
- n = ngx_utf8_decode(&p, i);
-
- if (n > 0xffff) {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "invalid value \"%V\"", &value[1]);
- return NGX_CONF_ERROR;
- }
-
- pp = (u_char **) &table->dst2src[0];
-
- dst2src = pp[n >> 8];
-
- if (dst2src == NULL) {
- dst2src = ngx_pcalloc(cf->pool, 256);
- if (dst2src == NULL) {
- return NGX_CONF_ERROR;
- }
-
- pp[n >> 8] = dst2src;
- }
-
- dst2src[n & 0xff] = (u_char) src;
-
- } else {
- dst = ngx_hextoi(value[1].data, value[1].len);
- if (dst == NGX_ERROR || dst > 255) {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "invalid value \"%V\"", &value[1]);
- return NGX_CONF_ERROR;
- }
-
- table->src2dst[src] = (u_char) dst;
- table->dst2src[dst] = (u_char) src;
- }
-
- return NGX_CONF_OK;
-}
-
-
-static char *
-ngx_http_set_charset_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
-{
- char *p = conf;
-
- ngx_int_t *cp;
- ngx_str_t *value, var;
- ngx_http_charset_main_conf_t *mcf;
-
- cp = (ngx_int_t *) (p + cmd->offset);
-
- if (*cp != NGX_CONF_UNSET) {
- return "is duplicate";
- }
-
- value = cf->args->elts;
-
- if (cmd->offset == offsetof(ngx_http_charset_loc_conf_t, charset)
- && ngx_strcmp(value[1].data, "off") == 0)
- {
- *cp = NGX_HTTP_CHARSET_OFF;
- return NGX_CONF_OK;
- }
-
-
- if (value[1].data[0] == '$') {
- var.len = value[1].len - 1;
- var.data = value[1].data + 1;
-
- *cp = ngx_http_get_variable_index(cf, &var);
-
- if (*cp == NGX_ERROR) {
- return NGX_CONF_ERROR;
- }
-
- *cp += NGX_HTTP_CHARSET_VAR;
-
- return NGX_CONF_OK;
- }
-
- mcf = ngx_http_conf_get_module_main_conf(cf,
- ngx_http_charset_filter_module);
-
- *cp = ngx_http_add_charset(&mcf->charsets, &value[1]);
- if (*cp == NGX_ERROR) {
- return NGX_CONF_ERROR;
- }
-
- return NGX_CONF_OK;
-}
-
-
-static ngx_int_t
-ngx_http_add_charset(ngx_array_t *charsets, ngx_str_t *name)
-{
- ngx_uint_t i;
- ngx_http_charset_t *c;
-
- c = charsets->elts;
- for (i = 0; i < charsets->nelts; i++) {
- if (name->len != c[i].name.len) {
- continue;
- }
-
- if (ngx_strcasecmp(name->data, c[i].name.data) == 0) {
- break;
- }
- }
-
- if (i < charsets->nelts) {
- return i;
- }
-
- c = ngx_array_push(charsets);
- if (c == NULL) {
- return NGX_ERROR;
- }
-
- c->tables = NULL;
- c->name = *name;
- c->length = 0;
-
- if (ngx_strcasecmp(name->data, (u_char *) "utf-8") == 0) {
- c->utf8 = 1;
-
- } else {
- c->utf8 = 0;
- }
-
- return i;
-}
-
-
-static void *
-ngx_http_charset_create_main_conf(ngx_conf_t *cf)
-{
- ngx_http_charset_main_conf_t *mcf;
-
- mcf = ngx_pcalloc(cf->pool, sizeof(ngx_http_charset_main_conf_t));
- if (mcf == NULL) {
- return NULL;
- }
-
- if (ngx_array_init(&mcf->charsets, cf->pool, 2, sizeof(ngx_http_charset_t))
- != NGX_OK)
- {
- return NULL;
- }
-
- if (ngx_array_init(&mcf->tables, cf->pool, 1,
- sizeof(ngx_http_charset_tables_t))
- != NGX_OK)
- {
- return NULL;
- }
-
- if (ngx_array_init(&mcf->recodes, cf->pool, 2,
- sizeof(ngx_http_charset_recode_t))
- != NGX_OK)
- {
- return NULL;
- }
-
- return mcf;
-}
-
-
-static void *
-ngx_http_charset_create_loc_conf(ngx_conf_t *cf)
-{
- ngx_http_charset_loc_conf_t *lcf;
-
- lcf = ngx_pcalloc(cf->pool, sizeof(ngx_http_charset_loc_conf_t));
- if (lcf == NULL) {
- return NULL;
- }
-
- /*
- * set by ngx_pcalloc():
- *
- * lcf->types = { NULL };
- * lcf->types_keys = NULL;
- */
-
- lcf->charset = NGX_CONF_UNSET;
- lcf->source_charset = NGX_CONF_UNSET;
- lcf->override_charset = NGX_CONF_UNSET;
-
- return lcf;
-}
-
-
-static char *
-ngx_http_charset_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
-{
- ngx_http_charset_loc_conf_t *prev = parent;
- ngx_http_charset_loc_conf_t *conf = child;
-
- ngx_uint_t i;
- ngx_http_charset_recode_t *recode;
- ngx_http_charset_main_conf_t *mcf;
-
- if (ngx_http_merge_types(cf, &conf->types_keys, &conf->types,
- &prev->types_keys, &prev->types,
- ngx_http_charset_default_types)
- != NGX_OK)
- {
- return NGX_CONF_ERROR;
- }
-
- ngx_conf_merge_value(conf->override_charset, prev->override_charset, 0);
- ngx_conf_merge_value(conf->charset, prev->charset, NGX_HTTP_CHARSET_OFF);
- ngx_conf_merge_value(conf->source_charset, prev->source_charset,
- NGX_HTTP_CHARSET_OFF);
-
- if (conf->charset == NGX_HTTP_CHARSET_OFF
- || conf->source_charset == NGX_HTTP_CHARSET_OFF
- || conf->charset == conf->source_charset)
- {
- return NGX_CONF_OK;
- }
-
- if (conf->source_charset >= NGX_HTTP_CHARSET_VAR
- || conf->charset >= NGX_HTTP_CHARSET_VAR)
- {
- return NGX_CONF_OK;
- }
-
- mcf = ngx_http_conf_get_module_main_conf(cf,
- ngx_http_charset_filter_module);
- recode = mcf->recodes.elts;
- for (i = 0; i < mcf->recodes.nelts; i++) {
- if (conf->source_charset == recode[i].src
- && conf->charset == recode[i].dst)
- {
- return NGX_CONF_OK;
- }
- }
-
- recode = ngx_array_push(&mcf->recodes);
- if (recode == NULL) {
- return NGX_CONF_ERROR;
- }
-
- recode->src = conf->source_charset;
- recode->dst = conf->charset;
-
- return NGX_CONF_OK;
-}
-
-
-static ngx_int_t
-ngx_http_charset_postconfiguration(ngx_conf_t *cf)
-{
- u_char **src, **dst;
- ngx_int_t c;
- ngx_uint_t i, t;
- ngx_http_charset_t *charset;
- ngx_http_charset_recode_t *recode;
- ngx_http_charset_tables_t *tables;
- ngx_http_charset_main_conf_t *mcf;
-
- mcf = ngx_http_conf_get_module_main_conf(cf,
- ngx_http_charset_filter_module);
-
- recode = mcf->recodes.elts;
- tables = mcf->tables.elts;
- charset = mcf->charsets.elts;
-
- for (i = 0; i < mcf->recodes.nelts; i++) {
-
- c = recode[i].src;
-
- for (t = 0; t < mcf->tables.nelts; t++) {
-
- if (c == tables[t].src && recode[i].dst == tables[t].dst) {
- goto next;
- }
-
- if (c == tables[t].dst && recode[i].dst == tables[t].src) {
- goto next;
- }
- }
-
- ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
- "no \"charset_map\" between the charsets \"%V\" and \"%V\"",
- &charset[c].name, &charset[recode[i].dst].name);
- return NGX_ERROR;
-
- next:
- continue;
- }
-
-
- for (t = 0; t < mcf->tables.nelts; t++) {
-
- src = charset[tables[t].src].tables;
-
- if (src == NULL) {
- src = ngx_pcalloc(cf->pool, sizeof(u_char *) * mcf->charsets.nelts);
- if (src == NULL) {
- return NGX_ERROR;
- }
-
- charset[tables[t].src].tables = src;
- }
-
- dst = charset[tables[t].dst].tables;
-
- if (dst == NULL) {
- dst = ngx_pcalloc(cf->pool, sizeof(u_char *) * mcf->charsets.nelts);
- if (dst == NULL) {
- return NGX_ERROR;
- }
-
- charset[tables[t].dst].tables = dst;
- }
-
- src[tables[t].dst] = tables[t].src2dst;
- dst[tables[t].src] = tables[t].dst2src;
- }
-
- ngx_http_next_header_filter = ngx_http_top_header_filter;
- ngx_http_top_header_filter = ngx_http_charset_header_filter;
-
- ngx_http_next_body_filter = ngx_http_top_body_filter;
- ngx_http_top_body_filter = ngx_http_charset_body_filter;
-
- return NGX_OK;
-}
diff --git a/nginx/src/http/modules/ngx_http_chunked_filter_module.c b/nginx/src/http/modules/ngx_http_chunked_filter_module.c
deleted file mode 100644
index 4d6fd3e..0000000
--- a/nginx/src/http/modules/ngx_http_chunked_filter_module.c
+++ /dev/null
@@ -1,341 +0,0 @@
-
-/*
- * Copyright (C) Igor Sysoev
- * Copyright (C) Nginx, Inc.
- */
-
-
-#include <ngx_config.h>
-#include <ngx_core.h>
-#include <ngx_http.h>
-
-
-typedef struct {
- ngx_chain_t *free;
- ngx_chain_t *busy;
-} ngx_http_chunked_filter_ctx_t;
-
-
-static ngx_int_t ngx_http_chunked_filter_init(ngx_conf_t *cf);
-static ngx_chain_t *ngx_http_chunked_create_trailers(ngx_http_request_t *r,
- ngx_http_chunked_filter_ctx_t *ctx);
-
-
-static ngx_http_module_t ngx_http_chunked_filter_module_ctx = {
- NULL, /* preconfiguration */
- ngx_http_chunked_filter_init, /* postconfiguration */
-
- NULL, /* create main configuration */
- NULL, /* init main configuration */
-
- NULL, /* create server configuration */
- NULL, /* merge server configuration */
-
- NULL, /* create location configuration */
- NULL /* merge location configuration */
-};
-
-
-ngx_module_t ngx_http_chunked_filter_module = {
- NGX_MODULE_V1,
- &ngx_http_chunked_filter_module_ctx, /* module context */
- NULL, /* module directives */
- NGX_HTTP_MODULE, /* module type */
- NULL, /* init master */
- NULL, /* init module */
- NULL, /* init process */
- NULL, /* init thread */
- NULL, /* exit thread */
- NULL, /* exit process */
- NULL, /* exit master */
- NGX_MODULE_V1_PADDING
-};
-
-
-static ngx_http_output_header_filter_pt ngx_http_next_header_filter;
-static ngx_http_output_body_filter_pt ngx_http_next_body_filter;
-
-
-static ngx_int_t
-ngx_http_chunked_header_filter(ngx_http_request_t *r)
-{
- ngx_http_core_loc_conf_t *clcf;
- ngx_http_chunked_filter_ctx_t *ctx;
-
- if (r->headers_out.status == NGX_HTTP_NOT_MODIFIED
- || r->headers_out.status == NGX_HTTP_NO_CONTENT
- || r->headers_out.status < NGX_HTTP_OK
- || r != r->main
- || r->method == NGX_HTTP_HEAD)
- {
- return ngx_http_next_header_filter(r);
- }
-
- if (r->headers_out.content_length_n == -1
- || r->expect_trailers)
- {
- clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
-
- if (r->http_version >= NGX_HTTP_VERSION_11
- && clcf->chunked_transfer_encoding)
- {
- if (r->expect_trailers) {
- ngx_http_clear_content_length(r);
- }
-
- r->chunked = 1;
-
- ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_chunked_filter_ctx_t));
- if (ctx == NULL) {
- return NGX_ERROR;
- }
-
- ngx_http_set_ctx(r, ctx, ngx_http_chunked_filter_module);
-
- } else if (r->headers_out.content_length_n == -1) {
- r->keepalive = 0;
- }
- }
-
- return ngx_http_next_header_filter(r);
-}
-
-
-static ngx_int_t
-ngx_http_chunked_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
-{
- u_char *chunk;
- off_t size;
- ngx_int_t rc;
- ngx_buf_t *b;
- ngx_chain_t *out, *cl, *tl, **ll;
- ngx_http_chunked_filter_ctx_t *ctx;
-
- if (in == NULL || !r->chunked || r->header_only) {
- return ngx_http_next_body_filter(r, in);
- }
-
- ctx = ngx_http_get_module_ctx(r, ngx_http_chunked_filter_module);
-
- out = NULL;
- ll = &out;
-
- size = 0;
- cl = in;
-
- for ( ;; ) {
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "http chunk: %O", ngx_buf_size(cl->buf));
-
- size += ngx_buf_size(cl->buf);
-
- if (cl->buf->flush
- || cl->buf->sync
- || ngx_buf_in_memory(cl->buf)
- || cl->buf->in_file)
- {
- tl = ngx_alloc_chain_link(r->pool);
- if (tl == NULL) {
- return NGX_ERROR;
- }
-
- tl->buf = cl->buf;
- *ll = tl;
- ll = &tl->next;
- }
-
- if (cl->next == NULL) {
- break;
- }
-
- cl = cl->next;
- }
-
- if (size) {
- tl = ngx_chain_get_free_buf(r->pool, &ctx->free);
- if (tl == NULL) {
- return NGX_ERROR;
- }
-
- b = tl->buf;
- chunk = b->start;
-
- if (chunk == NULL) {
- /* the "0000000000000000" is 64-bit hexadecimal string */
-
- chunk = ngx_palloc(r->pool, sizeof("0000000000000000" CRLF) - 1);
- if (chunk == NULL) {
- return NGX_ERROR;
- }
-
- b->start = chunk;
- b->end = chunk + sizeof("0000000000000000" CRLF) - 1;
- }
-
- b->tag = (ngx_buf_tag_t) &ngx_http_chunked_filter_module;
- b->memory = 0;
- b->temporary = 1;
- b->pos = chunk;
- b->last = ngx_sprintf(chunk, "%xO" CRLF, size);
-
- tl->next = out;
- out = tl;
- }
-
- if (cl->buf->last_buf) {
- tl = ngx_http_chunked_create_trailers(r, ctx);
- if (tl == NULL) {
- return NGX_ERROR;
- }
-
- cl->buf->last_buf = 0;
-
- *ll = tl;
-
- if (size == 0) {
- tl->buf->pos += 2;
- }
-
- } else if (size > 0) {
- tl = ngx_chain_get_free_buf(r->pool, &ctx->free);
- if (tl == NULL) {
- return NGX_ERROR;
- }
-
- b = tl->buf;
-
- b->tag = (ngx_buf_tag_t) &ngx_http_chunked_filter_module;
- b->temporary = 0;
- b->memory = 1;
- b->pos = (u_char *) CRLF;
- b->last = b->pos + 2;
-
- *ll = tl;
-
- } else {
- *ll = NULL;
- }
-
- rc = ngx_http_next_body_filter(r, out);
-
- ngx_chain_update_chains(r->pool, &ctx->free, &ctx->busy, &out,
- (ngx_buf_tag_t) &ngx_http_chunked_filter_module);
-
- return rc;
-}
-
-
-static ngx_chain_t *
-ngx_http_chunked_create_trailers(ngx_http_request_t *r,
- ngx_http_chunked_filter_ctx_t *ctx)
-{
- size_t len;
- ngx_buf_t *b;
- ngx_uint_t i;
- ngx_chain_t *cl;
- ngx_list_part_t *part;
- ngx_table_elt_t *header;
-
- len = 0;
-
- part = &r->headers_out.trailers.part;
- header = part->elts;
-
- for (i = 0; /* void */; i++) {
-
- if (i >= part->nelts) {
- if (part->next == NULL) {
- break;
- }
-
- part = part->next;
- header = part->elts;
- i = 0;
- }
-
- if (header[i].hash == 0) {
- continue;
- }
-
- len += header[i].key.len + sizeof(": ") - 1
- + header[i].value.len + sizeof(CRLF) - 1;
- }
-
- cl = ngx_chain_get_free_buf(r->pool, &ctx->free);
- if (cl == NULL) {
- return NULL;
- }
-
- b = cl->buf;
-
- b->tag = (ngx_buf_tag_t) &ngx_http_chunked_filter_module;
- b->temporary = 0;
- b->memory = 1;
- b->last_buf = 1;
-
- if (len == 0) {
- b->pos = (u_char *) CRLF "0" CRLF CRLF;
- b->last = b->pos + sizeof(CRLF "0" CRLF CRLF) - 1;
- return cl;
- }
-
- len += sizeof(CRLF "0" CRLF CRLF) - 1;
-
- b->pos = ngx_palloc(r->pool, len);
- if (b->pos == NULL) {
- return NULL;
- }
-
- b->last = b->pos;
-
- *b->last++ = CR; *b->last++ = LF;
- *b->last++ = '0';
- *b->last++ = CR; *b->last++ = LF;
-
- part = &r->headers_out.trailers.part;
- header = part->elts;
-
- for (i = 0; /* void */; i++) {
-
- if (i >= part->nelts) {
- if (part->next == NULL) {
- break;
- }
-
- part = part->next;
- header = part->elts;
- i = 0;
- }
-
- if (header[i].hash == 0) {
- continue;
- }
-
- ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "http trailer: \"%V: %V\"",
- &header[i].key, &header[i].value);
-
- b->last = ngx_copy(b->last, header[i].key.data, header[i].key.len);
- *b->last++ = ':'; *b->last++ = ' ';
-
- b->last = ngx_copy(b->last, header[i].value.data, header[i].value.len);
- *b->last++ = CR; *b->last++ = LF;
- }
-
- *b->last++ = CR; *b->last++ = LF;
-
- return cl;
-}
-
-
-static ngx_int_t
-ngx_http_chunked_filter_init(ngx_conf_t *cf)
-{
- ngx_http_next_header_filter = ngx_http_top_header_filter;
- ngx_http_top_header_filter = ngx_http_chunked_header_filter;
-
- ngx_http_next_body_filter = ngx_http_top_body_filter;
- ngx_http_top_body_filter = ngx_http_chunked_body_filter;
-
- return NGX_OK;
-}
diff --git a/nginx/src/http/modules/ngx_http_dav_module.c b/nginx/src/http/modules/ngx_http_dav_module.c
deleted file mode 100644
index 55ad9eb..0000000
--- a/nginx/src/http/modules/ngx_http_dav_module.c
+++ /dev/null
@@ -1,1169 +0,0 @@
-
-/*
- * Copyright (C) Igor Sysoev
- * Copyright (C) Nginx, Inc.
- */
-
-
-#include <ngx_config.h>
-#include <ngx_core.h>
-#include <ngx_http.h>
-
-
-#define NGX_HTTP_DAV_OFF 2
-
-
-#define NGX_HTTP_DAV_NO_DEPTH -3
-#define NGX_HTTP_DAV_INVALID_DEPTH -2
-#define NGX_HTTP_DAV_INFINITY_DEPTH -1
-
-
-typedef struct {
- ngx_uint_t methods;
- ngx_uint_t access;
- ngx_uint_t min_delete_depth;
- ngx_flag_t create_full_put_path;
-} ngx_http_dav_loc_conf_t;
-
-
-typedef struct {
- ngx_str_t path;
- size_t len;
-} ngx_http_dav_copy_ctx_t;
-
-
-static ngx_int_t ngx_http_dav_handler(ngx_http_request_t *r);
-
-static void ngx_http_dav_put_handler(ngx_http_request_t *r);
-
-static ngx_int_t ngx_http_dav_delete_handler(ngx_http_request_t *r);
-static ngx_int_t ngx_http_dav_delete_path(ngx_http_request_t *r,
- ngx_str_t *path, ngx_uint_t dir);
-static ngx_int_t ngx_http_dav_delete_dir(ngx_tree_ctx_t *ctx, ngx_str_t *path);
-static ngx_int_t ngx_http_dav_delete_file(ngx_tree_ctx_t *ctx, ngx_str_t *path);
-static ngx_int_t ngx_http_dav_noop(ngx_tree_ctx_t *ctx, ngx_str_t *path);
-
-static ngx_int_t ngx_http_dav_mkcol_handler(ngx_http_request_t *r,
- ngx_http_dav_loc_conf_t *dlcf);
-
-static ngx_int_t ngx_http_dav_copy_move_handler(ngx_http_request_t *r);
-static ngx_int_t ngx_http_dav_copy_dir(ngx_tree_ctx_t *ctx, ngx_str_t *path);
-static ngx_int_t ngx_http_dav_copy_dir_time(ngx_tree_ctx_t *ctx,
- ngx_str_t *path);
-static ngx_int_t ngx_http_dav_copy_tree_file(ngx_tree_ctx_t *ctx,
- ngx_str_t *path);
-
-static ngx_int_t ngx_http_dav_depth(ngx_http_request_t *r, ngx_int_t dflt);
-static ngx_int_t ngx_http_dav_error(ngx_log_t *log, ngx_err_t err,
- ngx_int_t not_found, char *failed, u_char *path);
-static ngx_int_t ngx_http_dav_location(ngx_http_request_t *r, u_char *path);
-static void *ngx_http_dav_create_loc_conf(ngx_conf_t *cf);
-static char *ngx_http_dav_merge_loc_conf(ngx_conf_t *cf,
- void *parent, void *child);
-static ngx_int_t ngx_http_dav_init(ngx_conf_t *cf);
-
-
-static ngx_conf_bitmask_t ngx_http_dav_methods_mask[] = {
- { ngx_string("off"), NGX_HTTP_DAV_OFF },
- { ngx_string("put"), NGX_HTTP_PUT },
- { ngx_string("delete"), NGX_HTTP_DELETE },
- { ngx_string("mkcol"), NGX_HTTP_MKCOL },
- { ngx_string("copy"), NGX_HTTP_COPY },
- { ngx_string("move"), NGX_HTTP_MOVE },
- { ngx_null_string, 0 }
-};
-
-
-static ngx_command_t ngx_http_dav_commands[] = {
-
- { ngx_string("dav_methods"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
- ngx_conf_set_bitmask_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_dav_loc_conf_t, methods),
- &ngx_http_dav_methods_mask },
-
- { ngx_string("create_full_put_path"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
- ngx_conf_set_flag_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_dav_loc_conf_t, create_full_put_path),
- NULL },
-
- { ngx_string("min_delete_depth"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_num_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_dav_loc_conf_t, min_delete_depth),
- NULL },
-
- { ngx_string("dav_access"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE123,
- ngx_conf_set_access_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_dav_loc_conf_t, access),
- NULL },
-
- ngx_null_command
-};
-
-
-static ngx_http_module_t ngx_http_dav_module_ctx = {
- NULL, /* preconfiguration */
- ngx_http_dav_init, /* postconfiguration */
-
- NULL, /* create main configuration */
- NULL, /* init main configuration */
-
- NULL, /* create server configuration */
- NULL, /* merge server configuration */
-
- ngx_http_dav_create_loc_conf, /* create location configuration */
- ngx_http_dav_merge_loc_conf /* merge location configuration */
-};
-
-
-ngx_module_t ngx_http_dav_module = {
- NGX_MODULE_V1,
- &ngx_http_dav_module_ctx, /* module context */
- ngx_http_dav_commands, /* module directives */
- NGX_HTTP_MODULE, /* module type */
- NULL, /* init master */
- NULL, /* init module */
- NULL, /* init process */
- NULL, /* init thread */
- NULL, /* exit thread */
- NULL, /* exit process */
- NULL, /* exit master */
- NGX_MODULE_V1_PADDING
-};
-
-
-static ngx_int_t
-ngx_http_dav_handler(ngx_http_request_t *r)
-{
- ngx_int_t rc;
- ngx_http_dav_loc_conf_t *dlcf;
-
- dlcf = ngx_http_get_module_loc_conf(r, ngx_http_dav_module);
-
- if (!(r->method & dlcf->methods)) {
- return NGX_DECLINED;
- }
-
- switch (r->method) {
-
- case NGX_HTTP_PUT:
-
- if (r->uri.data[r->uri.len - 1] == '/') {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "cannot PUT to a collection");
- return NGX_HTTP_CONFLICT;
- }
-
- if (r->headers_in.content_range) {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "PUT with range is unsupported");
- return NGX_HTTP_NOT_IMPLEMENTED;
- }
-
- r->request_body_in_file_only = 1;
- r->request_body_in_persistent_file = 1;
- r->request_body_in_clean_file = 1;
- r->request_body_file_group_access = 1;
- r->request_body_file_log_level = 0;
-
- rc = ngx_http_read_client_request_body(r, ngx_http_dav_put_handler);
-
- if (rc >= NGX_HTTP_SPECIAL_RESPONSE) {
- return rc;
- }
-
- return NGX_DONE;
-
- case NGX_HTTP_DELETE:
-
- return ngx_http_dav_delete_handler(r);
-
- case NGX_HTTP_MKCOL:
-
- return ngx_http_dav_mkcol_handler(r, dlcf);
-
- case NGX_HTTP_COPY:
-
- return ngx_http_dav_copy_move_handler(r);
-
- case NGX_HTTP_MOVE:
-
- return ngx_http_dav_copy_move_handler(r);
- }
-
- return NGX_DECLINED;
-}
-
-
-static void
-ngx_http_dav_put_handler(ngx_http_request_t *r)
-{
- size_t root;
- time_t date;
- ngx_str_t *temp, path;
- ngx_uint_t status;
- ngx_file_info_t fi;
- ngx_ext_rename_file_t ext;
- ngx_http_dav_loc_conf_t *dlcf;
-
- if (r->request_body == NULL) {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "PUT request body is unavailable");
- ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
- return;
- }
-
- if (r->request_body->temp_file == NULL) {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "PUT request body must be in a file");
- ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
- return;
- }
-
- if (ngx_http_map_uri_to_path(r, &path, &root, 0) == NULL) {
- ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
- return;
- }
-
- path.len--;
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "http put filename: \"%s\"", path.data);
-
- temp = &r->request_body->temp_file->file.name;
-
- if (ngx_file_info(path.data, &fi) == NGX_FILE_ERROR) {
- status = NGX_HTTP_CREATED;
-
- } else {
- status = NGX_HTTP_NO_CONTENT;
-
- if (ngx_is_dir(&fi)) {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, NGX_EISDIR,
- "\"%s\" could not be created", path.data);
-
- if (ngx_delete_file(temp->data) == NGX_FILE_ERROR) {
- ngx_log_error(NGX_LOG_CRIT, r->connection->log, ngx_errno,
- ngx_delete_file_n " \"%s\" failed",
- temp->data);
- }
-
- ngx_http_finalize_request(r, NGX_HTTP_CONFLICT);
- return;
- }
- }
-
- dlcf = ngx_http_get_module_loc_conf(r, ngx_http_dav_module);
-
- ext.access = dlcf->access;
- ext.path_access = dlcf->access;
- ext.time = -1;
- ext.create_path = dlcf->create_full_put_path;
- ext.delete_file = 1;
- ext.log = r->connection->log;
-
- if (r->headers_in.date) {
- date = ngx_parse_http_time(r->headers_in.date->value.data,
- r->headers_in.date->value.len);
-
- if (date != NGX_ERROR) {
- ext.time = date;
- ext.fd = r->request_body->temp_file->file.fd;
- }
- }
-
- if (ngx_ext_rename_file(temp, &path, &ext) != NGX_OK) {
- ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
- return;
- }
-
- if (status == NGX_HTTP_CREATED) {
- if (ngx_http_dav_location(r, path.data) != NGX_OK) {
- ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
- return;
- }
-
- r->headers_out.content_length_n = 0;
- }
-
- r->headers_out.status = status;
- r->header_only = 1;
-
- ngx_http_finalize_request(r, ngx_http_send_header(r));
- return;
-}
-
-
-static ngx_int_t
-ngx_http_dav_delete_handler(ngx_http_request_t *r)
-{
- size_t root;
- ngx_err_t err;
- ngx_int_t rc, depth;
- ngx_uint_t i, d, dir;
- ngx_str_t path;
- ngx_file_info_t fi;
- ngx_http_dav_loc_conf_t *dlcf;
-
- if (r->headers_in.content_length_n > 0) {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "DELETE with body is unsupported");
- return NGX_HTTP_UNSUPPORTED_MEDIA_TYPE;
- }
-
- dlcf = ngx_http_get_module_loc_conf(r, ngx_http_dav_module);
-
- if (dlcf->min_delete_depth) {
- d = 0;
-
- for (i = 0; i < r->uri.len; /* void */) {
- if (r->uri.data[i++] == '/') {
- if (++d >= dlcf->min_delete_depth && i < r->uri.len) {
- goto ok;
- }
- }
- }
-
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "insufficient URI depth:%i to DELETE", d);
- return NGX_HTTP_CONFLICT;
- }
-
-ok:
-
- if (ngx_http_map_uri_to_path(r, &path, &root, 0) == NULL) {
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "http delete filename: \"%s\"", path.data);
-
- if (ngx_link_info(path.data, &fi) == NGX_FILE_ERROR) {
- err = ngx_errno;
-
- rc = (err == NGX_ENOTDIR) ? NGX_HTTP_CONFLICT : NGX_HTTP_NOT_FOUND;
-
- return ngx_http_dav_error(r->connection->log, err,
- rc, ngx_link_info_n, path.data);
- }
-
- if (ngx_is_dir(&fi)) {
-
- if (r->uri.data[r->uri.len - 1] != '/') {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, NGX_EISDIR,
- "DELETE \"%s\" failed", path.data);
- return NGX_HTTP_CONFLICT;
- }
-
- depth = ngx_http_dav_depth(r, NGX_HTTP_DAV_INFINITY_DEPTH);
-
- if (depth != NGX_HTTP_DAV_INFINITY_DEPTH) {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "\"Depth\" header must be infinity");
- return NGX_HTTP_BAD_REQUEST;
- }
-
- path.len -= 2; /* omit "/\0" */
-
- dir = 1;
-
- } else {
-
- /*
- * we do not need to test (r->uri.data[r->uri.len - 1] == '/')
- * because ngx_link_info("/file/") returned NGX_ENOTDIR above
- */
-
- depth = ngx_http_dav_depth(r, 0);
-
- if (depth != 0 && depth != NGX_HTTP_DAV_INFINITY_DEPTH) {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "\"Depth\" header must be 0 or infinity");
- return NGX_HTTP_BAD_REQUEST;
- }
-
- dir = 0;
- }
-
- rc = ngx_http_dav_delete_path(r, &path, dir);
-
- if (rc == NGX_OK) {
- return NGX_HTTP_NO_CONTENT;
- }
-
- return rc;
-}
-
-
-static ngx_int_t
-ngx_http_dav_delete_path(ngx_http_request_t *r, ngx_str_t *path, ngx_uint_t dir)
-{
- char *failed;
- ngx_tree_ctx_t tree;
-
- if (dir) {
-
- tree.init_handler = NULL;
- tree.file_handler = ngx_http_dav_delete_file;
- tree.pre_tree_handler = ngx_http_dav_noop;
- tree.post_tree_handler = ngx_http_dav_delete_dir;
- tree.spec_handler = ngx_http_dav_delete_file;
- tree.data = NULL;
- tree.alloc = 0;
- tree.log = r->connection->log;
-
- /* TODO: 207 */
-
- if (ngx_walk_tree(&tree, path) != NGX_OK) {
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
-
- if (ngx_delete_dir(path->data) != NGX_FILE_ERROR) {
- return NGX_OK;
- }
-
- failed = ngx_delete_dir_n;
-
- } else {
-
- if (ngx_delete_file(path->data) != NGX_FILE_ERROR) {
- return NGX_OK;
- }
-
- failed = ngx_delete_file_n;
- }
-
- return ngx_http_dav_error(r->connection->log, ngx_errno,
- NGX_HTTP_NOT_FOUND, failed, path->data);
-}
-
-
-static ngx_int_t
-ngx_http_dav_delete_dir(ngx_tree_ctx_t *ctx, ngx_str_t *path)
-{
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, ctx->log, 0,
- "http delete dir: \"%s\"", path->data);
-
- if (ngx_delete_dir(path->data) == NGX_FILE_ERROR) {
-
- /* TODO: add to 207 */
-
- (void) ngx_http_dav_error(ctx->log, ngx_errno, 0, ngx_delete_dir_n,
- path->data);
- }
-
- return NGX_OK;
-}
-
-
-static ngx_int_t
-ngx_http_dav_delete_file(ngx_tree_ctx_t *ctx, ngx_str_t *path)
-{
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, ctx->log, 0,
- "http delete file: \"%s\"", path->data);
-
- if (ngx_delete_file(path->data) == NGX_FILE_ERROR) {
-
- /* TODO: add to 207 */
-
- (void) ngx_http_dav_error(ctx->log, ngx_errno, 0, ngx_delete_file_n,
- path->data);
- }
-
- return NGX_OK;
-}
-
-
-static ngx_int_t
-ngx_http_dav_noop(ngx_tree_ctx_t *ctx, ngx_str_t *path)
-{
- return NGX_OK;
-}
-
-
-static ngx_int_t
-ngx_http_dav_mkcol_handler(ngx_http_request_t *r, ngx_http_dav_loc_conf_t *dlcf)
-{
- u_char *p;
- size_t root;
- ngx_str_t path;
-
- if (r->headers_in.content_length_n > 0) {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "MKCOL with body is unsupported");
- return NGX_HTTP_UNSUPPORTED_MEDIA_TYPE;
- }
-
- if (r->uri.data[r->uri.len - 1] != '/') {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "MKCOL can create a collection only");
- return NGX_HTTP_CONFLICT;
- }
-
- p = ngx_http_map_uri_to_path(r, &path, &root, 0);
- if (p == NULL) {
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
-
- *(p - 1) = '\0';
- r->uri.len--;
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "http mkcol path: \"%s\"", path.data);
-
- if (ngx_create_dir(path.data, ngx_dir_access(dlcf->access))
- != NGX_FILE_ERROR)
- {
- if (ngx_http_dav_location(r, path.data) != NGX_OK) {
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
-
- return NGX_HTTP_CREATED;
- }
-
- return ngx_http_dav_error(r->connection->log, ngx_errno,
- NGX_HTTP_CONFLICT, ngx_create_dir_n, path.data);
-}
-
-
-static ngx_int_t
-ngx_http_dav_copy_move_handler(ngx_http_request_t *r)
-{
- u_char *p, *host, *last, ch;
- size_t len, root;
- ngx_err_t err;
- ngx_int_t rc, depth;
- ngx_uint_t overwrite, slash, dir, flags;
- ngx_str_t path, uri, duri, args;
- ngx_tree_ctx_t tree;
- ngx_copy_file_t cf;
- ngx_file_info_t fi;
- ngx_table_elt_t *dest, *over;
- ngx_ext_rename_file_t ext;
- ngx_http_dav_copy_ctx_t copy;
- ngx_http_dav_loc_conf_t *dlcf;
-
- if (r->headers_in.content_length_n > 0) {
- return NGX_HTTP_UNSUPPORTED_MEDIA_TYPE;
- }
-
- dest = r->headers_in.destination;
-
- if (dest == NULL) {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "client sent no \"Destination\" header");
- return NGX_HTTP_BAD_REQUEST;
- }
-
- p = dest->value.data;
- /* there is always '\0' even after empty header value */
- if (p[0] == '/') {
- last = p + dest->value.len;
- goto destination_done;
- }
-
- len = r->headers_in.server.len;
-
- if (len == 0) {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "client sent no \"Host\" header");
- return NGX_HTTP_BAD_REQUEST;
- }
-
-#if (NGX_HTTP_SSL)
-
- if (r->connection->ssl) {
- if (ngx_strncmp(dest->value.data, "https://", sizeof("https://") - 1)
- != 0)
- {
- goto invalid_destination;
- }
-
- host = dest->value.data + sizeof("https://") - 1;
-
- } else
-#endif
- {
- if (ngx_strncmp(dest->value.data, "http://", sizeof("http://") - 1)
- != 0)
- {
- goto invalid_destination;
- }
-
- host = dest->value.data + sizeof("http://") - 1;
- }
-
- if (ngx_strncmp(host, r->headers_in.server.data, len) != 0) {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "\"Destination\" URI \"%V\" is handled by "
- "different repository than the source URI",
- &dest->value);
- return NGX_HTTP_BAD_REQUEST;
- }
-
- last = dest->value.data + dest->value.len;
-
- for (p = host + len; p < last; p++) {
- if (*p == '/') {
- goto destination_done;
- }
- }
-
-invalid_destination:
-
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "client sent invalid \"Destination\" header: \"%V\"",
- &dest->value);
- return NGX_HTTP_BAD_REQUEST;
-
-destination_done:
-
- duri.len = last - p;
- duri.data = p;
- flags = NGX_HTTP_LOG_UNSAFE;
-
- if (ngx_http_parse_unsafe_uri(r, &duri, &args, &flags) != NGX_OK) {
- goto invalid_destination;
- }
-
- if ((r->uri.data[r->uri.len - 1] == '/' && *(last - 1) != '/')
- || (r->uri.data[r->uri.len - 1] != '/' && *(last - 1) == '/'))
- {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "both URI \"%V\" and \"Destination\" URI \"%V\" "
- "should be either collections or non-collections",
- &r->uri, &dest->value);
- return NGX_HTTP_CONFLICT;
- }
-
- depth = ngx_http_dav_depth(r, NGX_HTTP_DAV_INFINITY_DEPTH);
-
- if (depth != NGX_HTTP_DAV_INFINITY_DEPTH) {
-
- if (r->method == NGX_HTTP_COPY) {
- if (depth != 0) {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "\"Depth\" header must be 0 or infinity");
- return NGX_HTTP_BAD_REQUEST;
- }
-
- } else {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "\"Depth\" header must be infinity");
- return NGX_HTTP_BAD_REQUEST;
- }
- }
-
- over = r->headers_in.overwrite;
-
- if (over) {
- if (over->value.len == 1) {
- ch = over->value.data[0];
-
- if (ch == 'T' || ch == 't') {
- overwrite = 1;
- goto overwrite_done;
- }
-
- if (ch == 'F' || ch == 'f') {
- overwrite = 0;
- goto overwrite_done;
- }
-
- }
-
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "client sent invalid \"Overwrite\" header: \"%V\"",
- &over->value);
- return NGX_HTTP_BAD_REQUEST;
- }
-
- overwrite = 1;
-
-overwrite_done:
-
- if (ngx_http_map_uri_to_path(r, &path, &root, 0) == NULL) {
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "http copy from: \"%s\"", path.data);
-
- uri = r->uri;
- r->uri = duri;
-
- if (ngx_http_map_uri_to_path(r, &copy.path, &root, 0) == NULL) {
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
-
- r->uri = uri;
-
- copy.path.len--; /* omit "\0" */
-
- if (copy.path.data[copy.path.len - 1] == '/') {
- slash = 1;
- copy.path.len--;
- copy.path.data[copy.path.len] = '\0';
-
- } else {
- slash = 0;
- }
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "http copy to: \"%s\"", copy.path.data);
-
- if (ngx_link_info(copy.path.data, &fi) == NGX_FILE_ERROR) {
- err = ngx_errno;
-
- if (err != NGX_ENOENT) {
- return ngx_http_dav_error(r->connection->log, err,
- NGX_HTTP_NOT_FOUND, ngx_link_info_n,
- copy.path.data);
- }
-
- /* destination does not exist */
-
- overwrite = 0;
- dir = 0;
-
- } else {
-
- /* destination exists */
-
- if (ngx_is_dir(&fi) && !slash) {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "\"%V\" could not be %Ved to collection \"%V\"",
- &r->uri, &r->method_name, &dest->value);
- return NGX_HTTP_CONFLICT;
- }
-
- if (!overwrite) {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, NGX_EEXIST,
- "\"%s\" could not be created", copy.path.data);
- return NGX_HTTP_PRECONDITION_FAILED;
- }
-
- dir = ngx_is_dir(&fi);
- }
-
- if (ngx_link_info(path.data, &fi) == NGX_FILE_ERROR) {
- return ngx_http_dav_error(r->connection->log, ngx_errno,
- NGX_HTTP_NOT_FOUND, ngx_link_info_n,
- path.data);
- }
-
- if (ngx_is_dir(&fi)) {
-
- if (r->uri.data[r->uri.len - 1] != '/') {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "\"%V\" is collection", &r->uri);
- return NGX_HTTP_BAD_REQUEST;
- }
-
- if (overwrite) {
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "http delete: \"%s\"", copy.path.data);
-
- rc = ngx_http_dav_delete_path(r, &copy.path, dir);
-
- if (rc != NGX_OK) {
- return rc;
- }
- }
- }
-
- if (ngx_is_dir(&fi)) {
-
- path.len -= 2; /* omit "/\0" */
-
- if (r->method == NGX_HTTP_MOVE) {
- if (ngx_rename_file(path.data, copy.path.data) != NGX_FILE_ERROR) {
- return NGX_HTTP_CREATED;
- }
- }
-
- if (ngx_create_dir(copy.path.data, ngx_file_access(&fi))
- == NGX_FILE_ERROR)
- {
- return ngx_http_dav_error(r->connection->log, ngx_errno,
- NGX_HTTP_NOT_FOUND,
- ngx_create_dir_n, copy.path.data);
- }
-
- copy.len = path.len;
-
- tree.init_handler = NULL;
- tree.file_handler = ngx_http_dav_copy_tree_file;
- tree.pre_tree_handler = ngx_http_dav_copy_dir;
- tree.post_tree_handler = ngx_http_dav_copy_dir_time;
- tree.spec_handler = ngx_http_dav_noop;
- tree.data = &copy;
- tree.alloc = 0;
- tree.log = r->connection->log;
-
- if (ngx_walk_tree(&tree, &path) == NGX_OK) {
-
- if (r->method == NGX_HTTP_MOVE) {
- rc = ngx_http_dav_delete_path(r, &path, 1);
-
- if (rc != NGX_OK) {
- return rc;
- }
- }
-
- return NGX_HTTP_CREATED;
- }
-
- } else {
-
- if (r->method == NGX_HTTP_MOVE) {
-
- dlcf = ngx_http_get_module_loc_conf(r, ngx_http_dav_module);
-
- ext.access = 0;
- ext.path_access = dlcf->access;
- ext.time = -1;
- ext.create_path = 1;
- ext.delete_file = 0;
- ext.log = r->connection->log;
-
- if (ngx_ext_rename_file(&path, &copy.path, &ext) == NGX_OK) {
- return NGX_HTTP_NO_CONTENT;
- }
-
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
-
- dlcf = ngx_http_get_module_loc_conf(r, ngx_http_dav_module);
-
- cf.size = ngx_file_size(&fi);
- cf.buf_size = 0;
- cf.access = dlcf->access;
- cf.time = ngx_file_mtime(&fi);
- cf.log = r->connection->log;
-
- if (ngx_copy_file(path.data, copy.path.data, &cf) == NGX_OK) {
- return NGX_HTTP_NO_CONTENT;
- }
- }
-
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
-}
-
-
-static ngx_int_t
-ngx_http_dav_copy_dir(ngx_tree_ctx_t *ctx, ngx_str_t *path)
-{
- u_char *p, *dir;
- size_t len;
- ngx_http_dav_copy_ctx_t *copy;
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, ctx->log, 0,
- "http copy dir: \"%s\"", path->data);
-
- copy = ctx->data;
-
- len = copy->path.len + path->len;
-
- dir = ngx_alloc(len + 1, ctx->log);
- if (dir == NULL) {
- return NGX_ABORT;
- }
-
- p = ngx_cpymem(dir, copy->path.data, copy->path.len);
- (void) ngx_cpystrn(p, path->data + copy->len, path->len - copy->len + 1);
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, ctx->log, 0,
- "http copy dir to: \"%s\"", dir);
-
- if (ngx_create_dir(dir, ngx_dir_access(ctx->access)) == NGX_FILE_ERROR) {
- (void) ngx_http_dav_error(ctx->log, ngx_errno, 0, ngx_create_dir_n,
- dir);
- }
-
- ngx_free(dir);
-
- return NGX_OK;
-}
-
-
-static ngx_int_t
-ngx_http_dav_copy_dir_time(ngx_tree_ctx_t *ctx, ngx_str_t *path)
-{
- u_char *p, *dir;
- size_t len;
- ngx_http_dav_copy_ctx_t *copy;
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, ctx->log, 0,
- "http copy dir time: \"%s\"", path->data);
-
- copy = ctx->data;
-
- len = copy->path.len + path->len;
-
- dir = ngx_alloc(len + 1, ctx->log);
- if (dir == NULL) {
- return NGX_ABORT;
- }
-
- p = ngx_cpymem(dir, copy->path.data, copy->path.len);
- (void) ngx_cpystrn(p, path->data + copy->len, path->len - copy->len + 1);
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, ctx->log, 0,
- "http copy dir time to: \"%s\"", dir);
-
-#if (NGX_WIN32)
- {
- ngx_fd_t fd;
-
- fd = ngx_open_file(dir, NGX_FILE_RDWR, NGX_FILE_OPEN, 0);
-
- if (fd == NGX_INVALID_FILE) {
- (void) ngx_http_dav_error(ctx->log, ngx_errno, 0, ngx_open_file_n, dir);
- goto failed;
- }
-
- if (ngx_set_file_time(NULL, fd, ctx->mtime) != NGX_OK) {
- ngx_log_error(NGX_LOG_ALERT, ctx->log, ngx_errno,
- ngx_set_file_time_n " \"%s\" failed", dir);
- }
-
- if (ngx_close_file(fd) == NGX_FILE_ERROR) {
- ngx_log_error(NGX_LOG_ALERT, ctx->log, ngx_errno,
- ngx_close_file_n " \"%s\" failed", dir);
- }
- }
-
-failed:
-
-#else
-
- if (ngx_set_file_time(dir, 0, ctx->mtime) != NGX_OK) {
- ngx_log_error(NGX_LOG_ALERT, ctx->log, ngx_errno,
- ngx_set_file_time_n " \"%s\" failed", dir);
- }
-
-#endif
-
- ngx_free(dir);
-
- return NGX_OK;
-}
-
-
-static ngx_int_t
-ngx_http_dav_copy_tree_file(ngx_tree_ctx_t *ctx, ngx_str_t *path)
-{
- u_char *p, *file;
- size_t len;
- ngx_copy_file_t cf;
- ngx_http_dav_copy_ctx_t *copy;
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, ctx->log, 0,
- "http copy file: \"%s\"", path->data);
-
- copy = ctx->data;
-
- len = copy->path.len + path->len;
-
- file = ngx_alloc(len + 1, ctx->log);
- if (file == NULL) {
- return NGX_ABORT;
- }
-
- p = ngx_cpymem(file, copy->path.data, copy->path.len);
- (void) ngx_cpystrn(p, path->data + copy->len, path->len - copy->len + 1);
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, ctx->log, 0,
- "http copy file to: \"%s\"", file);
-
- cf.size = ctx->size;
- cf.buf_size = 0;
- cf.access = ctx->access;
- cf.time = ctx->mtime;
- cf.log = ctx->log;
-
- (void) ngx_copy_file(path->data, file, &cf);
-
- ngx_free(file);
-
- return NGX_OK;
-}
-
-
-static ngx_int_t
-ngx_http_dav_depth(ngx_http_request_t *r, ngx_int_t dflt)
-{
- ngx_table_elt_t *depth;
-
- depth = r->headers_in.depth;
-
- if (depth == NULL) {
- return dflt;
- }
-
- if (depth->value.len == 1) {
-
- if (depth->value.data[0] == '0') {
- return 0;
- }
-
- if (depth->value.data[0] == '1') {
- return 1;
- }
-
- } else {
-
- if (depth->value.len == sizeof("infinity") - 1
- && ngx_strcmp(depth->value.data, "infinity") == 0)
- {
- return NGX_HTTP_DAV_INFINITY_DEPTH;
- }
- }
-
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "client sent invalid \"Depth\" header: \"%V\"",
- &depth->value);
-
- return NGX_HTTP_DAV_INVALID_DEPTH;
-}
-
-
-static ngx_int_t
-ngx_http_dav_error(ngx_log_t *log, ngx_err_t err, ngx_int_t not_found,
- char *failed, u_char *path)
-{
- ngx_int_t rc;
- ngx_uint_t level;
-
- if (err == NGX_ENOENT || err == NGX_ENOTDIR || err == NGX_ENAMETOOLONG) {
- level = NGX_LOG_ERR;
- rc = not_found;
-
- } else if (err == NGX_EACCES || err == NGX_EPERM) {
- level = NGX_LOG_ERR;
- rc = NGX_HTTP_FORBIDDEN;
-
- } else if (err == NGX_EEXIST) {
- level = NGX_LOG_ERR;
- rc = NGX_HTTP_NOT_ALLOWED;
-
- } else if (err == NGX_ENOSPC) {
- level = NGX_LOG_CRIT;
- rc = NGX_HTTP_INSUFFICIENT_STORAGE;
-
- } else {
- level = NGX_LOG_CRIT;
- rc = NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
-
- ngx_log_error(level, log, err, "%s \"%s\" failed", failed, path);
-
- return rc;
-}
-
-
-static ngx_int_t
-ngx_http_dav_location(ngx_http_request_t *r, u_char *path)
-{
- u_char *location;
- ngx_http_core_loc_conf_t *clcf;
-
- r->headers_out.location = ngx_list_push(&r->headers_out.headers);
- if (r->headers_out.location == NULL) {
- return NGX_ERROR;
- }
-
- clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
-
- if (!clcf->alias && clcf->root_lengths == NULL) {
- location = path + clcf->root.len;
-
- } else {
- location = ngx_pnalloc(r->pool, r->uri.len);
- if (location == NULL) {
- ngx_http_clear_location(r);
- return NGX_ERROR;
- }
-
- ngx_memcpy(location, r->uri.data, r->uri.len);
- }
-
- r->headers_out.location->hash = 1;
- ngx_str_set(&r->headers_out.location->key, "Location");
- r->headers_out.location->value.len = r->uri.len;
- r->headers_out.location->value.data = location;
-
- return NGX_OK;
-}
-
-
-static void *
-ngx_http_dav_create_loc_conf(ngx_conf_t *cf)
-{
- ngx_http_dav_loc_conf_t *conf;
-
- conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_dav_loc_conf_t));
- if (conf == NULL) {
- return NULL;
- }
-
- /*
- * set by ngx_pcalloc():
- *
- * conf->methods = 0;
- */
-
- conf->min_delete_depth = NGX_CONF_UNSET_UINT;
- conf->access = NGX_CONF_UNSET_UINT;
- conf->create_full_put_path = NGX_CONF_UNSET;
-
- return conf;
-}
-
-
-static char *
-ngx_http_dav_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
-{
- ngx_http_dav_loc_conf_t *prev = parent;
- ngx_http_dav_loc_conf_t *conf = child;
-
- ngx_conf_merge_bitmask_value(conf->methods, prev->methods,
- (NGX_CONF_BITMASK_SET|NGX_HTTP_DAV_OFF));
-
- ngx_conf_merge_uint_value(conf->min_delete_depth,
- prev->min_delete_depth, 0);
-
- ngx_conf_merge_uint_value(conf->access, prev->access, 0600);
-
- ngx_conf_merge_value(conf->create_full_put_path,
- prev->create_full_put_path, 0);
-
- return NGX_CONF_OK;
-}
-
-
-static ngx_int_t
-ngx_http_dav_init(ngx_conf_t *cf)
-{
- ngx_http_handler_pt *h;
- ngx_http_core_main_conf_t *cmcf;
-
- cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);
-
- h = ngx_array_push(&cmcf->phases[NGX_HTTP_CONTENT_PHASE].handlers);
- if (h == NULL) {
- return NGX_ERROR;
- }
-
- *h = ngx_http_dav_handler;
-
- return NGX_OK;
-}
diff --git a/nginx/src/http/modules/ngx_http_degradation_module.c b/nginx/src/http/modules/ngx_http_degradation_module.c
deleted file mode 100644
index b9c65cd..0000000
--- a/nginx/src/http/modules/ngx_http_degradation_module.c
+++ /dev/null
@@ -1,243 +0,0 @@
-
-/*
- * Copyright (C) Igor Sysoev
- * Copyright (C) Nginx, Inc.
- */
-
-
-#include <ngx_config.h>
-#include <ngx_core.h>
-#include <ngx_http.h>
-
-
-typedef struct {
- size_t sbrk_size;
-} ngx_http_degradation_main_conf_t;
-
-
-typedef struct {
- ngx_uint_t degrade;
-} ngx_http_degradation_loc_conf_t;
-
-
-static ngx_conf_enum_t ngx_http_degrade[] = {
- { ngx_string("204"), 204 },
- { ngx_string("444"), 444 },
- { ngx_null_string, 0 }
-};
-
-
-static void *ngx_http_degradation_create_main_conf(ngx_conf_t *cf);
-static void *ngx_http_degradation_create_loc_conf(ngx_conf_t *cf);
-static char *ngx_http_degradation_merge_loc_conf(ngx_conf_t *cf, void *parent,
- void *child);
-static char *ngx_http_degradation(ngx_conf_t *cf, ngx_command_t *cmd,
- void *conf);
-static ngx_int_t ngx_http_degradation_init(ngx_conf_t *cf);
-
-
-static ngx_command_t ngx_http_degradation_commands[] = {
-
- { ngx_string("degradation"),
- NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1,
- ngx_http_degradation,
- NGX_HTTP_MAIN_CONF_OFFSET,
- 0,
- NULL },
-
- { ngx_string("degrade"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_enum_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_degradation_loc_conf_t, degrade),
- &ngx_http_degrade },
-
- ngx_null_command
-};
-
-
-static ngx_http_module_t ngx_http_degradation_module_ctx = {
- NULL, /* preconfiguration */
- ngx_http_degradation_init, /* postconfiguration */
-
- ngx_http_degradation_create_main_conf, /* create main configuration */
- NULL, /* init main configuration */
-
- NULL, /* create server configuration */
- NULL, /* merge server configuration */
-
- ngx_http_degradation_create_loc_conf, /* create location configuration */
- ngx_http_degradation_merge_loc_conf /* merge location configuration */
-};
-
-
-ngx_module_t ngx_http_degradation_module = {
- NGX_MODULE_V1,
- &ngx_http_degradation_module_ctx, /* module context */
- ngx_http_degradation_commands, /* module directives */
- NGX_HTTP_MODULE, /* module type */
- NULL, /* init master */
- NULL, /* init module */
- NULL, /* init process */
- NULL, /* init thread */
- NULL, /* exit thread */
- NULL, /* exit process */
- NULL, /* exit master */
- NGX_MODULE_V1_PADDING
-};
-
-
-static ngx_int_t
-ngx_http_degradation_handler(ngx_http_request_t *r)
-{
- ngx_http_degradation_loc_conf_t *dlcf;
-
- dlcf = ngx_http_get_module_loc_conf(r, ngx_http_degradation_module);
-
- if (dlcf->degrade && ngx_http_degraded(r)) {
- return dlcf->degrade;
- }
-
- return NGX_DECLINED;
-}
-
-
-ngx_uint_t
-ngx_http_degraded(ngx_http_request_t *r)
-{
- time_t now;
- ngx_uint_t log;
- static size_t sbrk_size;
- static time_t sbrk_time;
- ngx_http_degradation_main_conf_t *dmcf;
-
- dmcf = ngx_http_get_module_main_conf(r, ngx_http_degradation_module);
-
- if (dmcf->sbrk_size) {
-
- log = 0;
- now = ngx_time();
-
- /* lock mutex */
-
- if (now != sbrk_time) {
-
- /*
- * ELF/i386 is loaded at 0x08000000, 128M
- * ELF/amd64 is loaded at 0x00400000, 4M
- *
- * use a function address to subtract the loading address
- */
-
- sbrk_size = (size_t) sbrk(0) - ((uintptr_t) ngx_palloc & ~0x3FFFFF);
- sbrk_time = now;
- log = 1;
- }
-
- /* unlock mutex */
-
- if (sbrk_size >= dmcf->sbrk_size) {
- if (log) {
- ngx_log_error(NGX_LOG_NOTICE, r->connection->log, 0,
- "degradation sbrk:%uzM",
- sbrk_size / (1024 * 1024));
- }
-
- return 1;
- }
- }
-
- return 0;
-}
-
-
-static void *
-ngx_http_degradation_create_main_conf(ngx_conf_t *cf)
-{
- ngx_http_degradation_main_conf_t *dmcf;
-
- dmcf = ngx_pcalloc(cf->pool, sizeof(ngx_http_degradation_main_conf_t));
- if (dmcf == NULL) {
- return NULL;
- }
-
- return dmcf;
-}
-
-
-static void *
-ngx_http_degradation_create_loc_conf(ngx_conf_t *cf)
-{
- ngx_http_degradation_loc_conf_t *conf;
-
- conf = ngx_palloc(cf->pool, sizeof(ngx_http_degradation_loc_conf_t));
- if (conf == NULL) {
- return NULL;
- }
-
- conf->degrade = NGX_CONF_UNSET_UINT;
-
- return conf;
-}
-
-
-static char *
-ngx_http_degradation_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
-{
- ngx_http_degradation_loc_conf_t *prev = parent;
- ngx_http_degradation_loc_conf_t *conf = child;
-
- ngx_conf_merge_uint_value(conf->degrade, prev->degrade, 0);
-
- return NGX_CONF_OK;
-}
-
-
-static char *
-ngx_http_degradation(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
-{
- ngx_http_degradation_main_conf_t *dmcf = conf;
-
- ngx_str_t *value, s;
-
- value = cf->args->elts;
-
- if (ngx_strncmp(value[1].data, "sbrk=", 5) == 0) {
-
- s.len = value[1].len - 5;
- s.data = value[1].data + 5;
-
- dmcf->sbrk_size = ngx_parse_size(&s);
- if (dmcf->sbrk_size == (size_t) NGX_ERROR) {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "invalid sbrk size \"%V\"", &value[1]);
- return NGX_CONF_ERROR;
- }
-
- return NGX_CONF_OK;
- }
-
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "invalid parameter \"%V\"", &value[1]);
-
- return NGX_CONF_ERROR;
-}
-
-
-static ngx_int_t
-ngx_http_degradation_init(ngx_conf_t *cf)
-{
- ngx_http_handler_pt *h;
- ngx_http_core_main_conf_t *cmcf;
-
- cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);
-
- h = ngx_array_push(&cmcf->phases[NGX_HTTP_PREACCESS_PHASE].handlers);
- if (h == NULL) {
- return NGX_ERROR;
- }
-
- *h = ngx_http_degradation_handler;
-
- return NGX_OK;
-}
diff --git a/nginx/src/http/modules/ngx_http_empty_gif_module.c b/nginx/src/http/modules/ngx_http_empty_gif_module.c
deleted file mode 100644
index 04114dc..0000000
--- a/nginx/src/http/modules/ngx_http_empty_gif_module.c
+++ /dev/null
@@ -1,140 +0,0 @@
-
-/*
- * Copyright (C) Igor Sysoev
- * Copyright (C) Nginx, Inc.
- */
-
-#include <ngx_config.h>
-#include <ngx_core.h>
-#include <ngx_http.h>
-
-
-static char *ngx_http_empty_gif(ngx_conf_t *cf, ngx_command_t *cmd,
- void *conf);
-
-static ngx_command_t ngx_http_empty_gif_commands[] = {
-
- { ngx_string("empty_gif"),
- NGX_HTTP_LOC_CONF|NGX_CONF_NOARGS,
- ngx_http_empty_gif,
- 0,
- 0,
- NULL },
-
- ngx_null_command
-};
-
-
-/* the minimal single pixel transparent GIF, 43 bytes */
-
-static u_char ngx_empty_gif[] = {
-
- 'G', 'I', 'F', '8', '9', 'a', /* header */
-
- /* logical screen descriptor */
- 0x01, 0x00, /* logical screen width */
- 0x01, 0x00, /* logical screen height */
- 0x80, /* global 1-bit color table */
- 0x01, /* background color #1 */
- 0x00, /* no aspect ratio */
-
- /* global color table */
- 0x00, 0x00, 0x00, /* #0: black */
- 0xff, 0xff, 0xff, /* #1: white */
-
- /* graphic control extension */
- 0x21, /* extension introducer */
- 0xf9, /* graphic control label */
- 0x04, /* block size */
- 0x01, /* transparent color is given, */
- /* no disposal specified, */
- /* user input is not expected */
- 0x00, 0x00, /* delay time */
- 0x01, /* transparent color #1 */
- 0x00, /* block terminator */
-
- /* image descriptor */
- 0x2c, /* image separator */
- 0x00, 0x00, /* image left position */
- 0x00, 0x00, /* image top position */
- 0x01, 0x00, /* image width */
- 0x01, 0x00, /* image height */
- 0x00, /* no local color table, no interlaced */
-
- /* table based image data */
- 0x02, /* LZW minimum code size, */
- /* must be at least 2-bit */
- 0x02, /* block size */
- 0x4c, 0x01, /* compressed bytes 01_001_100, 0000000_1 */
- /* 100: clear code */
- /* 001: 1 */
- /* 101: end of information code */
- 0x00, /* block terminator */
-
- 0x3B /* trailer */
-};
-
-
-static ngx_http_module_t ngx_http_empty_gif_module_ctx = {
- NULL, /* preconfiguration */
- NULL, /* postconfiguration */
-
- NULL, /* create main configuration */
- NULL, /* init main configuration */
-
- NULL, /* create server configuration */
- NULL, /* merge server configuration */
-
- NULL, /* create location configuration */
- NULL /* merge location configuration */
-};
-
-
-ngx_module_t ngx_http_empty_gif_module = {
- NGX_MODULE_V1,
- &ngx_http_empty_gif_module_ctx, /* module context */
- ngx_http_empty_gif_commands, /* module directives */
- NGX_HTTP_MODULE, /* module type */
- NULL, /* init master */
- NULL, /* init module */
- NULL, /* init process */
- NULL, /* init thread */
- NULL, /* exit thread */
- NULL, /* exit process */
- NULL, /* exit master */
- NGX_MODULE_V1_PADDING
-};
-
-
-static ngx_str_t ngx_http_gif_type = ngx_string("image/gif");
-
-
-static ngx_int_t
-ngx_http_empty_gif_handler(ngx_http_request_t *r)
-{
- ngx_http_complex_value_t cv;
-
- if (!(r->method & (NGX_HTTP_GET|NGX_HTTP_HEAD))) {
- return NGX_HTTP_NOT_ALLOWED;
- }
-
- ngx_memzero(&cv, sizeof(ngx_http_complex_value_t));
-
- cv.value.len = sizeof(ngx_empty_gif);
- cv.value.data = ngx_empty_gif;
- r->headers_out.last_modified_time = 23349600;
-
- return ngx_http_send_response(r, NGX_HTTP_OK, &ngx_http_gif_type, &cv);
-}
-
-
-static char *
-ngx_http_empty_gif(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
-{
- ngx_http_core_loc_conf_t *clcf;
-
- clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);
- clcf->handler = ngx_http_empty_gif_handler;
-
- return NGX_CONF_OK;
-}
diff --git a/nginx/src/http/modules/ngx_http_fastcgi_module.c b/nginx/src/http/modules/ngx_http_fastcgi_module.c
deleted file mode 100644
index 3eec1b7..0000000
--- a/nginx/src/http/modules/ngx_http_fastcgi_module.c
+++ /dev/null
@@ -1,3762 +0,0 @@
-
-/*
- * Copyright (C) Igor Sysoev
- * Copyright (C) Nginx, Inc.
- */
-
-
-#include <ngx_config.h>
-#include <ngx_core.h>
-#include <ngx_http.h>
-
-
-typedef struct {
- ngx_array_t caches; /* ngx_http_file_cache_t * */
-} ngx_http_fastcgi_main_conf_t;
-
-
-typedef struct {
- ngx_array_t *flushes;
- ngx_array_t *lengths;
- ngx_array_t *values;
- ngx_uint_t number;
- ngx_hash_t hash;
-} ngx_http_fastcgi_params_t;
-
-
-typedef struct {
- ngx_http_upstream_conf_t upstream;
-
- ngx_str_t index;
-
- ngx_http_fastcgi_params_t params;
-#if (NGX_HTTP_CACHE)
- ngx_http_fastcgi_params_t params_cache;
-#endif
-
- ngx_array_t *params_source;
- ngx_array_t *catch_stderr;
-
- ngx_array_t *fastcgi_lengths;
- ngx_array_t *fastcgi_values;
-
- ngx_flag_t keep_conn;
-
-#if (NGX_HTTP_CACHE)
- ngx_http_complex_value_t cache_key;
-#endif
-
-#if (NGX_PCRE)
- ngx_regex_t *split_regex;
- ngx_str_t split_name;
-#endif
-} ngx_http_fastcgi_loc_conf_t;
-
-
-typedef enum {
- ngx_http_fastcgi_st_version = 0,
- ngx_http_fastcgi_st_type,
- ngx_http_fastcgi_st_request_id_hi,
- ngx_http_fastcgi_st_request_id_lo,
- ngx_http_fastcgi_st_content_length_hi,
- ngx_http_fastcgi_st_content_length_lo,
- ngx_http_fastcgi_st_padding_length,
- ngx_http_fastcgi_st_reserved,
- ngx_http_fastcgi_st_data,
- ngx_http_fastcgi_st_padding
-} ngx_http_fastcgi_state_e;
-
-
-typedef struct {
- u_char *start;
- u_char *end;
-} ngx_http_fastcgi_split_part_t;
-
-
-typedef struct {
- ngx_http_fastcgi_state_e state;
- u_char *pos;
- u_char *last;
- ngx_uint_t type;
- size_t length;
- size_t padding;
-
- ngx_chain_t *free;
- ngx_chain_t *busy;
-
- unsigned fastcgi_stdout:1;
- unsigned large_stderr:1;
- unsigned header_sent:1;
-
- ngx_array_t *split_parts;
-
- ngx_str_t script_name;
- ngx_str_t path_info;
-} ngx_http_fastcgi_ctx_t;
-
-
-#define NGX_HTTP_FASTCGI_RESPONDER 1
-
-#define NGX_HTTP_FASTCGI_KEEP_CONN 1
-
-#define NGX_HTTP_FASTCGI_BEGIN_REQUEST 1
-#define NGX_HTTP_FASTCGI_ABORT_REQUEST 2
-#define NGX_HTTP_FASTCGI_END_REQUEST 3
-#define NGX_HTTP_FASTCGI_PARAMS 4
-#define NGX_HTTP_FASTCGI_STDIN 5
-#define NGX_HTTP_FASTCGI_STDOUT 6
-#define NGX_HTTP_FASTCGI_STDERR 7
-#define NGX_HTTP_FASTCGI_DATA 8
-
-
-typedef struct {
- u_char version;
- u_char type;
- u_char request_id_hi;
- u_char request_id_lo;
- u_char content_length_hi;
- u_char content_length_lo;
- u_char padding_length;
- u_char reserved;
-} ngx_http_fastcgi_header_t;
-
-
-typedef struct {
- u_char role_hi;
- u_char role_lo;
- u_char flags;
- u_char reserved[5];
-} ngx_http_fastcgi_begin_request_t;
-
-
-typedef struct {
- u_char version;
- u_char type;
- u_char request_id_hi;
- u_char request_id_lo;
-} ngx_http_fastcgi_header_small_t;
-
-
-typedef struct {
- ngx_http_fastcgi_header_t h0;
- ngx_http_fastcgi_begin_request_t br;
- ngx_http_fastcgi_header_small_t h1;
-} ngx_http_fastcgi_request_start_t;
-
-
-static ngx_int_t ngx_http_fastcgi_eval(ngx_http_request_t *r,
- ngx_http_fastcgi_loc_conf_t *flcf);
-#if (NGX_HTTP_CACHE)
-static ngx_int_t ngx_http_fastcgi_create_key(ngx_http_request_t *r);
-#endif
-static ngx_int_t ngx_http_fastcgi_create_request(ngx_http_request_t *r);
-static ngx_int_t ngx_http_fastcgi_reinit_request(ngx_http_request_t *r);
-static ngx_int_t ngx_http_fastcgi_body_output_filter(void *data,
- ngx_chain_t *in);
-static ngx_int_t ngx_http_fastcgi_process_header(ngx_http_request_t *r);
-static ngx_int_t ngx_http_fastcgi_input_filter_init(void *data);
-static ngx_int_t ngx_http_fastcgi_input_filter(ngx_event_pipe_t *p,
- ngx_buf_t *buf);
-static ngx_int_t ngx_http_fastcgi_non_buffered_filter(void *data,
- ssize_t bytes);
-static ngx_int_t ngx_http_fastcgi_process_record(ngx_http_request_t *r,
- ngx_http_fastcgi_ctx_t *f);
-static void ngx_http_fastcgi_abort_request(ngx_http_request_t *r);
-static void ngx_http_fastcgi_finalize_request(ngx_http_request_t *r,
- ngx_int_t rc);
-
-static ngx_int_t ngx_http_fastcgi_add_variables(ngx_conf_t *cf);
-static void *ngx_http_fastcgi_create_main_conf(ngx_conf_t *cf);
-static void *ngx_http_fastcgi_create_loc_conf(ngx_conf_t *cf);
-static char *ngx_http_fastcgi_merge_loc_conf(ngx_conf_t *cf,
- void *parent, void *child);
-static ngx_int_t ngx_http_fastcgi_init_params(ngx_conf_t *cf,
- ngx_http_fastcgi_loc_conf_t *conf, ngx_http_fastcgi_params_t *params,
- ngx_keyval_t *default_params);
-
-static ngx_int_t ngx_http_fastcgi_script_name_variable(ngx_http_request_t *r,
- ngx_http_variable_value_t *v, uintptr_t data);
-static ngx_int_t ngx_http_fastcgi_path_info_variable(ngx_http_request_t *r,
- ngx_http_variable_value_t *v, uintptr_t data);
-static ngx_http_fastcgi_ctx_t *ngx_http_fastcgi_split(ngx_http_request_t *r,
- ngx_http_fastcgi_loc_conf_t *flcf);
-
-static char *ngx_http_fastcgi_pass(ngx_conf_t *cf, ngx_command_t *cmd,
- void *conf);
-static char *ngx_http_fastcgi_split_path_info(ngx_conf_t *cf,
- ngx_command_t *cmd, void *conf);
-static char *ngx_http_fastcgi_store(ngx_conf_t *cf, ngx_command_t *cmd,
- void *conf);
-#if (NGX_HTTP_CACHE)
-static char *ngx_http_fastcgi_cache(ngx_conf_t *cf, ngx_command_t *cmd,
- void *conf);
-static char *ngx_http_fastcgi_cache_key(ngx_conf_t *cf, ngx_command_t *cmd,
- void *conf);
-#endif
-
-static char *ngx_http_fastcgi_lowat_check(ngx_conf_t *cf, void *post,
- void *data);
-
-
-static ngx_conf_post_t ngx_http_fastcgi_lowat_post =
- { ngx_http_fastcgi_lowat_check };
-
-
-static ngx_conf_bitmask_t ngx_http_fastcgi_next_upstream_masks[] = {
- { ngx_string("error"), NGX_HTTP_UPSTREAM_FT_ERROR },
- { ngx_string("timeout"), NGX_HTTP_UPSTREAM_FT_TIMEOUT },
- { ngx_string("invalid_header"), NGX_HTTP_UPSTREAM_FT_INVALID_HEADER },
- { ngx_string("non_idempotent"), NGX_HTTP_UPSTREAM_FT_NON_IDEMPOTENT },
- { ngx_string("http_500"), NGX_HTTP_UPSTREAM_FT_HTTP_500 },
- { ngx_string("http_503"), NGX_HTTP_UPSTREAM_FT_HTTP_503 },
- { ngx_string("http_403"), NGX_HTTP_UPSTREAM_FT_HTTP_403 },
- { ngx_string("http_404"), NGX_HTTP_UPSTREAM_FT_HTTP_404 },
- { ngx_string("http_429"), NGX_HTTP_UPSTREAM_FT_HTTP_429 },
- { ngx_string("updating"), NGX_HTTP_UPSTREAM_FT_UPDATING },
- { ngx_string("off"), NGX_HTTP_UPSTREAM_FT_OFF },
- { ngx_null_string, 0 }
-};
-
-
-ngx_module_t ngx_http_fastcgi_module;
-
-
-static ngx_command_t ngx_http_fastcgi_commands[] = {
-
- { ngx_string("fastcgi_pass"),
- NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_TAKE1,
- ngx_http_fastcgi_pass,
- NGX_HTTP_LOC_CONF_OFFSET,
- 0,
- NULL },
-
- { ngx_string("fastcgi_index"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_str_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_fastcgi_loc_conf_t, index),
- NULL },
-
- { ngx_string("fastcgi_split_path_info"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_http_fastcgi_split_path_info,
- NGX_HTTP_LOC_CONF_OFFSET,
- 0,
- NULL },
-
- { ngx_string("fastcgi_store"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_http_fastcgi_store,
- NGX_HTTP_LOC_CONF_OFFSET,
- 0,
- NULL },
-
- { ngx_string("fastcgi_store_access"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE123,
- ngx_conf_set_access_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_fastcgi_loc_conf_t, upstream.store_access),
- NULL },
-
- { ngx_string("fastcgi_buffering"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
- ngx_conf_set_flag_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_fastcgi_loc_conf_t, upstream.buffering),
- NULL },
-
- { ngx_string("fastcgi_request_buffering"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
- ngx_conf_set_flag_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_fastcgi_loc_conf_t, upstream.request_buffering),
- NULL },
-
- { ngx_string("fastcgi_ignore_client_abort"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
- ngx_conf_set_flag_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_fastcgi_loc_conf_t, upstream.ignore_client_abort),
- NULL },
-
- { ngx_string("fastcgi_bind"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE12,
- ngx_http_upstream_bind_set_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_fastcgi_loc_conf_t, upstream.local),
- NULL },
-
- { ngx_string("fastcgi_connect_timeout"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_msec_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_fastcgi_loc_conf_t, upstream.connect_timeout),
- NULL },
-
- { ngx_string("fastcgi_send_timeout"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_msec_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_fastcgi_loc_conf_t, upstream.send_timeout),
- NULL },
-
- { ngx_string("fastcgi_send_lowat"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_size_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_fastcgi_loc_conf_t, upstream.send_lowat),
- &ngx_http_fastcgi_lowat_post },
-
- { ngx_string("fastcgi_buffer_size"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_size_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_fastcgi_loc_conf_t, upstream.buffer_size),
- NULL },
-
- { ngx_string("fastcgi_pass_request_headers"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
- ngx_conf_set_flag_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_fastcgi_loc_conf_t, upstream.pass_request_headers),
- NULL },
-
- { ngx_string("fastcgi_pass_request_body"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
- ngx_conf_set_flag_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_fastcgi_loc_conf_t, upstream.pass_request_body),
- NULL },
-
- { ngx_string("fastcgi_intercept_errors"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
- ngx_conf_set_flag_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_fastcgi_loc_conf_t, upstream.intercept_errors),
- NULL },
-
- { ngx_string("fastcgi_read_timeout"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_msec_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_fastcgi_loc_conf_t, upstream.read_timeout),
- NULL },
-
- { ngx_string("fastcgi_buffers"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE2,
- ngx_conf_set_bufs_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_fastcgi_loc_conf_t, upstream.bufs),
- NULL },
-
- { ngx_string("fastcgi_busy_buffers_size"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_size_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_fastcgi_loc_conf_t, upstream.busy_buffers_size_conf),
- NULL },
-
- { ngx_string("fastcgi_force_ranges"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
- ngx_conf_set_flag_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_fastcgi_loc_conf_t, upstream.force_ranges),
- NULL },
-
- { ngx_string("fastcgi_limit_rate"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_size_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_fastcgi_loc_conf_t, upstream.limit_rate),
- NULL },
-
-#if (NGX_HTTP_CACHE)
-
- { ngx_string("fastcgi_cache"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_http_fastcgi_cache,
- NGX_HTTP_LOC_CONF_OFFSET,
- 0,
- NULL },
-
- { ngx_string("fastcgi_cache_key"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_http_fastcgi_cache_key,
- NGX_HTTP_LOC_CONF_OFFSET,
- 0,
- NULL },
-
- { ngx_string("fastcgi_cache_path"),
- NGX_HTTP_MAIN_CONF|NGX_CONF_2MORE,
- ngx_http_file_cache_set_slot,
- NGX_HTTP_MAIN_CONF_OFFSET,
- offsetof(ngx_http_fastcgi_main_conf_t, caches),
- &ngx_http_fastcgi_module },
-
- { ngx_string("fastcgi_cache_bypass"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
- ngx_http_set_predicate_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_fastcgi_loc_conf_t, upstream.cache_bypass),
- NULL },
-
- { ngx_string("fastcgi_no_cache"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
- ngx_http_set_predicate_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_fastcgi_loc_conf_t, upstream.no_cache),
- NULL },
-
- { ngx_string("fastcgi_cache_valid"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
- ngx_http_file_cache_valid_set_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_fastcgi_loc_conf_t, upstream.cache_valid),
- NULL },
-
- { ngx_string("fastcgi_cache_min_uses"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_num_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_fastcgi_loc_conf_t, upstream.cache_min_uses),
- NULL },
-
- { ngx_string("fastcgi_cache_max_range_offset"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_off_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_fastcgi_loc_conf_t, upstream.cache_max_range_offset),
- NULL },
-
- { ngx_string("fastcgi_cache_use_stale"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
- ngx_conf_set_bitmask_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_fastcgi_loc_conf_t, upstream.cache_use_stale),
- &ngx_http_fastcgi_next_upstream_masks },
-
- { ngx_string("fastcgi_cache_methods"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
- ngx_conf_set_bitmask_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_fastcgi_loc_conf_t, upstream.cache_methods),
- &ngx_http_upstream_cache_method_mask },
-
- { ngx_string("fastcgi_cache_lock"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
- ngx_conf_set_flag_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_fastcgi_loc_conf_t, upstream.cache_lock),
- NULL },
-
- { ngx_string("fastcgi_cache_lock_timeout"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_msec_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_fastcgi_loc_conf_t, upstream.cache_lock_timeout),
- NULL },
-
- { ngx_string("fastcgi_cache_lock_age"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_msec_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_fastcgi_loc_conf_t, upstream.cache_lock_age),
- NULL },
-
- { ngx_string("fastcgi_cache_revalidate"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
- ngx_conf_set_flag_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_fastcgi_loc_conf_t, upstream.cache_revalidate),
- NULL },
-
- { ngx_string("fastcgi_cache_background_update"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
- ngx_conf_set_flag_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_fastcgi_loc_conf_t, upstream.cache_background_update),
- NULL },
-
-#endif
-
- { ngx_string("fastcgi_temp_path"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1234,
- ngx_conf_set_path_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_fastcgi_loc_conf_t, upstream.temp_path),
- NULL },
-
- { ngx_string("fastcgi_max_temp_file_size"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_size_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_fastcgi_loc_conf_t, upstream.max_temp_file_size_conf),
- NULL },
-
- { ngx_string("fastcgi_temp_file_write_size"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_size_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_fastcgi_loc_conf_t, upstream.temp_file_write_size_conf),
- NULL },
-
- { ngx_string("fastcgi_next_upstream"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
- ngx_conf_set_bitmask_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_fastcgi_loc_conf_t, upstream.next_upstream),
- &ngx_http_fastcgi_next_upstream_masks },
-
- { ngx_string("fastcgi_next_upstream_tries"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_num_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_fastcgi_loc_conf_t, upstream.next_upstream_tries),
- NULL },
-
- { ngx_string("fastcgi_next_upstream_timeout"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_msec_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_fastcgi_loc_conf_t, upstream.next_upstream_timeout),
- NULL },
-
- { ngx_string("fastcgi_param"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE23,
- ngx_http_upstream_param_set_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_fastcgi_loc_conf_t, params_source),
- NULL },
-
- { ngx_string("fastcgi_pass_header"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_str_array_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_fastcgi_loc_conf_t, upstream.pass_headers),
- NULL },
-
- { ngx_string("fastcgi_hide_header"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_str_array_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_fastcgi_loc_conf_t, upstream.hide_headers),
- NULL },
-
- { ngx_string("fastcgi_ignore_headers"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
- ngx_conf_set_bitmask_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_fastcgi_loc_conf_t, upstream.ignore_headers),
- &ngx_http_upstream_ignore_headers_masks },
-
- { ngx_string("fastcgi_catch_stderr"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_str_array_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_fastcgi_loc_conf_t, catch_stderr),
- NULL },
-
- { ngx_string("fastcgi_keep_conn"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
- ngx_conf_set_flag_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_fastcgi_loc_conf_t, keep_conn),
- NULL },
-
- ngx_null_command
-};
-
-
-static ngx_http_module_t ngx_http_fastcgi_module_ctx = {
- ngx_http_fastcgi_add_variables, /* preconfiguration */
- NULL, /* postconfiguration */
-
- ngx_http_fastcgi_create_main_conf, /* create main configuration */
- NULL, /* init main configuration */
-
- NULL, /* create server configuration */
- NULL, /* merge server configuration */
-
- ngx_http_fastcgi_create_loc_conf, /* create location configuration */
- ngx_http_fastcgi_merge_loc_conf /* merge location configuration */
-};
-
-
-ngx_module_t ngx_http_fastcgi_module = {
- NGX_MODULE_V1,
- &ngx_http_fastcgi_module_ctx, /* module context */
- ngx_http_fastcgi_commands, /* module directives */
- NGX_HTTP_MODULE, /* module type */
- NULL, /* init master */
- NULL, /* init module */
- NULL, /* init process */
- NULL, /* init thread */
- NULL, /* exit thread */
- NULL, /* exit process */
- NULL, /* exit master */
- NGX_MODULE_V1_PADDING
-};
-
-
-static ngx_http_fastcgi_request_start_t ngx_http_fastcgi_request_start = {
- { 1, /* version */
- NGX_HTTP_FASTCGI_BEGIN_REQUEST, /* type */
- 0, /* request_id_hi */
- 1, /* request_id_lo */
- 0, /* content_length_hi */
- sizeof(ngx_http_fastcgi_begin_request_t), /* content_length_lo */
- 0, /* padding_length */
- 0 }, /* reserved */
-
- { 0, /* role_hi */
- NGX_HTTP_FASTCGI_RESPONDER, /* role_lo */
- 0, /* NGX_HTTP_FASTCGI_KEEP_CONN */ /* flags */
- { 0, 0, 0, 0, 0 } }, /* reserved[5] */
-
- { 1, /* version */
- NGX_HTTP_FASTCGI_PARAMS, /* type */
- 0, /* request_id_hi */
- 1 }, /* request_id_lo */
-
-};
-
-
-static ngx_http_variable_t ngx_http_fastcgi_vars[] = {
-
- { ngx_string("fastcgi_script_name"), NULL,
- ngx_http_fastcgi_script_name_variable, 0,
- NGX_HTTP_VAR_NOCACHEABLE|NGX_HTTP_VAR_NOHASH, 0 },
-
- { ngx_string("fastcgi_path_info"), NULL,
- ngx_http_fastcgi_path_info_variable, 0,
- NGX_HTTP_VAR_NOCACHEABLE|NGX_HTTP_VAR_NOHASH, 0 },
-
- ngx_http_null_variable
-};
-
-
-static ngx_str_t ngx_http_fastcgi_hide_headers[] = {
- ngx_string("Status"),
- ngx_string("X-Accel-Expires"),
- ngx_string("X-Accel-Redirect"),
- ngx_string("X-Accel-Limit-Rate"),
- ngx_string("X-Accel-Buffering"),
- ngx_string("X-Accel-Charset"),
- ngx_null_string
-};
-
-
-#if (NGX_HTTP_CACHE)
-
-static ngx_keyval_t ngx_http_fastcgi_cache_headers[] = {
- { ngx_string("HTTP_IF_MODIFIED_SINCE"),
- ngx_string("$upstream_cache_last_modified") },
- { ngx_string("HTTP_IF_UNMODIFIED_SINCE"), ngx_string("") },
- { ngx_string("HTTP_IF_NONE_MATCH"), ngx_string("$upstream_cache_etag") },
- { ngx_string("HTTP_IF_MATCH"), ngx_string("") },
- { ngx_string("HTTP_RANGE"), ngx_string("") },
- { ngx_string("HTTP_IF_RANGE"), ngx_string("") },
- { ngx_null_string, ngx_null_string }
-};
-
-#endif
-
-
-static ngx_path_init_t ngx_http_fastcgi_temp_path = {
- ngx_string(NGX_HTTP_FASTCGI_TEMP_PATH), { 1, 2, 0 }
-};
-
-
-static ngx_int_t
-ngx_http_fastcgi_handler(ngx_http_request_t *r)
-{
- ngx_int_t rc;
- ngx_http_upstream_t *u;
- ngx_http_fastcgi_ctx_t *f;
- ngx_http_fastcgi_loc_conf_t *flcf;
-#if (NGX_HTTP_CACHE)
- ngx_http_fastcgi_main_conf_t *fmcf;
-#endif
-
- if (ngx_http_upstream_create(r) != NGX_OK) {
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
-
- f = ngx_pcalloc(r->pool, sizeof(ngx_http_fastcgi_ctx_t));
- if (f == NULL) {
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
-
- ngx_http_set_ctx(r, f, ngx_http_fastcgi_module);
-
- flcf = ngx_http_get_module_loc_conf(r, ngx_http_fastcgi_module);
-
- if (flcf->fastcgi_lengths) {
- if (ngx_http_fastcgi_eval(r, flcf) != NGX_OK) {
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
- }
-
- u = r->upstream;
-
- ngx_str_set(&u->schema, "fastcgi://");
- u->output.tag = (ngx_buf_tag_t) &ngx_http_fastcgi_module;
-
- u->conf = &flcf->upstream;
-
-#if (NGX_HTTP_CACHE)
- fmcf = ngx_http_get_module_main_conf(r, ngx_http_fastcgi_module);
-
- u->caches = &fmcf->caches;
- u->create_key = ngx_http_fastcgi_create_key;
-#endif
-
- u->create_request = ngx_http_fastcgi_create_request;
- u->reinit_request = ngx_http_fastcgi_reinit_request;
- u->process_header = ngx_http_fastcgi_process_header;
- u->abort_request = ngx_http_fastcgi_abort_request;
- u->finalize_request = ngx_http_fastcgi_finalize_request;
- r->state = 0;
-
- u->buffering = flcf->upstream.buffering;
-
- u->pipe = ngx_pcalloc(r->pool, sizeof(ngx_event_pipe_t));
- if (u->pipe == NULL) {
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
-
- u->pipe->input_filter = ngx_http_fastcgi_input_filter;
- u->pipe->input_ctx = r;
-
- u->input_filter_init = ngx_http_fastcgi_input_filter_init;
- u->input_filter = ngx_http_fastcgi_non_buffered_filter;
- u->input_filter_ctx = r;
-
- if (!flcf->upstream.request_buffering
- && flcf->upstream.pass_request_body)
- {
- r->request_body_no_buffering = 1;
- }
-
- rc = ngx_http_read_client_request_body(r, ngx_http_upstream_init);
-
- if (rc >= NGX_HTTP_SPECIAL_RESPONSE) {
- return rc;
- }
-
- return NGX_DONE;
-}
-
-
-static ngx_int_t
-ngx_http_fastcgi_eval(ngx_http_request_t *r, ngx_http_fastcgi_loc_conf_t *flcf)
-{
- ngx_url_t url;
- ngx_http_upstream_t *u;
-
- ngx_memzero(&url, sizeof(ngx_url_t));
-
- if (ngx_http_script_run(r, &url.url, flcf->fastcgi_lengths->elts, 0,
- flcf->fastcgi_values->elts)
- == NULL)
- {
- return NGX_ERROR;
- }
-
- url.no_resolve = 1;
-
- if (ngx_parse_url(r->pool, &url) != NGX_OK) {
- if (url.err) {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "%s in upstream \"%V\"", url.err, &url.url);
- }
-
- return NGX_ERROR;
- }
-
- u = r->upstream;
-
- u->resolved = ngx_pcalloc(r->pool, sizeof(ngx_http_upstream_resolved_t));
- if (u->resolved == NULL) {
- return NGX_ERROR;
- }
-
- if (url.addrs) {
- u->resolved->sockaddr = url.addrs[0].sockaddr;
- u->resolved->socklen = url.addrs[0].socklen;
- u->resolved->name = url.addrs[0].name;
- u->resolved->naddrs = 1;
- }
-
- u->resolved->host = url.host;
- u->resolved->port = url.port;
- u->resolved->no_port = url.no_port;
-
- return NGX_OK;
-}
-
-
-#if (NGX_HTTP_CACHE)
-
-static ngx_int_t
-ngx_http_fastcgi_create_key(ngx_http_request_t *r)
-{
- ngx_str_t *key;
- ngx_http_fastcgi_loc_conf_t *flcf;
-
- key = ngx_array_push(&r->cache->keys);
- if (key == NULL) {
- return NGX_ERROR;
- }
-
- flcf = ngx_http_get_module_loc_conf(r, ngx_http_fastcgi_module);
-
- if (ngx_http_complex_value(r, &flcf->cache_key, key) != NGX_OK) {
- return NGX_ERROR;
- }
-
- return NGX_OK;
-}
-
-#endif
-
-
-static ngx_int_t
-ngx_http_fastcgi_create_request(ngx_http_request_t *r)
-{
- off_t file_pos;
- u_char ch, *pos, *lowcase_key;
- size_t size, len, key_len, val_len, padding,
- allocated;
- ngx_uint_t i, n, next, hash, skip_empty, header_params;
- ngx_buf_t *b;
- ngx_chain_t *cl, *body;
- ngx_list_part_t *part;
- ngx_table_elt_t *header, **ignored;
- ngx_http_upstream_t *u;
- ngx_http_script_code_pt code;
- ngx_http_script_engine_t e, le;
- ngx_http_fastcgi_header_t *h;
- ngx_http_fastcgi_params_t *params;
- ngx_http_fastcgi_loc_conf_t *flcf;
- ngx_http_script_len_code_pt lcode;
-
- len = 0;
- header_params = 0;
- ignored = NULL;
-
- u = r->upstream;
-
- flcf = ngx_http_get_module_loc_conf(r, ngx_http_fastcgi_module);
-
-#if (NGX_HTTP_CACHE)
- params = u->cacheable ? &flcf->params_cache : &flcf->params;
-#else
- params = &flcf->params;
-#endif
-
- if (params->lengths) {
- ngx_memzero(&le, sizeof(ngx_http_script_engine_t));
-
- ngx_http_script_flush_no_cacheable_variables(r, params->flushes);
- le.flushed = 1;
-
- le.ip = params->lengths->elts;
- le.request = r;
-
- while (*(uintptr_t *) le.ip) {
-
- lcode = *(ngx_http_script_len_code_pt *) le.ip;
- key_len = lcode(&le);
-
- lcode = *(ngx_http_script_len_code_pt *) le.ip;
- skip_empty = lcode(&le);
-
- for (val_len = 0; *(uintptr_t *) le.ip; val_len += lcode(&le)) {
- lcode = *(ngx_http_script_len_code_pt *) le.ip;
- }
- le.ip += sizeof(uintptr_t);
-
- if (skip_empty && val_len == 0) {
- continue;
- }
-
- len += 1 + key_len + ((val_len > 127) ? 4 : 1) + val_len;
- }
- }
-
- if (flcf->upstream.pass_request_headers) {
-
- allocated = 0;
- lowcase_key = NULL;
-
- if (params->number) {
- n = 0;
- part = &r->headers_in.headers.part;
-
- while (part) {
- n += part->nelts;
- part = part->next;
- }
-
- ignored = ngx_palloc(r->pool, n * sizeof(void *));
- if (ignored == NULL) {
- return NGX_ERROR;
- }
- }
-
- part = &r->headers_in.headers.part;
- header = part->elts;
-
- for (i = 0; /* void */; i++) {
-
- if (i >= part->nelts) {
- if (part->next == NULL) {
- break;
- }
-
- part = part->next;
- header = part->elts;
- i = 0;
- }
-
- if (params->number) {
- if (allocated < header[i].key.len) {
- allocated = header[i].key.len + 16;
- lowcase_key = ngx_pnalloc(r->pool, allocated);
- if (lowcase_key == NULL) {
- return NGX_ERROR;
- }
- }
-
- hash = 0;
-
- for (n = 0; n < header[i].key.len; n++) {
- ch = header[i].key.data[n];
-
- if (ch >= 'A' && ch <= 'Z') {
- ch |= 0x20;
-
- } else if (ch == '-') {
- ch = '_';
- }
-
- hash = ngx_hash(hash, ch);
- lowcase_key[n] = ch;
- }
-
- if (ngx_hash_find(&params->hash, hash, lowcase_key, n)) {
- ignored[header_params++] = &header[i];
- continue;
- }
-
- n += sizeof("HTTP_") - 1;
-
- } else {
- n = sizeof("HTTP_") - 1 + header[i].key.len;
- }
-
- len += ((n > 127) ? 4 : 1) + ((header[i].value.len > 127) ? 4 : 1)
- + n + header[i].value.len;
- }
- }
-
-
- if (len > 65535) {
- ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
- "fastcgi request record is too big: %uz", len);
- return NGX_ERROR;
- }
-
-
- padding = 8 - len % 8;
- padding = (padding == 8) ? 0 : padding;
-
-
- size = sizeof(ngx_http_fastcgi_header_t)
- + sizeof(ngx_http_fastcgi_begin_request_t)
-
- + sizeof(ngx_http_fastcgi_header_t) /* NGX_HTTP_FASTCGI_PARAMS */
- + len + padding
- + sizeof(ngx_http_fastcgi_header_t) /* NGX_HTTP_FASTCGI_PARAMS */
-
- + sizeof(ngx_http_fastcgi_header_t); /* NGX_HTTP_FASTCGI_STDIN */
-
-
- b = ngx_create_temp_buf(r->pool, size);
- if (b == NULL) {
- return NGX_ERROR;
- }
-
- cl = ngx_alloc_chain_link(r->pool);
- if (cl == NULL) {
- return NGX_ERROR;
- }
-
- cl->buf = b;
-
- ngx_http_fastcgi_request_start.br.flags =
- flcf->keep_conn ? NGX_HTTP_FASTCGI_KEEP_CONN : 0;
-
- ngx_memcpy(b->pos, &ngx_http_fastcgi_request_start,
- sizeof(ngx_http_fastcgi_request_start_t));
-
- h = (ngx_http_fastcgi_header_t *)
- (b->pos + sizeof(ngx_http_fastcgi_header_t)
- + sizeof(ngx_http_fastcgi_begin_request_t));
-
- h->content_length_hi = (u_char) ((len >> 8) & 0xff);
- h->content_length_lo = (u_char) (len & 0xff);
- h->padding_length = (u_char) padding;
- h->reserved = 0;
-
- b->last = b->pos + sizeof(ngx_http_fastcgi_header_t)
- + sizeof(ngx_http_fastcgi_begin_request_t)
- + sizeof(ngx_http_fastcgi_header_t);
-
-
- if (params->lengths) {
- ngx_memzero(&e, sizeof(ngx_http_script_engine_t));
-
- e.ip = params->values->elts;
- e.pos = b->last;
- e.request = r;
- e.flushed = 1;
-
- le.ip = params->lengths->elts;
-
- while (*(uintptr_t *) le.ip) {
-
- lcode = *(ngx_http_script_len_code_pt *) le.ip;
- key_len = (u_char) lcode(&le);
-
- lcode = *(ngx_http_script_len_code_pt *) le.ip;
- skip_empty = lcode(&le);
-
- for (val_len = 0; *(uintptr_t *) le.ip; val_len += lcode(&le)) {
- lcode = *(ngx_http_script_len_code_pt *) le.ip;
- }
- le.ip += sizeof(uintptr_t);
-
- if (skip_empty && val_len == 0) {
- e.skip = 1;
-
- while (*(uintptr_t *) e.ip) {
- code = *(ngx_http_script_code_pt *) e.ip;
- code((ngx_http_script_engine_t *) &e);
- }
- e.ip += sizeof(uintptr_t);
-
- e.skip = 0;
-
- continue;
- }
-
- *e.pos++ = (u_char) key_len;
-
- if (val_len > 127) {
- *e.pos++ = (u_char) (((val_len >> 24) & 0x7f) | 0x80);
- *e.pos++ = (u_char) ((val_len >> 16) & 0xff);
- *e.pos++ = (u_char) ((val_len >> 8) & 0xff);
- *e.pos++ = (u_char) (val_len & 0xff);
-
- } else {
- *e.pos++ = (u_char) val_len;
- }
-
- while (*(uintptr_t *) e.ip) {
- code = *(ngx_http_script_code_pt *) e.ip;
- code((ngx_http_script_engine_t *) &e);
- }
- e.ip += sizeof(uintptr_t);
-
- ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "fastcgi param: \"%*s: %*s\"",
- key_len, e.pos - (key_len + val_len),
- val_len, e.pos - val_len);
- }
-
- b->last = e.pos;
- }
-
-
- if (flcf->upstream.pass_request_headers) {
-
- part = &r->headers_in.headers.part;
- header = part->elts;
-
- for (i = 0; /* void */; i++) {
-
- if (i >= part->nelts) {
- if (part->next == NULL) {
- break;
- }
-
- part = part->next;
- header = part->elts;
- i = 0;
- }
-
- for (n = 0; n < header_params; n++) {
- if (&header[i] == ignored[n]) {
- goto next;
- }
- }
-
- key_len = sizeof("HTTP_") - 1 + header[i].key.len;
- if (key_len > 127) {
- *b->last++ = (u_char) (((key_len >> 24) & 0x7f) | 0x80);
- *b->last++ = (u_char) ((key_len >> 16) & 0xff);
- *b->last++ = (u_char) ((key_len >> 8) & 0xff);
- *b->last++ = (u_char) (key_len & 0xff);
-
- } else {
- *b->last++ = (u_char) key_len;
- }
-
- val_len = header[i].value.len;
- if (val_len > 127) {
- *b->last++ = (u_char) (((val_len >> 24) & 0x7f) | 0x80);
- *b->last++ = (u_char) ((val_len >> 16) & 0xff);
- *b->last++ = (u_char) ((val_len >> 8) & 0xff);
- *b->last++ = (u_char) (val_len & 0xff);
-
- } else {
- *b->last++ = (u_char) val_len;
- }
-
- b->last = ngx_cpymem(b->last, "HTTP_", sizeof("HTTP_") - 1);
-
- for (n = 0; n < header[i].key.len; n++) {
- ch = header[i].key.data[n];
-
- if (ch >= 'a' && ch <= 'z') {
- ch &= ~0x20;
-
- } else if (ch == '-') {
- ch = '_';
- }
-
- *b->last++ = ch;
- }
-
- b->last = ngx_copy(b->last, header[i].value.data, val_len);
-
- ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "fastcgi param: \"%*s: %*s\"",
- key_len, b->last - (key_len + val_len),
- val_len, b->last - val_len);
- next:
-
- continue;
- }
- }
-
-
- if (padding) {
- ngx_memzero(b->last, padding);
- b->last += padding;
- }
-
-
- h = (ngx_http_fastcgi_header_t *) b->last;
- b->last += sizeof(ngx_http_fastcgi_header_t);
-
- h->version = 1;
- h->type = NGX_HTTP_FASTCGI_PARAMS;
- h->request_id_hi = 0;
- h->request_id_lo = 1;
- h->content_length_hi = 0;
- h->content_length_lo = 0;
- h->padding_length = 0;
- h->reserved = 0;
-
- if (r->request_body_no_buffering) {
-
- u->request_bufs = cl;
-
- u->output.output_filter = ngx_http_fastcgi_body_output_filter;
- u->output.filter_ctx = r;
-
- } else if (flcf->upstream.pass_request_body) {
-
- body = u->request_bufs;
- u->request_bufs = cl;
-
-#if (NGX_SUPPRESS_WARN)
- file_pos = 0;
- pos = NULL;
-#endif
-
- while (body) {
-
- if (ngx_buf_special(body->buf)) {
- body = body->next;
- continue;
- }
-
- if (body->buf->in_file) {
- file_pos = body->buf->file_pos;
-
- } else {
- pos = body->buf->pos;
- }
-
- next = 0;
-
- do {
- b = ngx_alloc_buf(r->pool);
- if (b == NULL) {
- return NGX_ERROR;
- }
-
- ngx_memcpy(b, body->buf, sizeof(ngx_buf_t));
-
- if (body->buf->in_file) {
- b->file_pos = file_pos;
- file_pos += 32 * 1024;
-
- if (file_pos >= body->buf->file_last) {
- file_pos = body->buf->file_last;
- next = 1;
- }
-
- b->file_last = file_pos;
- len = (ngx_uint_t) (file_pos - b->file_pos);
-
- } else {
- b->pos = pos;
- b->start = pos;
- pos += 32 * 1024;
-
- if (pos >= body->buf->last) {
- pos = body->buf->last;
- next = 1;
- }
-
- b->last = pos;
- len = (ngx_uint_t) (pos - b->pos);
- }
-
- padding = 8 - len % 8;
- padding = (padding == 8) ? 0 : padding;
-
- h = (ngx_http_fastcgi_header_t *) cl->buf->last;
- cl->buf->last += sizeof(ngx_http_fastcgi_header_t);
-
- h->version = 1;
- h->type = NGX_HTTP_FASTCGI_STDIN;
- h->request_id_hi = 0;
- h->request_id_lo = 1;
- h->content_length_hi = (u_char) ((len >> 8) & 0xff);
- h->content_length_lo = (u_char) (len & 0xff);
- h->padding_length = (u_char) padding;
- h->reserved = 0;
-
- cl->next = ngx_alloc_chain_link(r->pool);
- if (cl->next == NULL) {
- return NGX_ERROR;
- }
-
- cl = cl->next;
- cl->buf = b;
-
- b = ngx_create_temp_buf(r->pool,
- sizeof(ngx_http_fastcgi_header_t)
- + padding);
- if (b == NULL) {
- return NGX_ERROR;
- }
-
- if (padding) {
- ngx_memzero(b->last, padding);
- b->last += padding;
- }
-
- cl->next = ngx_alloc_chain_link(r->pool);
- if (cl->next == NULL) {
- return NGX_ERROR;
- }
-
- cl = cl->next;
- cl->buf = b;
-
- } while (!next);
-
- body = body->next;
- }
-
- } else {
- u->request_bufs = cl;
- }
-
- if (!r->request_body_no_buffering) {
- h = (ngx_http_fastcgi_header_t *) cl->buf->last;
- cl->buf->last += sizeof(ngx_http_fastcgi_header_t);
-
- h->version = 1;
- h->type = NGX_HTTP_FASTCGI_STDIN;
- h->request_id_hi = 0;
- h->request_id_lo = 1;
- h->content_length_hi = 0;
- h->content_length_lo = 0;
- h->padding_length = 0;
- h->reserved = 0;
- }
-
- cl->next = NULL;
-
- return NGX_OK;
-}
-
-
-static ngx_int_t
-ngx_http_fastcgi_reinit_request(ngx_http_request_t *r)
-{
- ngx_http_fastcgi_ctx_t *f;
-
- f = ngx_http_get_module_ctx(r, ngx_http_fastcgi_module);
-
- if (f == NULL) {
- return NGX_OK;
- }
-
- f->state = ngx_http_fastcgi_st_version;
- f->fastcgi_stdout = 0;
- f->large_stderr = 0;
-
- if (f->split_parts) {
- f->split_parts->nelts = 0;
- }
-
- r->state = 0;
-
- return NGX_OK;
-}
-
-
-static ngx_int_t
-ngx_http_fastcgi_body_output_filter(void *data, ngx_chain_t *in)
-{
- ngx_http_request_t *r = data;
-
- off_t file_pos;
- u_char *pos, *start;
- size_t len, padding;
- ngx_buf_t *b;
- ngx_int_t rc;
- ngx_uint_t next, last;
- ngx_chain_t *cl, *tl, *out, **ll;
- ngx_http_fastcgi_ctx_t *f;
- ngx_http_fastcgi_header_t *h;
-
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "fastcgi output filter");
-
- f = ngx_http_get_module_ctx(r, ngx_http_fastcgi_module);
-
- if (in == NULL) {
- out = in;
- goto out;
- }
-
- out = NULL;
- ll = &out;
-
- if (!f->header_sent) {
- /* first buffer contains headers, pass it unmodified */
-
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "fastcgi output header");
-
- f->header_sent = 1;
-
- tl = ngx_alloc_chain_link(r->pool);
- if (tl == NULL) {
- return NGX_ERROR;
- }
-
- tl->buf = in->buf;
- *ll = tl;
- ll = &tl->next;
-
- in = in->next;
-
- if (in == NULL) {
- tl->next = NULL;
- goto out;
- }
- }
-
- cl = ngx_chain_get_free_buf(r->pool, &f->free);
- if (cl == NULL) {
- return NGX_ERROR;
- }
-
- b = cl->buf;
-
- b->tag = (ngx_buf_tag_t) &ngx_http_fastcgi_body_output_filter;
- b->temporary = 1;
-
- if (b->start == NULL) {
- /* reserve space for maximum possible padding, 7 bytes */
-
- b->start = ngx_palloc(r->pool,
- sizeof(ngx_http_fastcgi_header_t) + 7);
- if (b->start == NULL) {
- return NGX_ERROR;
- }
-
- b->pos = b->start;
- b->last = b->start;
-
- b->end = b->start + sizeof(ngx_http_fastcgi_header_t) + 7;
- }
-
- *ll = cl;
-
- last = 0;
- padding = 0;
-
-#if (NGX_SUPPRESS_WARN)
- file_pos = 0;
- pos = NULL;
-#endif
-
- while (in) {
-
- ngx_log_debug7(NGX_LOG_DEBUG_EVENT, r->connection->log, 0,
- "fastcgi output in l:%d f:%d %p, pos %p, size: %z "
- "file: %O, size: %O",
- in->buf->last_buf,
- in->buf->in_file,
- in->buf->start, in->buf->pos,
- in->buf->last - in->buf->pos,
- in->buf->file_pos,
- in->buf->file_last - in->buf->file_pos);
-
- if (in->buf->last_buf) {
- last = 1;
- }
-
- if (ngx_buf_special(in->buf)) {
- in = in->next;
- continue;
- }
-
- if (in->buf->in_file) {
- file_pos = in->buf->file_pos;
-
- } else {
- pos = in->buf->pos;
- }
-
- next = 0;
-
- do {
- tl = ngx_chain_get_free_buf(r->pool, &f->free);
- if (tl == NULL) {
- return NGX_ERROR;
- }
-
- b = tl->buf;
- start = b->start;
-
- ngx_memcpy(b, in->buf, sizeof(ngx_buf_t));
-
- /*
- * restore b->start to preserve memory allocated in the buffer,
- * to reuse it later for headers and padding
- */
-
- b->start = start;
-
- if (in->buf->in_file) {
- b->file_pos = file_pos;
- file_pos += 32 * 1024;
-
- if (file_pos >= in->buf->file_last) {
- file_pos = in->buf->file_last;
- next = 1;
- }
-
- b->file_last = file_pos;
- len = (ngx_uint_t) (file_pos - b->file_pos);
-
- } else {
- b->pos = pos;
- pos += 32 * 1024;
-
- if (pos >= in->buf->last) {
- pos = in->buf->last;
- next = 1;
- }
-
- b->last = pos;
- len = (ngx_uint_t) (pos - b->pos);
- }
-
- b->tag = (ngx_buf_tag_t) &ngx_http_fastcgi_body_output_filter;
- b->shadow = in->buf;
- b->last_shadow = next;
-
- b->last_buf = 0;
- b->last_in_chain = 0;
-
- padding = 8 - len % 8;
- padding = (padding == 8) ? 0 : padding;
-
- h = (ngx_http_fastcgi_header_t *) cl->buf->last;
- cl->buf->last += sizeof(ngx_http_fastcgi_header_t);
-
- h->version = 1;
- h->type = NGX_HTTP_FASTCGI_STDIN;
- h->request_id_hi = 0;
- h->request_id_lo = 1;
- h->content_length_hi = (u_char) ((len >> 8) & 0xff);
- h->content_length_lo = (u_char) (len & 0xff);
- h->padding_length = (u_char) padding;
- h->reserved = 0;
-
- cl->next = tl;
- cl = tl;
-
- tl = ngx_chain_get_free_buf(r->pool, &f->free);
- if (tl == NULL) {
- return NGX_ERROR;
- }
-
- b = tl->buf;
-
- b->tag = (ngx_buf_tag_t) &ngx_http_fastcgi_body_output_filter;
- b->temporary = 1;
-
- if (b->start == NULL) {
- /* reserve space for maximum possible padding, 7 bytes */
-
- b->start = ngx_palloc(r->pool,
- sizeof(ngx_http_fastcgi_header_t) + 7);
- if (b->start == NULL) {
- return NGX_ERROR;
- }
-
- b->pos = b->start;
- b->last = b->start;
-
- b->end = b->start + sizeof(ngx_http_fastcgi_header_t) + 7;
- }
-
- if (padding) {
- ngx_memzero(b->last, padding);
- b->last += padding;
- }
-
- cl->next = tl;
- cl = tl;
-
- } while (!next);
-
- in = in->next;
- }
-
- if (last) {
- h = (ngx_http_fastcgi_header_t *) cl->buf->last;
- cl->buf->last += sizeof(ngx_http_fastcgi_header_t);
-
- h->version = 1;
- h->type = NGX_HTTP_FASTCGI_STDIN;
- h->request_id_hi = 0;
- h->request_id_lo = 1;
- h->content_length_hi = 0;
- h->content_length_lo = 0;
- h->padding_length = 0;
- h->reserved = 0;
-
- cl->buf->last_buf = 1;
-
- } else if (padding == 0) {
- /* TODO: do not allocate buffers instead */
- cl->buf->temporary = 0;
- cl->buf->sync = 1;
- }
-
- cl->next = NULL;
-
-out:
-
-#if (NGX_DEBUG)
-
- for (cl = out; cl; cl = cl->next) {
- ngx_log_debug7(NGX_LOG_DEBUG_EVENT, r->connection->log, 0,
- "fastcgi output out l:%d f:%d %p, pos %p, size: %z "
- "file: %O, size: %O",
- cl->buf->last_buf,
- cl->buf->in_file,
- cl->buf->start, cl->buf->pos,
- cl->buf->last - cl->buf->pos,
- cl->buf->file_pos,
- cl->buf->file_last - cl->buf->file_pos);
- }
-
-#endif
-
- rc = ngx_chain_writer(&r->upstream->writer, out);
-
- ngx_chain_update_chains(r->pool, &f->free, &f->busy, &out,
- (ngx_buf_tag_t) &ngx_http_fastcgi_body_output_filter);
-
- for (cl = f->free; cl; cl = cl->next) {
-
- /* mark original buffers as sent */
-
- if (cl->buf->shadow) {
- if (cl->buf->last_shadow) {
- b = cl->buf->shadow;
- b->pos = b->last;
- }
-
- cl->buf->shadow = NULL;
- }
- }
-
- return rc;
-}
-
-
-static ngx_int_t
-ngx_http_fastcgi_process_header(ngx_http_request_t *r)
-{
- u_char *p, *msg, *start, *last,
- *part_start, *part_end;
- size_t size;
- ngx_str_t *status_line, *pattern;
- ngx_int_t rc, status;
- ngx_buf_t buf;
- ngx_uint_t i;
- ngx_table_elt_t *h;
- ngx_http_upstream_t *u;
- ngx_http_fastcgi_ctx_t *f;
- ngx_http_upstream_header_t *hh;
- ngx_http_fastcgi_loc_conf_t *flcf;
- ngx_http_fastcgi_split_part_t *part;
- ngx_http_upstream_main_conf_t *umcf;
-
- f = ngx_http_get_module_ctx(r, ngx_http_fastcgi_module);
-
- umcf = ngx_http_get_module_main_conf(r, ngx_http_upstream_module);
-
- u = r->upstream;
-
- for ( ;; ) {
-
- if (f->state < ngx_http_fastcgi_st_data) {
-
- f->pos = u->buffer.pos;
- f->last = u->buffer.last;
-
- rc = ngx_http_fastcgi_process_record(r, f);
-
- u->buffer.pos = f->pos;
- u->buffer.last = f->last;
-
- if (rc == NGX_AGAIN) {
- return NGX_AGAIN;
- }
-
- if (rc == NGX_ERROR) {
- return NGX_HTTP_UPSTREAM_INVALID_HEADER;
- }
-
- if (f->type != NGX_HTTP_FASTCGI_STDOUT
- && f->type != NGX_HTTP_FASTCGI_STDERR)
- {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "upstream sent unexpected FastCGI record: %ui",
- f->type);
-
- return NGX_HTTP_UPSTREAM_INVALID_HEADER;
- }
-
- if (f->type == NGX_HTTP_FASTCGI_STDOUT && f->length == 0) {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "upstream prematurely closed FastCGI stdout");
-
- return NGX_HTTP_UPSTREAM_INVALID_HEADER;
- }
- }
-
- if (f->state == ngx_http_fastcgi_st_padding) {
-
- if (u->buffer.pos + f->padding < u->buffer.last) {
- f->state = ngx_http_fastcgi_st_version;
- u->buffer.pos += f->padding;
-
- continue;
- }
-
- if (u->buffer.pos + f->padding == u->buffer.last) {
- f->state = ngx_http_fastcgi_st_version;
- u->buffer.pos = u->buffer.last;
-
- return NGX_AGAIN;
- }
-
- f->padding -= u->buffer.last - u->buffer.pos;
- u->buffer.pos = u->buffer.last;
-
- return NGX_AGAIN;
- }
-
-
- /* f->state == ngx_http_fastcgi_st_data */
-
- if (f->type == NGX_HTTP_FASTCGI_STDERR) {
-
- if (f->length) {
- msg = u->buffer.pos;
-
- if (u->buffer.pos + f->length <= u->buffer.last) {
- u->buffer.pos += f->length;
- f->length = 0;
- f->state = ngx_http_fastcgi_st_padding;
-
- } else {
- f->length -= u->buffer.last - u->buffer.pos;
- u->buffer.pos = u->buffer.last;
- }
-
- for (p = u->buffer.pos - 1; msg < p; p--) {
- if (*p != LF && *p != CR && *p != '.' && *p != ' ') {
- break;
- }
- }
-
- p++;
-
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "FastCGI sent in stderr: \"%*s\"", p - msg, msg);
-
- flcf = ngx_http_get_module_loc_conf(r, ngx_http_fastcgi_module);
-
- if (flcf->catch_stderr) {
- pattern = flcf->catch_stderr->elts;
-
- for (i = 0; i < flcf->catch_stderr->nelts; i++) {
- if (ngx_strnstr(msg, (char *) pattern[i].data,
- p - msg)
- != NULL)
- {
- return NGX_HTTP_UPSTREAM_INVALID_HEADER;
- }
- }
- }
-
- if (u->buffer.pos == u->buffer.last) {
-
- if (!f->fastcgi_stdout) {
-
- /*
- * the special handling the large number
- * of the PHP warnings to not allocate memory
- */
-
-#if (NGX_HTTP_CACHE)
- if (r->cache) {
- u->buffer.pos = u->buffer.start
- + r->cache->header_start;
- } else {
- u->buffer.pos = u->buffer.start;
- }
-#else
- u->buffer.pos = u->buffer.start;
-#endif
- u->buffer.last = u->buffer.pos;
- f->large_stderr = 1;
- }
-
- return NGX_AGAIN;
- }
-
- } else {
- f->state = ngx_http_fastcgi_st_padding;
- }
-
- continue;
- }
-
-
- /* f->type == NGX_HTTP_FASTCGI_STDOUT */
-
-#if (NGX_HTTP_CACHE)
-
- if (f->large_stderr && r->cache) {
- ssize_t len;
- ngx_http_fastcgi_header_t *fh;
-
- start = u->buffer.start + r->cache->header_start;
-
- len = u->buffer.pos - start - 2 * sizeof(ngx_http_fastcgi_header_t);
-
- /*
- * A tail of large stderr output before HTTP header is placed
- * in a cache file without a FastCGI record header.
- * To workaround it we put a dummy FastCGI record header at the
- * start of the stderr output or update r->cache_header_start,
- * if there is no enough place for the record header.
- */
-
- if (len >= 0) {
- fh = (ngx_http_fastcgi_header_t *) start;
- fh->version = 1;
- fh->type = NGX_HTTP_FASTCGI_STDERR;
- fh->request_id_hi = 0;
- fh->request_id_lo = 1;
- fh->content_length_hi = (u_char) ((len >> 8) & 0xff);
- fh->content_length_lo = (u_char) (len & 0xff);
- fh->padding_length = 0;
- fh->reserved = 0;
-
- } else {
- r->cache->header_start += u->buffer.pos - start
- - sizeof(ngx_http_fastcgi_header_t);
- }
-
- f->large_stderr = 0;
- }
-
-#endif
-
- f->fastcgi_stdout = 1;
-
- start = u->buffer.pos;
-
- if (u->buffer.pos + f->length < u->buffer.last) {
-
- /*
- * set u->buffer.last to the end of the FastCGI record data
- * for ngx_http_parse_header_line()
- */
-
- last = u->buffer.last;
- u->buffer.last = u->buffer.pos + f->length;
-
- } else {
- last = NULL;
- }
-
- for ( ;; ) {
-
- part_start = u->buffer.pos;
- part_end = u->buffer.last;
-
- rc = ngx_http_parse_header_line(r, &u->buffer, 1);
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "http fastcgi parser: %i", rc);
-
- if (rc == NGX_AGAIN) {
- break;
- }
-
- if (rc == NGX_OK) {
-
- /* a header line has been parsed successfully */
-
- h = ngx_list_push(&u->headers_in.headers);
- if (h == NULL) {
- return NGX_ERROR;
- }
-
- if (f->split_parts && f->split_parts->nelts) {
-
- part = f->split_parts->elts;
- size = u->buffer.pos - part_start;
-
- for (i = 0; i < f->split_parts->nelts; i++) {
- size += part[i].end - part[i].start;
- }
-
- p = ngx_pnalloc(r->pool, size);
- if (p == NULL) {
- h->hash = 0;
- return NGX_ERROR;
- }
-
- buf.pos = p;
-
- for (i = 0; i < f->split_parts->nelts; i++) {
- p = ngx_cpymem(p, part[i].start,
- part[i].end - part[i].start);
- }
-
- p = ngx_cpymem(p, part_start, u->buffer.pos - part_start);
-
- buf.last = p;
-
- f->split_parts->nelts = 0;
-
- rc = ngx_http_parse_header_line(r, &buf, 1);
-
- if (rc != NGX_OK) {
- ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
- "invalid header after joining "
- "FastCGI records");
- h->hash = 0;
- return NGX_ERROR;
- }
-
- h->key.len = r->header_name_end - r->header_name_start;
- h->key.data = r->header_name_start;
- h->key.data[h->key.len] = '\0';
-
- h->value.len = r->header_end - r->header_start;
- h->value.data = r->header_start;
- h->value.data[h->value.len] = '\0';
-
- h->lowcase_key = ngx_pnalloc(r->pool, h->key.len);
- if (h->lowcase_key == NULL) {
- return NGX_ERROR;
- }
-
- } else {
-
- h->key.len = r->header_name_end - r->header_name_start;
- h->value.len = r->header_end - r->header_start;
-
- h->key.data = ngx_pnalloc(r->pool,
- h->key.len + 1 + h->value.len + 1
- + h->key.len);
- if (h->key.data == NULL) {
- h->hash = 0;
- return NGX_ERROR;
- }
-
- h->value.data = h->key.data + h->key.len + 1;
- h->lowcase_key = h->key.data + h->key.len + 1
- + h->value.len + 1;
-
- ngx_memcpy(h->key.data, r->header_name_start, h->key.len);
- h->key.data[h->key.len] = '\0';
- ngx_memcpy(h->value.data, r->header_start, h->value.len);
- h->value.data[h->value.len] = '\0';
- }
-
- h->hash = r->header_hash;
-
- if (h->key.len == r->lowcase_index) {
- ngx_memcpy(h->lowcase_key, r->lowcase_header, h->key.len);
-
- } else {
- ngx_strlow(h->lowcase_key, h->key.data, h->key.len);
- }
-
- hh = ngx_hash_find(&umcf->headers_in_hash, h->hash,
- h->lowcase_key, h->key.len);
-
- if (hh && hh->handler(r, h, hh->offset) != NGX_OK) {
- return NGX_ERROR;
- }
-
- ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "http fastcgi header: \"%V: %V\"",
- &h->key, &h->value);
-
- if (u->buffer.pos < u->buffer.last) {
- continue;
- }
-
- /* the end of the FastCGI record */
-
- break;
- }
-
- if (rc == NGX_HTTP_PARSE_HEADER_DONE) {
-
- /* a whole header has been parsed successfully */
-
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "http fastcgi header done");
-
- if (u->headers_in.status) {
- status_line = &u->headers_in.status->value;
-
- status = ngx_atoi(status_line->data, 3);
-
- if (status == NGX_ERROR) {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "upstream sent invalid status \"%V\"",
- status_line);
- return NGX_HTTP_UPSTREAM_INVALID_HEADER;
- }
-
- u->headers_in.status_n = status;
- u->headers_in.status_line = *status_line;
-
- } else if (u->headers_in.location) {
- u->headers_in.status_n = 302;
- ngx_str_set(&u->headers_in.status_line,
- "302 Moved Temporarily");
-
- } else {
- u->headers_in.status_n = 200;
- ngx_str_set(&u->headers_in.status_line, "200 OK");
- }
-
- if (u->state && u->state->status == 0) {
- u->state->status = u->headers_in.status_n;
- }
-
- break;
- }
-
- /* there was error while a header line parsing */
-
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "upstream sent invalid header");
-
- return NGX_HTTP_UPSTREAM_INVALID_HEADER;
- }
-
- if (last) {
- u->buffer.last = last;
- }
-
- f->length -= u->buffer.pos - start;
-
- if (f->length == 0) {
- f->state = ngx_http_fastcgi_st_padding;
- }
-
- if (rc == NGX_HTTP_PARSE_HEADER_DONE) {
- return NGX_OK;
- }
-
- if (rc == NGX_OK) {
- continue;
- }
-
- /* rc == NGX_AGAIN */
-
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "upstream split a header line in FastCGI records");
-
- if (f->split_parts == NULL) {
- f->split_parts = ngx_array_create(r->pool, 1,
- sizeof(ngx_http_fastcgi_split_part_t));
- if (f->split_parts == NULL) {
- return NGX_ERROR;
- }
- }
-
- part = ngx_array_push(f->split_parts);
- if (part == NULL) {
- return NGX_ERROR;
- }
-
- part->start = part_start;
- part->end = part_end;
-
- if (u->buffer.pos < u->buffer.last) {
- continue;
- }
-
- return NGX_AGAIN;
- }
-}
-
-
-static ngx_int_t
-ngx_http_fastcgi_input_filter_init(void *data)
-{
- ngx_http_request_t *r = data;
- ngx_http_fastcgi_loc_conf_t *flcf;
-
- flcf = ngx_http_get_module_loc_conf(r, ngx_http_fastcgi_module);
-
- r->upstream->pipe->length = flcf->keep_conn ?
- (off_t) sizeof(ngx_http_fastcgi_header_t) : -1;
-
- return NGX_OK;
-}
-
-
-static ngx_int_t
-ngx_http_fastcgi_input_filter(ngx_event_pipe_t *p, ngx_buf_t *buf)
-{
- u_char *m, *msg;
- ngx_int_t rc;
- ngx_buf_t *b, **prev;
- ngx_chain_t *cl;
- ngx_http_request_t *r;
- ngx_http_fastcgi_ctx_t *f;
- ngx_http_fastcgi_loc_conf_t *flcf;
-
- if (buf->pos == buf->last) {
- return NGX_OK;
- }
-
- r = p->input_ctx;
- f = ngx_http_get_module_ctx(r, ngx_http_fastcgi_module);
- flcf = ngx_http_get_module_loc_conf(r, ngx_http_fastcgi_module);
-
- b = NULL;
- prev = &buf->shadow;
-
- f->pos = buf->pos;
- f->last = buf->last;
-
- for ( ;; ) {
- if (f->state < ngx_http_fastcgi_st_data) {
-
- rc = ngx_http_fastcgi_process_record(r, f);
-
- if (rc == NGX_AGAIN) {
- break;
- }
-
- if (rc == NGX_ERROR) {
- return NGX_ERROR;
- }
-
- if (f->type == NGX_HTTP_FASTCGI_STDOUT && f->length == 0) {
- f->state = ngx_http_fastcgi_st_padding;
-
- if (!flcf->keep_conn) {
- p->upstream_done = 1;
- }
-
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, p->log, 0,
- "http fastcgi closed stdout");
-
- continue;
- }
-
- if (f->type == NGX_HTTP_FASTCGI_END_REQUEST) {
-
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, p->log, 0,
- "http fastcgi sent end request");
-
- if (!flcf->keep_conn) {
- p->upstream_done = 1;
- break;
- }
-
- continue;
- }
- }
-
-
- if (f->state == ngx_http_fastcgi_st_padding) {
-
- if (f->type == NGX_HTTP_FASTCGI_END_REQUEST) {
-
- if (f->pos + f->padding < f->last) {
- p->upstream_done = 1;
- break;
- }
-
- if (f->pos + f->padding == f->last) {
- p->upstream_done = 1;
- r->upstream->keepalive = 1;
- break;
- }
-
- f->padding -= f->last - f->pos;
-
- break;
- }
-
- if (f->pos + f->padding < f->last) {
- f->state = ngx_http_fastcgi_st_version;
- f->pos += f->padding;
-
- continue;
- }
-
- if (f->pos + f->padding == f->last) {
- f->state = ngx_http_fastcgi_st_version;
-
- break;
- }
-
- f->padding -= f->last - f->pos;
-
- break;
- }
-
-
- /* f->state == ngx_http_fastcgi_st_data */
-
- if (f->type == NGX_HTTP_FASTCGI_STDERR) {
-
- if (f->length) {
-
- if (f->pos == f->last) {
- break;
- }
-
- msg = f->pos;
-
- if (f->pos + f->length <= f->last) {
- f->pos += f->length;
- f->length = 0;
- f->state = ngx_http_fastcgi_st_padding;
-
- } else {
- f->length -= f->last - f->pos;
- f->pos = f->last;
- }
-
- for (m = f->pos - 1; msg < m; m--) {
- if (*m != LF && *m != CR && *m != '.' && *m != ' ') {
- break;
- }
- }
-
- ngx_log_error(NGX_LOG_ERR, p->log, 0,
- "FastCGI sent in stderr: \"%*s\"",
- m + 1 - msg, msg);
-
- } else {
- f->state = ngx_http_fastcgi_st_padding;
- }
-
- continue;
- }
-
- if (f->type == NGX_HTTP_FASTCGI_END_REQUEST) {
-
- if (f->pos + f->length <= f->last) {
- f->state = ngx_http_fastcgi_st_padding;
- f->pos += f->length;
-
- continue;
- }
-
- f->length -= f->last - f->pos;
-
- break;
- }
-
-
- /* f->type == NGX_HTTP_FASTCGI_STDOUT */
-
- if (f->pos == f->last) {
- break;
- }
-
- cl = ngx_chain_get_free_buf(p->pool, &p->free);
- if (cl == NULL) {
- return NGX_ERROR;
- }
-
- b = cl->buf;
-
- ngx_memzero(b, sizeof(ngx_buf_t));
-
- b->pos = f->pos;
- b->start = buf->start;
- b->end = buf->end;
- b->tag = p->tag;
- b->temporary = 1;
- b->recycled = 1;
-
- *prev = b;
- prev = &b->shadow;
-
- if (p->in) {
- *p->last_in = cl;
- } else {
- p->in = cl;
- }
- p->last_in = &cl->next;
-
-
- /* STUB */ b->num = buf->num;
-
- ngx_log_debug2(NGX_LOG_DEBUG_EVENT, p->log, 0,
- "input buf #%d %p", b->num, b->pos);
-
- if (f->pos + f->length <= f->last) {
- f->state = ngx_http_fastcgi_st_padding;
- f->pos += f->length;
- b->last = f->pos;
-
- continue;
- }
-
- f->length -= f->last - f->pos;
-
- b->last = f->last;
-
- break;
-
- }
-
- if (flcf->keep_conn) {
-
- /* set p->length, minimal amount of data we want to see */
-
- if (f->state < ngx_http_fastcgi_st_data) {
- p->length = 1;
-
- } else if (f->state == ngx_http_fastcgi_st_padding) {
- p->length = f->padding;
-
- } else {
- /* ngx_http_fastcgi_st_data */
-
- p->length = f->length;
- }
- }
-
- if (b) {
- b->shadow = buf;
- b->last_shadow = 1;
-
- ngx_log_debug2(NGX_LOG_DEBUG_EVENT, p->log, 0,
- "input buf %p %z", b->pos, b->last - b->pos);
-
- return NGX_OK;
- }
-
- /* there is no data record in the buf, add it to free chain */
-
- if (ngx_event_pipe_add_free_buf(p, buf) != NGX_OK) {
- return NGX_ERROR;
- }
-
- return NGX_OK;
-}
-
-
-static ngx_int_t
-ngx_http_fastcgi_non_buffered_filter(void *data, ssize_t bytes)
-{
- u_char *m, *msg;
- ngx_int_t rc;
- ngx_buf_t *b, *buf;
- ngx_chain_t *cl, **ll;
- ngx_http_request_t *r;
- ngx_http_upstream_t *u;
- ngx_http_fastcgi_ctx_t *f;
-
- r = data;
- f = ngx_http_get_module_ctx(r, ngx_http_fastcgi_module);
-
- u = r->upstream;
- buf = &u->buffer;
-
- buf->pos = buf->last;
- buf->last += bytes;
-
- for (cl = u->out_bufs, ll = &u->out_bufs; cl; cl = cl->next) {
- ll = &cl->next;
- }
-
- f->pos = buf->pos;
- f->last = buf->last;
-
- for ( ;; ) {
- if (f->state < ngx_http_fastcgi_st_data) {
-
- rc = ngx_http_fastcgi_process_record(r, f);
-
- if (rc == NGX_AGAIN) {
- break;
- }
-
- if (rc == NGX_ERROR) {
- return NGX_ERROR;
- }
-
- if (f->type == NGX_HTTP_FASTCGI_STDOUT && f->length == 0) {
- f->state = ngx_http_fastcgi_st_padding;
-
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "http fastcgi closed stdout");
-
- continue;
- }
- }
-
- if (f->state == ngx_http_fastcgi_st_padding) {
-
- if (f->type == NGX_HTTP_FASTCGI_END_REQUEST) {
-
- if (f->pos + f->padding < f->last) {
- u->length = 0;
- break;
- }
-
- if (f->pos + f->padding == f->last) {
- u->length = 0;
- u->keepalive = 1;
- break;
- }
-
- f->padding -= f->last - f->pos;
-
- break;
- }
-
- if (f->pos + f->padding < f->last) {
- f->state = ngx_http_fastcgi_st_version;
- f->pos += f->padding;
-
- continue;
- }
-
- if (f->pos + f->padding == f->last) {
- f->state = ngx_http_fastcgi_st_version;
-
- break;
- }
-
- f->padding -= f->last - f->pos;
-
- break;
- }
-
-
- /* f->state == ngx_http_fastcgi_st_data */
-
- if (f->type == NGX_HTTP_FASTCGI_STDERR) {
-
- if (f->length) {
-
- if (f->pos == f->last) {
- break;
- }
-
- msg = f->pos;
-
- if (f->pos + f->length <= f->last) {
- f->pos += f->length;
- f->length = 0;
- f->state = ngx_http_fastcgi_st_padding;
-
- } else {
- f->length -= f->last - f->pos;
- f->pos = f->last;
- }
-
- for (m = f->pos - 1; msg < m; m--) {
- if (*m != LF && *m != CR && *m != '.' && *m != ' ') {
- break;
- }
- }
-
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "FastCGI sent in stderr: \"%*s\"",
- m + 1 - msg, msg);
-
- } else {
- f->state = ngx_http_fastcgi_st_padding;
- }
-
- continue;
- }
-
- if (f->type == NGX_HTTP_FASTCGI_END_REQUEST) {
-
- if (f->pos + f->length <= f->last) {
- f->state = ngx_http_fastcgi_st_padding;
- f->pos += f->length;
-
- continue;
- }
-
- f->length -= f->last - f->pos;
-
- break;
- }
-
-
- /* f->type == NGX_HTTP_FASTCGI_STDOUT */
-
- if (f->pos == f->last) {
- break;
- }
-
- cl = ngx_chain_get_free_buf(r->pool, &u->free_bufs);
- if (cl == NULL) {
- return NGX_ERROR;
- }
-
- *ll = cl;
- ll = &cl->next;
-
- b = cl->buf;
-
- b->flush = 1;
- b->memory = 1;
-
- b->pos = f->pos;
- b->tag = u->output.tag;
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "http fastcgi output buf %p", b->pos);
-
- if (f->pos + f->length <= f->last) {
- f->state = ngx_http_fastcgi_st_padding;
- f->pos += f->length;
- b->last = f->pos;
-
- continue;
- }
-
- f->length -= f->last - f->pos;
- b->last = f->last;
-
- break;
- }
-
- return NGX_OK;
-}
-
-
-static ngx_int_t
-ngx_http_fastcgi_process_record(ngx_http_request_t *r,
- ngx_http_fastcgi_ctx_t *f)
-{
- u_char ch, *p;
- ngx_http_fastcgi_state_e state;
-
- state = f->state;
-
- for (p = f->pos; p < f->last; p++) {
-
- ch = *p;
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "http fastcgi record byte: %02Xd", ch);
-
- switch (state) {
-
- case ngx_http_fastcgi_st_version:
- if (ch != 1) {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "upstream sent unsupported FastCGI "
- "protocol version: %d", ch);
- return NGX_ERROR;
- }
- state = ngx_http_fastcgi_st_type;
- break;
-
- case ngx_http_fastcgi_st_type:
- switch (ch) {
- case NGX_HTTP_FASTCGI_STDOUT:
- case NGX_HTTP_FASTCGI_STDERR:
- case NGX_HTTP_FASTCGI_END_REQUEST:
- f->type = (ngx_uint_t) ch;
- break;
- default:
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "upstream sent invalid FastCGI "
- "record type: %d", ch);
- return NGX_ERROR;
-
- }
- state = ngx_http_fastcgi_st_request_id_hi;
- break;
-
- /* we support the single request per connection */
-
- case ngx_http_fastcgi_st_request_id_hi:
- if (ch != 0) {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "upstream sent unexpected FastCGI "
- "request id high byte: %d", ch);
- return NGX_ERROR;
- }
- state = ngx_http_fastcgi_st_request_id_lo;
- break;
-
- case ngx_http_fastcgi_st_request_id_lo:
- if (ch != 1) {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "upstream sent unexpected FastCGI "
- "request id low byte: %d", ch);
- return NGX_ERROR;
- }
- state = ngx_http_fastcgi_st_content_length_hi;
- break;
-
- case ngx_http_fastcgi_st_content_length_hi:
- f->length = ch << 8;
- state = ngx_http_fastcgi_st_content_length_lo;
- break;
-
- case ngx_http_fastcgi_st_content_length_lo:
- f->length |= (size_t) ch;
- state = ngx_http_fastcgi_st_padding_length;
- break;
-
- case ngx_http_fastcgi_st_padding_length:
- f->padding = (size_t) ch;
- state = ngx_http_fastcgi_st_reserved;
- break;
-
- case ngx_http_fastcgi_st_reserved:
- state = ngx_http_fastcgi_st_data;
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "http fastcgi record length: %z", f->length);
-
- f->pos = p + 1;
- f->state = state;
-
- return NGX_OK;
-
- /* suppress warning */
- case ngx_http_fastcgi_st_data:
- case ngx_http_fastcgi_st_padding:
- break;
- }
- }
-
- f->pos = p;
- f->state = state;
-
- return NGX_AGAIN;
-}
-
-
-static void
-ngx_http_fastcgi_abort_request(ngx_http_request_t *r)
-{
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "abort http fastcgi request");
-
- return;
-}
-
-
-static void
-ngx_http_fastcgi_finalize_request(ngx_http_request_t *r, ngx_int_t rc)
-{
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "finalize http fastcgi request");
-
- return;
-}
-
-
-static ngx_int_t
-ngx_http_fastcgi_add_variables(ngx_conf_t *cf)
-{
- ngx_http_variable_t *var, *v;
-
- for (v = ngx_http_fastcgi_vars; v->name.len; v++) {
- var = ngx_http_add_variable(cf, &v->name, v->flags);
- if (var == NULL) {
- return NGX_ERROR;
- }
-
- var->get_handler = v->get_handler;
- var->data = v->data;
- }
-
- return NGX_OK;
-}
-
-
-static void *
-ngx_http_fastcgi_create_main_conf(ngx_conf_t *cf)
-{
- ngx_http_fastcgi_main_conf_t *conf;
-
- conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_fastcgi_main_conf_t));
- if (conf == NULL) {
- return NULL;
- }
-
-#if (NGX_HTTP_CACHE)
- if (ngx_array_init(&conf->caches, cf->pool, 4,
- sizeof(ngx_http_file_cache_t *))
- != NGX_OK)
- {
- return NULL;
- }
-#endif
-
- return conf;
-}
-
-
-static void *
-ngx_http_fastcgi_create_loc_conf(ngx_conf_t *cf)
-{
- ngx_http_fastcgi_loc_conf_t *conf;
-
- conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_fastcgi_loc_conf_t));
- if (conf == NULL) {
- return NULL;
- }
-
- /*
- * set by ngx_pcalloc():
- *
- * conf->upstream.bufs.num = 0;
- * conf->upstream.ignore_headers = 0;
- * conf->upstream.next_upstream = 0;
- * conf->upstream.cache_zone = NULL;
- * conf->upstream.cache_use_stale = 0;
- * conf->upstream.cache_methods = 0;
- * conf->upstream.temp_path = NULL;
- * conf->upstream.hide_headers_hash = { NULL, 0 };
- * conf->upstream.store_lengths = NULL;
- * conf->upstream.store_values = NULL;
- *
- * conf->index.len = { 0, NULL };
- */
-
- conf->upstream.store = NGX_CONF_UNSET;
- conf->upstream.store_access = NGX_CONF_UNSET_UINT;
- conf->upstream.next_upstream_tries = NGX_CONF_UNSET_UINT;
- conf->upstream.buffering = NGX_CONF_UNSET;
- conf->upstream.request_buffering = NGX_CONF_UNSET;
- conf->upstream.ignore_client_abort = NGX_CONF_UNSET;
- conf->upstream.force_ranges = NGX_CONF_UNSET;
-
- conf->upstream.local = NGX_CONF_UNSET_PTR;
-
- conf->upstream.connect_timeout = NGX_CONF_UNSET_MSEC;
- conf->upstream.send_timeout = NGX_CONF_UNSET_MSEC;
- conf->upstream.read_timeout = NGX_CONF_UNSET_MSEC;
- conf->upstream.next_upstream_timeout = NGX_CONF_UNSET_MSEC;
-
- conf->upstream.send_lowat = NGX_CONF_UNSET_SIZE;
- conf->upstream.buffer_size = NGX_CONF_UNSET_SIZE;
- conf->upstream.limit_rate = NGX_CONF_UNSET_SIZE;
-
- conf->upstream.busy_buffers_size_conf = NGX_CONF_UNSET_SIZE;
- conf->upstream.max_temp_file_size_conf = NGX_CONF_UNSET_SIZE;
- conf->upstream.temp_file_write_size_conf = NGX_CONF_UNSET_SIZE;
-
- conf->upstream.pass_request_headers = NGX_CONF_UNSET;
- conf->upstream.pass_request_body = NGX_CONF_UNSET;
-
-#if (NGX_HTTP_CACHE)
- conf->upstream.cache = NGX_CONF_UNSET;
- conf->upstream.cache_min_uses = NGX_CONF_UNSET_UINT;
- conf->upstream.cache_max_range_offset = NGX_CONF_UNSET;
- conf->upstream.cache_bypass = NGX_CONF_UNSET_PTR;
- conf->upstream.no_cache = NGX_CONF_UNSET_PTR;
- conf->upstream.cache_valid = NGX_CONF_UNSET_PTR;
- conf->upstream.cache_lock = NGX_CONF_UNSET;
- conf->upstream.cache_lock_timeout = NGX_CONF_UNSET_MSEC;
- conf->upstream.cache_lock_age = NGX_CONF_UNSET_MSEC;
- conf->upstream.cache_revalidate = NGX_CONF_UNSET;
- conf->upstream.cache_background_update = NGX_CONF_UNSET;
-#endif
-
- conf->upstream.hide_headers = NGX_CONF_UNSET_PTR;
- conf->upstream.pass_headers = NGX_CONF_UNSET_PTR;
-
- conf->upstream.intercept_errors = NGX_CONF_UNSET;
-
- /* "fastcgi_cyclic_temp_file" is disabled */
- conf->upstream.cyclic_temp_file = 0;
-
- conf->upstream.change_buffering = 1;
-
- conf->catch_stderr = NGX_CONF_UNSET_PTR;
-
- conf->keep_conn = NGX_CONF_UNSET;
-
- ngx_str_set(&conf->upstream.module, "fastcgi");
-
- return conf;
-}
-
-
-static char *
-ngx_http_fastcgi_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
-{
- ngx_http_fastcgi_loc_conf_t *prev = parent;
- ngx_http_fastcgi_loc_conf_t *conf = child;
-
- size_t size;
- ngx_int_t rc;
- ngx_hash_init_t hash;
- ngx_http_core_loc_conf_t *clcf;
-
-#if (NGX_HTTP_CACHE)
-
- if (conf->upstream.store > 0) {
- conf->upstream.cache = 0;
- }
-
- if (conf->upstream.cache > 0) {
- conf->upstream.store = 0;
- }
-
-#endif
-
- if (conf->upstream.store == NGX_CONF_UNSET) {
- ngx_conf_merge_value(conf->upstream.store,
- prev->upstream.store, 0);
-
- conf->upstream.store_lengths = prev->upstream.store_lengths;
- conf->upstream.store_values = prev->upstream.store_values;
- }
-
- ngx_conf_merge_uint_value(conf->upstream.store_access,
- prev->upstream.store_access, 0600);
-
- ngx_conf_merge_uint_value(conf->upstream.next_upstream_tries,
- prev->upstream.next_upstream_tries, 0);
-
- ngx_conf_merge_value(conf->upstream.buffering,
- prev->upstream.buffering, 1);
-
- ngx_conf_merge_value(conf->upstream.request_buffering,
- prev->upstream.request_buffering, 1);
-
- ngx_conf_merge_value(conf->upstream.ignore_client_abort,
- prev->upstream.ignore_client_abort, 0);
-
- ngx_conf_merge_value(conf->upstream.force_ranges,
- prev->upstream.force_ranges, 0);
-
- ngx_conf_merge_ptr_value(conf->upstream.local,
- prev->upstream.local, NULL);
-
- ngx_conf_merge_msec_value(conf->upstream.connect_timeout,
- prev->upstream.connect_timeout, 60000);
-
- ngx_conf_merge_msec_value(conf->upstream.send_timeout,
- prev->upstream.send_timeout, 60000);
-
- ngx_conf_merge_msec_value(conf->upstream.read_timeout,
- prev->upstream.read_timeout, 60000);
-
- ngx_conf_merge_msec_value(conf->upstream.next_upstream_timeout,
- prev->upstream.next_upstream_timeout, 0);
-
- ngx_conf_merge_size_value(conf->upstream.send_lowat,
- prev->upstream.send_lowat, 0);
-
- ngx_conf_merge_size_value(conf->upstream.buffer_size,
- prev->upstream.buffer_size,
- (size_t) ngx_pagesize);
-
- ngx_conf_merge_size_value(conf->upstream.limit_rate,
- prev->upstream.limit_rate, 0);
-
-
- ngx_conf_merge_bufs_value(conf->upstream.bufs, prev->upstream.bufs,
- 8, ngx_pagesize);
-
- if (conf->upstream.bufs.num < 2) {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "there must be at least 2 \"fastcgi_buffers\"");
- return NGX_CONF_ERROR;
- }
-
-
- size = conf->upstream.buffer_size;
- if (size < conf->upstream.bufs.size) {
- size = conf->upstream.bufs.size;
- }
-
-
- ngx_conf_merge_size_value(conf->upstream.busy_buffers_size_conf,
- prev->upstream.busy_buffers_size_conf,
- NGX_CONF_UNSET_SIZE);
-
- if (conf->upstream.busy_buffers_size_conf == NGX_CONF_UNSET_SIZE) {
- conf->upstream.busy_buffers_size = 2 * size;
- } else {
- conf->upstream.busy_buffers_size =
- conf->upstream.busy_buffers_size_conf;
- }
-
- if (conf->upstream.busy_buffers_size < size) {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "\"fastcgi_busy_buffers_size\" must be equal to or greater than "
- "the maximum of the value of \"fastcgi_buffer_size\" and "
- "one of the \"fastcgi_buffers\"");
-
- return NGX_CONF_ERROR;
- }
-
- if (conf->upstream.busy_buffers_size
- > (conf->upstream.bufs.num - 1) * conf->upstream.bufs.size)
- {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "\"fastcgi_busy_buffers_size\" must be less than "
- "the size of all \"fastcgi_buffers\" minus one buffer");
-
- return NGX_CONF_ERROR;
- }
-
-
- ngx_conf_merge_size_value(conf->upstream.temp_file_write_size_conf,
- prev->upstream.temp_file_write_size_conf,
- NGX_CONF_UNSET_SIZE);
-
- if (conf->upstream.temp_file_write_size_conf == NGX_CONF_UNSET_SIZE) {
- conf->upstream.temp_file_write_size = 2 * size;
- } else {
- conf->upstream.temp_file_write_size =
- conf->upstream.temp_file_write_size_conf;
- }
-
- if (conf->upstream.temp_file_write_size < size) {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "\"fastcgi_temp_file_write_size\" must be equal to or greater "
- "than the maximum of the value of \"fastcgi_buffer_size\" and "
- "one of the \"fastcgi_buffers\"");
-
- return NGX_CONF_ERROR;
- }
-
-
- ngx_conf_merge_size_value(conf->upstream.max_temp_file_size_conf,
- prev->upstream.max_temp_file_size_conf,
- NGX_CONF_UNSET_SIZE);
-
- if (conf->upstream.max_temp_file_size_conf == NGX_CONF_UNSET_SIZE) {
- conf->upstream.max_temp_file_size = 1024 * 1024 * 1024;
- } else {
- conf->upstream.max_temp_file_size =
- conf->upstream.max_temp_file_size_conf;
- }
-
- if (conf->upstream.max_temp_file_size != 0
- && conf->upstream.max_temp_file_size < size)
- {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "\"fastcgi_max_temp_file_size\" must be equal to zero to disable "
- "temporary files usage or must be equal to or greater than "
- "the maximum of the value of \"fastcgi_buffer_size\" and "
- "one of the \"fastcgi_buffers\"");
-
- return NGX_CONF_ERROR;
- }
-
-
- ngx_conf_merge_bitmask_value(conf->upstream.ignore_headers,
- prev->upstream.ignore_headers,
- NGX_CONF_BITMASK_SET);
-
-
- ngx_conf_merge_bitmask_value(conf->upstream.next_upstream,
- prev->upstream.next_upstream,
- (NGX_CONF_BITMASK_SET
- |NGX_HTTP_UPSTREAM_FT_ERROR
- |NGX_HTTP_UPSTREAM_FT_TIMEOUT));
-
- if (conf->upstream.next_upstream & NGX_HTTP_UPSTREAM_FT_OFF) {
- conf->upstream.next_upstream = NGX_CONF_BITMASK_SET
- |NGX_HTTP_UPSTREAM_FT_OFF;
- }
-
- if (ngx_conf_merge_path_value(cf, &conf->upstream.temp_path,
- prev->upstream.temp_path,
- &ngx_http_fastcgi_temp_path)
- != NGX_OK)
- {
- return NGX_CONF_ERROR;
- }
-
-#if (NGX_HTTP_CACHE)
-
- if (conf->upstream.cache == NGX_CONF_UNSET) {
- ngx_conf_merge_value(conf->upstream.cache,
- prev->upstream.cache, 0);
-
- conf->upstream.cache_zone = prev->upstream.cache_zone;
- conf->upstream.cache_value = prev->upstream.cache_value;
- }
-
- if (conf->upstream.cache_zone && conf->upstream.cache_zone->data == NULL) {
- ngx_shm_zone_t *shm_zone;
-
- shm_zone = conf->upstream.cache_zone;
-
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "\"fastcgi_cache\" zone \"%V\" is unknown",
- &shm_zone->shm.name);
-
- return NGX_CONF_ERROR;
- }
-
- ngx_conf_merge_uint_value(conf->upstream.cache_min_uses,
- prev->upstream.cache_min_uses, 1);
-
- ngx_conf_merge_off_value(conf->upstream.cache_max_range_offset,
- prev->upstream.cache_max_range_offset,
- NGX_MAX_OFF_T_VALUE);
-
- ngx_conf_merge_bitmask_value(conf->upstream.cache_use_stale,
- prev->upstream.cache_use_stale,
- (NGX_CONF_BITMASK_SET
- |NGX_HTTP_UPSTREAM_FT_OFF));
-
- if (conf->upstream.cache_use_stale & NGX_HTTP_UPSTREAM_FT_OFF) {
- conf->upstream.cache_use_stale = NGX_CONF_BITMASK_SET
- |NGX_HTTP_UPSTREAM_FT_OFF;
- }
-
- if (conf->upstream.cache_use_stale & NGX_HTTP_UPSTREAM_FT_ERROR) {
- conf->upstream.cache_use_stale |= NGX_HTTP_UPSTREAM_FT_NOLIVE;
- }
-
- if (conf->upstream.cache_methods == 0) {
- conf->upstream.cache_methods = prev->upstream.cache_methods;
- }
-
- conf->upstream.cache_methods |= NGX_HTTP_GET|NGX_HTTP_HEAD;
-
- ngx_conf_merge_ptr_value(conf->upstream.cache_bypass,
- prev->upstream.cache_bypass, NULL);
-
- ngx_conf_merge_ptr_value(conf->upstream.no_cache,
- prev->upstream.no_cache, NULL);
-
- ngx_conf_merge_ptr_value(conf->upstream.cache_valid,
- prev->upstream.cache_valid, NULL);
-
- if (conf->cache_key.value.data == NULL) {
- conf->cache_key = prev->cache_key;
- }
-
- if (conf->upstream.cache && conf->cache_key.value.data == NULL) {
- ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
- "no \"fastcgi_cache_key\" for \"fastcgi_cache\"");
- }
-
- ngx_conf_merge_value(conf->upstream.cache_lock,
- prev->upstream.cache_lock, 0);
-
- ngx_conf_merge_msec_value(conf->upstream.cache_lock_timeout,
- prev->upstream.cache_lock_timeout, 5000);
-
- ngx_conf_merge_msec_value(conf->upstream.cache_lock_age,
- prev->upstream.cache_lock_age, 5000);
-
- ngx_conf_merge_value(conf->upstream.cache_revalidate,
- prev->upstream.cache_revalidate, 0);
-
- ngx_conf_merge_value(conf->upstream.cache_background_update,
- prev->upstream.cache_background_update, 0);
-
-#endif
-
- ngx_conf_merge_value(conf->upstream.pass_request_headers,
- prev->upstream.pass_request_headers, 1);
- ngx_conf_merge_value(conf->upstream.pass_request_body,
- prev->upstream.pass_request_body, 1);
-
- ngx_conf_merge_value(conf->upstream.intercept_errors,
- prev->upstream.intercept_errors, 0);
-
- ngx_conf_merge_ptr_value(conf->catch_stderr, prev->catch_stderr, NULL);
-
- ngx_conf_merge_value(conf->keep_conn, prev->keep_conn, 0);
-
-
- ngx_conf_merge_str_value(conf->index, prev->index, "");
-
- hash.max_size = 512;
- hash.bucket_size = ngx_align(64, ngx_cacheline_size);
- hash.name = "fastcgi_hide_headers_hash";
-
- if (ngx_http_upstream_hide_headers_hash(cf, &conf->upstream,
- &prev->upstream, ngx_http_fastcgi_hide_headers, &hash)
- != NGX_OK)
- {
- return NGX_CONF_ERROR;
- }
-
- clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);
-
- if (clcf->noname
- && conf->upstream.upstream == NULL && conf->fastcgi_lengths == NULL)
- {
- conf->upstream.upstream = prev->upstream.upstream;
- conf->fastcgi_lengths = prev->fastcgi_lengths;
- conf->fastcgi_values = prev->fastcgi_values;
- }
-
- if (clcf->lmt_excpt && clcf->handler == NULL
- && (conf->upstream.upstream || conf->fastcgi_lengths))
- {
- clcf->handler = ngx_http_fastcgi_handler;
- }
-
-#if (NGX_PCRE)
- if (conf->split_regex == NULL) {
- conf->split_regex = prev->split_regex;
- conf->split_name = prev->split_name;
- }
-#endif
-
- if (conf->params_source == NULL) {
- conf->params = prev->params;
-#if (NGX_HTTP_CACHE)
- conf->params_cache = prev->params_cache;
-#endif
- conf->params_source = prev->params_source;
- }
-
- rc = ngx_http_fastcgi_init_params(cf, conf, &conf->params, NULL);
- if (rc != NGX_OK) {
- return NGX_CONF_ERROR;
- }
-
-#if (NGX_HTTP_CACHE)
-
- if (conf->upstream.cache) {
- rc = ngx_http_fastcgi_init_params(cf, conf, &conf->params_cache,
- ngx_http_fastcgi_cache_headers);
- if (rc != NGX_OK) {
- return NGX_CONF_ERROR;
- }
- }
-
-#endif
-
- /*
- * special handling to preserve conf->params in the "http" section
- * to inherit it to all servers
- */
-
- if (prev->params.hash.buckets == NULL
- && conf->params_source == prev->params_source)
- {
- prev->params = conf->params;
-#if (NGX_HTTP_CACHE)
- prev->params_cache = conf->params_cache;
-#endif
- }
-
- return NGX_CONF_OK;
-}
-
-
-static ngx_int_t
-ngx_http_fastcgi_init_params(ngx_conf_t *cf, ngx_http_fastcgi_loc_conf_t *conf,
- ngx_http_fastcgi_params_t *params, ngx_keyval_t *default_params)
-{
- u_char *p;
- size_t size;
- uintptr_t *code;
- ngx_uint_t i, nsrc;
- ngx_array_t headers_names, params_merged;
- ngx_keyval_t *h;
- ngx_hash_key_t *hk;
- ngx_hash_init_t hash;
- ngx_http_upstream_param_t *src, *s;
- ngx_http_script_compile_t sc;
- ngx_http_script_copy_code_t *copy;
-
- if (params->hash.buckets) {
- return NGX_OK;
- }
-
- if (conf->params_source == NULL && default_params == NULL) {
- params->hash.buckets = (void *) 1;
- return NGX_OK;
- }
-
- params->lengths = ngx_array_create(cf->pool, 64, 1);
- if (params->lengths == NULL) {
- return NGX_ERROR;
- }
-
- params->values = ngx_array_create(cf->pool, 512, 1);
- if (params->values == NULL) {
- return NGX_ERROR;
- }
-
- if (ngx_array_init(&headers_names, cf->temp_pool, 4, sizeof(ngx_hash_key_t))
- != NGX_OK)
- {
- return NGX_ERROR;
- }
-
- if (conf->params_source) {
- src = conf->params_source->elts;
- nsrc = conf->params_source->nelts;
-
- } else {
- src = NULL;
- nsrc = 0;
- }
-
- if (default_params) {
- if (ngx_array_init(&params_merged, cf->temp_pool, 4,
- sizeof(ngx_http_upstream_param_t))
- != NGX_OK)
- {
- return NGX_ERROR;
- }
-
- for (i = 0; i < nsrc; i++) {
-
- s = ngx_array_push(&params_merged);
- if (s == NULL) {
- return NGX_ERROR;
- }
-
- *s = src[i];
- }
-
- h = default_params;
-
- while (h->key.len) {
-
- src = params_merged.elts;
- nsrc = params_merged.nelts;
-
- for (i = 0; i < nsrc; i++) {
- if (ngx_strcasecmp(h->key.data, src[i].key.data) == 0) {
- goto next;
- }
- }
-
- s = ngx_array_push(&params_merged);
- if (s == NULL) {
- return NGX_ERROR;
- }
-
- s->key = h->key;
- s->value = h->value;
- s->skip_empty = 1;
-
- next:
-
- h++;
- }
-
- src = params_merged.elts;
- nsrc = params_merged.nelts;
- }
-
- for (i = 0; i < nsrc; i++) {
-
- if (src[i].key.len > sizeof("HTTP_") - 1
- && ngx_strncmp(src[i].key.data, "HTTP_", sizeof("HTTP_") - 1) == 0)
- {
- hk = ngx_array_push(&headers_names);
- if (hk == NULL) {
- return NGX_ERROR;
- }
-
- hk->key.len = src[i].key.len - 5;
- hk->key.data = src[i].key.data + 5;
- hk->key_hash = ngx_hash_key_lc(hk->key.data, hk->key.len);
- hk->value = (void *) 1;
-
- if (src[i].value.len == 0) {
- continue;
- }
- }
-
- copy = ngx_array_push_n(params->lengths,
- sizeof(ngx_http_script_copy_code_t));
- if (copy == NULL) {
- return NGX_ERROR;
- }
-
- copy->code = (ngx_http_script_code_pt) (void *)
- ngx_http_script_copy_len_code;
- copy->len = src[i].key.len;
-
- copy = ngx_array_push_n(params->lengths,
- sizeof(ngx_http_script_copy_code_t));
- if (copy == NULL) {
- return NGX_ERROR;
- }
-
- copy->code = (ngx_http_script_code_pt) (void *)
- ngx_http_script_copy_len_code;
- copy->len = src[i].skip_empty;
-
-
- size = (sizeof(ngx_http_script_copy_code_t)
- + src[i].key.len + sizeof(uintptr_t) - 1)
- & ~(sizeof(uintptr_t) - 1);
-
- copy = ngx_array_push_n(params->values, size);
- if (copy == NULL) {
- return NGX_ERROR;
- }
-
- copy->code = ngx_http_script_copy_code;
- copy->len = src[i].key.len;
-
- p = (u_char *) copy + sizeof(ngx_http_script_copy_code_t);
- ngx_memcpy(p, src[i].key.data, src[i].key.len);
-
-
- ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));
-
- sc.cf = cf;
- sc.source = &src[i].value;
- sc.flushes = &params->flushes;
- sc.lengths = &params->lengths;
- sc.values = &params->values;
-
- if (ngx_http_script_compile(&sc) != NGX_OK) {
- return NGX_ERROR;
- }
-
- code = ngx_array_push_n(params->lengths, sizeof(uintptr_t));
- if (code == NULL) {
- return NGX_ERROR;
- }
-
- *code = (uintptr_t) NULL;
-
-
- code = ngx_array_push_n(params->values, sizeof(uintptr_t));
- if (code == NULL) {
- return NGX_ERROR;
- }
-
- *code = (uintptr_t) NULL;
- }
-
- code = ngx_array_push_n(params->lengths, sizeof(uintptr_t));
- if (code == NULL) {
- return NGX_ERROR;
- }
-
- *code = (uintptr_t) NULL;
-
- params->number = headers_names.nelts;
-
- hash.hash = &params->hash;
- hash.key = ngx_hash_key_lc;
- hash.max_size = 512;
- hash.bucket_size = 64;
- hash.name = "fastcgi_params_hash";
- hash.pool = cf->pool;
- hash.temp_pool = NULL;
-
- return ngx_hash_init(&hash, headers_names.elts, headers_names.nelts);
-}
-
-
-static ngx_int_t
-ngx_http_fastcgi_script_name_variable(ngx_http_request_t *r,
- ngx_http_variable_value_t *v, uintptr_t data)
-{
- u_char *p;
- ngx_http_fastcgi_ctx_t *f;
- ngx_http_fastcgi_loc_conf_t *flcf;
-
- flcf = ngx_http_get_module_loc_conf(r, ngx_http_fastcgi_module);
-
- f = ngx_http_fastcgi_split(r, flcf);
-
- if (f == NULL) {
- return NGX_ERROR;
- }
-
- if (f->script_name.len == 0
- || f->script_name.data[f->script_name.len - 1] != '/')
- {
- v->len = f->script_name.len;
- v->valid = 1;
- v->no_cacheable = 0;
- v->not_found = 0;
- v->data = f->script_name.data;
-
- return NGX_OK;
- }
-
- v->len = f->script_name.len + flcf->index.len;
-
- v->data = ngx_pnalloc(r->pool, v->len);
- if (v->data == NULL) {
- return NGX_ERROR;
- }
-
- p = ngx_copy(v->data, f->script_name.data, f->script_name.len);
- ngx_memcpy(p, flcf->index.data, flcf->index.len);
-
- return NGX_OK;
-}
-
-
-static ngx_int_t
-ngx_http_fastcgi_path_info_variable(ngx_http_request_t *r,
- ngx_http_variable_value_t *v, uintptr_t data)
-{
- ngx_http_fastcgi_ctx_t *f;
- ngx_http_fastcgi_loc_conf_t *flcf;
-
- flcf = ngx_http_get_module_loc_conf(r, ngx_http_fastcgi_module);
-
- f = ngx_http_fastcgi_split(r, flcf);
-
- if (f == NULL) {
- return NGX_ERROR;
- }
-
- v->len = f->path_info.len;
- v->valid = 1;
- v->no_cacheable = 0;
- v->not_found = 0;
- v->data = f->path_info.data;
-
- return NGX_OK;
-}
-
-
-static ngx_http_fastcgi_ctx_t *
-ngx_http_fastcgi_split(ngx_http_request_t *r, ngx_http_fastcgi_loc_conf_t *flcf)
-{
- ngx_http_fastcgi_ctx_t *f;
-#if (NGX_PCRE)
- ngx_int_t n;
- int captures[(1 + 2) * 3];
-
- f = ngx_http_get_module_ctx(r, ngx_http_fastcgi_module);
-
- if (f == NULL) {
- f = ngx_pcalloc(r->pool, sizeof(ngx_http_fastcgi_ctx_t));
- if (f == NULL) {
- return NULL;
- }
-
- ngx_http_set_ctx(r, f, ngx_http_fastcgi_module);
- }
-
- if (f->script_name.len) {
- return f;
- }
-
- if (flcf->split_regex == NULL) {
- f->script_name = r->uri;
- return f;
- }
-
- n = ngx_regex_exec(flcf->split_regex, &r->uri, captures, (1 + 2) * 3);
-
- if (n >= 0) { /* match */
- f->script_name.len = captures[3] - captures[2];
- f->script_name.data = r->uri.data + captures[2];
-
- f->path_info.len = captures[5] - captures[4];
- f->path_info.data = r->uri.data + captures[4];
-
- return f;
- }
-
- if (n == NGX_REGEX_NO_MATCHED) {
- f->script_name = r->uri;
- return f;
- }
-
- ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
- ngx_regex_exec_n " failed: %i on \"%V\" using \"%V\"",
- n, &r->uri, &flcf->split_name);
- return NULL;
-
-#else
-
- f = ngx_http_get_module_ctx(r, ngx_http_fastcgi_module);
-
- if (f == NULL) {
- f = ngx_pcalloc(r->pool, sizeof(ngx_http_fastcgi_ctx_t));
- if (f == NULL) {
- return NULL;
- }
-
- ngx_http_set_ctx(r, f, ngx_http_fastcgi_module);
- }
-
- f->script_name = r->uri;
-
- return f;
-
-#endif
-}
-
-
-static char *
-ngx_http_fastcgi_pass(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
-{
- ngx_http_fastcgi_loc_conf_t *flcf = conf;
-
- ngx_url_t u;
- ngx_str_t *value, *url;
- ngx_uint_t n;
- ngx_http_core_loc_conf_t *clcf;
- ngx_http_script_compile_t sc;
-
- if (flcf->upstream.upstream || flcf->fastcgi_lengths) {
- return "is duplicate";
- }
-
- clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);
-
- clcf->handler = ngx_http_fastcgi_handler;
-
- if (clcf->name.data[clcf->name.len - 1] == '/') {
- clcf->auto_redirect = 1;
- }
-
- value = cf->args->elts;
-
- url = &value[1];
-
- n = ngx_http_script_variables_count(url);
-
- if (n) {
-
- ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));
-
- sc.cf = cf;
- sc.source = url;
- sc.lengths = &flcf->fastcgi_lengths;
- sc.values = &flcf->fastcgi_values;
- sc.variables = n;
- sc.complete_lengths = 1;
- sc.complete_values = 1;
-
- if (ngx_http_script_compile(&sc) != NGX_OK) {
- return NGX_CONF_ERROR;
- }
-
- return NGX_CONF_OK;
- }
-
- ngx_memzero(&u, sizeof(ngx_url_t));
-
- u.url = value[1];
- u.no_resolve = 1;
-
- flcf->upstream.upstream = ngx_http_upstream_add(cf, &u, 0);
- if (flcf->upstream.upstream == NULL) {
- return NGX_CONF_ERROR;
- }
-
- return NGX_CONF_OK;
-}
-
-
-static char *
-ngx_http_fastcgi_split_path_info(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
-{
-#if (NGX_PCRE)
- ngx_http_fastcgi_loc_conf_t *flcf = conf;
-
- ngx_str_t *value;
- ngx_regex_compile_t rc;
- u_char errstr[NGX_MAX_CONF_ERRSTR];
-
- value = cf->args->elts;
-
- flcf->split_name = value[1];
-
- ngx_memzero(&rc, sizeof(ngx_regex_compile_t));
-
- rc.pattern = value[1];
- rc.pool = cf->pool;
- rc.err.len = NGX_MAX_CONF_ERRSTR;
- rc.err.data = errstr;
-
- if (ngx_regex_compile(&rc) != NGX_OK) {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%V", &rc.err);
- return NGX_CONF_ERROR;
- }
-
- if (rc.captures != 2) {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "pattern \"%V\" must have 2 captures", &value[1]);
- return NGX_CONF_ERROR;
- }
-
- flcf->split_regex = rc.regex;
-
- return NGX_CONF_OK;
-
-#else
-
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "\"%V\" requires PCRE library", &cmd->name);
- return NGX_CONF_ERROR;
-
-#endif
-}
-
-
-static char *
-ngx_http_fastcgi_store(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
-{
- ngx_http_fastcgi_loc_conf_t *flcf = conf;
-
- ngx_str_t *value;
- ngx_http_script_compile_t sc;
-
- if (flcf->upstream.store != NGX_CONF_UNSET) {
- return "is duplicate";
- }
-
- value = cf->args->elts;
-
- if (ngx_strcmp(value[1].data, "off") == 0) {
- flcf->upstream.store = 0;
- return NGX_CONF_OK;
- }
-
-#if (NGX_HTTP_CACHE)
- if (flcf->upstream.cache > 0) {
- return "is incompatible with \"fastcgi_cache\"";
- }
-#endif
-
- flcf->upstream.store = 1;
-
- if (ngx_strcmp(value[1].data, "on") == 0) {
- return NGX_CONF_OK;
- }
-
- /* include the terminating '\0' into script */
- value[1].len++;
-
- ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));
-
- sc.cf = cf;
- sc.source = &value[1];
- sc.lengths = &flcf->upstream.store_lengths;
- sc.values = &flcf->upstream.store_values;
- sc.variables = ngx_http_script_variables_count(&value[1]);
- sc.complete_lengths = 1;
- sc.complete_values = 1;
-
- if (ngx_http_script_compile(&sc) != NGX_OK) {
- return NGX_CONF_ERROR;
- }
-
- return NGX_CONF_OK;
-}
-
-
-#if (NGX_HTTP_CACHE)
-
-static char *
-ngx_http_fastcgi_cache(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
-{
- ngx_http_fastcgi_loc_conf_t *flcf = conf;
-
- ngx_str_t *value;
- ngx_http_complex_value_t cv;
- ngx_http_compile_complex_value_t ccv;
-
- value = cf->args->elts;
-
- if (flcf->upstream.cache != NGX_CONF_UNSET) {
- return "is duplicate";
- }
-
- if (ngx_strcmp(value[1].data, "off") == 0) {
- flcf->upstream.cache = 0;
- return NGX_CONF_OK;
- }
-
- if (flcf->upstream.store > 0) {
- return "is incompatible with \"fastcgi_store\"";
- }
-
- flcf->upstream.cache = 1;
-
- 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) {
-
- flcf->upstream.cache_value = ngx_palloc(cf->pool,
- sizeof(ngx_http_complex_value_t));
- if (flcf->upstream.cache_value == NULL) {
- return NGX_CONF_ERROR;
- }
-
- *flcf->upstream.cache_value = cv;
-
- return NGX_CONF_OK;
- }
-
- flcf->upstream.cache_zone = ngx_shared_memory_add(cf, &value[1], 0,
- &ngx_http_fastcgi_module);
- if (flcf->upstream.cache_zone == NULL) {
- return NGX_CONF_ERROR;
- }
-
- return NGX_CONF_OK;
-}
-
-
-static char *
-ngx_http_fastcgi_cache_key(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
-{
- ngx_http_fastcgi_loc_conf_t *flcf = conf;
-
- ngx_str_t *value;
- ngx_http_compile_complex_value_t ccv;
-
- value = cf->args->elts;
-
- if (flcf->cache_key.value.data) {
- return "is duplicate";
- }
-
- ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));
-
- ccv.cf = cf;
- ccv.value = &value[1];
- ccv.complex_value = &flcf->cache_key;
-
- if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
- return NGX_CONF_ERROR;
- }
-
- return NGX_CONF_OK;
-}
-
-#endif
-
-
-static char *
-ngx_http_fastcgi_lowat_check(ngx_conf_t *cf, void *post, void *data)
-{
-#if (NGX_FREEBSD)
- ssize_t *np = data;
-
- if ((u_long) *np >= ngx_freebsd_net_inet_tcp_sendspace) {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "\"fastcgi_send_lowat\" must be less than %d "
- "(sysctl net.inet.tcp.sendspace)",
- ngx_freebsd_net_inet_tcp_sendspace);
-
- return NGX_CONF_ERROR;
- }
-
-#elif !(NGX_HAVE_SO_SNDLOWAT)
- ssize_t *np = data;
-
- ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
- "\"fastcgi_send_lowat\" is not supported, ignored");
-
- *np = 0;
-
-#endif
-
- return NGX_CONF_OK;
-}
diff --git a/nginx/src/http/modules/ngx_http_flv_module.c b/nginx/src/http/modules/ngx_http_flv_module.c
deleted file mode 100644
index 7b72fae..0000000
--- a/nginx/src/http/modules/ngx_http_flv_module.c
+++ /dev/null
@@ -1,266 +0,0 @@
-
-/*
- * Copyright (C) Igor Sysoev
- * Copyright (C) Nginx, Inc.
- */
-
-#include <ngx_config.h>
-#include <ngx_core.h>
-#include <ngx_http.h>
-
-
-static char *ngx_http_flv(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
-
-static ngx_command_t ngx_http_flv_commands[] = {
-
- { ngx_string("flv"),
- NGX_HTTP_LOC_CONF|NGX_CONF_NOARGS,
- ngx_http_flv,
- 0,
- 0,
- NULL },
-
- ngx_null_command
-};
-
-
-static u_char ngx_flv_header[] = "FLV\x1\x5\0\0\0\x9\0\0\0\0";
-
-
-static ngx_http_module_t ngx_http_flv_module_ctx = {
- NULL, /* preconfiguration */
- NULL, /* postconfiguration */
-
- NULL, /* create main configuration */
- NULL, /* init main configuration */
-
- NULL, /* create server configuration */
- NULL, /* merge server configuration */
-
- NULL, /* create location configuration */
- NULL /* merge location configuration */
-};
-
-
-ngx_module_t ngx_http_flv_module = {
- NGX_MODULE_V1,
- &ngx_http_flv_module_ctx, /* module context */
- ngx_http_flv_commands, /* module directives */
- NGX_HTTP_MODULE, /* module type */
- NULL, /* init master */
- NULL, /* init module */
- NULL, /* init process */
- NULL, /* init thread */
- NULL, /* exit thread */
- NULL, /* exit process */
- NULL, /* exit master */
- NGX_MODULE_V1_PADDING
-};
-
-
-static ngx_int_t
-ngx_http_flv_handler(ngx_http_request_t *r)
-{
- u_char *last;
- off_t start, len;
- size_t root;
- ngx_int_t rc;
- ngx_uint_t level, i;
- ngx_str_t path, value;
- ngx_log_t *log;
- ngx_buf_t *b;
- ngx_chain_t out[2];
- ngx_open_file_info_t of;
- ngx_http_core_loc_conf_t *clcf;
-
- if (!(r->method & (NGX_HTTP_GET|NGX_HTTP_HEAD))) {
- return NGX_HTTP_NOT_ALLOWED;
- }
-
- if (r->uri.data[r->uri.len - 1] == '/') {
- return NGX_DECLINED;
- }
-
- rc = ngx_http_discard_request_body(r);
-
- if (rc != NGX_OK) {
- return rc;
- }
-
- last = ngx_http_map_uri_to_path(r, &path, &root, 0);
- if (last == NULL) {
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
-
- log = r->connection->log;
-
- path.len = last - path.data;
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0,
- "http flv filename: \"%V\"", &path);
-
- clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
-
- ngx_memzero(&of, sizeof(ngx_open_file_info_t));
-
- of.read_ahead = clcf->read_ahead;
- of.directio = clcf->directio;
- of.valid = clcf->open_file_cache_valid;
- of.min_uses = clcf->open_file_cache_min_uses;
- of.errors = clcf->open_file_cache_errors;
- of.events = clcf->open_file_cache_events;
-
- if (ngx_http_set_disable_symlinks(r, clcf, &path, &of) != NGX_OK) {
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
-
- if (ngx_open_cached_file(clcf->open_file_cache, &path, &of, r->pool)
- != NGX_OK)
- {
- switch (of.err) {
-
- case 0:
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
-
- case NGX_ENOENT:
- case NGX_ENOTDIR:
- case NGX_ENAMETOOLONG:
-
- level = NGX_LOG_ERR;
- rc = NGX_HTTP_NOT_FOUND;
- break;
-
- case NGX_EACCES:
-#if (NGX_HAVE_OPENAT)
- case NGX_EMLINK:
- case NGX_ELOOP:
-#endif
-
- level = NGX_LOG_ERR;
- rc = NGX_HTTP_FORBIDDEN;
- break;
-
- default:
-
- level = NGX_LOG_CRIT;
- rc = NGX_HTTP_INTERNAL_SERVER_ERROR;
- break;
- }
-
- if (rc != NGX_HTTP_NOT_FOUND || clcf->log_not_found) {
- ngx_log_error(level, log, of.err,
- "%s \"%s\" failed", of.failed, path.data);
- }
-
- return rc;
- }
-
- if (!of.is_file) {
-
- if (ngx_close_file(of.fd) == NGX_FILE_ERROR) {
- ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
- ngx_close_file_n " \"%s\" failed", path.data);
- }
-
- return NGX_DECLINED;
- }
-
- r->root_tested = !r->error_page;
-
- start = 0;
- len = of.size;
- i = 1;
-
- if (r->args.len) {
-
- if (ngx_http_arg(r, (u_char *) "start", 5, &value) == NGX_OK) {
-
- start = ngx_atoof(value.data, value.len);
-
- if (start == NGX_ERROR || start >= len) {
- start = 0;
- }
-
- if (start) {
- len = sizeof(ngx_flv_header) - 1 + len - start;
- i = 0;
- }
- }
- }
-
- log->action = "sending flv to client";
-
- r->headers_out.status = NGX_HTTP_OK;
- r->headers_out.content_length_n = len;
- r->headers_out.last_modified_time = of.mtime;
-
- if (ngx_http_set_etag(r) != NGX_OK) {
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
-
- if (ngx_http_set_content_type(r) != NGX_OK) {
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
-
- if (i == 0) {
- b = ngx_calloc_buf(r->pool);
- if (b == NULL) {
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
-
- b->pos = ngx_flv_header;
- b->last = ngx_flv_header + sizeof(ngx_flv_header) - 1;
- b->memory = 1;
-
- out[0].buf = b;
- out[0].next = &out[1];
- }
-
-
- b = ngx_calloc_buf(r->pool);
- if (b == NULL) {
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
-
- b->file = ngx_pcalloc(r->pool, sizeof(ngx_file_t));
- if (b->file == NULL) {
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
-
- r->allow_ranges = 1;
-
- rc = ngx_http_send_header(r);
-
- if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) {
- return rc;
- }
-
- b->file_pos = start;
- b->file_last = of.size;
-
- b->in_file = b->file_last ? 1: 0;
- b->last_buf = (r == r->main) ? 1 : 0;
- b->last_in_chain = 1;
-
- b->file->fd = of.fd;
- b->file->name = path;
- b->file->log = log;
- b->file->directio = of.is_directio;
-
- out[1].buf = b;
- out[1].next = NULL;
-
- return ngx_http_output_filter(r, &out[i]);
-}
-
-
-static char *
-ngx_http_flv(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
-{
- ngx_http_core_loc_conf_t *clcf;
-
- clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);
- clcf->handler = ngx_http_flv_handler;
-
- return NGX_CONF_OK;
-}
diff --git a/nginx/src/http/modules/ngx_http_geo_module.c b/nginx/src/http/modules/ngx_http_geo_module.c
deleted file mode 100644
index c11bafa..0000000
--- a/nginx/src/http/modules/ngx_http_geo_module.c
+++ /dev/null
@@ -1,1668 +0,0 @@
-
-/*
- * Copyright (C) Igor Sysoev
- * Copyright (C) Nginx, Inc.
- */
-
-
-#include <ngx_config.h>
-#include <ngx_core.h>
-#include <ngx_http.h>
-
-
-typedef struct {
- ngx_http_variable_value_t *value;
- u_short start;
- u_short end;
-} ngx_http_geo_range_t;
-
-
-typedef struct {
- ngx_radix_tree_t *tree;
-#if (NGX_HAVE_INET6)
- ngx_radix_tree_t *tree6;
-#endif
-} ngx_http_geo_trees_t;
-
-
-typedef struct {
- ngx_http_geo_range_t **low;
- ngx_http_variable_value_t *default_value;
-} ngx_http_geo_high_ranges_t;
-
-
-typedef struct {
- ngx_str_node_t sn;
- ngx_http_variable_value_t *value;
- size_t offset;
-} ngx_http_geo_variable_value_node_t;
-
-
-typedef struct {
- ngx_http_variable_value_t *value;
- ngx_str_t *net;
- ngx_http_geo_high_ranges_t high;
- ngx_radix_tree_t *tree;
-#if (NGX_HAVE_INET6)
- ngx_radix_tree_t *tree6;
-#endif
- ngx_rbtree_t rbtree;
- ngx_rbtree_node_t sentinel;
- ngx_array_t *proxies;
- ngx_pool_t *pool;
- ngx_pool_t *temp_pool;
-
- size_t data_size;
-
- ngx_str_t include_name;
- ngx_uint_t includes;
- ngx_uint_t entries;
-
- unsigned ranges:1;
- unsigned outside_entries:1;
- unsigned allow_binary_include:1;
- unsigned binary_include:1;
- unsigned proxy_recursive:1;
-} ngx_http_geo_conf_ctx_t;
-
-
-typedef struct {
- union {
- ngx_http_geo_trees_t trees;
- ngx_http_geo_high_ranges_t high;
- } u;
-
- ngx_array_t *proxies;
- unsigned proxy_recursive:1;
-
- ngx_int_t index;
-} ngx_http_geo_ctx_t;
-
-
-static ngx_int_t ngx_http_geo_addr(ngx_http_request_t *r,
- ngx_http_geo_ctx_t *ctx, ngx_addr_t *addr);
-static ngx_int_t ngx_http_geo_real_addr(ngx_http_request_t *r,
- ngx_http_geo_ctx_t *ctx, ngx_addr_t *addr);
-static char *ngx_http_geo_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
-static char *ngx_http_geo(ngx_conf_t *cf, ngx_command_t *dummy, void *conf);
-static char *ngx_http_geo_range(ngx_conf_t *cf, ngx_http_geo_conf_ctx_t *ctx,
- ngx_str_t *value);
-static char *ngx_http_geo_add_range(ngx_conf_t *cf,
- ngx_http_geo_conf_ctx_t *ctx, in_addr_t start, in_addr_t end);
-static ngx_uint_t ngx_http_geo_delete_range(ngx_conf_t *cf,
- ngx_http_geo_conf_ctx_t *ctx, in_addr_t start, in_addr_t end);
-static char *ngx_http_geo_cidr(ngx_conf_t *cf, ngx_http_geo_conf_ctx_t *ctx,
- ngx_str_t *value);
-static char *ngx_http_geo_cidr_add(ngx_conf_t *cf, ngx_http_geo_conf_ctx_t *ctx,
- ngx_cidr_t *cidr, ngx_str_t *value, ngx_str_t *net);
-static ngx_http_variable_value_t *ngx_http_geo_value(ngx_conf_t *cf,
- ngx_http_geo_conf_ctx_t *ctx, ngx_str_t *value);
-static char *ngx_http_geo_add_proxy(ngx_conf_t *cf,
- ngx_http_geo_conf_ctx_t *ctx, ngx_cidr_t *cidr);
-static ngx_int_t ngx_http_geo_cidr_value(ngx_conf_t *cf, ngx_str_t *net,
- ngx_cidr_t *cidr);
-static char *ngx_http_geo_include(ngx_conf_t *cf, ngx_http_geo_conf_ctx_t *ctx,
- ngx_str_t *name);
-static ngx_int_t ngx_http_geo_include_binary_base(ngx_conf_t *cf,
- ngx_http_geo_conf_ctx_t *ctx, ngx_str_t *name);
-static void ngx_http_geo_create_binary_base(ngx_http_geo_conf_ctx_t *ctx);
-static u_char *ngx_http_geo_copy_values(u_char *base, u_char *p,
- ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel);
-
-
-static ngx_command_t ngx_http_geo_commands[] = {
-
- { ngx_string("geo"),
- NGX_HTTP_MAIN_CONF|NGX_CONF_BLOCK|NGX_CONF_TAKE12,
- ngx_http_geo_block,
- NGX_HTTP_MAIN_CONF_OFFSET,
- 0,
- NULL },
-
- ngx_null_command
-};
-
-
-static ngx_http_module_t ngx_http_geo_module_ctx = {
- NULL, /* preconfiguration */
- NULL, /* postconfiguration */
-
- NULL, /* create main configuration */
- NULL, /* init main configuration */
-
- NULL, /* create server configuration */
- NULL, /* merge server configuration */
-
- NULL, /* create location configuration */
- NULL /* merge location configuration */
-};
-
-
-ngx_module_t ngx_http_geo_module = {
- NGX_MODULE_V1,
- &ngx_http_geo_module_ctx, /* module context */
- ngx_http_geo_commands, /* module directives */
- NGX_HTTP_MODULE, /* module type */
- NULL, /* init master */
- NULL, /* init module */
- NULL, /* init process */
- NULL, /* init thread */
- NULL, /* exit thread */
- NULL, /* exit process */
- NULL, /* exit master */
- NGX_MODULE_V1_PADDING
-};
-
-
-typedef struct {
- u_char GEORNG[6];
- u_char version;
- u_char ptr_size;
- uint32_t endianness;
- uint32_t crc32;
-} ngx_http_geo_header_t;
-
-
-static ngx_http_geo_header_t ngx_http_geo_header = {
- { 'G', 'E', 'O', 'R', 'N', 'G' }, 0, sizeof(void *), 0x12345678, 0
-};
-
-
-/* geo range is AF_INET only */
-
-static ngx_int_t
-ngx_http_geo_cidr_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v,
- uintptr_t data)
-{
- ngx_http_geo_ctx_t *ctx = (ngx_http_geo_ctx_t *) data;
-
- in_addr_t inaddr;
- ngx_addr_t addr;
- struct sockaddr_in *sin;
- ngx_http_variable_value_t *vv;
-#if (NGX_HAVE_INET6)
- u_char *p;
- struct in6_addr *inaddr6;
-#endif
-
- if (ngx_http_geo_addr(r, ctx, &addr) != NGX_OK) {
- vv = (ngx_http_variable_value_t *)
- ngx_radix32tree_find(ctx->u.trees.tree, INADDR_NONE);
- goto done;
- }
-
- switch (addr.sockaddr->sa_family) {
-
-#if (NGX_HAVE_INET6)
- case AF_INET6:
- inaddr6 = &((struct sockaddr_in6 *) addr.sockaddr)->sin6_addr;
- p = inaddr6->s6_addr;
-
- if (IN6_IS_ADDR_V4MAPPED(inaddr6)) {
- inaddr = p[12] << 24;
- inaddr += p[13] << 16;
- inaddr += p[14] << 8;
- inaddr += p[15];
-
- vv = (ngx_http_variable_value_t *)
- ngx_radix32tree_find(ctx->u.trees.tree, inaddr);
-
- } else {
- vv = (ngx_http_variable_value_t *)
- ngx_radix128tree_find(ctx->u.trees.tree6, p);
- }
-
- break;
-#endif
-
- default: /* AF_INET */
- sin = (struct sockaddr_in *) addr.sockaddr;
- inaddr = ntohl(sin->sin_addr.s_addr);
-
- vv = (ngx_http_variable_value_t *)
- ngx_radix32tree_find(ctx->u.trees.tree, inaddr);
-
- break;
- }
-
-done:
-
- *v = *vv;
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "http geo: %v", v);
-
- return NGX_OK;
-}
-
-
-static ngx_int_t
-ngx_http_geo_range_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v,
- uintptr_t data)
-{
- ngx_http_geo_ctx_t *ctx = (ngx_http_geo_ctx_t *) data;
-
- in_addr_t inaddr;
- ngx_addr_t addr;
- ngx_uint_t n;
- struct sockaddr_in *sin;
- ngx_http_geo_range_t *range;
-#if (NGX_HAVE_INET6)
- u_char *p;
- struct in6_addr *inaddr6;
-#endif
-
- *v = *ctx->u.high.default_value;
-
- if (ngx_http_geo_addr(r, ctx, &addr) == NGX_OK) {
-
- switch (addr.sockaddr->sa_family) {
-
-#if (NGX_HAVE_INET6)
- case AF_INET6:
- inaddr6 = &((struct sockaddr_in6 *) addr.sockaddr)->sin6_addr;
-
- if (IN6_IS_ADDR_V4MAPPED(inaddr6)) {
- p = inaddr6->s6_addr;
-
- inaddr = p[12] << 24;
- inaddr += p[13] << 16;
- inaddr += p[14] << 8;
- inaddr += p[15];
-
- } else {
- inaddr = INADDR_NONE;
- }
-
- break;
-#endif
-
- default: /* AF_INET */
- sin = (struct sockaddr_in *) addr.sockaddr;
- inaddr = ntohl(sin->sin_addr.s_addr);
- break;
- }
-
- } else {
- inaddr = INADDR_NONE;
- }
-
- if (ctx->u.high.low) {
- range = ctx->u.high.low[inaddr >> 16];
-
- if (range) {
- n = inaddr & 0xffff;
- do {
- if (n >= (ngx_uint_t) range->start
- && n <= (ngx_uint_t) range->end)
- {
- *v = *range->value;
- break;
- }
- } while ((++range)->value);
- }
- }
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "http geo: %v", v);
-
- return NGX_OK;
-}
-
-
-static ngx_int_t
-ngx_http_geo_addr(ngx_http_request_t *r, ngx_http_geo_ctx_t *ctx,
- ngx_addr_t *addr)
-{
- ngx_array_t *xfwd;
-
- if (ngx_http_geo_real_addr(r, ctx, addr) != NGX_OK) {
- return NGX_ERROR;
- }
-
- xfwd = &r->headers_in.x_forwarded_for;
-
- if (xfwd->nelts > 0 && ctx->proxies != NULL) {
- (void) ngx_http_get_forwarded_addr(r, addr, xfwd, NULL,
- ctx->proxies, ctx->proxy_recursive);
- }
-
- return NGX_OK;
-}
-
-
-static ngx_int_t
-ngx_http_geo_real_addr(ngx_http_request_t *r, ngx_http_geo_ctx_t *ctx,
- ngx_addr_t *addr)
-{
- ngx_http_variable_value_t *v;
-
- if (ctx->index == -1) {
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "http geo started: %V", &r->connection->addr_text);
-
- addr->sockaddr = r->connection->sockaddr;
- addr->socklen = r->connection->socklen;
- /* addr->name = r->connection->addr_text; */
-
- return NGX_OK;
- }
-
- v = ngx_http_get_flushed_variable(r, ctx->index);
-
- if (v == NULL || v->not_found) {
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "http geo not found");
-
- return NGX_ERROR;
- }
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "http geo started: %v", v);
-
- if (ngx_parse_addr(r->pool, addr, v->data, v->len) == NGX_OK) {
- return NGX_OK;
- }
-
- return NGX_ERROR;
-}
-
-
-static char *
-ngx_http_geo_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
-{
- char *rv;
- size_t len;
- ngx_str_t *value, name;
- ngx_uint_t i;
- ngx_conf_t save;
- ngx_pool_t *pool;
- ngx_array_t *a;
- ngx_http_variable_t *var;
- ngx_http_geo_ctx_t *geo;
- ngx_http_geo_conf_ctx_t ctx;
-#if (NGX_HAVE_INET6)
- static struct in6_addr zero;
-#endif
-
- value = cf->args->elts;
-
- geo = ngx_palloc(cf->pool, sizeof(ngx_http_geo_ctx_t));
- if (geo == NULL) {
- return NGX_CONF_ERROR;
- }
-
- name = value[1];
-
- if (name.data[0] != '$') {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "invalid variable name \"%V\"", &name);
- return NGX_CONF_ERROR;
- }
-
- name.len--;
- name.data++;
-
- if (cf->args->nelts == 3) {
-
- geo->index = ngx_http_get_variable_index(cf, &name);
- if (geo->index == NGX_ERROR) {
- return NGX_CONF_ERROR;
- }
-
- name = value[2];
-
- if (name.data[0] != '$') {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "invalid variable name \"%V\"", &name);
- return NGX_CONF_ERROR;
- }
-
- name.len--;
- name.data++;
-
- } else {
- geo->index = -1;
- }
-
- var = ngx_http_add_variable(cf, &name, NGX_HTTP_VAR_CHANGEABLE);
- if (var == NULL) {
- return NGX_CONF_ERROR;
- }
-
- pool = ngx_create_pool(NGX_DEFAULT_POOL_SIZE, cf->log);
- if (pool == NULL) {
- return NGX_CONF_ERROR;
- }
-
- ngx_memzero(&ctx, sizeof(ngx_http_geo_conf_ctx_t));
-
- ctx.temp_pool = ngx_create_pool(NGX_DEFAULT_POOL_SIZE, cf->log);
- if (ctx.temp_pool == NULL) {
- ngx_destroy_pool(pool);
- return NGX_CONF_ERROR;
- }
-
- ngx_rbtree_init(&ctx.rbtree, &ctx.sentinel, ngx_str_rbtree_insert_value);
-
- ctx.pool = cf->pool;
- ctx.data_size = sizeof(ngx_http_geo_header_t)
- + sizeof(ngx_http_variable_value_t)
- + 0x10000 * sizeof(ngx_http_geo_range_t *);
- ctx.allow_binary_include = 1;
-
- save = *cf;
- cf->pool = pool;
- cf->ctx = &ctx;
- cf->handler = ngx_http_geo;
- cf->handler_conf = conf;
-
- rv = ngx_conf_parse(cf, NULL);
-
- *cf = save;
-
- if (rv != NGX_CONF_OK) {
- goto failed;
- }
-
- geo->proxies = ctx.proxies;
- geo->proxy_recursive = ctx.proxy_recursive;
-
- if (ctx.ranges) {
-
- if (ctx.high.low && !ctx.binary_include) {
- for (i = 0; i < 0x10000; i++) {
- a = (ngx_array_t *) ctx.high.low[i];
-
- if (a == NULL) {
- continue;
- }
-
- if (a->nelts == 0) {
- ctx.high.low[i] = NULL;
- continue;
- }
-
- len = a->nelts * sizeof(ngx_http_geo_range_t);
-
- ctx.high.low[i] = ngx_palloc(cf->pool, len + sizeof(void *));
- if (ctx.high.low[i] == NULL) {
- goto failed;
- }
-
- ngx_memcpy(ctx.high.low[i], a->elts, len);
- ctx.high.low[i][a->nelts].value = NULL;
- ctx.data_size += len + sizeof(void *);
- }
-
- if (ctx.allow_binary_include
- && !ctx.outside_entries
- && ctx.entries > 100000
- && ctx.includes == 1)
- {
- ngx_http_geo_create_binary_base(&ctx);
- }
- }
-
- if (ctx.high.default_value == NULL) {
- ctx.high.default_value = &ngx_http_variable_null_value;
- }
-
- geo->u.high = ctx.high;
-
- var->get_handler = ngx_http_geo_range_variable;
- var->data = (uintptr_t) geo;
-
- } else {
- if (ctx.tree == NULL) {
- ctx.tree = ngx_radix_tree_create(cf->pool, -1);
- if (ctx.tree == NULL) {
- goto failed;
- }
- }
-
- geo->u.trees.tree = ctx.tree;
-
-#if (NGX_HAVE_INET6)
- if (ctx.tree6 == NULL) {
- ctx.tree6 = ngx_radix_tree_create(cf->pool, -1);
- if (ctx.tree6 == NULL) {
- goto failed;
- }
- }
-
- geo->u.trees.tree6 = ctx.tree6;
-#endif
-
- var->get_handler = ngx_http_geo_cidr_variable;
- var->data = (uintptr_t) geo;
-
- if (ngx_radix32tree_insert(ctx.tree, 0, 0,
- (uintptr_t) &ngx_http_variable_null_value)
- == NGX_ERROR)
- {
- goto failed;
- }
-
- /* NGX_BUSY is okay (default was set explicitly) */
-
-#if (NGX_HAVE_INET6)
- if (ngx_radix128tree_insert(ctx.tree6, zero.s6_addr, zero.s6_addr,
- (uintptr_t) &ngx_http_variable_null_value)
- == NGX_ERROR)
- {
- goto failed;
- }
-#endif
- }
-
- ngx_destroy_pool(ctx.temp_pool);
- ngx_destroy_pool(pool);
-
- return NGX_CONF_OK;
-
-failed:
-
- ngx_destroy_pool(ctx.temp_pool);
- ngx_destroy_pool(pool);
-
- return NGX_CONF_ERROR;
-}
-
-
-static char *
-ngx_http_geo(ngx_conf_t *cf, ngx_command_t *dummy, void *conf)
-{
- char *rv;
- ngx_str_t *value;
- ngx_cidr_t cidr;
- ngx_http_geo_conf_ctx_t *ctx;
-
- ctx = cf->ctx;
-
- value = cf->args->elts;
-
- if (cf->args->nelts == 1) {
-
- if (ngx_strcmp(value[0].data, "ranges") == 0) {
-
- if (ctx->tree
-#if (NGX_HAVE_INET6)
- || ctx->tree6
-#endif
- )
- {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "the \"ranges\" directive must be "
- "the first directive inside \"geo\" block");
- goto failed;
- }
-
- ctx->ranges = 1;
-
- rv = NGX_CONF_OK;
-
- goto done;
- }
-
- else if (ngx_strcmp(value[0].data, "proxy_recursive") == 0) {
- ctx->proxy_recursive = 1;
- rv = NGX_CONF_OK;
- goto done;
- }
- }
-
- if (cf->args->nelts != 2) {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "invalid number of the geo parameters");
- goto failed;
- }
-
- if (ngx_strcmp(value[0].data, "include") == 0) {
-
- rv = ngx_http_geo_include(cf, ctx, &value[1]);
-
- goto done;
-
- } else if (ngx_strcmp(value[0].data, "proxy") == 0) {
-
- if (ngx_http_geo_cidr_value(cf, &value[1], &cidr) != NGX_OK) {
- goto failed;
- }
-
- rv = ngx_http_geo_add_proxy(cf, ctx, &cidr);
-
- goto done;
- }
-
- if (ctx->ranges) {
- rv = ngx_http_geo_range(cf, ctx, value);
-
- } else {
- rv = ngx_http_geo_cidr(cf, ctx, value);
- }
-
-done:
-
- ngx_reset_pool(cf->pool);
-
- return rv;
-
-failed:
-
- ngx_reset_pool(cf->pool);
-
- return NGX_CONF_ERROR;
-}
-
-
-static char *
-ngx_http_geo_range(ngx_conf_t *cf, ngx_http_geo_conf_ctx_t *ctx,
- ngx_str_t *value)
-{
- u_char *p, *last;
- in_addr_t start, end;
- ngx_str_t *net;
- ngx_uint_t del;
-
- if (ngx_strcmp(value[0].data, "default") == 0) {
-
- if (ctx->high.default_value) {
- ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
- "duplicate default geo range value: \"%V\", old value: \"%v\"",
- &value[1], ctx->high.default_value);
- }
-
- ctx->high.default_value = ngx_http_geo_value(cf, ctx, &value[1]);
- if (ctx->high.default_value == NULL) {
- return NGX_CONF_ERROR;
- }
-
- return NGX_CONF_OK;
- }
-
- if (ctx->binary_include) {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "binary geo range base \"%s\" cannot be mixed with usual entries",
- ctx->include_name.data);
- return NGX_CONF_ERROR;
- }
-
- if (ctx->high.low == NULL) {
- ctx->high.low = ngx_pcalloc(ctx->pool,
- 0x10000 * sizeof(ngx_http_geo_range_t *));
- if (ctx->high.low == NULL) {
- return NGX_CONF_ERROR;
- }
- }
-
- ctx->entries++;
- ctx->outside_entries = 1;
-
- if (ngx_strcmp(value[0].data, "delete") == 0) {
- net = &value[1];
- del = 1;
-
- } else {
- net = &value[0];
- del = 0;
- }
-
- last = net->data + net->len;
-
- p = ngx_strlchr(net->data, last, '-');
-
- if (p == NULL) {
- goto invalid;
- }
-
- start = ngx_inet_addr(net->data, p - net->data);
-
- if (start == INADDR_NONE) {
- goto invalid;
- }
-
- start = ntohl(start);
-
- p++;
-
- end = ngx_inet_addr(p, last - p);
-
- if (end == INADDR_NONE) {
- goto invalid;
- }
-
- end = ntohl(end);
-
- if (start > end) {
- goto invalid;
- }
-
- if (del) {
- if (ngx_http_geo_delete_range(cf, ctx, start, end)) {
- ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
- "no address range \"%V\" to delete", net);
- }
-
- return NGX_CONF_OK;
- }
-
- ctx->value = ngx_http_geo_value(cf, ctx, &value[1]);
-
- if (ctx->value == NULL) {
- return NGX_CONF_ERROR;
- }
-
- ctx->net = net;
-
- return ngx_http_geo_add_range(cf, ctx, start, end);
-
-invalid:
-
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid range \"%V\"", net);
-
- return NGX_CONF_ERROR;
-}
-
-
-/* the add procedure is optimized to add a growing up sequence */
-
-static char *
-ngx_http_geo_add_range(ngx_conf_t *cf, ngx_http_geo_conf_ctx_t *ctx,
- in_addr_t start, in_addr_t end)
-{
- in_addr_t n;
- ngx_uint_t h, i, s, e;
- ngx_array_t *a;
- ngx_http_geo_range_t *range;
-
- for (n = start; n <= end; n = (n + 0x10000) & 0xffff0000) {
-
- h = n >> 16;
-
- if (n == start) {
- s = n & 0xffff;
- } else {
- s = 0;
- }
-
- if ((n | 0xffff) > end) {
- e = end & 0xffff;
-
- } else {
- e = 0xffff;
- }
-
- a = (ngx_array_t *) ctx->high.low[h];
-
- if (a == NULL) {
- a = ngx_array_create(ctx->temp_pool, 64,
- sizeof(ngx_http_geo_range_t));
- if (a == NULL) {
- return NGX_CONF_ERROR;
- }
-
- ctx->high.low[h] = (ngx_http_geo_range_t *) a;
- }
-
- i = a->nelts;
- range = a->elts;
-
- while (i) {
-
- i--;
-
- if (e < (ngx_uint_t) range[i].start) {
- continue;
- }
-
- if (s > (ngx_uint_t) range[i].end) {
-
- /* add after the range */
-
- range = ngx_array_push(a);
- if (range == NULL) {
- return NGX_CONF_ERROR;
- }
-
- range = a->elts;
-
- ngx_memmove(&range[i + 2], &range[i + 1],
- (a->nelts - 2 - i) * sizeof(ngx_http_geo_range_t));
-
- range[i + 1].start = (u_short) s;
- range[i + 1].end = (u_short) e;
- range[i + 1].value = ctx->value;
-
- goto next;
- }
-
- if (s == (ngx_uint_t) range[i].start
- && e == (ngx_uint_t) range[i].end)
- {
- ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
- "duplicate range \"%V\", value: \"%v\", old value: \"%v\"",
- ctx->net, ctx->value, range[i].value);
-
- range[i].value = ctx->value;
-
- goto next;
- }
-
- if (s > (ngx_uint_t) range[i].start
- && e < (ngx_uint_t) range[i].end)
- {
- /* split the range and insert the new one */
-
- range = ngx_array_push(a);
- if (range == NULL) {
- return NGX_CONF_ERROR;
- }
-
- range = ngx_array_push(a);
- if (range == NULL) {
- return NGX_CONF_ERROR;
- }
-
- range = a->elts;
-
- ngx_memmove(&range[i + 3], &range[i + 1],
- (a->nelts - 3 - i) * sizeof(ngx_http_geo_range_t));
-
- range[i + 2].start = (u_short) (e + 1);
- range[i + 2].end = range[i].end;
- range[i + 2].value = range[i].value;
-
- range[i + 1].start = (u_short) s;
- range[i + 1].end = (u_short) e;
- range[i + 1].value = ctx->value;
-
- range[i].end = (u_short) (s - 1);
-
- goto next;
- }
-
- if (s == (ngx_uint_t) range[i].start
- && e < (ngx_uint_t) range[i].end)
- {
- /* shift the range start and insert the new range */
-
- range = ngx_array_push(a);
- if (range == NULL) {
- return NGX_CONF_ERROR;
- }
-
- range = a->elts;
-
- ngx_memmove(&range[i + 1], &range[i],
- (a->nelts - 1 - i) * sizeof(ngx_http_geo_range_t));
-
- range[i + 1].start = (u_short) (e + 1);
-
- range[i].start = (u_short) s;
- range[i].end = (u_short) e;
- range[i].value = ctx->value;
-
- goto next;
- }
-
- if (s > (ngx_uint_t) range[i].start
- && e == (ngx_uint_t) range[i].end)
- {
- /* shift the range end and insert the new range */
-
- range = ngx_array_push(a);
- if (range == NULL) {
- return NGX_CONF_ERROR;
- }
-
- range = a->elts;
-
- ngx_memmove(&range[i + 2], &range[i + 1],
- (a->nelts - 2 - i) * sizeof(ngx_http_geo_range_t));
-
- range[i + 1].start = (u_short) s;
- range[i + 1].end = (u_short) e;
- range[i + 1].value = ctx->value;
-
- range[i].end = (u_short) (s - 1);
-
- goto next;
- }
-
- s = (ngx_uint_t) range[i].start;
- e = (ngx_uint_t) range[i].end;
-
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "range \"%V\" overlaps \"%d.%d.%d.%d-%d.%d.%d.%d\"",
- ctx->net,
- h >> 8, h & 0xff, s >> 8, s & 0xff,
- h >> 8, h & 0xff, e >> 8, e & 0xff);
-
- return NGX_CONF_ERROR;
- }
-
- /* add the first range */
-
- range = ngx_array_push(a);
- if (range == NULL) {
- return NGX_CONF_ERROR;
- }
-
- range = a->elts;
-
- ngx_memmove(&range[1], &range[0],
- (a->nelts - 1) * sizeof(ngx_http_geo_range_t));
-
- range[0].start = (u_short) s;
- range[0].end = (u_short) e;
- range[0].value = ctx->value;
-
- next:
-
- if (h == 0xffff) {
- break;
- }
- }
-
- return NGX_CONF_OK;
-}
-
-
-static ngx_uint_t
-ngx_http_geo_delete_range(ngx_conf_t *cf, ngx_http_geo_conf_ctx_t *ctx,
- in_addr_t start, in_addr_t end)
-{
- in_addr_t n;
- ngx_uint_t h, i, s, e, warn;
- ngx_array_t *a;
- ngx_http_geo_range_t *range;
-
- warn = 0;
-
- for (n = start; n <= end; n = (n + 0x10000) & 0xffff0000) {
-
- h = n >> 16;
-
- if (n == start) {
- s = n & 0xffff;
- } else {
- s = 0;
- }
-
- if ((n | 0xffff) > end) {
- e = end & 0xffff;
-
- } else {
- e = 0xffff;
- }
-
- a = (ngx_array_t *) ctx->high.low[h];
-
- if (a == NULL || a->nelts == 0) {
- warn = 1;
- goto next;
- }
-
- range = a->elts;
- for (i = 0; i < a->nelts; i++) {
-
- if (s == (ngx_uint_t) range[i].start
- && e == (ngx_uint_t) range[i].end)
- {
- ngx_memmove(&range[i], &range[i + 1],
- (a->nelts - 1 - i) * sizeof(ngx_http_geo_range_t));
-
- a->nelts--;
-
- break;
- }
-
- if (i == a->nelts - 1) {
- warn = 1;
- }
- }
-
- next:
-
- if (h == 0xffff) {
- break;
- }
- }
-
- return warn;
-}
-
-
-static char *
-ngx_http_geo_cidr(ngx_conf_t *cf, ngx_http_geo_conf_ctx_t *ctx,
- ngx_str_t *value)
-{
- char *rv;
- ngx_int_t rc, del;
- ngx_str_t *net;
- ngx_cidr_t cidr;
-
- if (ctx->tree == NULL) {
- ctx->tree = ngx_radix_tree_create(ctx->pool, -1);
- if (ctx->tree == NULL) {
- return NGX_CONF_ERROR;
- }
- }
-
-#if (NGX_HAVE_INET6)
- if (ctx->tree6 == NULL) {
- ctx->tree6 = ngx_radix_tree_create(ctx->pool, -1);
- if (ctx->tree6 == NULL) {
- return NGX_CONF_ERROR;
- }
- }
-#endif
-
- if (ngx_strcmp(value[0].data, "default") == 0) {
- cidr.family = AF_INET;
- cidr.u.in.addr = 0;
- cidr.u.in.mask = 0;
-
- rv = ngx_http_geo_cidr_add(cf, ctx, &cidr, &value[1], &value[0]);
-
- if (rv != NGX_CONF_OK) {
- return rv;
- }
-
-#if (NGX_HAVE_INET6)
- cidr.family = AF_INET6;
- ngx_memzero(&cidr.u.in6, sizeof(ngx_in6_cidr_t));
-
- rv = ngx_http_geo_cidr_add(cf, ctx, &cidr, &value[1], &value[0]);
-
- if (rv != NGX_CONF_OK) {
- return rv;
- }
-#endif
-
- return NGX_CONF_OK;
- }
-
- if (ngx_strcmp(value[0].data, "delete") == 0) {
- net = &value[1];
- del = 1;
-
- } else {
- net = &value[0];
- del = 0;
- }
-
- if (ngx_http_geo_cidr_value(cf, net, &cidr) != NGX_OK) {
- return NGX_CONF_ERROR;
- }
-
- if (cidr.family == AF_INET) {
- cidr.u.in.addr = ntohl(cidr.u.in.addr);
- cidr.u.in.mask = ntohl(cidr.u.in.mask);
- }
-
- if (del) {
- switch (cidr.family) {
-
-#if (NGX_HAVE_INET6)
- case AF_INET6:
- rc = ngx_radix128tree_delete(ctx->tree6,
- cidr.u.in6.addr.s6_addr,
- cidr.u.in6.mask.s6_addr);
- break;
-#endif
-
- default: /* AF_INET */
- rc = ngx_radix32tree_delete(ctx->tree, cidr.u.in.addr,
- cidr.u.in.mask);
- break;
- }
-
- if (rc != NGX_OK) {
- ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
- "no network \"%V\" to delete", net);
- }
-
- return NGX_CONF_OK;
- }
-
- return ngx_http_geo_cidr_add(cf, ctx, &cidr, &value[1], net);
-}
-
-
-static char *
-ngx_http_geo_cidr_add(ngx_conf_t *cf, ngx_http_geo_conf_ctx_t *ctx,
- ngx_cidr_t *cidr, ngx_str_t *value, ngx_str_t *net)
-{
- ngx_int_t rc;
- ngx_http_variable_value_t *val, *old;
-
- val = ngx_http_geo_value(cf, ctx, value);
-
- if (val == NULL) {
- return NGX_CONF_ERROR;
- }
-
- switch (cidr->family) {
-
-#if (NGX_HAVE_INET6)
- case AF_INET6:
- rc = ngx_radix128tree_insert(ctx->tree6, cidr->u.in6.addr.s6_addr,
- cidr->u.in6.mask.s6_addr,
- (uintptr_t) val);
-
- if (rc == NGX_OK) {
- return NGX_CONF_OK;
- }
-
- if (rc == NGX_ERROR) {
- return NGX_CONF_ERROR;
- }
-
- /* rc == NGX_BUSY */
-
- old = (ngx_http_variable_value_t *)
- ngx_radix128tree_find(ctx->tree6,
- cidr->u.in6.addr.s6_addr);
-
- ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
- "duplicate network \"%V\", value: \"%v\", old value: \"%v\"",
- net, val, old);
-
- rc = ngx_radix128tree_delete(ctx->tree6,
- cidr->u.in6.addr.s6_addr,
- cidr->u.in6.mask.s6_addr);
-
- if (rc == NGX_ERROR) {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid radix tree");
- return NGX_CONF_ERROR;
- }
-
- rc = ngx_radix128tree_insert(ctx->tree6, cidr->u.in6.addr.s6_addr,
- cidr->u.in6.mask.s6_addr,
- (uintptr_t) val);
-
- break;
-#endif
-
- default: /* AF_INET */
- rc = ngx_radix32tree_insert(ctx->tree, cidr->u.in.addr,
- cidr->u.in.mask, (uintptr_t) val);
-
- if (rc == NGX_OK) {
- return NGX_CONF_OK;
- }
-
- if (rc == NGX_ERROR) {
- return NGX_CONF_ERROR;
- }
-
- /* rc == NGX_BUSY */
-
- old = (ngx_http_variable_value_t *)
- ngx_radix32tree_find(ctx->tree, cidr->u.in.addr);
-
- ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
- "duplicate network \"%V\", value: \"%v\", old value: \"%v\"",
- net, val, old);
-
- rc = ngx_radix32tree_delete(ctx->tree,
- cidr->u.in.addr, cidr->u.in.mask);
-
- if (rc == NGX_ERROR) {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid radix tree");
- return NGX_CONF_ERROR;
- }
-
- rc = ngx_radix32tree_insert(ctx->tree, cidr->u.in.addr,
- cidr->u.in.mask, (uintptr_t) val);
-
- break;
- }
-
- if (rc == NGX_OK) {
- return NGX_CONF_OK;
- }
-
- return NGX_CONF_ERROR;
-}
-
-
-static ngx_http_variable_value_t *
-ngx_http_geo_value(ngx_conf_t *cf, ngx_http_geo_conf_ctx_t *ctx,
- ngx_str_t *value)
-{
- uint32_t hash;
- ngx_http_variable_value_t *val;
- ngx_http_geo_variable_value_node_t *gvvn;
-
- hash = ngx_crc32_long(value->data, value->len);
-
- gvvn = (ngx_http_geo_variable_value_node_t *)
- ngx_str_rbtree_lookup(&ctx->rbtree, value, hash);
-
- if (gvvn) {
- return gvvn->value;
- }
-
- val = ngx_palloc(ctx->pool, sizeof(ngx_http_variable_value_t));
- if (val == NULL) {
- return NULL;
- }
-
- val->len = value->len;
- val->data = ngx_pstrdup(ctx->pool, value);
- if (val->data == NULL) {
- return NULL;
- }
-
- val->valid = 1;
- val->no_cacheable = 0;
- val->not_found = 0;
-
- gvvn = ngx_palloc(ctx->temp_pool,
- sizeof(ngx_http_geo_variable_value_node_t));
- if (gvvn == NULL) {
- return NULL;
- }
-
- gvvn->sn.node.key = hash;
- gvvn->sn.str.len = val->len;
- gvvn->sn.str.data = val->data;
- gvvn->value = val;
- gvvn->offset = 0;
-
- ngx_rbtree_insert(&ctx->rbtree, &gvvn->sn.node);
-
- ctx->data_size += ngx_align(sizeof(ngx_http_variable_value_t) + value->len,
- sizeof(void *));
-
- return val;
-}
-
-
-static char *
-ngx_http_geo_add_proxy(ngx_conf_t *cf, ngx_http_geo_conf_ctx_t *ctx,
- ngx_cidr_t *cidr)
-{
- ngx_cidr_t *c;
-
- if (ctx->proxies == NULL) {
- ctx->proxies = ngx_array_create(ctx->pool, 4, sizeof(ngx_cidr_t));
- if (ctx->proxies == NULL) {
- return NGX_CONF_ERROR;
- }
- }
-
- c = ngx_array_push(ctx->proxies);
- if (c == NULL) {
- return NGX_CONF_ERROR;
- }
-
- *c = *cidr;
-
- return NGX_CONF_OK;
-}
-
-
-static ngx_int_t
-ngx_http_geo_cidr_value(ngx_conf_t *cf, ngx_str_t *net, ngx_cidr_t *cidr)
-{
- ngx_int_t rc;
-
- if (ngx_strcmp(net->data, "255.255.255.255") == 0) {
- cidr->family = AF_INET;
- cidr->u.in.addr = 0xffffffff;
- cidr->u.in.mask = 0xffffffff;
-
- return NGX_OK;
- }
-
- rc = ngx_ptocidr(net, cidr);
-
- if (rc == NGX_ERROR) {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid network \"%V\"", net);
- return NGX_ERROR;
- }
-
- if (rc == NGX_DONE) {
- ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
- "low address bits of %V are meaningless", net);
- }
-
- return NGX_OK;
-}
-
-
-static char *
-ngx_http_geo_include(ngx_conf_t *cf, ngx_http_geo_conf_ctx_t *ctx,
- ngx_str_t *name)
-{
- char *rv;
- ngx_str_t file;
-
- file.len = name->len + 4;
- file.data = ngx_pnalloc(ctx->temp_pool, name->len + 5);
- if (file.data == NULL) {
- return NGX_CONF_ERROR;
- }
-
- ngx_sprintf(file.data, "%V.bin%Z", name);
-
- if (ngx_conf_full_name(cf->cycle, &file, 1) != NGX_OK) {
- return NGX_CONF_ERROR;
- }
-
- if (ctx->ranges) {
- ngx_log_debug1(NGX_LOG_DEBUG_CORE, cf->log, 0, "include %s", file.data);
-
- switch (ngx_http_geo_include_binary_base(cf, ctx, &file)) {
- case NGX_OK:
- return NGX_CONF_OK;
- case NGX_ERROR:
- return NGX_CONF_ERROR;
- default:
- break;
- }
- }
-
- file.len -= 4;
- file.data[file.len] = '\0';
-
- ctx->include_name = file;
-
- if (ctx->outside_entries) {
- ctx->allow_binary_include = 0;
- }
-
- ngx_log_debug1(NGX_LOG_DEBUG_CORE, cf->log, 0, "include %s", file.data);
-
- rv = ngx_conf_parse(cf, &file);
-
- ctx->includes++;
- ctx->outside_entries = 0;
-
- return rv;
-}
-
-
-static ngx_int_t
-ngx_http_geo_include_binary_base(ngx_conf_t *cf, ngx_http_geo_conf_ctx_t *ctx,
- ngx_str_t *name)
-{
- u_char *base, ch;
- time_t mtime;
- size_t size, len;
- ssize_t n;
- uint32_t crc32;
- ngx_err_t err;
- ngx_int_t rc;
- ngx_uint_t i;
- ngx_file_t file;
- ngx_file_info_t fi;
- ngx_http_geo_range_t *range, **ranges;
- ngx_http_geo_header_t *header;
- ngx_http_variable_value_t *vv;
-
- ngx_memzero(&file, sizeof(ngx_file_t));
- file.name = *name;
- file.log = cf->log;
-
- file.fd = ngx_open_file(name->data, NGX_FILE_RDONLY, NGX_FILE_OPEN, 0);
-
- if (file.fd == NGX_INVALID_FILE) {
- err = ngx_errno;
- if (err != NGX_ENOENT) {
- ngx_conf_log_error(NGX_LOG_CRIT, cf, err,
- ngx_open_file_n " \"%s\" failed", name->data);
- }
- return NGX_DECLINED;
- }
-
- if (ctx->outside_entries) {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "binary geo range base \"%s\" cannot be mixed with usual entries",
- name->data);
- rc = NGX_ERROR;
- goto done;
- }
-
- if (ctx->binary_include) {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "second binary geo range base \"%s\" cannot be mixed with \"%s\"",
- name->data, ctx->include_name.data);
- rc = NGX_ERROR;
- goto done;
- }
-
- if (ngx_fd_info(file.fd, &fi) == NGX_FILE_ERROR) {
- ngx_conf_log_error(NGX_LOG_CRIT, cf, ngx_errno,
- ngx_fd_info_n " \"%s\" failed", name->data);
- goto failed;
- }
-
- size = (size_t) ngx_file_size(&fi);
- mtime = ngx_file_mtime(&fi);
-
- ch = name->data[name->len - 4];
- name->data[name->len - 4] = '\0';
-
- if (ngx_file_info(name->data, &fi) == NGX_FILE_ERROR) {
- ngx_conf_log_error(NGX_LOG_CRIT, cf, ngx_errno,
- ngx_file_info_n " \"%s\" failed", name->data);
- goto failed;
- }
-
- name->data[name->len - 4] = ch;
-
- if (mtime < ngx_file_mtime(&fi)) {
- ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
- "stale binary geo range base \"%s\"", name->data);
- goto failed;
- }
-
- base = ngx_palloc(ctx->pool, size);
- if (base == NULL) {
- goto failed;
- }
-
- n = ngx_read_file(&file, base, size, 0);
-
- if (n == NGX_ERROR) {
- ngx_conf_log_error(NGX_LOG_CRIT, cf, ngx_errno,
- ngx_read_file_n " \"%s\" failed", name->data);
- goto failed;
- }
-
- if ((size_t) n != size) {
- ngx_conf_log_error(NGX_LOG_CRIT, cf, 0,
- ngx_read_file_n " \"%s\" returned only %z bytes instead of %z",
- name->data, n, size);
- goto failed;
- }
-
- header = (ngx_http_geo_header_t *) base;
-
- if (size < 16 || ngx_memcmp(&ngx_http_geo_header, header, 12) != 0) {
- ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
- "incompatible binary geo range base \"%s\"", name->data);
- goto failed;
- }
-
- ngx_crc32_init(crc32);
-
- vv = (ngx_http_variable_value_t *) (base + sizeof(ngx_http_geo_header_t));
-
- while (vv->data) {
- len = ngx_align(sizeof(ngx_http_variable_value_t) + vv->len,
- sizeof(void *));
- ngx_crc32_update(&crc32, (u_char *) vv, len);
- vv->data += (size_t) base;
- vv = (ngx_http_variable_value_t *) ((u_char *) vv + len);
- }
- ngx_crc32_update(&crc32, (u_char *) vv, sizeof(ngx_http_variable_value_t));
- vv++;
-
- ranges = (ngx_http_geo_range_t **) vv;
-
- for (i = 0; i < 0x10000; i++) {
- ngx_crc32_update(&crc32, (u_char *) &ranges[i], sizeof(void *));
- if (ranges[i]) {
- ranges[i] = (ngx_http_geo_range_t *)
- ((u_char *) ranges[i] + (size_t) base);
- }
- }
-
- range = (ngx_http_geo_range_t *) &ranges[0x10000];
-
- while ((u_char *) range < base + size) {
- while (range->value) {
- ngx_crc32_update(&crc32, (u_char *) range,
- sizeof(ngx_http_geo_range_t));
- range->value = (ngx_http_variable_value_t *)
- ((u_char *) range->value + (size_t) base);
- range++;
- }
- ngx_crc32_update(&crc32, (u_char *) range, sizeof(void *));
- range = (ngx_http_geo_range_t *) ((u_char *) range + sizeof(void *));
- }
-
- ngx_crc32_final(crc32);
-
- if (crc32 != header->crc32) {
- ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
- "CRC32 mismatch in binary geo range base \"%s\"", name->data);
- goto failed;
- }
-
- ngx_conf_log_error(NGX_LOG_NOTICE, cf, 0,
- "using binary geo range base \"%s\"", name->data);
-
- ctx->include_name = *name;
- ctx->binary_include = 1;
- ctx->high.low = ranges;
- rc = NGX_OK;
-
- goto done;
-
-failed:
-
- rc = NGX_DECLINED;
-
-done:
-
- if (ngx_close_file(file.fd) == NGX_FILE_ERROR) {
- ngx_log_error(NGX_LOG_ALERT, cf->log, ngx_errno,
- ngx_close_file_n " \"%s\" failed", name->data);
- }
-
- return rc;
-}
-
-
-static void
-ngx_http_geo_create_binary_base(ngx_http_geo_conf_ctx_t *ctx)
-{
- u_char *p;
- uint32_t hash;
- ngx_str_t s;
- ngx_uint_t i;
- ngx_file_mapping_t fm;
- ngx_http_geo_range_t *r, *range, **ranges;
- ngx_http_geo_header_t *header;
- ngx_http_geo_variable_value_node_t *gvvn;
-
- fm.name = ngx_pnalloc(ctx->temp_pool, ctx->include_name.len + 5);
- if (fm.name == NULL) {
- return;
- }
-
- ngx_sprintf(fm.name, "%V.bin%Z", &ctx->include_name);
-
- fm.size = ctx->data_size;
- fm.log = ctx->pool->log;
-
- ngx_log_error(NGX_LOG_NOTICE, fm.log, 0,
- "creating binary geo range base \"%s\"", fm.name);
-
- if (ngx_create_file_mapping(&fm) != NGX_OK) {
- return;
- }
-
- p = ngx_cpymem(fm.addr, &ngx_http_geo_header,
- sizeof(ngx_http_geo_header_t));
-
- p = ngx_http_geo_copy_values(fm.addr, p, ctx->rbtree.root,
- ctx->rbtree.sentinel);
-
- p += sizeof(ngx_http_variable_value_t);
-
- ranges = (ngx_http_geo_range_t **) p;
-
- p += 0x10000 * sizeof(ngx_http_geo_range_t *);
-
- for (i = 0; i < 0x10000; i++) {
- r = ctx->high.low[i];
- if (r == NULL) {
- continue;
- }
-
- range = (ngx_http_geo_range_t *) p;
- ranges[i] = (ngx_http_geo_range_t *) (p - (u_char *) fm.addr);
-
- do {
- s.len = r->value->len;
- s.data = r->value->data;
- hash = ngx_crc32_long(s.data, s.len);
- gvvn = (ngx_http_geo_variable_value_node_t *)
- ngx_str_rbtree_lookup(&ctx->rbtree, &s, hash);
-
- range->value = (ngx_http_variable_value_t *) gvvn->offset;
- range->start = r->start;
- range->end = r->end;
- range++;
-
- } while ((++r)->value);
-
- range->value = NULL;
-
- p = (u_char *) range + sizeof(void *);
- }
-
- header = fm.addr;
- header->crc32 = ngx_crc32_long((u_char *) fm.addr
- + sizeof(ngx_http_geo_header_t),
- fm.size - sizeof(ngx_http_geo_header_t));
-
- ngx_close_file_mapping(&fm);
-}
-
-
-static u_char *
-ngx_http_geo_copy_values(u_char *base, u_char *p, ngx_rbtree_node_t *node,
- ngx_rbtree_node_t *sentinel)
-{
- ngx_http_variable_value_t *vv;
- ngx_http_geo_variable_value_node_t *gvvn;
-
- if (node == sentinel) {
- return p;
- }
-
- gvvn = (ngx_http_geo_variable_value_node_t *) node;
- gvvn->offset = p - base;
-
- vv = (ngx_http_variable_value_t *) p;
- *vv = *gvvn->value;
- p += sizeof(ngx_http_variable_value_t);
- vv->data = (u_char *) (p - base);
-
- p = ngx_cpymem(p, gvvn->sn.str.data, gvvn->sn.str.len);
-
- p = ngx_align_ptr(p, sizeof(void *));
-
- p = ngx_http_geo_copy_values(base, p, node->left, sentinel);
-
- return ngx_http_geo_copy_values(base, p, node->right, sentinel);
-}
diff --git a/nginx/src/http/modules/ngx_http_geoip_module.c b/nginx/src/http/modules/ngx_http_geoip_module.c
deleted file mode 100644
index 5ea4f5f..0000000
--- a/nginx/src/http/modules/ngx_http_geoip_module.c
+++ /dev/null
@@ -1,925 +0,0 @@
-
-/*
- * Copyright (C) Igor Sysoev
- * Copyright (C) Nginx, Inc.
- */
-
-
-#include <ngx_config.h>
-#include <ngx_core.h>
-#include <ngx_http.h>
-
-#include <GeoIP.h>
-#include <GeoIPCity.h>
-
-
-#define NGX_GEOIP_COUNTRY_CODE 0
-#define NGX_GEOIP_COUNTRY_CODE3 1
-#define NGX_GEOIP_COUNTRY_NAME 2
-
-
-typedef struct {
- GeoIP *country;
- GeoIP *org;
- GeoIP *city;
- ngx_array_t *proxies; /* array of ngx_cidr_t */
- ngx_flag_t proxy_recursive;
-#if (NGX_HAVE_GEOIP_V6)
- unsigned country_v6:1;
- unsigned org_v6:1;
- unsigned city_v6:1;
-#endif
-} ngx_http_geoip_conf_t;
-
-
-typedef struct {
- ngx_str_t *name;
- uintptr_t data;
-} ngx_http_geoip_var_t;
-
-
-typedef const char *(*ngx_http_geoip_variable_handler_pt)(GeoIP *,
- u_long addr);
-
-
-ngx_http_geoip_variable_handler_pt ngx_http_geoip_country_functions[] = {
- GeoIP_country_code_by_ipnum,
- GeoIP_country_code3_by_ipnum,
- GeoIP_country_name_by_ipnum,
-};
-
-
-#if (NGX_HAVE_GEOIP_V6)
-
-typedef const char *(*ngx_http_geoip_variable_handler_v6_pt)(GeoIP *,
- geoipv6_t addr);
-
-
-ngx_http_geoip_variable_handler_v6_pt ngx_http_geoip_country_v6_functions[] = {
- GeoIP_country_code_by_ipnum_v6,
- GeoIP_country_code3_by_ipnum_v6,
- GeoIP_country_name_by_ipnum_v6,
-};
-
-#endif
-
-
-static ngx_int_t ngx_http_geoip_country_variable(ngx_http_request_t *r,
- ngx_http_variable_value_t *v, uintptr_t data);
-static ngx_int_t ngx_http_geoip_org_variable(ngx_http_request_t *r,
- ngx_http_variable_value_t *v, uintptr_t data);
-static ngx_int_t ngx_http_geoip_city_variable(ngx_http_request_t *r,
- ngx_http_variable_value_t *v, uintptr_t data);
-static ngx_int_t ngx_http_geoip_region_name_variable(ngx_http_request_t *r,
- ngx_http_variable_value_t *v, uintptr_t data);
-static ngx_int_t ngx_http_geoip_city_float_variable(ngx_http_request_t *r,
- ngx_http_variable_value_t *v, uintptr_t data);
-static ngx_int_t ngx_http_geoip_city_int_variable(ngx_http_request_t *r,
- ngx_http_variable_value_t *v, uintptr_t data);
-static GeoIPRecord *ngx_http_geoip_get_city_record(ngx_http_request_t *r);
-
-static ngx_int_t ngx_http_geoip_add_variables(ngx_conf_t *cf);
-static void *ngx_http_geoip_create_conf(ngx_conf_t *cf);
-static char *ngx_http_geoip_init_conf(ngx_conf_t *cf, void *conf);
-static char *ngx_http_geoip_country(ngx_conf_t *cf, ngx_command_t *cmd,
- void *conf);
-static char *ngx_http_geoip_org(ngx_conf_t *cf, ngx_command_t *cmd,
- void *conf);
-static char *ngx_http_geoip_city(ngx_conf_t *cf, ngx_command_t *cmd,
- void *conf);
-static char *ngx_http_geoip_proxy(ngx_conf_t *cf, ngx_command_t *cmd,
- void *conf);
-static ngx_int_t ngx_http_geoip_cidr_value(ngx_conf_t *cf, ngx_str_t *net,
- ngx_cidr_t *cidr);
-static void ngx_http_geoip_cleanup(void *data);
-
-
-static ngx_command_t ngx_http_geoip_commands[] = {
-
- { ngx_string("geoip_country"),
- NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE12,
- ngx_http_geoip_country,
- NGX_HTTP_MAIN_CONF_OFFSET,
- 0,
- NULL },
-
- { ngx_string("geoip_org"),
- NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE12,
- ngx_http_geoip_org,
- NGX_HTTP_MAIN_CONF_OFFSET,
- 0,
- NULL },
-
- { ngx_string("geoip_city"),
- NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE12,
- ngx_http_geoip_city,
- NGX_HTTP_MAIN_CONF_OFFSET,
- 0,
- NULL },
-
- { ngx_string("geoip_proxy"),
- NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1,
- ngx_http_geoip_proxy,
- NGX_HTTP_MAIN_CONF_OFFSET,
- 0,
- NULL },
-
- { ngx_string("geoip_proxy_recursive"),
- NGX_HTTP_MAIN_CONF|NGX_CONF_FLAG,
- ngx_conf_set_flag_slot,
- NGX_HTTP_MAIN_CONF_OFFSET,
- offsetof(ngx_http_geoip_conf_t, proxy_recursive),
- NULL },
-
- ngx_null_command
-};
-
-
-static ngx_http_module_t ngx_http_geoip_module_ctx = {
- ngx_http_geoip_add_variables, /* preconfiguration */
- NULL, /* postconfiguration */
-
- ngx_http_geoip_create_conf, /* create main configuration */
- ngx_http_geoip_init_conf, /* init main configuration */
-
- NULL, /* create server configuration */
- NULL, /* merge server configuration */
-
- NULL, /* create location configuration */
- NULL /* merge location configuration */
-};
-
-
-ngx_module_t ngx_http_geoip_module = {
- NGX_MODULE_V1,
- &ngx_http_geoip_module_ctx, /* module context */
- ngx_http_geoip_commands, /* module directives */
- NGX_HTTP_MODULE, /* module type */
- NULL, /* init master */
- NULL, /* init module */
- NULL, /* init process */
- NULL, /* init thread */
- NULL, /* exit thread */
- NULL, /* exit process */
- NULL, /* exit master */
- NGX_MODULE_V1_PADDING
-};
-
-
-static ngx_http_variable_t ngx_http_geoip_vars[] = {
-
- { ngx_string("geoip_country_code"), NULL,
- ngx_http_geoip_country_variable,
- NGX_GEOIP_COUNTRY_CODE, 0, 0 },
-
- { ngx_string("geoip_country_code3"), NULL,
- ngx_http_geoip_country_variable,
- NGX_GEOIP_COUNTRY_CODE3, 0, 0 },
-
- { ngx_string("geoip_country_name"), NULL,
- ngx_http_geoip_country_variable,
- NGX_GEOIP_COUNTRY_NAME, 0, 0 },
-
- { ngx_string("geoip_org"), NULL,
- ngx_http_geoip_org_variable,
- 0, 0, 0 },
-
- { ngx_string("geoip_city_continent_code"), NULL,
- ngx_http_geoip_city_variable,
- offsetof(GeoIPRecord, continent_code), 0, 0 },
-
- { ngx_string("geoip_city_country_code"), NULL,
- ngx_http_geoip_city_variable,
- offsetof(GeoIPRecord, country_code), 0, 0 },
-
- { ngx_string("geoip_city_country_code3"), NULL,
- ngx_http_geoip_city_variable,
- offsetof(GeoIPRecord, country_code3), 0, 0 },
-
- { ngx_string("geoip_city_country_name"), NULL,
- ngx_http_geoip_city_variable,
- offsetof(GeoIPRecord, country_name), 0, 0 },
-
- { ngx_string("geoip_region"), NULL,
- ngx_http_geoip_city_variable,
- offsetof(GeoIPRecord, region), 0, 0 },
-
- { ngx_string("geoip_region_name"), NULL,
- ngx_http_geoip_region_name_variable,
- 0, 0, 0 },
-
- { ngx_string("geoip_city"), NULL,
- ngx_http_geoip_city_variable,
- offsetof(GeoIPRecord, city), 0, 0 },
-
- { ngx_string("geoip_postal_code"), NULL,
- ngx_http_geoip_city_variable,
- offsetof(GeoIPRecord, postal_code), 0, 0 },
-
- { ngx_string("geoip_latitude"), NULL,
- ngx_http_geoip_city_float_variable,
- offsetof(GeoIPRecord, latitude), 0, 0 },
-
- { ngx_string("geoip_longitude"), NULL,
- ngx_http_geoip_city_float_variable,
- offsetof(GeoIPRecord, longitude), 0, 0 },
-
- { ngx_string("geoip_dma_code"), NULL,
- ngx_http_geoip_city_int_variable,
- offsetof(GeoIPRecord, dma_code), 0, 0 },
-
- { ngx_string("geoip_area_code"), NULL,
- ngx_http_geoip_city_int_variable,
- offsetof(GeoIPRecord, area_code), 0, 0 },
-
- ngx_http_null_variable
-};
-
-
-static u_long
-ngx_http_geoip_addr(ngx_http_request_t *r, ngx_http_geoip_conf_t *gcf)
-{
- ngx_addr_t addr;
- ngx_array_t *xfwd;
- struct sockaddr_in *sin;
-
- addr.sockaddr = r->connection->sockaddr;
- addr.socklen = r->connection->socklen;
- /* addr.name = r->connection->addr_text; */
-
- xfwd = &r->headers_in.x_forwarded_for;
-
- if (xfwd->nelts > 0 && gcf->proxies != NULL) {
- (void) ngx_http_get_forwarded_addr(r, &addr, xfwd, NULL,
- gcf->proxies, gcf->proxy_recursive);
- }
-
-#if (NGX_HAVE_INET6)
-
- if (addr.sockaddr->sa_family == AF_INET6) {
- u_char *p;
- in_addr_t inaddr;
- struct in6_addr *inaddr6;
-
- inaddr6 = &((struct sockaddr_in6 *) addr.sockaddr)->sin6_addr;
-
- if (IN6_IS_ADDR_V4MAPPED(inaddr6)) {
- p = inaddr6->s6_addr;
-
- inaddr = p[12] << 24;
- inaddr += p[13] << 16;
- inaddr += p[14] << 8;
- inaddr += p[15];
-
- return inaddr;
- }
- }
-
-#endif
-
- if (addr.sockaddr->sa_family != AF_INET) {
- return INADDR_NONE;
- }
-
- sin = (struct sockaddr_in *) addr.sockaddr;
- return ntohl(sin->sin_addr.s_addr);
-}
-
-
-#if (NGX_HAVE_GEOIP_V6)
-
-static geoipv6_t
-ngx_http_geoip_addr_v6(ngx_http_request_t *r, ngx_http_geoip_conf_t *gcf)
-{
- ngx_addr_t addr;
- ngx_array_t *xfwd;
- in_addr_t addr4;
- struct in6_addr addr6;
- struct sockaddr_in *sin;
- struct sockaddr_in6 *sin6;
-
- addr.sockaddr = r->connection->sockaddr;
- addr.socklen = r->connection->socklen;
- /* addr.name = r->connection->addr_text; */
-
- xfwd = &r->headers_in.x_forwarded_for;
-
- if (xfwd->nelts > 0 && gcf->proxies != NULL) {
- (void) ngx_http_get_forwarded_addr(r, &addr, xfwd, NULL,
- gcf->proxies, gcf->proxy_recursive);
- }
-
- switch (addr.sockaddr->sa_family) {
-
- case AF_INET:
- /* Produce IPv4-mapped IPv6 address. */
- sin = (struct sockaddr_in *) addr.sockaddr;
- addr4 = ntohl(sin->sin_addr.s_addr);
-
- ngx_memzero(&addr6, sizeof(struct in6_addr));
- addr6.s6_addr[10] = 0xff;
- addr6.s6_addr[11] = 0xff;
- addr6.s6_addr[12] = addr4 >> 24;
- addr6.s6_addr[13] = addr4 >> 16;
- addr6.s6_addr[14] = addr4 >> 8;
- addr6.s6_addr[15] = addr4;
- return addr6;
-
- case AF_INET6:
- sin6 = (struct sockaddr_in6 *) addr.sockaddr;
- return sin6->sin6_addr;
-
- default:
- return in6addr_any;
- }
-}
-
-#endif
-
-
-static ngx_int_t
-ngx_http_geoip_country_variable(ngx_http_request_t *r,
- ngx_http_variable_value_t *v, uintptr_t data)
-{
- ngx_http_geoip_variable_handler_pt handler =
- ngx_http_geoip_country_functions[data];
-#if (NGX_HAVE_GEOIP_V6)
- ngx_http_geoip_variable_handler_v6_pt handler_v6 =
- ngx_http_geoip_country_v6_functions[data];
-#endif
-
- const char *val;
- ngx_http_geoip_conf_t *gcf;
-
- gcf = ngx_http_get_module_main_conf(r, ngx_http_geoip_module);
-
- if (gcf->country == NULL) {
- goto not_found;
- }
-
-#if (NGX_HAVE_GEOIP_V6)
- val = gcf->country_v6
- ? handler_v6(gcf->country, ngx_http_geoip_addr_v6(r, gcf))
- : handler(gcf->country, ngx_http_geoip_addr(r, gcf));
-#else
- val = handler(gcf->country, ngx_http_geoip_addr(r, gcf));
-#endif
-
- if (val == NULL) {
- goto not_found;
- }
-
- v->len = ngx_strlen(val);
- v->valid = 1;
- v->no_cacheable = 0;
- v->not_found = 0;
- v->data = (u_char *) val;
-
- return NGX_OK;
-
-not_found:
-
- v->not_found = 1;
-
- return NGX_OK;
-}
-
-
-static ngx_int_t
-ngx_http_geoip_org_variable(ngx_http_request_t *r,
- ngx_http_variable_value_t *v, uintptr_t data)
-{
- size_t len;
- char *val;
- ngx_http_geoip_conf_t *gcf;
-
- gcf = ngx_http_get_module_main_conf(r, ngx_http_geoip_module);
-
- if (gcf->org == NULL) {
- goto not_found;
- }
-
-#if (NGX_HAVE_GEOIP_V6)
- val = gcf->org_v6
- ? GeoIP_name_by_ipnum_v6(gcf->org,
- ngx_http_geoip_addr_v6(r, gcf))
- : GeoIP_name_by_ipnum(gcf->org,
- ngx_http_geoip_addr(r, gcf));
-#else
- val = GeoIP_name_by_ipnum(gcf->org, ngx_http_geoip_addr(r, gcf));
-#endif
-
- if (val == NULL) {
- goto not_found;
- }
-
- len = ngx_strlen(val);
- v->data = ngx_pnalloc(r->pool, len);
- if (v->data == NULL) {
- ngx_free(val);
- return NGX_ERROR;
- }
-
- ngx_memcpy(v->data, val, len);
-
- v->len = len;
- v->valid = 1;
- v->no_cacheable = 0;
- v->not_found = 0;
-
- ngx_free(val);
-
- return NGX_OK;
-
-not_found:
-
- v->not_found = 1;
-
- return NGX_OK;
-}
-
-
-static ngx_int_t
-ngx_http_geoip_city_variable(ngx_http_request_t *r,
- ngx_http_variable_value_t *v, uintptr_t data)
-{
- char *val;
- size_t len;
- GeoIPRecord *gr;
-
- gr = ngx_http_geoip_get_city_record(r);
- if (gr == NULL) {
- goto not_found;
- }
-
- val = *(char **) ((char *) gr + data);
- if (val == NULL) {
- goto no_value;
- }
-
- len = ngx_strlen(val);
- v->data = ngx_pnalloc(r->pool, len);
- if (v->data == NULL) {
- GeoIPRecord_delete(gr);
- return NGX_ERROR;
- }
-
- ngx_memcpy(v->data, val, len);
-
- v->len = len;
- v->valid = 1;
- v->no_cacheable = 0;
- v->not_found = 0;
-
- GeoIPRecord_delete(gr);
-
- return NGX_OK;
-
-no_value:
-
- GeoIPRecord_delete(gr);
-
-not_found:
-
- v->not_found = 1;
-
- return NGX_OK;
-}
-
-
-static ngx_int_t
-ngx_http_geoip_region_name_variable(ngx_http_request_t *r,
- ngx_http_variable_value_t *v, uintptr_t data)
-{
- size_t len;
- const char *val;
- GeoIPRecord *gr;
-
- gr = ngx_http_geoip_get_city_record(r);
- if (gr == NULL) {
- goto not_found;
- }
-
- 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) {
- return NGX_ERROR;
- }
-
- ngx_memcpy(v->data, val, len);
-
- v->len = len;
- v->valid = 1;
- v->no_cacheable = 0;
- v->not_found = 0;
-
- return NGX_OK;
-
-not_found:
-
- v->not_found = 1;
-
- return NGX_OK;
-}
-
-
-static ngx_int_t
-ngx_http_geoip_city_float_variable(ngx_http_request_t *r,
- ngx_http_variable_value_t *v, uintptr_t data)
-{
- float val;
- GeoIPRecord *gr;
-
- gr = ngx_http_geoip_get_city_record(r);
- if (gr == NULL) {
- v->not_found = 1;
- return NGX_OK;
- }
-
- v->data = ngx_pnalloc(r->pool, NGX_INT64_LEN + 5);
- if (v->data == NULL) {
- GeoIPRecord_delete(gr);
- return NGX_ERROR;
- }
-
- val = *(float *) ((char *) gr + data);
-
- v->len = ngx_sprintf(v->data, "%.4f", val) - v->data;
- v->valid = 1;
- v->no_cacheable = 0;
- v->not_found = 0;
-
- GeoIPRecord_delete(gr);
-
- return NGX_OK;
-}
-
-
-static ngx_int_t
-ngx_http_geoip_city_int_variable(ngx_http_request_t *r,
- ngx_http_variable_value_t *v, uintptr_t data)
-{
- int val;
- GeoIPRecord *gr;
-
- gr = ngx_http_geoip_get_city_record(r);
- if (gr == NULL) {
- v->not_found = 1;
- return NGX_OK;
- }
-
- v->data = ngx_pnalloc(r->pool, NGX_INT64_LEN);
- if (v->data == NULL) {
- GeoIPRecord_delete(gr);
- return NGX_ERROR;
- }
-
- val = *(int *) ((char *) gr + data);
-
- v->len = ngx_sprintf(v->data, "%d", val) - v->data;
- v->valid = 1;
- v->no_cacheable = 0;
- v->not_found = 0;
-
- GeoIPRecord_delete(gr);
-
- return NGX_OK;
-}
-
-
-static GeoIPRecord *
-ngx_http_geoip_get_city_record(ngx_http_request_t *r)
-{
- ngx_http_geoip_conf_t *gcf;
-
- gcf = ngx_http_get_module_main_conf(r, ngx_http_geoip_module);
-
- if (gcf->city) {
-#if (NGX_HAVE_GEOIP_V6)
- return gcf->city_v6
- ? GeoIP_record_by_ipnum_v6(gcf->city,
- ngx_http_geoip_addr_v6(r, gcf))
- : GeoIP_record_by_ipnum(gcf->city,
- ngx_http_geoip_addr(r, gcf));
-#else
- return GeoIP_record_by_ipnum(gcf->city, ngx_http_geoip_addr(r, gcf));
-#endif
- }
-
- return NULL;
-}
-
-
-static ngx_int_t
-ngx_http_geoip_add_variables(ngx_conf_t *cf)
-{
- ngx_http_variable_t *var, *v;
-
- for (v = ngx_http_geoip_vars; v->name.len; v++) {
- var = ngx_http_add_variable(cf, &v->name, v->flags);
- if (var == NULL) {
- return NGX_ERROR;
- }
-
- var->get_handler = v->get_handler;
- var->data = v->data;
- }
-
- return NGX_OK;
-}
-
-
-static void *
-ngx_http_geoip_create_conf(ngx_conf_t *cf)
-{
- ngx_pool_cleanup_t *cln;
- ngx_http_geoip_conf_t *conf;
-
- conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_geoip_conf_t));
- if (conf == NULL) {
- return NULL;
- }
-
- conf->proxy_recursive = NGX_CONF_UNSET;
-
- cln = ngx_pool_cleanup_add(cf->pool, 0);
- if (cln == NULL) {
- return NULL;
- }
-
- cln->handler = ngx_http_geoip_cleanup;
- cln->data = conf;
-
- return conf;
-}
-
-
-static char *
-ngx_http_geoip_init_conf(ngx_conf_t *cf, void *conf)
-{
- ngx_http_geoip_conf_t *gcf = conf;
-
- ngx_conf_init_value(gcf->proxy_recursive, 0);
-
- return NGX_CONF_OK;
-}
-
-
-static char *
-ngx_http_geoip_country(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
-{
- ngx_http_geoip_conf_t *gcf = conf;
-
- ngx_str_t *value;
-
- if (gcf->country) {
- return "is duplicate";
- }
-
- value = cf->args->elts;
-
- gcf->country = GeoIP_open((char *) value[1].data, GEOIP_MEMORY_CACHE);
-
- if (gcf->country == NULL) {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "GeoIP_open(\"%V\") failed", &value[1]);
-
- return NGX_CONF_ERROR;
- }
-
- if (cf->args->nelts == 3) {
- if (ngx_strcmp(value[2].data, "utf8") == 0) {
- GeoIP_set_charset(gcf->country, GEOIP_CHARSET_UTF8);
-
- } else {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "invalid parameter \"%V\"", &value[2]);
- return NGX_CONF_ERROR;
- }
- }
-
- switch (gcf->country->databaseType) {
-
- case GEOIP_COUNTRY_EDITION:
-
- return NGX_CONF_OK;
-
-#if (NGX_HAVE_GEOIP_V6)
- case GEOIP_COUNTRY_EDITION_V6:
-
- gcf->country_v6 = 1;
- return NGX_CONF_OK;
-#endif
-
- default:
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "invalid GeoIP database \"%V\" type:%d",
- &value[1], gcf->country->databaseType);
- return NGX_CONF_ERROR;
- }
-}
-
-
-static char *
-ngx_http_geoip_org(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
-{
- ngx_http_geoip_conf_t *gcf = conf;
-
- ngx_str_t *value;
-
- if (gcf->org) {
- return "is duplicate";
- }
-
- value = cf->args->elts;
-
- gcf->org = GeoIP_open((char *) value[1].data, GEOIP_MEMORY_CACHE);
-
- if (gcf->org == NULL) {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "GeoIP_open(\"%V\") failed", &value[1]);
-
- return NGX_CONF_ERROR;
- }
-
- if (cf->args->nelts == 3) {
- if (ngx_strcmp(value[2].data, "utf8") == 0) {
- GeoIP_set_charset(gcf->org, GEOIP_CHARSET_UTF8);
-
- } else {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "invalid parameter \"%V\"", &value[2]);
- return NGX_CONF_ERROR;
- }
- }
-
- switch (gcf->org->databaseType) {
-
- case GEOIP_ISP_EDITION:
- case GEOIP_ORG_EDITION:
- case GEOIP_DOMAIN_EDITION:
- case GEOIP_ASNUM_EDITION:
-
- return NGX_CONF_OK;
-
-#if (NGX_HAVE_GEOIP_V6)
- case GEOIP_ISP_EDITION_V6:
- case GEOIP_ORG_EDITION_V6:
- case GEOIP_DOMAIN_EDITION_V6:
- case GEOIP_ASNUM_EDITION_V6:
-
- gcf->org_v6 = 1;
- return NGX_CONF_OK;
-#endif
-
- default:
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "invalid GeoIP database \"%V\" type:%d",
- &value[1], gcf->org->databaseType);
- return NGX_CONF_ERROR;
- }
-}
-
-
-static char *
-ngx_http_geoip_city(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
-{
- ngx_http_geoip_conf_t *gcf = conf;
-
- ngx_str_t *value;
-
- if (gcf->city) {
- return "is duplicate";
- }
-
- value = cf->args->elts;
-
- gcf->city = GeoIP_open((char *) value[1].data, GEOIP_MEMORY_CACHE);
-
- if (gcf->city == NULL) {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "GeoIP_open(\"%V\") failed", &value[1]);
-
- return NGX_CONF_ERROR;
- }
-
- if (cf->args->nelts == 3) {
- if (ngx_strcmp(value[2].data, "utf8") == 0) {
- GeoIP_set_charset(gcf->city, GEOIP_CHARSET_UTF8);
-
- } else {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "invalid parameter \"%V\"", &value[2]);
- return NGX_CONF_ERROR;
- }
- }
-
- switch (gcf->city->databaseType) {
-
- case GEOIP_CITY_EDITION_REV0:
- case GEOIP_CITY_EDITION_REV1:
-
- return NGX_CONF_OK;
-
-#if (NGX_HAVE_GEOIP_V6)
- case GEOIP_CITY_EDITION_REV0_V6:
- case GEOIP_CITY_EDITION_REV1_V6:
-
- gcf->city_v6 = 1;
- return NGX_CONF_OK;
-#endif
-
- default:
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "invalid GeoIP City database \"%V\" type:%d",
- &value[1], gcf->city->databaseType);
- return NGX_CONF_ERROR;
- }
-}
-
-
-static char *
-ngx_http_geoip_proxy(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
-{
- ngx_http_geoip_conf_t *gcf = conf;
-
- ngx_str_t *value;
- ngx_cidr_t cidr, *c;
-
- value = cf->args->elts;
-
- if (ngx_http_geoip_cidr_value(cf, &value[1], &cidr) != NGX_OK) {
- return NGX_CONF_ERROR;
- }
-
- if (gcf->proxies == NULL) {
- gcf->proxies = ngx_array_create(cf->pool, 4, sizeof(ngx_cidr_t));
- if (gcf->proxies == NULL) {
- return NGX_CONF_ERROR;
- }
- }
-
- c = ngx_array_push(gcf->proxies);
- if (c == NULL) {
- return NGX_CONF_ERROR;
- }
-
- *c = cidr;
-
- return NGX_CONF_OK;
-}
-
-static ngx_int_t
-ngx_http_geoip_cidr_value(ngx_conf_t *cf, ngx_str_t *net, ngx_cidr_t *cidr)
-{
- ngx_int_t rc;
-
- if (ngx_strcmp(net->data, "255.255.255.255") == 0) {
- cidr->family = AF_INET;
- cidr->u.in.addr = 0xffffffff;
- cidr->u.in.mask = 0xffffffff;
-
- return NGX_OK;
- }
-
- rc = ngx_ptocidr(net, cidr);
-
- if (rc == NGX_ERROR) {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid network \"%V\"", net);
- return NGX_ERROR;
- }
-
- if (rc == NGX_DONE) {
- ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
- "low address bits of %V are meaningless", net);
- }
-
- return NGX_OK;
-}
-
-
-static void
-ngx_http_geoip_cleanup(void *data)
-{
- ngx_http_geoip_conf_t *gcf = data;
-
- if (gcf->country) {
- GeoIP_delete(gcf->country);
- }
-
- if (gcf->org) {
- GeoIP_delete(gcf->org);
- }
-
- if (gcf->city) {
- GeoIP_delete(gcf->city);
- }
-}
diff --git a/nginx/src/http/modules/ngx_http_grpc_module.c b/nginx/src/http/modules/ngx_http_grpc_module.c
deleted file mode 100644
index 62b33fd..0000000
--- a/nginx/src/http/modules/ngx_http_grpc_module.c
+++ /dev/null
@@ -1,4707 +0,0 @@
-
-/*
- * Copyright (C) Maxim Dounin
- * Copyright (C) Nginx, Inc.
- */
-
-
-#include <ngx_config.h>
-#include <ngx_core.h>
-#include <ngx_http.h>
-
-
-typedef struct {
- ngx_array_t *flushes;
- ngx_array_t *lengths;
- ngx_array_t *values;
- ngx_hash_t hash;
-} ngx_http_grpc_headers_t;
-
-
-typedef struct {
- ngx_http_upstream_conf_t upstream;
-
- ngx_http_grpc_headers_t headers;
- ngx_array_t *headers_source;
-
- ngx_str_t host;
- ngx_uint_t host_set;
-
-#if (NGX_HTTP_SSL)
- ngx_uint_t ssl;
- ngx_uint_t ssl_protocols;
- ngx_str_t ssl_ciphers;
- ngx_uint_t ssl_verify_depth;
- ngx_str_t ssl_trusted_certificate;
- ngx_str_t ssl_crl;
- ngx_str_t ssl_certificate;
- ngx_str_t ssl_certificate_key;
- ngx_array_t *ssl_passwords;
-#endif
-} ngx_http_grpc_loc_conf_t;
-
-
-typedef enum {
- ngx_http_grpc_st_start = 0,
- ngx_http_grpc_st_length_2,
- ngx_http_grpc_st_length_3,
- ngx_http_grpc_st_type,
- ngx_http_grpc_st_flags,
- ngx_http_grpc_st_stream_id,
- ngx_http_grpc_st_stream_id_2,
- ngx_http_grpc_st_stream_id_3,
- ngx_http_grpc_st_stream_id_4,
- ngx_http_grpc_st_payload,
- ngx_http_grpc_st_padding
-} ngx_http_grpc_state_e;
-
-
-typedef struct {
- size_t init_window;
- size_t send_window;
- size_t recv_window;
- ngx_uint_t last_stream_id;
-} ngx_http_grpc_conn_t;
-
-
-typedef struct {
- ngx_http_grpc_state_e state;
- ngx_uint_t frame_state;
- ngx_uint_t fragment_state;
-
- ngx_chain_t *in;
- ngx_chain_t *out;
- ngx_chain_t *free;
- ngx_chain_t *busy;
-
- ngx_http_grpc_conn_t *connection;
-
- ngx_uint_t id;
-
- ngx_uint_t pings;
- ngx_uint_t settings;
-
- ssize_t send_window;
- size_t recv_window;
-
- size_t rest;
- ngx_uint_t stream_id;
- u_char type;
- u_char flags;
- u_char padding;
-
- ngx_uint_t error;
- ngx_uint_t window_update;
-
- ngx_uint_t setting_id;
- ngx_uint_t setting_value;
-
- u_char ping_data[8];
-
- ngx_uint_t index;
- ngx_str_t name;
- ngx_str_t value;
-
- u_char *field_end;
- size_t field_length;
- size_t field_rest;
- u_char field_state;
-
- unsigned literal:1;
- unsigned field_huffman:1;
-
- unsigned header_sent:1;
- unsigned output_closed:1;
- unsigned output_blocked:1;
- unsigned parsing_headers:1;
- unsigned end_stream:1;
- unsigned done:1;
- unsigned status:1;
-
- ngx_http_request_t *request;
-} ngx_http_grpc_ctx_t;
-
-
-typedef struct {
- u_char length_0;
- u_char length_1;
- u_char length_2;
- u_char type;
- u_char flags;
- u_char stream_id_0;
- u_char stream_id_1;
- u_char stream_id_2;
- u_char stream_id_3;
-} ngx_http_grpc_frame_t;
-
-
-static ngx_int_t ngx_http_grpc_create_request(ngx_http_request_t *r);
-static ngx_int_t ngx_http_grpc_reinit_request(ngx_http_request_t *r);
-static ngx_int_t ngx_http_grpc_body_output_filter(void *data, ngx_chain_t *in);
-static ngx_int_t ngx_http_grpc_process_header(ngx_http_request_t *r);
-static ngx_int_t ngx_http_grpc_filter_init(void *data);
-static ngx_int_t ngx_http_grpc_filter(void *data, ssize_t bytes);
-
-static ngx_int_t ngx_http_grpc_parse_frame(ngx_http_request_t *r,
- ngx_http_grpc_ctx_t *ctx, ngx_buf_t *b);
-static ngx_int_t ngx_http_grpc_parse_header(ngx_http_request_t *r,
- ngx_http_grpc_ctx_t *ctx, ngx_buf_t *b);
-static ngx_int_t ngx_http_grpc_parse_fragment(ngx_http_request_t *r,
- ngx_http_grpc_ctx_t *ctx, ngx_buf_t *b);
-static ngx_int_t ngx_http_grpc_validate_header_name(ngx_http_request_t *r,
- ngx_str_t *s);
-static ngx_int_t ngx_http_grpc_validate_header_value(ngx_http_request_t *r,
- ngx_str_t *s);
-static ngx_int_t ngx_http_grpc_parse_rst_stream(ngx_http_request_t *r,
- ngx_http_grpc_ctx_t *ctx, ngx_buf_t *b);
-static ngx_int_t ngx_http_grpc_parse_goaway(ngx_http_request_t *r,
- ngx_http_grpc_ctx_t *ctx, ngx_buf_t *b);
-static ngx_int_t ngx_http_grpc_parse_window_update(ngx_http_request_t *r,
- ngx_http_grpc_ctx_t *ctx, ngx_buf_t *b);
-static ngx_int_t ngx_http_grpc_parse_settings(ngx_http_request_t *r,
- ngx_http_grpc_ctx_t *ctx, ngx_buf_t *b);
-static ngx_int_t ngx_http_grpc_parse_ping(ngx_http_request_t *r,
- ngx_http_grpc_ctx_t *ctx, ngx_buf_t *b);
-
-static ngx_int_t ngx_http_grpc_send_settings_ack(ngx_http_request_t *r,
- ngx_http_grpc_ctx_t *ctx);
-static ngx_int_t ngx_http_grpc_send_ping_ack(ngx_http_request_t *r,
- ngx_http_grpc_ctx_t *ctx);
-static ngx_int_t ngx_http_grpc_send_window_update(ngx_http_request_t *r,
- ngx_http_grpc_ctx_t *ctx);
-
-static ngx_chain_t *ngx_http_grpc_get_buf(ngx_http_request_t *r,
- ngx_http_grpc_ctx_t *ctx);
-static ngx_http_grpc_ctx_t *ngx_http_grpc_get_ctx(ngx_http_request_t *r);
-static ngx_int_t ngx_http_grpc_get_connection_data(ngx_http_request_t *r,
- ngx_http_grpc_ctx_t *ctx, ngx_peer_connection_t *pc);
-static void ngx_http_grpc_cleanup(void *data);
-
-static void ngx_http_grpc_abort_request(ngx_http_request_t *r);
-static void ngx_http_grpc_finalize_request(ngx_http_request_t *r,
- ngx_int_t rc);
-
-static ngx_int_t ngx_http_grpc_internal_trailers_variable(
- ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data);
-
-static ngx_int_t ngx_http_grpc_add_variables(ngx_conf_t *cf);
-static void *ngx_http_grpc_create_loc_conf(ngx_conf_t *cf);
-static char *ngx_http_grpc_merge_loc_conf(ngx_conf_t *cf,
- void *parent, void *child);
-static ngx_int_t ngx_http_grpc_init_headers(ngx_conf_t *cf,
- ngx_http_grpc_loc_conf_t *conf, ngx_http_grpc_headers_t *headers,
- ngx_keyval_t *default_headers);
-
-static char *ngx_http_grpc_pass(ngx_conf_t *cf, ngx_command_t *cmd,
- void *conf);
-
-#if (NGX_HTTP_SSL)
-static char *ngx_http_grpc_ssl_password_file(ngx_conf_t *cf,
- ngx_command_t *cmd, void *conf);
-static ngx_int_t ngx_http_grpc_set_ssl(ngx_conf_t *cf,
- ngx_http_grpc_loc_conf_t *glcf);
-#endif
-
-
-static ngx_conf_bitmask_t ngx_http_grpc_next_upstream_masks[] = {
- { ngx_string("error"), NGX_HTTP_UPSTREAM_FT_ERROR },
- { ngx_string("timeout"), NGX_HTTP_UPSTREAM_FT_TIMEOUT },
- { ngx_string("invalid_header"), NGX_HTTP_UPSTREAM_FT_INVALID_HEADER },
- { ngx_string("non_idempotent"), NGX_HTTP_UPSTREAM_FT_NON_IDEMPOTENT },
- { ngx_string("http_500"), NGX_HTTP_UPSTREAM_FT_HTTP_500 },
- { ngx_string("http_502"), NGX_HTTP_UPSTREAM_FT_HTTP_502 },
- { ngx_string("http_503"), NGX_HTTP_UPSTREAM_FT_HTTP_503 },
- { ngx_string("http_504"), NGX_HTTP_UPSTREAM_FT_HTTP_504 },
- { ngx_string("http_403"), NGX_HTTP_UPSTREAM_FT_HTTP_403 },
- { ngx_string("http_404"), NGX_HTTP_UPSTREAM_FT_HTTP_404 },
- { ngx_string("http_429"), NGX_HTTP_UPSTREAM_FT_HTTP_429 },
- { ngx_string("off"), NGX_HTTP_UPSTREAM_FT_OFF },
- { ngx_null_string, 0 }
-};
-
-
-#if (NGX_HTTP_SSL)
-
-static ngx_conf_bitmask_t ngx_http_grpc_ssl_protocols[] = {
- { ngx_string("SSLv2"), NGX_SSL_SSLv2 },
- { ngx_string("SSLv3"), NGX_SSL_SSLv3 },
- { ngx_string("TLSv1"), NGX_SSL_TLSv1 },
- { ngx_string("TLSv1.1"), NGX_SSL_TLSv1_1 },
- { ngx_string("TLSv1.2"), NGX_SSL_TLSv1_2 },
- { ngx_string("TLSv1.3"), NGX_SSL_TLSv1_3 },
- { ngx_null_string, 0 }
-};
-
-#endif
-
-
-static ngx_command_t ngx_http_grpc_commands[] = {
-
- { ngx_string("grpc_pass"),
- NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_TAKE1,
- ngx_http_grpc_pass,
- NGX_HTTP_LOC_CONF_OFFSET,
- 0,
- NULL },
-
- { ngx_string("grpc_bind"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE12,
- ngx_http_upstream_bind_set_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_grpc_loc_conf_t, upstream.local),
- NULL },
-
- { ngx_string("grpc_connect_timeout"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_msec_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_grpc_loc_conf_t, upstream.connect_timeout),
- NULL },
-
- { ngx_string("grpc_send_timeout"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_msec_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_grpc_loc_conf_t, upstream.send_timeout),
- NULL },
-
- { ngx_string("grpc_intercept_errors"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
- ngx_conf_set_flag_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_grpc_loc_conf_t, upstream.intercept_errors),
- NULL },
-
- { ngx_string("grpc_buffer_size"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_size_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_grpc_loc_conf_t, upstream.buffer_size),
- NULL },
-
- { ngx_string("grpc_read_timeout"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_msec_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_grpc_loc_conf_t, upstream.read_timeout),
- NULL },
-
- { ngx_string("grpc_next_upstream"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
- ngx_conf_set_bitmask_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_grpc_loc_conf_t, upstream.next_upstream),
- &ngx_http_grpc_next_upstream_masks },
-
- { ngx_string("grpc_next_upstream_tries"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_num_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_grpc_loc_conf_t, upstream.next_upstream_tries),
- NULL },
-
- { ngx_string("grpc_next_upstream_timeout"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_msec_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_grpc_loc_conf_t, upstream.next_upstream_timeout),
- NULL },
-
- { ngx_string("grpc_set_header"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE2,
- ngx_conf_set_keyval_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_grpc_loc_conf_t, headers_source),
- NULL },
-
- { ngx_string("grpc_pass_header"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_str_array_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_grpc_loc_conf_t, upstream.pass_headers),
- NULL },
-
- { ngx_string("grpc_hide_header"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_str_array_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_grpc_loc_conf_t, upstream.hide_headers),
- NULL },
-
- { ngx_string("grpc_ignore_headers"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
- ngx_conf_set_bitmask_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_grpc_loc_conf_t, upstream.ignore_headers),
- &ngx_http_upstream_ignore_headers_masks },
-
-#if (NGX_HTTP_SSL)
-
- { ngx_string("grpc_ssl_session_reuse"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
- ngx_conf_set_flag_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_grpc_loc_conf_t, upstream.ssl_session_reuse),
- NULL },
-
- { ngx_string("grpc_ssl_protocols"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
- ngx_conf_set_bitmask_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_grpc_loc_conf_t, ssl_protocols),
- &ngx_http_grpc_ssl_protocols },
-
- { ngx_string("grpc_ssl_ciphers"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_str_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_grpc_loc_conf_t, ssl_ciphers),
- NULL },
-
- { ngx_string("grpc_ssl_name"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_http_set_complex_value_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_grpc_loc_conf_t, upstream.ssl_name),
- NULL },
-
- { ngx_string("grpc_ssl_server_name"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
- ngx_conf_set_flag_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_grpc_loc_conf_t, upstream.ssl_server_name),
- NULL },
-
- { ngx_string("grpc_ssl_verify"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
- ngx_conf_set_flag_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_grpc_loc_conf_t, upstream.ssl_verify),
- NULL },
-
- { ngx_string("grpc_ssl_verify_depth"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_num_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_grpc_loc_conf_t, ssl_verify_depth),
- NULL },
-
- { ngx_string("grpc_ssl_trusted_certificate"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_str_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_grpc_loc_conf_t, ssl_trusted_certificate),
- NULL },
-
- { ngx_string("grpc_ssl_crl"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_str_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_grpc_loc_conf_t, ssl_crl),
- NULL },
-
- { ngx_string("grpc_ssl_certificate"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_str_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_grpc_loc_conf_t, ssl_certificate),
- NULL },
-
- { ngx_string("grpc_ssl_certificate_key"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_str_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_grpc_loc_conf_t, ssl_certificate_key),
- NULL },
-
- { ngx_string("grpc_ssl_password_file"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_http_grpc_ssl_password_file,
- NGX_HTTP_LOC_CONF_OFFSET,
- 0,
- NULL },
-
-#endif
-
- ngx_null_command
-};
-
-
-static ngx_http_module_t ngx_http_grpc_module_ctx = {
- ngx_http_grpc_add_variables, /* preconfiguration */
- NULL, /* postconfiguration */
-
- NULL, /* create main configuration */
- NULL, /* init main configuration */
-
- NULL, /* create server configuration */
- NULL, /* merge server configuration */
-
- ngx_http_grpc_create_loc_conf, /* create location configuration */
- ngx_http_grpc_merge_loc_conf /* merge location configuration */
-};
-
-
-ngx_module_t ngx_http_grpc_module = {
- NGX_MODULE_V1,
- &ngx_http_grpc_module_ctx, /* module context */
- ngx_http_grpc_commands, /* module directives */
- NGX_HTTP_MODULE, /* module type */
- NULL, /* init master */
- NULL, /* init module */
- NULL, /* init process */
- NULL, /* init thread */
- NULL, /* exit thread */
- NULL, /* exit process */
- NULL, /* exit master */
- NGX_MODULE_V1_PADDING
-};
-
-
-static u_char ngx_http_grpc_connection_start[] =
- "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n" /* connection preface */
-
- "\x00\x00\x12\x04\x00\x00\x00\x00\x00" /* settings frame */
- "\x00\x01\x00\x00\x00\x00" /* header table size */
- "\x00\x02\x00\x00\x00\x00" /* disable push */
- "\x00\x04\x7f\xff\xff\xff" /* initial window */
-
- "\x00\x00\x04\x08\x00\x00\x00\x00\x00" /* window update frame */
- "\x7f\xff\x00\x00";
-
-
-static ngx_keyval_t ngx_http_grpc_headers[] = {
- { ngx_string("Content-Length"), ngx_string("$content_length") },
- { ngx_string("TE"), ngx_string("$grpc_internal_trailers") },
- { ngx_string("Host"), ngx_string("") },
- { ngx_string("Connection"), ngx_string("") },
- { ngx_string("Transfer-Encoding"), ngx_string("") },
- { ngx_string("Keep-Alive"), ngx_string("") },
- { ngx_string("Expect"), ngx_string("") },
- { ngx_string("Upgrade"), ngx_string("") },
- { ngx_null_string, ngx_null_string }
-};
-
-
-static ngx_str_t ngx_http_grpc_hide_headers[] = {
- ngx_string("Date"),
- ngx_string("Server"),
- ngx_string("X-Accel-Expires"),
- ngx_string("X-Accel-Redirect"),
- ngx_string("X-Accel-Limit-Rate"),
- ngx_string("X-Accel-Buffering"),
- ngx_string("X-Accel-Charset"),
- ngx_null_string
-};
-
-
-static ngx_http_variable_t ngx_http_grpc_vars[] = {
-
- { ngx_string("grpc_internal_trailers"), NULL,
- ngx_http_grpc_internal_trailers_variable, 0,
- NGX_HTTP_VAR_NOCACHEABLE|NGX_HTTP_VAR_NOHASH, 0 },
-
- ngx_http_null_variable
-};
-
-
-static ngx_int_t
-ngx_http_grpc_handler(ngx_http_request_t *r)
-{
- ngx_int_t rc;
- ngx_http_upstream_t *u;
- ngx_http_grpc_ctx_t *ctx;
- ngx_http_grpc_loc_conf_t *glcf;
-
- if (ngx_http_upstream_create(r) != NGX_OK) {
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
-
- glcf = ngx_http_get_module_loc_conf(r, ngx_http_grpc_module);
-
- u = r->upstream;
-
-#if (NGX_HTTP_SSL)
- u->ssl = (glcf->upstream.ssl != NULL);
-
- if (u->ssl) {
- ngx_str_set(&u->schema, "grpcs://");
-
- } else {
- ngx_str_set(&u->schema, "grpc://");
- }
-#else
- ngx_str_set(&u->schema, "grpc://");
-#endif
-
- u->output.tag = (ngx_buf_tag_t) &ngx_http_grpc_module;
-
- u->conf = &glcf->upstream;
-
- u->create_request = ngx_http_grpc_create_request;
- u->reinit_request = ngx_http_grpc_reinit_request;
- u->process_header = ngx_http_grpc_process_header;
- u->abort_request = ngx_http_grpc_abort_request;
- u->finalize_request = ngx_http_grpc_finalize_request;
-
- ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_grpc_ctx_t));
- if (ctx == NULL) {
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
-
- ctx->request = r;
-
- ngx_http_set_ctx(r, ctx, ngx_http_grpc_module);
-
- u->input_filter_init = ngx_http_grpc_filter_init;
- u->input_filter = ngx_http_grpc_filter;
- u->input_filter_ctx = ctx;
-
- r->request_body_no_buffering = 1;
-
- rc = ngx_http_read_client_request_body(r, ngx_http_upstream_init);
-
- if (rc >= NGX_HTTP_SPECIAL_RESPONSE) {
- return rc;
- }
-
- return NGX_DONE;
-}
-
-
-static ngx_int_t
-ngx_http_grpc_create_request(ngx_http_request_t *r)
-{
- u_char *p, *tmp, *key_tmp, *val_tmp, *headers_frame;
- size_t len, tmp_len, key_len, val_len, uri_len;
- uintptr_t escape;
- ngx_buf_t *b;
- ngx_uint_t i, next;
- ngx_chain_t *cl, *body;
- ngx_list_part_t *part;
- ngx_table_elt_t *header;
- ngx_http_upstream_t *u;
- ngx_http_grpc_frame_t *f;
- ngx_http_script_code_pt code;
- ngx_http_grpc_loc_conf_t *glcf;
- ngx_http_script_engine_t e, le;
- ngx_http_script_len_code_pt lcode;
-
- u = r->upstream;
-
- glcf = ngx_http_get_module_loc_conf(r, ngx_http_grpc_module);
-
- len = sizeof(ngx_http_grpc_connection_start) - 1
- + sizeof(ngx_http_grpc_frame_t); /* headers frame */
-
- /* :method header */
-
- if (r->method == NGX_HTTP_GET || r->method == NGX_HTTP_POST) {
- len += 1;
- tmp_len = 0;
-
- } else {
- len += 1 + NGX_HTTP_V2_INT_OCTETS + r->method_name.len;
- tmp_len = r->method_name.len;
- }
-
- /* :scheme header */
-
- len += 1;
-
- /* :path header */
-
- if (r->valid_unparsed_uri) {
- escape = 0;
- uri_len = r->unparsed_uri.len;
-
- } else {
- escape = 2 * ngx_escape_uri(NULL, r->uri.data, r->uri.len,
- NGX_ESCAPE_URI);
- uri_len = r->uri.len + escape + sizeof("?") - 1 + r->args.len;
- }
-
- len += 1 + NGX_HTTP_V2_INT_OCTETS + uri_len;
-
- if (tmp_len < uri_len) {
- tmp_len = uri_len;
- }
-
- /* :authority header */
-
- if (!glcf->host_set) {
- len += 1 + NGX_HTTP_V2_INT_OCTETS + glcf->host.len;
-
- if (tmp_len < glcf->host.len) {
- tmp_len = glcf->host.len;
- }
- }
-
- /* other headers */
-
- ngx_http_script_flush_no_cacheable_variables(r, glcf->headers.flushes);
- ngx_memzero(&le, sizeof(ngx_http_script_engine_t));
-
- le.ip = glcf->headers.lengths->elts;
- le.request = r;
- le.flushed = 1;
-
- while (*(uintptr_t *) le.ip) {
-
- lcode = *(ngx_http_script_len_code_pt *) le.ip;
- key_len = lcode(&le);
-
- for (val_len = 0; *(uintptr_t *) le.ip; val_len += lcode(&le)) {
- lcode = *(ngx_http_script_len_code_pt *) le.ip;
- }
- le.ip += sizeof(uintptr_t);
-
- if (val_len == 0) {
- continue;
- }
-
- len += 1 + NGX_HTTP_V2_INT_OCTETS + key_len
- + NGX_HTTP_V2_INT_OCTETS + val_len;
-
- if (tmp_len < key_len) {
- tmp_len = key_len;
- }
-
- if (tmp_len < val_len) {
- tmp_len = val_len;
- }
- }
-
- if (glcf->upstream.pass_request_headers) {
- part = &r->headers_in.headers.part;
- header = part->elts;
-
- for (i = 0; /* void */; i++) {
-
- if (i >= part->nelts) {
- if (part->next == NULL) {
- break;
- }
-
- part = part->next;
- header = part->elts;
- i = 0;
- }
-
- if (ngx_hash_find(&glcf->headers.hash, header[i].hash,
- header[i].lowcase_key, header[i].key.len))
- {
- continue;
- }
-
- len += 1 + NGX_HTTP_V2_INT_OCTETS + header[i].key.len
- + NGX_HTTP_V2_INT_OCTETS + header[i].value.len;
-
- if (tmp_len < header[i].key.len) {
- tmp_len = header[i].key.len;
- }
-
- if (tmp_len < header[i].value.len) {
- tmp_len = header[i].value.len;
- }
- }
- }
-
- /* continuation frames */
-
- len += sizeof(ngx_http_grpc_frame_t)
- * (len / NGX_HTTP_V2_DEFAULT_FRAME_SIZE);
-
-
- b = ngx_create_temp_buf(r->pool, len);
- if (b == NULL) {
- return NGX_ERROR;
- }
-
- cl = ngx_alloc_chain_link(r->pool);
- if (cl == NULL) {
- return NGX_ERROR;
- }
-
- cl->buf = b;
- cl->next = NULL;
-
- tmp = ngx_palloc(r->pool, tmp_len * 3);
- if (tmp == NULL) {
- return NGX_ERROR;
- }
-
- key_tmp = tmp + tmp_len;
- val_tmp = tmp + 2 * tmp_len;
-
- /* connection preface */
-
- b->last = ngx_copy(b->last, ngx_http_grpc_connection_start,
- sizeof(ngx_http_grpc_connection_start) - 1);
-
- /* headers frame */
-
- headers_frame = b->last;
-
- f = (ngx_http_grpc_frame_t *) b->last;
- b->last += sizeof(ngx_http_grpc_frame_t);
-
- f->length_0 = 0;
- f->length_1 = 0;
- f->length_2 = 0;
- f->type = NGX_HTTP_V2_HEADERS_FRAME;
- f->flags = 0;
- f->stream_id_0 = 0;
- f->stream_id_1 = 0;
- f->stream_id_2 = 0;
- f->stream_id_3 = 1;
-
- if (r->method == NGX_HTTP_GET) {
- *b->last++ = ngx_http_v2_indexed(NGX_HTTP_V2_METHOD_GET_INDEX);
-
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "grpc header: \":method: GET\"");
-
- } else if (r->method == NGX_HTTP_POST) {
- *b->last++ = ngx_http_v2_indexed(NGX_HTTP_V2_METHOD_POST_INDEX);
-
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "grpc header: \":method: POST\"");
-
- } else {
- *b->last++ = ngx_http_v2_inc_indexed(NGX_HTTP_V2_METHOD_INDEX);
- b->last = ngx_http_v2_write_value(b->last, r->method_name.data,
- r->method_name.len, tmp);
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "grpc header: \":method: %V\"", &r->method_name);
- }
-
-#if (NGX_HTTP_SSL)
- if (glcf->ssl) {
- *b->last++ = ngx_http_v2_indexed(NGX_HTTP_V2_SCHEME_HTTPS_INDEX);
-
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "grpc header: \":scheme: https\"");
- } else
-#endif
- {
- *b->last++ = ngx_http_v2_indexed(NGX_HTTP_V2_SCHEME_HTTP_INDEX);
-
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "grpc header: \":scheme: http\"");
- }
-
- if (r->valid_unparsed_uri) {
-
- if (r->unparsed_uri.len == 1 && r->unparsed_uri.data[0] == '/') {
- *b->last++ = ngx_http_v2_indexed(NGX_HTTP_V2_PATH_ROOT_INDEX);
-
- } else {
- *b->last++ = ngx_http_v2_inc_indexed(NGX_HTTP_V2_PATH_INDEX);
- b->last = ngx_http_v2_write_value(b->last, r->unparsed_uri.data,
- r->unparsed_uri.len, tmp);
- }
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "grpc header: \":path: %V\"", &r->unparsed_uri);
-
- } else if (escape || r->args.len > 0) {
- p = val_tmp;
-
- if (escape) {
- p = (u_char *) ngx_escape_uri(p, r->uri.data, r->uri.len,
- NGX_ESCAPE_URI);
-
- } else {
- p = ngx_copy(p, r->uri.data, r->uri.len);
- }
-
- if (r->args.len > 0) {
- *p++ = '?';
- p = ngx_copy(p, r->args.data, r->args.len);
- }
-
- *b->last++ = ngx_http_v2_inc_indexed(NGX_HTTP_V2_PATH_INDEX);
- b->last = ngx_http_v2_write_value(b->last, val_tmp, p - val_tmp, tmp);
-
- ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "grpc header: \":path: %*s\"", p - val_tmp, val_tmp);
-
- } else {
- *b->last++ = ngx_http_v2_inc_indexed(NGX_HTTP_V2_PATH_INDEX);
- b->last = ngx_http_v2_write_value(b->last, r->uri.data,
- r->uri.len, tmp);
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "grpc header: \":path: %V\"", &r->uri);
- }
-
- if (!glcf->host_set) {
- *b->last++ = ngx_http_v2_inc_indexed(NGX_HTTP_V2_AUTHORITY_INDEX);
- b->last = ngx_http_v2_write_value(b->last, glcf->host.data,
- glcf->host.len, tmp);
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "grpc header: \":authority: %V\"", &glcf->host);
- }
-
- ngx_memzero(&e, sizeof(ngx_http_script_engine_t));
-
- e.ip = glcf->headers.values->elts;
- e.request = r;
- e.flushed = 1;
-
- le.ip = glcf->headers.lengths->elts;
-
- while (*(uintptr_t *) le.ip) {
-
- lcode = *(ngx_http_script_len_code_pt *) le.ip;
- key_len = lcode(&le);
-
- for (val_len = 0; *(uintptr_t *) le.ip; val_len += lcode(&le)) {
- lcode = *(ngx_http_script_len_code_pt *) le.ip;
- }
- le.ip += sizeof(uintptr_t);
-
- if (val_len == 0) {
- e.skip = 1;
-
- while (*(uintptr_t *) e.ip) {
- code = *(ngx_http_script_code_pt *) e.ip;
- code((ngx_http_script_engine_t *) &e);
- }
- e.ip += sizeof(uintptr_t);
-
- e.skip = 0;
-
- continue;
- }
-
- *b->last++ = 0;
-
- e.pos = key_tmp;
-
- code = *(ngx_http_script_code_pt *) e.ip;
- code((ngx_http_script_engine_t *) &e);
-
- b->last = ngx_http_v2_write_name(b->last, key_tmp, key_len, tmp);
-
- e.pos = val_tmp;
-
- while (*(uintptr_t *) e.ip) {
- code = *(ngx_http_script_code_pt *) e.ip;
- code((ngx_http_script_engine_t *) &e);
- }
- e.ip += sizeof(uintptr_t);
-
- b->last = ngx_http_v2_write_value(b->last, val_tmp, val_len, tmp);
-
-#if (NGX_DEBUG)
- if (r->connection->log->log_level & NGX_LOG_DEBUG_HTTP) {
- ngx_strlow(key_tmp, key_tmp, key_len);
-
- ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "grpc header: \"%*s: %*s\"",
- key_len, key_tmp, val_len, val_tmp);
- }
-#endif
- }
-
- if (glcf->upstream.pass_request_headers) {
- part = &r->headers_in.headers.part;
- header = part->elts;
-
- for (i = 0; /* void */; i++) {
-
- if (i >= part->nelts) {
- if (part->next == NULL) {
- break;
- }
-
- part = part->next;
- header = part->elts;
- i = 0;
- }
-
- if (ngx_hash_find(&glcf->headers.hash, header[i].hash,
- header[i].lowcase_key, header[i].key.len))
- {
- continue;
- }
-
- *b->last++ = 0;
-
- b->last = ngx_http_v2_write_name(b->last, header[i].key.data,
- header[i].key.len, tmp);
-
- b->last = ngx_http_v2_write_value(b->last, header[i].value.data,
- header[i].value.len, tmp);
-
-#if (NGX_DEBUG)
- if (r->connection->log->log_level & NGX_LOG_DEBUG_HTTP) {
- ngx_strlow(tmp, header[i].key.data, header[i].key.len);
-
- ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "grpc header: \"%*s: %V\"",
- header[i].key.len, tmp, &header[i].value);
- }
-#endif
- }
- }
-
- /* update headers frame length */
-
- len = b->last - headers_frame - sizeof(ngx_http_grpc_frame_t);
-
- if (len > NGX_HTTP_V2_DEFAULT_FRAME_SIZE) {
- len = NGX_HTTP_V2_DEFAULT_FRAME_SIZE;
- next = 1;
-
- } else {
- next = 0;
- }
-
- f = (ngx_http_grpc_frame_t *) headers_frame;
-
- f->length_0 = (u_char) ((len >> 16) & 0xff);
- f->length_1 = (u_char) ((len >> 8) & 0xff);
- f->length_2 = (u_char) (len & 0xff);
-
- /* create additional continuation frames */
-
- p = headers_frame;
-
- while (next) {
- p += sizeof(ngx_http_grpc_frame_t) + NGX_HTTP_V2_DEFAULT_FRAME_SIZE;
- len = b->last - p;
-
- ngx_memmove(p + sizeof(ngx_http_grpc_frame_t), p, len);
- b->last += sizeof(ngx_http_grpc_frame_t);
-
- if (len > NGX_HTTP_V2_DEFAULT_FRAME_SIZE) {
- len = NGX_HTTP_V2_DEFAULT_FRAME_SIZE;
- next = 1;
-
- } else {
- next = 0;
- }
-
- f = (ngx_http_grpc_frame_t *) p;
-
- f->length_0 = (u_char) ((len >> 16) & 0xff);
- f->length_1 = (u_char) ((len >> 8) & 0xff);
- f->length_2 = (u_char) (len & 0xff);
- f->type = NGX_HTTP_V2_CONTINUATION_FRAME;
- f->flags = 0;
- f->stream_id_0 = 0;
- f->stream_id_1 = 0;
- f->stream_id_2 = 0;
- f->stream_id_3 = 1;
- }
-
- f->flags |= NGX_HTTP_V2_END_HEADERS_FLAG;
-
-#if (NGX_DEBUG)
- if (r->connection->log->log_level & NGX_LOG_DEBUG_HTTP) {
- u_char buf[512];
- size_t n, m;
-
- n = ngx_min(b->last - b->pos, 256);
- m = ngx_hex_dump(buf, b->pos, n) - buf;
-
- ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "grpc header: %*s%s, len: %uz",
- m, buf, b->last - b->pos > 256 ? "..." : "",
- b->last - b->pos);
- }
-#endif
-
- if (r->request_body_no_buffering) {
-
- u->request_bufs = cl;
-
- } else {
-
- body = u->request_bufs;
- u->request_bufs = cl;
-
- if (body == NULL) {
- f = (ngx_http_grpc_frame_t *) headers_frame;
- f->flags |= NGX_HTTP_V2_END_STREAM_FLAG;
- }
-
- while (body) {
- b = ngx_alloc_buf(r->pool);
- if (b == NULL) {
- return NGX_ERROR;
- }
-
- ngx_memcpy(b, body->buf, sizeof(ngx_buf_t));
-
- cl->next = ngx_alloc_chain_link(r->pool);
- if (cl->next == NULL) {
- return NGX_ERROR;
- }
-
- cl = cl->next;
- cl->buf = b;
-
- body = body->next;
- }
-
- b->last_buf = 1;
- }
-
- u->output.output_filter = ngx_http_grpc_body_output_filter;
- u->output.filter_ctx = r;
-
- b->flush = 1;
- cl->next = NULL;
-
- return NGX_OK;
-}
-
-
-static ngx_int_t
-ngx_http_grpc_reinit_request(ngx_http_request_t *r)
-{
- ngx_http_grpc_ctx_t *ctx;
-
- ctx = ngx_http_get_module_ctx(r, ngx_http_grpc_module);
-
- if (ctx == NULL) {
- return NGX_OK;
- }
-
- ctx->state = 0;
- ctx->header_sent = 0;
- ctx->output_closed = 0;
- ctx->output_blocked = 0;
- ctx->parsing_headers = 0;
- ctx->end_stream = 0;
- ctx->done = 0;
- ctx->status = 0;
- ctx->connection = NULL;
-
- return NGX_OK;
-}
-
-
-static ngx_int_t
-ngx_http_grpc_body_output_filter(void *data, ngx_chain_t *in)
-{
- ngx_http_request_t *r = data;
-
- off_t file_pos;
- u_char *p, *pos, *start;
- size_t len, limit;
- ngx_buf_t *b;
- ngx_int_t rc;
- ngx_uint_t next, last;
- ngx_chain_t *cl, *out, **ll;
- ngx_http_upstream_t *u;
- ngx_http_grpc_ctx_t *ctx;
- ngx_http_grpc_frame_t *f;
-
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "grpc output filter");
-
- ctx = ngx_http_grpc_get_ctx(r);
-
- if (ctx == NULL) {
- return NGX_ERROR;
- }
-
- if (in) {
- if (ngx_chain_add_copy(r->pool, &ctx->in, in) != NGX_OK) {
- return NGX_ERROR;
- }
- }
-
- out = NULL;
- ll = &out;
-
- if (!ctx->header_sent) {
- /* first buffer contains headers */
-
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "grpc output header");
-
- ctx->header_sent = 1;
-
- if (ctx->id != 1) {
- /*
- * keepalive connection: skip connection preface,
- * update stream identifiers
- */
-
- b = ctx->in->buf;
- b->pos += sizeof(ngx_http_grpc_connection_start) - 1;
-
- p = b->pos;
-
- while (p < b->last) {
- f = (ngx_http_grpc_frame_t *) p;
- p += sizeof(ngx_http_grpc_frame_t);
-
- f->stream_id_0 = (u_char) ((ctx->id >> 24) & 0xff);
- f->stream_id_1 = (u_char) ((ctx->id >> 16) & 0xff);
- f->stream_id_2 = (u_char) ((ctx->id >> 8) & 0xff);
- f->stream_id_3 = (u_char) (ctx->id & 0xff);
-
- p += (f->length_0 << 16) + (f->length_1 << 8) + f->length_2;
- }
- }
-
- if (ctx->in->buf->last_buf) {
- ctx->output_closed = 1;
- }
-
- *ll = ctx->in;
- ll = &ctx->in->next;
-
- ctx->in = ctx->in->next;
- }
-
- if (ctx->out) {
- /* queued control frames */
-
- *ll = ctx->out;
-
- for (cl = ctx->out, ll = &cl->next; cl; cl = cl->next) {
- ll = &cl->next;
- }
-
- ctx->out = NULL;
- }
-
- f = NULL;
- last = 0;
-
- limit = ngx_max(0, ctx->send_window);
-
- if (limit > ctx->connection->send_window) {
- limit = ctx->connection->send_window;
- }
-
- ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "grpc output limit: %uz w:%z:%uz",
- limit, ctx->send_window, ctx->connection->send_window);
-
-#if (NGX_SUPPRESS_WARN)
- file_pos = 0;
- pos = NULL;
- cl = NULL;
-#endif
-
- in = ctx->in;
-
- while (in && limit > 0) {
-
- ngx_log_debug7(NGX_LOG_DEBUG_EVENT, r->connection->log, 0,
- "grpc output in l:%d f:%d %p, pos %p, size: %z "
- "file: %O, size: %O",
- in->buf->last_buf,
- in->buf->in_file,
- in->buf->start, in->buf->pos,
- in->buf->last - in->buf->pos,
- in->buf->file_pos,
- in->buf->file_last - in->buf->file_pos);
-
- if (ngx_buf_special(in->buf)) {
- goto next;
- }
-
- if (in->buf->in_file) {
- file_pos = in->buf->file_pos;
-
- } else {
- pos = in->buf->pos;
- }
-
- next = 0;
-
- do {
-
- cl = ngx_http_grpc_get_buf(r, ctx);
- if (cl == NULL) {
- return NGX_ERROR;
- }
-
- b = cl->buf;
-
- f = (ngx_http_grpc_frame_t *) b->last;
- b->last += sizeof(ngx_http_grpc_frame_t);
-
- *ll = cl;
- ll = &cl->next;
-
- cl = ngx_chain_get_free_buf(r->pool, &ctx->free);
- if (cl == NULL) {
- return NGX_ERROR;
- }
-
- b = cl->buf;
- start = b->start;
-
- ngx_memcpy(b, in->buf, sizeof(ngx_buf_t));
-
- /*
- * restore b->start to preserve memory allocated in the buffer,
- * to reuse it later for headers and control frames
- */
-
- b->start = start;
-
- if (in->buf->in_file) {
- b->file_pos = file_pos;
- file_pos += ngx_min(NGX_HTTP_V2_DEFAULT_FRAME_SIZE, limit);
-
- if (file_pos >= in->buf->file_last) {
- file_pos = in->buf->file_last;
- next = 1;
- }
-
- b->file_last = file_pos;
- len = (ngx_uint_t) (file_pos - b->file_pos);
-
- } else {
- b->pos = pos;
- pos += ngx_min(NGX_HTTP_V2_DEFAULT_FRAME_SIZE, limit);
-
- if (pos >= in->buf->last) {
- pos = in->buf->last;
- next = 1;
- }
-
- b->last = pos;
- len = (ngx_uint_t) (pos - b->pos);
- }
-
- b->tag = (ngx_buf_tag_t) &ngx_http_grpc_body_output_filter;
- b->shadow = in->buf;
- b->last_shadow = next;
-
- b->last_buf = 0;
- b->last_in_chain = 0;
-
- *ll = cl;
- ll = &cl->next;
-
- f->length_0 = (u_char) ((len >> 16) & 0xff);
- f->length_1 = (u_char) ((len >> 8) & 0xff);
- f->length_2 = (u_char) (len & 0xff);
- f->type = NGX_HTTP_V2_DATA_FRAME;
- f->flags = 0;
- f->stream_id_0 = (u_char) ((ctx->id >> 24) & 0xff);
- f->stream_id_1 = (u_char) ((ctx->id >> 16) & 0xff);
- f->stream_id_2 = (u_char) ((ctx->id >> 8) & 0xff);
- f->stream_id_3 = (u_char) (ctx->id & 0xff);
-
- limit -= len;
- ctx->send_window -= len;
- ctx->connection->send_window -= len;
-
- } while (!next && limit > 0);
-
- if (!next) {
- /*
- * if the buffer wasn't fully sent due to flow control limits,
- * preserve position for future use
- */
-
- if (in->buf->in_file) {
- in->buf->file_pos = file_pos;
-
- } else {
- in->buf->pos = pos;
- }
-
- break;
- }
-
- next:
-
- if (in->buf->last_buf) {
- last = 1;
- }
-
- in = in->next;
- }
-
- ctx->in = in;
-
- if (last) {
-
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "grpc output last");
-
- ctx->output_closed = 1;
-
- if (f) {
- f->flags |= NGX_HTTP_V2_END_STREAM_FLAG;
-
- } else {
- cl = ngx_http_grpc_get_buf(r, ctx);
- if (cl == NULL) {
- return NGX_ERROR;
- }
-
- b = cl->buf;
-
- f = (ngx_http_grpc_frame_t *) b->last;
- b->last += sizeof(ngx_http_grpc_frame_t);
-
- f->length_0 = 0;
- f->length_1 = 0;
- f->length_2 = 0;
- f->type = NGX_HTTP_V2_DATA_FRAME;
- f->flags = NGX_HTTP_V2_END_STREAM_FLAG;
- f->stream_id_0 = (u_char) ((ctx->id >> 24) & 0xff);
- f->stream_id_1 = (u_char) ((ctx->id >> 16) & 0xff);
- f->stream_id_2 = (u_char) ((ctx->id >> 8) & 0xff);
- f->stream_id_3 = (u_char) (ctx->id & 0xff);
-
- *ll = cl;
- ll = &cl->next;
- }
-
- cl->buf->last_buf = 1;
- }
-
- *ll = NULL;
-
-#if (NGX_DEBUG)
-
- for (cl = out; cl; cl = cl->next) {
- ngx_log_debug7(NGX_LOG_DEBUG_EVENT, r->connection->log, 0,
- "grpc output out l:%d f:%d %p, pos %p, size: %z "
- "file: %O, size: %O",
- cl->buf->last_buf,
- cl->buf->in_file,
- cl->buf->start, cl->buf->pos,
- cl->buf->last - cl->buf->pos,
- cl->buf->file_pos,
- cl->buf->file_last - cl->buf->file_pos);
- }
-
- ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "grpc output limit: %uz w:%z:%uz",
- limit, ctx->send_window, ctx->connection->send_window);
-
-#endif
-
- rc = ngx_chain_writer(&r->upstream->writer, out);
-
- ngx_chain_update_chains(r->pool, &ctx->free, &ctx->busy, &out,
- (ngx_buf_tag_t) &ngx_http_grpc_body_output_filter);
-
- for (cl = ctx->free; cl; cl = cl->next) {
-
- /* mark original buffers as sent */
-
- if (cl->buf->shadow) {
- if (cl->buf->last_shadow) {
- b = cl->buf->shadow;
- b->pos = b->last;
- }
-
- cl->buf->shadow = NULL;
- }
- }
-
- if (rc == NGX_OK && ctx->in) {
- rc = NGX_AGAIN;
- }
-
- if (rc == NGX_AGAIN) {
- ctx->output_blocked = 1;
-
- } else {
- ctx->output_blocked = 0;
- }
-
- if (ctx->done) {
-
- /*
- * We have already got the response and were sending some additional
- * control frames. Even if there is still something unsent, stop
- * here anyway.
- */
-
- u = r->upstream;
- u->length = 0;
-
- if (ctx->in == NULL
- && ctx->out == NULL
- && ctx->output_closed
- && !ctx->output_blocked
- && ctx->state == ngx_http_grpc_st_start)
- {
- u->keepalive = 1;
- }
-
- ngx_post_event(u->peer.connection->read, &ngx_posted_events);
- }
-
- return rc;
-}
-
-
-static ngx_int_t
-ngx_http_grpc_process_header(ngx_http_request_t *r)
-{
- ngx_str_t *status_line;
- ngx_int_t rc, status;
- ngx_buf_t *b;
- ngx_table_elt_t *h;
- ngx_http_upstream_t *u;
- ngx_http_grpc_ctx_t *ctx;
- ngx_http_upstream_header_t *hh;
- ngx_http_upstream_main_conf_t *umcf;
-
- u = r->upstream;
- b = &u->buffer;
-
-#if (NGX_DEBUG)
- if (r->connection->log->log_level & NGX_LOG_DEBUG_HTTP) {
- u_char buf[512];
- size_t n, m;
-
- n = ngx_min(b->last - b->pos, 256);
- m = ngx_hex_dump(buf, b->pos, n) - buf;
-
- ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "grpc response: %*s%s, len: %uz",
- m, buf, b->last - b->pos > 256 ? "..." : "",
- b->last - b->pos);
- }
-#endif
-
- ctx = ngx_http_grpc_get_ctx(r);
-
- if (ctx == NULL) {
- return NGX_ERROR;
- }
-
- umcf = ngx_http_get_module_main_conf(r, ngx_http_upstream_module);
-
- for ( ;; ) {
-
- if (ctx->state < ngx_http_grpc_st_payload) {
-
- rc = ngx_http_grpc_parse_frame(r, ctx, b);
-
- if (rc == NGX_AGAIN) {
-
- /*
- * there can be a lot of window update frames,
- * so we reset buffer if it is empty and we haven't
- * started parsing headers yet
- */
-
- if (!ctx->parsing_headers) {
- b->pos = b->start;
- b->last = b->pos;
- }
-
- return NGX_AGAIN;
- }
-
- if (rc == NGX_ERROR) {
- return NGX_HTTP_UPSTREAM_INVALID_HEADER;
- }
-
- /*
- * RFC 7540 says that implementations MUST discard frames
- * that have unknown or unsupported types. However, extension
- * frames that appear in the middle of a header block are
- * not permitted. Also, for obvious reasons CONTINUATION frames
- * cannot appear before headers, and DATA frames are not expected
- * to appear before all headers are parsed.
- */
-
- if (ctx->type == NGX_HTTP_V2_DATA_FRAME
- || (ctx->type == NGX_HTTP_V2_CONTINUATION_FRAME
- && !ctx->parsing_headers)
- || (ctx->type != NGX_HTTP_V2_CONTINUATION_FRAME
- && ctx->parsing_headers))
- {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "upstream sent unexpected http2 frame: %d",
- ctx->type);
- return NGX_HTTP_UPSTREAM_INVALID_HEADER;
- }
-
- if (ctx->stream_id && ctx->stream_id != ctx->id) {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "upstream sent frame for unknown stream %ui",
- ctx->stream_id);
- return NGX_HTTP_UPSTREAM_INVALID_HEADER;
- }
- }
-
- /* frame payload */
-
- if (ctx->type == NGX_HTTP_V2_RST_STREAM_FRAME) {
-
- rc = ngx_http_grpc_parse_rst_stream(r, ctx, b);
-
- if (rc == NGX_AGAIN) {
- return NGX_AGAIN;
- }
-
- if (rc == NGX_ERROR) {
- return NGX_HTTP_UPSTREAM_INVALID_HEADER;
- }
-
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "upstream rejected request with error %ui",
- ctx->error);
-
- return NGX_HTTP_UPSTREAM_INVALID_HEADER;
- }
-
- if (ctx->type == NGX_HTTP_V2_GOAWAY_FRAME) {
-
- rc = ngx_http_grpc_parse_goaway(r, ctx, b);
-
- if (rc == NGX_AGAIN) {
- return NGX_AGAIN;
- }
-
- if (rc == NGX_ERROR) {
- return NGX_HTTP_UPSTREAM_INVALID_HEADER;
- }
-
- /*
- * If stream_id is lower than one we use, our
- * request won't be processed and needs to be retried.
- * If stream_id is greater or equal to the one we use,
- * we can continue normally (except we can't use this
- * connection for additional requests). If there is
- * a real error, the connection will be closed.
- */
-
- if (ctx->stream_id < ctx->id) {
-
- /* TODO: we can retry non-idempotent requests */
-
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "upstream sent goaway with error %ui",
- ctx->error);
-
- return NGX_HTTP_UPSTREAM_INVALID_HEADER;
- }
-
- continue;
- }
-
- if (ctx->type == NGX_HTTP_V2_WINDOW_UPDATE_FRAME) {
-
- rc = ngx_http_grpc_parse_window_update(r, ctx, b);
-
- if (rc == NGX_AGAIN) {
- return NGX_AGAIN;
- }
-
- if (rc == NGX_ERROR) {
- return NGX_HTTP_UPSTREAM_INVALID_HEADER;
- }
-
- if (ctx->in) {
- ngx_post_event(u->peer.connection->write, &ngx_posted_events);
- }
-
- continue;
- }
-
- if (ctx->type == NGX_HTTP_V2_SETTINGS_FRAME) {
-
- rc = ngx_http_grpc_parse_settings(r, ctx, b);
-
- if (rc == NGX_AGAIN) {
- return NGX_AGAIN;
- }
-
- if (rc == NGX_ERROR) {
- return NGX_HTTP_UPSTREAM_INVALID_HEADER;
- }
-
- if (ctx->in) {
- ngx_post_event(u->peer.connection->write, &ngx_posted_events);
- }
-
- continue;
- }
-
- if (ctx->type == NGX_HTTP_V2_PING_FRAME) {
-
- rc = ngx_http_grpc_parse_ping(r, ctx, b);
-
- if (rc == NGX_AGAIN) {
- return NGX_AGAIN;
- }
-
- if (rc == NGX_ERROR) {
- return NGX_HTTP_UPSTREAM_INVALID_HEADER;
- }
-
- ngx_post_event(u->peer.connection->write, &ngx_posted_events);
- continue;
- }
-
- if (ctx->type == NGX_HTTP_V2_PUSH_PROMISE_FRAME) {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "upstream sent unexpected push promise frame");
- return NGX_HTTP_UPSTREAM_INVALID_HEADER;
- }
-
- if (ctx->type != NGX_HTTP_V2_HEADERS_FRAME
- && ctx->type != NGX_HTTP_V2_CONTINUATION_FRAME)
- {
- /* priority, unknown frames */
-
- if (b->last - b->pos < (ssize_t) ctx->rest) {
- ctx->rest -= b->last - b->pos;
- b->pos = b->last;
- return NGX_AGAIN;
- }
-
- b->pos += ctx->rest;
- ctx->rest = 0;
- ctx->state = ngx_http_grpc_st_start;
-
- continue;
- }
-
- /* headers */
-
- for ( ;; ) {
-
- rc = ngx_http_grpc_parse_header(r, ctx, b);
-
- if (rc == NGX_AGAIN) {
- break;
- }
-
- if (rc == NGX_OK) {
-
- /* a header line has been parsed successfully */
-
- ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "grpc header: \"%V: %V\"",
- &ctx->name, &ctx->value);
-
- if (ctx->name.len && ctx->name.data[0] == ':') {
-
- if (ctx->name.len != sizeof(":status") - 1
- || ngx_strncmp(ctx->name.data, ":status",
- sizeof(":status") - 1)
- != 0)
- {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "upstream sent invalid header \"%V: %V\"",
- &ctx->name, &ctx->value);
- return NGX_HTTP_UPSTREAM_INVALID_HEADER;
- }
-
- if (ctx->status) {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "upstream sent duplicate :status header");
- return NGX_HTTP_UPSTREAM_INVALID_HEADER;
- }
-
- status_line = &ctx->value;
-
- if (status_line->len != 3) {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "upstream sent invalid :status \"%V\"",
- status_line);
- return NGX_HTTP_UPSTREAM_INVALID_HEADER;
- }
-
- status = ngx_atoi(status_line->data, 3);
-
- if (status == NGX_ERROR) {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "upstream sent invalid :status \"%V\"",
- status_line);
- return NGX_HTTP_UPSTREAM_INVALID_HEADER;
- }
-
- if (status < NGX_HTTP_OK) {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "upstream sent unexpected :status \"%V\"",
- status_line);
- return NGX_HTTP_UPSTREAM_INVALID_HEADER;
- }
-
- u->headers_in.status_n = status;
-
- if (u->state && u->state->status == 0) {
- u->state->status = status;
- }
-
- ctx->status = 1;
-
- continue;
-
- } else if (!ctx->status) {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "upstream sent no :status header");
- return NGX_HTTP_UPSTREAM_INVALID_HEADER;
- }
-
- h = ngx_list_push(&u->headers_in.headers);
- if (h == NULL) {
- return NGX_ERROR;
- }
-
- h->key = ctx->name;
- h->value = ctx->value;
- h->lowcase_key = h->key.data;
- h->hash = ngx_hash_key(h->key.data, h->key.len);
-
- hh = ngx_hash_find(&umcf->headers_in_hash, h->hash,
- h->lowcase_key, h->key.len);
-
- if (hh && hh->handler(r, h, hh->offset) != NGX_OK) {
- return NGX_ERROR;
- }
-
- continue;
- }
-
- if (rc == NGX_HTTP_PARSE_HEADER_DONE) {
-
- /* a whole header has been parsed successfully */
-
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "grpc header done");
-
- if (ctx->end_stream) {
- u->headers_in.content_length_n = 0;
-
- if (ctx->in == NULL
- && ctx->out == NULL
- && ctx->output_closed
- && !ctx->output_blocked
- && b->last == b->pos)
- {
- u->keepalive = 1;
- }
- }
-
- return NGX_OK;
- }
-
- /* there was error while a header line parsing */
-
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "upstream sent invalid header");
-
- return NGX_HTTP_UPSTREAM_INVALID_HEADER;
- }
-
- /* rc == NGX_AGAIN */
-
- if (ctx->rest == 0) {
- ctx->state = ngx_http_grpc_st_start;
- continue;
- }
-
- return NGX_AGAIN;
- }
-}
-
-
-static ngx_int_t
-ngx_http_grpc_filter_init(void *data)
-{
- ngx_http_grpc_ctx_t *ctx = data;
-
- ngx_http_request_t *r;
- ngx_http_upstream_t *u;
-
- r = ctx->request;
- u = r->upstream;
-
- u->length = 1;
-
- if (ctx->end_stream) {
- u->length = 0;
- }
-
- return NGX_OK;
-}
-
-
-static ngx_int_t
-ngx_http_grpc_filter(void *data, ssize_t bytes)
-{
- ngx_http_grpc_ctx_t *ctx = data;
-
- ngx_int_t rc;
- ngx_buf_t *b, *buf;
- ngx_chain_t *cl, **ll;
- ngx_table_elt_t *h;
- ngx_http_request_t *r;
- ngx_http_upstream_t *u;
-
- r = ctx->request;
- u = r->upstream;
- b = &u->buffer;
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "grpc filter bytes:%z", bytes);
-
- b->pos = b->last;
- b->last += bytes;
-
- for (cl = u->out_bufs, ll = &u->out_bufs; cl; cl = cl->next) {
- ll = &cl->next;
- }
-
- for ( ;; ) {
-
- if (ctx->state < ngx_http_grpc_st_payload) {
-
- rc = ngx_http_grpc_parse_frame(r, ctx, b);
-
- if (rc == NGX_AGAIN) {
-
- if (ctx->done) {
-
- /*
- * We have finished parsing the response and the
- * remaining control frames. If there are unsent
- * control frames, post a write event to send them.
- */
-
- if (ctx->out) {
- ngx_post_event(u->peer.connection->write,
- &ngx_posted_events);
- return NGX_AGAIN;
- }
-
- u->length = 0;
-
- if (ctx->in == NULL
- && ctx->output_closed
- && !ctx->output_blocked
- && ctx->state == ngx_http_grpc_st_start)
- {
- u->keepalive = 1;
- }
-
- break;
- }
-
- return NGX_AGAIN;
- }
-
- if (rc == NGX_ERROR) {
- return NGX_ERROR;
- }
-
- if ((ctx->type == NGX_HTTP_V2_CONTINUATION_FRAME
- && !ctx->parsing_headers)
- || (ctx->type != NGX_HTTP_V2_CONTINUATION_FRAME
- && ctx->parsing_headers))
- {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "upstream sent unexpected http2 frame: %d",
- ctx->type);
- return NGX_ERROR;
- }
-
- if (ctx->type == NGX_HTTP_V2_DATA_FRAME) {
-
- if (ctx->stream_id != ctx->id) {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "upstream sent data frame "
- "for unknown stream %ui",
- ctx->stream_id);
- return NGX_ERROR;
- }
-
- if (ctx->rest > ctx->recv_window) {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "upstream violated stream flow control, "
- "received %uz data frame with window %uz",
- ctx->rest, ctx->recv_window);
- return NGX_ERROR;
- }
-
- if (ctx->rest > ctx->connection->recv_window) {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "upstream violated connection flow control, "
- "received %uz data frame with window %uz",
- ctx->rest, ctx->connection->recv_window);
- return NGX_ERROR;
- }
-
- ctx->recv_window -= ctx->rest;
- ctx->connection->recv_window -= ctx->rest;
-
- if (ctx->connection->recv_window < NGX_HTTP_V2_MAX_WINDOW / 4
- || ctx->recv_window < NGX_HTTP_V2_MAX_WINDOW / 4)
- {
- if (ngx_http_grpc_send_window_update(r, ctx) != NGX_OK) {
- return NGX_ERROR;
- }
-
- ngx_post_event(u->peer.connection->write,
- &ngx_posted_events);
- }
- }
-
- if (ctx->stream_id && ctx->stream_id != ctx->id) {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "upstream sent frame for unknown stream %ui",
- ctx->stream_id);
- return NGX_ERROR;
- }
-
- if (ctx->stream_id && ctx->done) {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "upstream sent frame for closed stream %ui",
- ctx->stream_id);
- return NGX_ERROR;
- }
-
- ctx->padding = 0;
- }
-
- if (ctx->state == ngx_http_grpc_st_padding) {
-
- if (b->last - b->pos < (ssize_t) ctx->rest) {
- ctx->rest -= b->last - b->pos;
- b->pos = b->last;
- return NGX_AGAIN;
- }
-
- b->pos += ctx->rest;
- ctx->rest = 0;
- ctx->state = ngx_http_grpc_st_start;
-
- if (ctx->flags & NGX_HTTP_V2_END_STREAM_FLAG) {
- ctx->done = 1;
- }
-
- continue;
- }
-
- /* frame payload */
-
- if (ctx->type == NGX_HTTP_V2_RST_STREAM_FRAME) {
-
- rc = ngx_http_grpc_parse_rst_stream(r, ctx, b);
-
- if (rc == NGX_AGAIN) {
- return NGX_AGAIN;
- }
-
- if (rc == NGX_ERROR) {
- return NGX_ERROR;
- }
-
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "upstream rejected request with error %ui",
- ctx->error);
-
- return NGX_ERROR;
- }
-
- if (ctx->type == NGX_HTTP_V2_GOAWAY_FRAME) {
-
- rc = ngx_http_grpc_parse_goaway(r, ctx, b);
-
- if (rc == NGX_AGAIN) {
- return NGX_AGAIN;
- }
-
- if (rc == NGX_ERROR) {
- return NGX_ERROR;
- }
-
- /*
- * If stream_id is lower than one we use, our
- * request won't be processed and needs to be retried.
- * If stream_id is greater or equal to the one we use,
- * we can continue normally (except we can't use this
- * connection for additional requests). If there is
- * a real error, the connection will be closed.
- */
-
- if (ctx->stream_id < ctx->id) {
-
- /* TODO: we can retry non-idempotent requests */
-
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "upstream sent goaway with error %ui",
- ctx->error);
-
- return NGX_ERROR;
- }
-
- continue;
- }
-
- if (ctx->type == NGX_HTTP_V2_WINDOW_UPDATE_FRAME) {
-
- rc = ngx_http_grpc_parse_window_update(r, ctx, b);
-
- if (rc == NGX_AGAIN) {
- return NGX_AGAIN;
- }
-
- if (rc == NGX_ERROR) {
- return NGX_ERROR;
- }
-
- if (ctx->in) {
- ngx_post_event(u->peer.connection->write, &ngx_posted_events);
- }
-
- continue;
- }
-
- if (ctx->type == NGX_HTTP_V2_SETTINGS_FRAME) {
-
- rc = ngx_http_grpc_parse_settings(r, ctx, b);
-
- if (rc == NGX_AGAIN) {
- return NGX_AGAIN;
- }
-
- if (rc == NGX_ERROR) {
- return NGX_ERROR;
- }
-
- if (ctx->in) {
- ngx_post_event(u->peer.connection->write, &ngx_posted_events);
- }
-
- continue;
- }
-
- if (ctx->type == NGX_HTTP_V2_PING_FRAME) {
-
- rc = ngx_http_grpc_parse_ping(r, ctx, b);
-
- if (rc == NGX_AGAIN) {
- return NGX_AGAIN;
- }
-
- if (rc == NGX_ERROR) {
- return NGX_ERROR;
- }
-
- ngx_post_event(u->peer.connection->write, &ngx_posted_events);
- continue;
- }
-
- if (ctx->type == NGX_HTTP_V2_PUSH_PROMISE_FRAME) {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "upstream sent unexpected push promise frame");
- return NGX_ERROR;
- }
-
- if (ctx->type == NGX_HTTP_V2_HEADERS_FRAME
- || ctx->type == NGX_HTTP_V2_CONTINUATION_FRAME)
- {
- for ( ;; ) {
-
- rc = ngx_http_grpc_parse_header(r, ctx, b);
-
- if (rc == NGX_AGAIN) {
- break;
- }
-
- if (rc == NGX_OK) {
-
- /* a header line has been parsed successfully */
-
- ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "grpc trailer: \"%V: %V\"",
- &ctx->name, &ctx->value);
-
- if (ctx->name.len && ctx->name.data[0] == ':') {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "upstream sent invalid "
- "trailer \"%V: %V\"",
- &ctx->name, &ctx->value);
- return NGX_ERROR;
- }
-
- h = ngx_list_push(&u->headers_in.trailers);
- if (h == NULL) {
- return NGX_ERROR;
- }
-
- h->key = ctx->name;
- h->value = ctx->value;
- h->lowcase_key = h->key.data;
- h->hash = ngx_hash_key(h->key.data, h->key.len);
-
- continue;
- }
-
- if (rc == NGX_HTTP_PARSE_HEADER_DONE) {
-
- /* a whole header has been parsed successfully */
-
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "grpc trailer done");
-
- if (ctx->end_stream) {
- ctx->done = 1;
- break;
- }
-
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "upstream sent trailer without "
- "end stream flag");
- return NGX_ERROR;
- }
-
- /* there was error while a header line parsing */
-
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "upstream sent invalid trailer");
-
- return NGX_ERROR;
- }
-
- if (rc == NGX_HTTP_PARSE_HEADER_DONE) {
- continue;
- }
-
- /* rc == NGX_AGAIN */
-
- if (ctx->rest == 0) {
- ctx->state = ngx_http_grpc_st_start;
- continue;
- }
-
- return NGX_AGAIN;
- }
-
- if (ctx->type != NGX_HTTP_V2_DATA_FRAME) {
-
- /* priority, unknown frames */
-
- if (b->last - b->pos < (ssize_t) ctx->rest) {
- ctx->rest -= b->last - b->pos;
- b->pos = b->last;
- return NGX_AGAIN;
- }
-
- b->pos += ctx->rest;
- ctx->rest = 0;
- ctx->state = ngx_http_grpc_st_start;
-
- continue;
- }
-
- /*
- * data frame:
- *
- * +---------------+
- * |Pad Length? (8)|
- * +---------------+-----------------------------------------------+
- * | Data (*) ...
- * +---------------------------------------------------------------+
- * | Padding (*) ...
- * +---------------------------------------------------------------+
- */
-
- if (ctx->flags & NGX_HTTP_V2_PADDED_FLAG) {
-
- if (ctx->rest == 0) {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "upstream sent too short http2 frame");
- return NGX_ERROR;
- }
-
- if (b->pos == b->last) {
- return NGX_AGAIN;
- }
-
- ctx->flags &= ~NGX_HTTP_V2_PADDED_FLAG;
- ctx->padding = *b->pos++;
- ctx->rest -= 1;
-
- if (ctx->padding > ctx->rest) {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "upstream sent http2 frame with too long "
- "padding: %d in frame %uz",
- ctx->padding, ctx->rest);
- return NGX_ERROR;
- }
-
- continue;
- }
-
- if (ctx->rest == ctx->padding) {
- goto done;
- }
-
- if (b->pos == b->last) {
- return NGX_AGAIN;
- }
-
- cl = ngx_chain_get_free_buf(r->pool, &u->free_bufs);
- if (cl == NULL) {
- return NGX_ERROR;
- }
-
- *ll = cl;
- ll = &cl->next;
-
- buf = cl->buf;
-
- buf->flush = 1;
- buf->memory = 1;
-
- buf->pos = b->pos;
- buf->tag = u->output.tag;
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "grpc output buf %p", buf->pos);
-
- if (b->last - b->pos < (ssize_t) ctx->rest - ctx->padding) {
-
- ctx->rest -= b->last - b->pos;
- b->pos = b->last;
- buf->last = b->pos;
-
- return NGX_AGAIN;
- }
-
- b->pos += ctx->rest - ctx->padding;
- buf->last = b->pos;
- ctx->rest = ctx->padding;
-
- done:
-
- if (ctx->padding) {
- ctx->state = ngx_http_grpc_st_padding;
- continue;
- }
-
- ctx->state = ngx_http_grpc_st_start;
-
- if (ctx->flags & NGX_HTTP_V2_END_STREAM_FLAG) {
- ctx->done = 1;
- }
- }
-
- return NGX_OK;
-}
-
-
-static ngx_int_t
-ngx_http_grpc_parse_frame(ngx_http_request_t *r, ngx_http_grpc_ctx_t *ctx,
- ngx_buf_t *b)
-{
- u_char ch, *p;
- ngx_http_grpc_state_e state;
-
- state = ctx->state;
-
- for (p = b->pos; p < b->last; p++) {
- ch = *p;
-
-#if 0
- ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "grpc frame byte: %02Xd, s:%d", ch, state);
-#endif
-
- switch (state) {
-
- case ngx_http_grpc_st_start:
- ctx->rest = ch << 16;
- state = ngx_http_grpc_st_length_2;
- break;
-
- case ngx_http_grpc_st_length_2:
- ctx->rest |= ch << 8;
- state = ngx_http_grpc_st_length_3;
- break;
-
- case ngx_http_grpc_st_length_3:
- ctx->rest |= ch;
-
- if (ctx->rest > NGX_HTTP_V2_DEFAULT_FRAME_SIZE) {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "upstream sent too large http2 frame: %uz",
- ctx->rest);
- return NGX_ERROR;
- }
-
- state = ngx_http_grpc_st_type;
- break;
-
- case ngx_http_grpc_st_type:
- ctx->type = ch;
- state = ngx_http_grpc_st_flags;
- break;
-
- case ngx_http_grpc_st_flags:
- ctx->flags = ch;
- state = ngx_http_grpc_st_stream_id;
- break;
-
- case ngx_http_grpc_st_stream_id:
- ctx->stream_id = (ch & 0x7f) << 24;
- state = ngx_http_grpc_st_stream_id_2;
- break;
-
- case ngx_http_grpc_st_stream_id_2:
- ctx->stream_id |= ch << 16;
- state = ngx_http_grpc_st_stream_id_3;
- break;
-
- case ngx_http_grpc_st_stream_id_3:
- ctx->stream_id |= ch << 8;
- state = ngx_http_grpc_st_stream_id_4;
- break;
-
- case ngx_http_grpc_st_stream_id_4:
- ctx->stream_id |= ch;
-
- ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "grpc frame: %d, len: %uz, f:%d, i:%ui",
- ctx->type, ctx->rest, ctx->flags, ctx->stream_id);
-
- b->pos = p + 1;
-
- ctx->state = ngx_http_grpc_st_payload;
- ctx->frame_state = 0;
-
- return NGX_OK;
-
- /* suppress warning */
- case ngx_http_grpc_st_payload:
- case ngx_http_grpc_st_padding:
- break;
- }
- }
-
- b->pos = p;
- ctx->state = state;
-
- return NGX_AGAIN;
-}
-
-
-static ngx_int_t
-ngx_http_grpc_parse_header(ngx_http_request_t *r, ngx_http_grpc_ctx_t *ctx,
- ngx_buf_t *b)
-{
- u_char ch, *p, *last;
- size_t min;
- ngx_int_t rc;
- enum {
- sw_start = 0,
- sw_padding_length,
- sw_dependency,
- sw_dependency_2,
- sw_dependency_3,
- sw_dependency_4,
- sw_weight,
- sw_fragment,
- sw_padding
- } state;
-
- state = ctx->frame_state;
-
- if (state == sw_start) {
-
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "grpc parse header: start");
-
- if (ctx->type == NGX_HTTP_V2_HEADERS_FRAME) {
- ctx->parsing_headers = 1;
- ctx->fragment_state = 0;
-
- min = (ctx->flags & NGX_HTTP_V2_PADDED_FLAG ? 1 : 0)
- + (ctx->flags & NGX_HTTP_V2_PRIORITY_FLAG ? 5 : 0);
-
- if (ctx->rest < min) {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "upstream sent headers frame "
- "with invalid length: %uz",
- ctx->rest);
- return NGX_ERROR;
- }
-
- if (ctx->flags & NGX_HTTP_V2_END_STREAM_FLAG) {
- ctx->end_stream = 1;
- }
-
- if (ctx->flags & NGX_HTTP_V2_PADDED_FLAG) {
- state = sw_padding_length;
-
- } else if (ctx->flags & NGX_HTTP_V2_PRIORITY_FLAG) {
- state = sw_dependency;
-
- } else {
- state = sw_fragment;
- }
-
- } else if (ctx->type == NGX_HTTP_V2_CONTINUATION_FRAME) {
- state = sw_fragment;
- }
-
- ctx->padding = 0;
- ctx->frame_state = state;
- }
-
- if (state < sw_fragment) {
-
- if (b->last - b->pos < (ssize_t) ctx->rest) {
- last = b->last;
-
- } else {
- last = b->pos + ctx->rest;
- }
-
- for (p = b->pos; p < last; p++) {
- ch = *p;
-
-#if 0
- ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "grpc header byte: %02Xd s:%d", ch, state);
-#endif
-
- /*
- * headers frame:
- *
- * +---------------+
- * |Pad Length? (8)|
- * +-+-------------+----------------------------------------------+
- * |E| Stream Dependency? (31) |
- * +-+-------------+----------------------------------------------+
- * | Weight? (8) |
- * +-+-------------+----------------------------------------------+
- * | Header Block Fragment (*) ...
- * +--------------------------------------------------------------+
- * | Padding (*) ...
- * +--------------------------------------------------------------+
- */
-
- switch (state) {
-
- case sw_padding_length:
-
- ctx->padding = ch;
-
- if (ctx->flags & NGX_HTTP_V2_PRIORITY_FLAG) {
- state = sw_dependency;
- break;
- }
-
- goto fragment;
-
- case sw_dependency:
- state = sw_dependency_2;
- break;
-
- case sw_dependency_2:
- state = sw_dependency_3;
- break;
-
- case sw_dependency_3:
- state = sw_dependency_4;
- break;
-
- case sw_dependency_4:
- state = sw_weight;
- break;
-
- case sw_weight:
- goto fragment;
-
- /* suppress warning */
- case sw_start:
- case sw_fragment:
- case sw_padding:
- break;
- }
- }
-
- ctx->rest -= p - b->pos;
- b->pos = p;
-
- ctx->frame_state = state;
- return NGX_AGAIN;
-
- fragment:
-
- p++;
- ctx->rest -= p - b->pos;
- b->pos = p;
-
- if (ctx->padding > ctx->rest) {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "upstream sent http2 frame with too long "
- "padding: %d in frame %uz",
- ctx->padding, ctx->rest);
- return NGX_ERROR;
- }
-
- state = sw_fragment;
- ctx->frame_state = state;
- }
-
- if (state == sw_fragment) {
-
- rc = ngx_http_grpc_parse_fragment(r, ctx, b);
-
- if (rc == NGX_AGAIN) {
- return NGX_AGAIN;
- }
-
- if (rc == NGX_ERROR) {
- return NGX_ERROR;
- }
-
- if (rc == NGX_OK) {
- return NGX_OK;
- }
-
- /* rc == NGX_DONE */
-
- state = sw_padding;
- ctx->frame_state = state;
- }
-
- if (state == sw_padding) {
-
- if (b->last - b->pos < (ssize_t) ctx->rest) {
-
- ctx->rest -= b->last - b->pos;
- b->pos = b->last;
-
- return NGX_AGAIN;
- }
-
- b->pos += ctx->rest;
- ctx->rest = 0;
-
- ctx->state = ngx_http_grpc_st_start;
-
- if (ctx->flags & NGX_HTTP_V2_END_HEADERS_FLAG) {
-
- if (ctx->fragment_state) {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "upstream sent truncated http2 header");
- return NGX_ERROR;
- }
-
- ctx->parsing_headers = 0;
-
- return NGX_HTTP_PARSE_HEADER_DONE;
- }
-
- return NGX_AGAIN;
- }
-
- /* unreachable */
-
- return NGX_ERROR;
-}
-
-
-static ngx_int_t
-ngx_http_grpc_parse_fragment(ngx_http_request_t *r, ngx_http_grpc_ctx_t *ctx,
- ngx_buf_t *b)
-{
- u_char ch, *p, *last;
- size_t size;
- ngx_uint_t index, size_update;
- enum {
- sw_start = 0,
- sw_index,
- sw_name_length,
- sw_name_length_2,
- sw_name_length_3,
- sw_name_length_4,
- sw_name,
- sw_name_bytes,
- sw_value_length,
- sw_value_length_2,
- sw_value_length_3,
- sw_value_length_4,
- sw_value,
- sw_value_bytes
- } state;
-
- /* header block fragment */
-
-#if 0
- ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "grpc header fragment %p:%p rest:%uz",
- b->pos, b->last, ctx->rest);
-#endif
-
- if (b->last - b->pos < (ssize_t) ctx->rest - ctx->padding) {
- last = b->last;
-
- } else {
- last = b->pos + ctx->rest - ctx->padding;
- }
-
- state = ctx->fragment_state;
-
- for (p = b->pos; p < last; p++) {
- ch = *p;
-
-#if 0
- ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "grpc header byte: %02Xd s:%d", ch, state);
-#endif
-
- switch (state) {
-
- case sw_start:
- ctx->index = 0;
-
- if ((ch & 0x80) == 0x80) {
- /*
- * indexed header:
- *
- * 0 1 2 3 4 5 6 7
- * +---+---+---+---+---+---+---+---+
- * | 1 | Index (7+) |
- * +---+---------------------------+
- */
-
- index = ch & ~0x80;
-
- if (index == 0 || index > 61) {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "upstream sent invalid http2 "
- "table index: %ui", index);
- return NGX_ERROR;
- }
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "grpc indexed header: %ui", index);
-
- ctx->index = index;
- ctx->literal = 0;
-
- goto done;
-
- } else if ((ch & 0xc0) == 0x40) {
- /*
- * literal header with incremental indexing:
- *
- * 0 1 2 3 4 5 6 7
- * +---+---+---+---+---+---+---+---+
- * | 0 | 1 | Index (6+) |
- * +---+---+-----------------------+
- * | H | Value Length (7+) |
- * +---+---------------------------+
- * | Value String (Length octets) |
- * +-------------------------------+
- *
- * 0 1 2 3 4 5 6 7
- * +---+---+---+---+---+---+---+---+
- * | 0 | 1 | 0 |
- * +---+---+-----------------------+
- * | H | Name Length (7+) |
- * +---+---------------------------+
- * | Name String (Length octets) |
- * +---+---------------------------+
- * | H | Value Length (7+) |
- * +---+---------------------------+
- * | Value String (Length octets) |
- * +-------------------------------+
- */
-
- index = ch & ~0xc0;
-
- if (index > 61) {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "upstream sent invalid http2 "
- "table index: %ui", index);
- return NGX_ERROR;
- }
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "grpc literal header: %ui", index);
-
- if (index == 0) {
- state = sw_name_length;
- break;
- }
-
- ctx->index = index;
- ctx->literal = 1;
-
- state = sw_value_length;
- break;
-
- } else if ((ch & 0xe0) == 0x20) {
- /*
- * dynamic table size update:
- *
- * 0 1 2 3 4 5 6 7
- * +---+---+---+---+---+---+---+---+
- * | 0 | 0 | 1 | Max size (5+) |
- * +---+---------------------------+
- */
-
- size_update = ch & ~0xe0;
-
- if (size_update > 0) {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "upstream sent invalid http2 "
- "dynamic table size update: %ui",
- size_update);
- return NGX_ERROR;
- }
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "grpc table size update: %ui", size_update);
-
- break;
-
- } else if ((ch & 0xf0) == 0x10) {
- /*
- * literal header field never indexed:
- *
- * 0 1 2 3 4 5 6 7
- * +---+---+---+---+---+---+---+---+
- * | 0 | 0 | 0 | 1 | Index (4+) |
- * +---+---+-----------------------+
- * | H | Value Length (7+) |
- * +---+---------------------------+
- * | Value String (Length octets) |
- * +-------------------------------+
- *
- * 0 1 2 3 4 5 6 7
- * +---+---+---+---+---+---+---+---+
- * | 0 | 0 | 0 | 1 | 0 |
- * +---+---+-----------------------+
- * | H | Name Length (7+) |
- * +---+---------------------------+
- * | Name String (Length octets) |
- * +---+---------------------------+
- * | H | Value Length (7+) |
- * +---+---------------------------+
- * | Value String (Length octets) |
- * +-------------------------------+
- */
-
- index = ch & ~0xf0;
-
- if (index == 0x0f) {
- ctx->index = index;
- ctx->literal = 1;
- state = sw_index;
- break;
- }
-
- if (index == 0) {
- state = sw_name_length;
- break;
- }
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "grpc literal header never indexed: %ui",
- index);
-
- ctx->index = index;
- ctx->literal = 1;
-
- state = sw_value_length;
- break;
-
- } else if ((ch & 0xf0) == 0x00) {
- /*
- * literal header field without indexing:
- *
- * 0 1 2 3 4 5 6 7
- * +---+---+---+---+---+---+---+---+
- * | 0 | 0 | 0 | 0 | Index (4+) |
- * +---+---+-----------------------+
- * | H | Value Length (7+) |
- * +---+---------------------------+
- * | Value String (Length octets) |
- * +-------------------------------+
- *
- * 0 1 2 3 4 5 6 7
- * +---+---+---+---+---+---+---+---+
- * | 0 | 0 | 0 | 0 | 0 |
- * +---+---+-----------------------+
- * | H | Name Length (7+) |
- * +---+---------------------------+
- * | Name String (Length octets) |
- * +---+---------------------------+
- * | H | Value Length (7+) |
- * +---+---------------------------+
- * | Value String (Length octets) |
- * +-------------------------------+
- */
-
- index = ch & ~0xf0;
-
- if (index == 0x0f) {
- ctx->index = index;
- ctx->literal = 1;
- state = sw_index;
- break;
- }
-
- if (index == 0) {
- state = sw_name_length;
- break;
- }
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "grpc literal header without indexing: %ui",
- index);
-
- ctx->index = index;
- ctx->literal = 1;
-
- state = sw_value_length;
- break;
- }
-
- /* not reached */
-
- return NGX_ERROR;
-
- case sw_index:
- ctx->index = ctx->index + (ch & ~0x80);
-
- if (ch & 0x80) {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "upstream sent http2 table index "
- "with continuation flag");
- return NGX_ERROR;
- }
-
- if (ctx->index > 61) {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "upstream sent invalid http2 "
- "table index: %ui", ctx->index);
- return NGX_ERROR;
- }
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "grpc header index: %ui", ctx->index);
-
- state = sw_value_length;
- break;
-
- case sw_name_length:
- ctx->field_huffman = ch & 0x80 ? 1 : 0;
- ctx->field_length = ch & ~0x80;
-
- if (ctx->field_length == 0x7f) {
- state = sw_name_length_2;
- break;
- }
-
- if (ctx->field_length == 0) {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "upstream sent zero http2 "
- "header name length");
- return NGX_ERROR;
- }
-
- state = sw_name;
- break;
-
- case sw_name_length_2:
- ctx->field_length += ch & ~0x80;
-
- if (ch & 0x80) {
- state = sw_name_length_3;
- break;
- }
-
- state = sw_name;
- break;
-
- case sw_name_length_3:
- ctx->field_length += (ch & ~0x80) << 7;
-
- if (ch & 0x80) {
- state = sw_name_length_4;
- break;
- }
-
- state = sw_name;
- break;
-
- case sw_name_length_4:
- ctx->field_length += (ch & ~0x80) << 14;
-
- if (ch & 0x80) {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "upstream sent too large http2 "
- "header name length");
- return NGX_ERROR;
- }
-
- state = sw_name;
- break;
-
- case sw_name:
- ctx->name.len = ctx->field_huffman ?
- ctx->field_length * 8 / 5 : ctx->field_length;
-
- ctx->name.data = ngx_pnalloc(r->pool, ctx->name.len + 1);
- if (ctx->name.data == NULL) {
- return NGX_ERROR;
- }
-
- ctx->field_end = ctx->name.data;
- ctx->field_rest = ctx->field_length;
- ctx->field_state = 0;
-
- state = sw_name_bytes;
-
- /* fall through */
-
- case sw_name_bytes:
-
- ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "grpc name: len:%uz h:%d last:%uz, rest:%uz",
- ctx->field_length,
- ctx->field_huffman,
- last - p,
- ctx->rest - (p - b->pos));
-
- size = ngx_min(last - p, (ssize_t) ctx->field_rest);
- ctx->field_rest -= size;
-
- if (ctx->field_huffman) {
- if (ngx_http_v2_huff_decode(&ctx->field_state, p, size,
- &ctx->field_end,
- ctx->field_rest == 0,
- r->connection->log)
- != NGX_OK)
- {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "upstream sent invalid encoded header");
- return NGX_ERROR;
- }
-
- ctx->name.len = ctx->field_end - ctx->name.data;
- ctx->name.data[ctx->name.len] = '\0';
-
- } else {
- ctx->field_end = ngx_cpymem(ctx->field_end, p, size);
- ctx->name.data[ctx->name.len] = '\0';
- }
-
- p += size - 1;
-
- if (ctx->field_rest == 0) {
- state = sw_value_length;
- }
-
- break;
-
- case sw_value_length:
- ctx->field_huffman = ch & 0x80 ? 1 : 0;
- ctx->field_length = ch & ~0x80;
-
- if (ctx->field_length == 0x7f) {
- state = sw_value_length_2;
- break;
- }
-
- if (ctx->field_length == 0) {
- ngx_str_set(&ctx->value, "");
- goto done;
- }
-
- state = sw_value;
- break;
-
- case sw_value_length_2:
- ctx->field_length += ch & ~0x80;
-
- if (ch & 0x80) {
- state = sw_value_length_3;
- break;
- }
-
- state = sw_value;
- break;
-
- case sw_value_length_3:
- ctx->field_length += (ch & ~0x80) << 7;
-
- if (ch & 0x80) {
- state = sw_value_length_4;
- break;
- }
-
- state = sw_value;
- break;
-
- case sw_value_length_4:
- ctx->field_length += (ch & ~0x80) << 14;
-
- if (ch & 0x80) {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "upstream sent too large http2 "
- "header value length");
- return NGX_ERROR;
- }
-
- state = sw_value;
- break;
-
- case sw_value:
- ctx->value.len = ctx->field_huffman ?
- ctx->field_length * 8 / 5 : ctx->field_length;
-
- ctx->value.data = ngx_pnalloc(r->pool, ctx->value.len + 1);
- if (ctx->value.data == NULL) {
- return NGX_ERROR;
- }
-
- ctx->field_end = ctx->value.data;
- ctx->field_rest = ctx->field_length;
- ctx->field_state = 0;
-
- state = sw_value_bytes;
-
- /* fall through */
-
- case sw_value_bytes:
-
- ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "grpc value: len:%uz h:%d last:%uz, rest:%uz",
- ctx->field_length,
- ctx->field_huffman,
- last - p,
- ctx->rest - (p - b->pos));
-
- size = ngx_min(last - p, (ssize_t) ctx->field_rest);
- ctx->field_rest -= size;
-
- if (ctx->field_huffman) {
- if (ngx_http_v2_huff_decode(&ctx->field_state, p, size,
- &ctx->field_end,
- ctx->field_rest == 0,
- r->connection->log)
- != NGX_OK)
- {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "upstream sent invalid encoded header");
- return NGX_ERROR;
- }
-
- ctx->value.len = ctx->field_end - ctx->value.data;
- ctx->value.data[ctx->value.len] = '\0';
-
- } else {
- ctx->field_end = ngx_cpymem(ctx->field_end, p, size);
- ctx->value.data[ctx->value.len] = '\0';
- }
-
- p += size - 1;
-
- if (ctx->field_rest == 0) {
- goto done;
- }
-
- break;
- }
-
- continue;
-
- done:
-
- p++;
- ctx->rest -= p - b->pos;
- ctx->fragment_state = sw_start;
- b->pos = p;
-
- if (ctx->index) {
- ctx->name = *ngx_http_v2_get_static_name(ctx->index);
- }
-
- if (ctx->index && !ctx->literal) {
- ctx->value = *ngx_http_v2_get_static_value(ctx->index);
- }
-
- if (!ctx->index) {
- if (ngx_http_grpc_validate_header_name(r, &ctx->name) != NGX_OK) {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "upstream sent invalid header: \"%V: %V\"",
- &ctx->name, &ctx->value);
- return NGX_ERROR;
- }
- }
-
- if (!ctx->index || ctx->literal) {
- if (ngx_http_grpc_validate_header_value(r, &ctx->value) != NGX_OK) {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "upstream sent invalid header: \"%V: %V\"",
- &ctx->name, &ctx->value);
- return NGX_ERROR;
- }
- }
-
- return NGX_OK;
- }
-
- ctx->rest -= p - b->pos;
- ctx->fragment_state = state;
- b->pos = p;
-
- if (ctx->rest > ctx->padding) {
- return NGX_AGAIN;
- }
-
- return NGX_DONE;
-}
-
-
-static ngx_int_t
-ngx_http_grpc_validate_header_name(ngx_http_request_t *r, ngx_str_t *s)
-{
- u_char ch;
- ngx_uint_t i;
-
- for (i = 0; i < s->len; i++) {
- ch = s->data[i];
-
- if (ch == ':' && i > 0) {
- return NGX_ERROR;
- }
-
- if (ch >= 'A' && ch <= 'Z') {
- return NGX_ERROR;
- }
-
- if (ch == '\0' || ch == CR || ch == LF) {
- return NGX_ERROR;
- }
- }
-
- return NGX_OK;
-}
-
-
-static ngx_int_t
-ngx_http_grpc_validate_header_value(ngx_http_request_t *r, ngx_str_t *s)
-{
- u_char ch;
- ngx_uint_t i;
-
- for (i = 0; i < s->len; i++) {
- ch = s->data[i];
-
- if (ch == '\0' || ch == CR || ch == LF) {
- return NGX_ERROR;
- }
- }
-
- return NGX_OK;
-}
-
-
-static ngx_int_t
-ngx_http_grpc_parse_rst_stream(ngx_http_request_t *r, ngx_http_grpc_ctx_t *ctx,
- ngx_buf_t *b)
-{
- u_char ch, *p, *last;
- enum {
- sw_start = 0,
- sw_error_2,
- sw_error_3,
- sw_error_4
- } state;
-
- if (b->last - b->pos < (ssize_t) ctx->rest) {
- last = b->last;
-
- } else {
- last = b->pos + ctx->rest;
- }
-
- state = ctx->frame_state;
-
- if (state == sw_start) {
- if (ctx->rest != 4) {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "upstream sent rst stream frame "
- "with invalid length: %uz",
- ctx->rest);
- return NGX_ERROR;
- }
- }
-
- for (p = b->pos; p < last; p++) {
- ch = *p;
-
-#if 0
- ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "grpc rst byte: %02Xd s:%d", ch, state);
-#endif
-
- switch (state) {
-
- case sw_start:
- ctx->error = (ngx_uint_t) ch << 24;
- state = sw_error_2;
- break;
-
- case sw_error_2:
- ctx->error |= ch << 16;
- state = sw_error_3;
- break;
-
- case sw_error_3:
- ctx->error |= ch << 8;
- state = sw_error_4;
- break;
-
- case sw_error_4:
- ctx->error |= ch;
- state = sw_start;
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "grpc error: %ui", ctx->error);
-
- break;
- }
- }
-
- ctx->rest -= p - b->pos;
- ctx->frame_state = state;
- b->pos = p;
-
- if (ctx->rest > 0) {
- return NGX_AGAIN;
- }
-
- return NGX_OK;
-}
-
-
-static ngx_int_t
-ngx_http_grpc_parse_goaway(ngx_http_request_t *r, ngx_http_grpc_ctx_t *ctx,
- ngx_buf_t *b)
-{
- u_char ch, *p, *last;
- enum {
- sw_start = 0,
- sw_last_stream_id_2,
- sw_last_stream_id_3,
- sw_last_stream_id_4,
- sw_error,
- sw_error_2,
- sw_error_3,
- sw_error_4,
- sw_debug
- } state;
-
- if (b->last - b->pos < (ssize_t) ctx->rest) {
- last = b->last;
-
- } else {
- last = b->pos + ctx->rest;
- }
-
- state = ctx->frame_state;
-
- if (state == sw_start) {
-
- if (ctx->stream_id) {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "upstream sent goaway frame "
- "with non-zero stream id: %ui",
- ctx->stream_id);
- return NGX_ERROR;
- }
-
- if (ctx->rest < 8) {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "upstream sent goaway frame "
- "with invalid length: %uz",
- ctx->rest);
- return NGX_ERROR;
- }
- }
-
- for (p = b->pos; p < last; p++) {
- ch = *p;
-
-#if 0
- ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "grpc goaway byte: %02Xd s:%d", ch, state);
-#endif
-
- switch (state) {
-
- case sw_start:
- ctx->stream_id = (ch & 0x7f) << 24;
- state = sw_last_stream_id_2;
- break;
-
- case sw_last_stream_id_2:
- ctx->stream_id |= ch << 16;
- state = sw_last_stream_id_3;
- break;
-
- case sw_last_stream_id_3:
- ctx->stream_id |= ch << 8;
- state = sw_last_stream_id_4;
- break;
-
- case sw_last_stream_id_4:
- ctx->stream_id |= ch;
- state = sw_error;
- break;
-
- case sw_error:
- ctx->error = (ngx_uint_t) ch << 24;
- state = sw_error_2;
- break;
-
- case sw_error_2:
- ctx->error |= ch << 16;
- state = sw_error_3;
- break;
-
- case sw_error_3:
- ctx->error |= ch << 8;
- state = sw_error_4;
- break;
-
- case sw_error_4:
- ctx->error |= ch;
- state = sw_debug;
- break;
-
- case sw_debug:
- break;
- }
- }
-
- ctx->rest -= p - b->pos;
- ctx->frame_state = state;
- b->pos = p;
-
- if (ctx->rest > 0) {
- return NGX_AGAIN;
- }
-
- ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "grpc goaway: %ui, stream %ui",
- ctx->error, ctx->stream_id);
-
- ctx->state = ngx_http_grpc_st_start;
-
- return NGX_OK;
-}
-
-
-static ngx_int_t
-ngx_http_grpc_parse_window_update(ngx_http_request_t *r,
- ngx_http_grpc_ctx_t *ctx, ngx_buf_t *b)
-{
- u_char ch, *p, *last;
- enum {
- sw_start = 0,
- sw_size_2,
- sw_size_3,
- sw_size_4
- } state;
-
- if (b->last - b->pos < (ssize_t) ctx->rest) {
- last = b->last;
-
- } else {
- last = b->pos + ctx->rest;
- }
-
- state = ctx->frame_state;
-
- if (state == sw_start) {
- if (ctx->rest != 4) {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "upstream sent window update frame "
- "with invalid length: %uz",
- ctx->rest);
- return NGX_ERROR;
- }
- }
-
- for (p = b->pos; p < last; p++) {
- ch = *p;
-
-#if 0
- ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "grpc window update byte: %02Xd s:%d", ch, state);
-#endif
-
- switch (state) {
-
- case sw_start:
- ctx->window_update = (ch & 0x7f) << 24;
- state = sw_size_2;
- break;
-
- case sw_size_2:
- ctx->window_update |= ch << 16;
- state = sw_size_3;
- break;
-
- case sw_size_3:
- ctx->window_update |= ch << 8;
- state = sw_size_4;
- break;
-
- case sw_size_4:
- ctx->window_update |= ch;
- state = sw_start;
- break;
- }
- }
-
- ctx->rest -= p - b->pos;
- ctx->frame_state = state;
- b->pos = p;
-
- if (ctx->rest > 0) {
- return NGX_AGAIN;
- }
-
- ctx->state = ngx_http_grpc_st_start;
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "grpc window update: %ui", ctx->window_update);
-
- if (ctx->stream_id) {
-
- if (ctx->window_update > (size_t) NGX_HTTP_V2_MAX_WINDOW
- - ctx->send_window)
- {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "upstream sent too large window update");
- return NGX_ERROR;
- }
-
- ctx->send_window += ctx->window_update;
-
- } else {
-
- if (ctx->window_update > NGX_HTTP_V2_MAX_WINDOW
- - ctx->connection->send_window)
- {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "upstream sent too large window update");
- return NGX_ERROR;
- }
-
- ctx->connection->send_window += ctx->window_update;
- }
-
- return NGX_OK;
-}
-
-
-static ngx_int_t
-ngx_http_grpc_parse_settings(ngx_http_request_t *r, ngx_http_grpc_ctx_t *ctx,
- ngx_buf_t *b)
-{
- u_char ch, *p, *last;
- ssize_t window_update;
- enum {
- sw_start = 0,
- sw_id,
- sw_id_2,
- sw_value,
- sw_value_2,
- sw_value_3,
- sw_value_4
- } state;
-
- if (b->last - b->pos < (ssize_t) ctx->rest) {
- last = b->last;
-
- } else {
- last = b->pos + ctx->rest;
- }
-
- state = ctx->frame_state;
-
- if (state == sw_start) {
-
- if (ctx->stream_id) {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "upstream sent settings frame "
- "with non-zero stream id: %ui",
- ctx->stream_id);
- return NGX_ERROR;
- }
-
- if (ctx->flags & NGX_HTTP_V2_ACK_FLAG) {
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "grpc settings ack");
-
- if (ctx->rest != 0) {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "upstream sent settings frame "
- "with ack flag and non-zero length: %uz",
- ctx->rest);
- return NGX_ERROR;
- }
-
- ctx->state = ngx_http_grpc_st_start;
-
- return NGX_OK;
- }
-
- if (ctx->rest % 6 != 0) {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "upstream sent settings frame "
- "with invalid length: %uz",
- ctx->rest);
- return NGX_ERROR;
- }
-
- if (ctx->free == NULL && ctx->settings++ > 1000) {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "upstream sent too many settings frames");
- return NGX_ERROR;
- }
- }
-
- for (p = b->pos; p < last; p++) {
- ch = *p;
-
-#if 0
- ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "grpc settings byte: %02Xd s:%d", ch, state);
-#endif
-
- switch (state) {
-
- case sw_start:
- case sw_id:
- ctx->setting_id = ch << 8;
- state = sw_id_2;
- break;
-
- case sw_id_2:
- ctx->setting_id |= ch;
- state = sw_value;
- break;
-
- case sw_value:
- ctx->setting_value = (ngx_uint_t) ch << 24;
- state = sw_value_2;
- break;
-
- case sw_value_2:
- ctx->setting_value |= ch << 16;
- state = sw_value_3;
- break;
-
- case sw_value_3:
- ctx->setting_value |= ch << 8;
- state = sw_value_4;
- break;
-
- case sw_value_4:
- ctx->setting_value |= ch;
- state = sw_id;
-
- ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "grpc setting: %ui %ui",
- ctx->setting_id, ctx->setting_value);
-
- /*
- * The following settings are defined by the protocol:
- *
- * SETTINGS_HEADER_TABLE_SIZE, SETTINGS_ENABLE_PUSH,
- * SETTINGS_MAX_CONCURRENT_STREAMS, SETTINGS_INITIAL_WINDOW_SIZE,
- * SETTINGS_MAX_FRAME_SIZE, SETTINGS_MAX_HEADER_LIST_SIZE
- *
- * Only SETTINGS_INITIAL_WINDOW_SIZE seems to be needed in
- * a simple client.
- */
-
- if (ctx->setting_id == 0x04) {
- /* SETTINGS_INITIAL_WINDOW_SIZE */
-
- if (ctx->setting_value > NGX_HTTP_V2_MAX_WINDOW) {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "upstream sent settings frame "
- "with too large initial window size: %ui",
- ctx->setting_value);
- return NGX_ERROR;
- }
-
- window_update = ctx->setting_value
- - ctx->connection->init_window;
- ctx->connection->init_window = ctx->setting_value;
-
- if (ctx->send_window > 0
- && window_update > (ssize_t) NGX_HTTP_V2_MAX_WINDOW
- - ctx->send_window)
- {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "upstream sent settings frame "
- "with too large initial window size: %ui",
- ctx->setting_value);
- return NGX_ERROR;
- }
-
- ctx->send_window += window_update;
- }
-
- break;
- }
- }
-
- ctx->rest -= p - b->pos;
- ctx->frame_state = state;
- b->pos = p;
-
- if (ctx->rest > 0) {
- return NGX_AGAIN;
- }
-
- ctx->state = ngx_http_grpc_st_start;
-
- return ngx_http_grpc_send_settings_ack(r, ctx);
-}
-
-
-static ngx_int_t
-ngx_http_grpc_parse_ping(ngx_http_request_t *r,
- ngx_http_grpc_ctx_t *ctx, ngx_buf_t *b)
-{
- u_char ch, *p, *last;
- enum {
- sw_start = 0,
- sw_data_2,
- sw_data_3,
- sw_data_4,
- sw_data_5,
- sw_data_6,
- sw_data_7,
- sw_data_8
- } state;
-
- if (b->last - b->pos < (ssize_t) ctx->rest) {
- last = b->last;
-
- } else {
- last = b->pos + ctx->rest;
- }
-
- state = ctx->frame_state;
-
- if (state == sw_start) {
-
- if (ctx->stream_id) {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "upstream sent ping frame "
- "with non-zero stream id: %ui",
- ctx->stream_id);
- return NGX_ERROR;
- }
-
- if (ctx->rest != 8) {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "upstream sent ping frame "
- "with invalid length: %uz",
- ctx->rest);
- return NGX_ERROR;
- }
-
- if (ctx->flags & NGX_HTTP_V2_ACK_FLAG) {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "upstream sent ping frame with ack flag");
- return NGX_ERROR;
- }
-
- if (ctx->free == NULL && ctx->pings++ > 1000) {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "upstream sent too many ping frames");
- return NGX_ERROR;
- }
- }
-
- for (p = b->pos; p < last; p++) {
- ch = *p;
-
-#if 0
- ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "grpc ping byte: %02Xd s:%d", ch, state);
-#endif
-
- if (state < sw_data_8) {
- ctx->ping_data[state] = ch;
- state++;
-
- } else {
- ctx->ping_data[7] = ch;
- state = sw_start;
-
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "grpc ping");
- }
- }
-
- ctx->rest -= p - b->pos;
- ctx->frame_state = state;
- b->pos = p;
-
- if (ctx->rest > 0) {
- return NGX_AGAIN;
- }
-
- ctx->state = ngx_http_grpc_st_start;
-
- return ngx_http_grpc_send_ping_ack(r, ctx);
-}
-
-
-static ngx_int_t
-ngx_http_grpc_send_settings_ack(ngx_http_request_t *r, ngx_http_grpc_ctx_t *ctx)
-{
- ngx_chain_t *cl, **ll;
- ngx_http_grpc_frame_t *f;
-
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "grpc send settings ack");
-
- for (cl = ctx->out, ll = &ctx->out; cl; cl = cl->next) {
- ll = &cl->next;
- }
-
- cl = ngx_http_grpc_get_buf(r, ctx);
- if (cl == NULL) {
- return NGX_ERROR;
- }
-
- f = (ngx_http_grpc_frame_t *) cl->buf->last;
- cl->buf->last += sizeof(ngx_http_grpc_frame_t);
-
- f->length_0 = 0;
- f->length_1 = 0;
- f->length_2 = 0;
- f->type = NGX_HTTP_V2_SETTINGS_FRAME;
- f->flags = NGX_HTTP_V2_ACK_FLAG;
- f->stream_id_0 = 0;
- f->stream_id_1 = 0;
- f->stream_id_2 = 0;
- f->stream_id_3 = 0;
-
- *ll = cl;
-
- return NGX_OK;
-}
-
-
-static ngx_int_t
-ngx_http_grpc_send_ping_ack(ngx_http_request_t *r, ngx_http_grpc_ctx_t *ctx)
-{
- ngx_chain_t *cl, **ll;
- ngx_http_grpc_frame_t *f;
-
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "grpc send ping ack");
-
- for (cl = ctx->out, ll = &ctx->out; cl; cl = cl->next) {
- ll = &cl->next;
- }
-
- cl = ngx_http_grpc_get_buf(r, ctx);
- if (cl == NULL) {
- return NGX_ERROR;
- }
-
- f = (ngx_http_grpc_frame_t *) cl->buf->last;
- cl->buf->last += sizeof(ngx_http_grpc_frame_t);
-
- f->length_0 = 0;
- f->length_1 = 0;
- f->length_2 = 8;
- f->type = NGX_HTTP_V2_PING_FRAME;
- f->flags = NGX_HTTP_V2_ACK_FLAG;
- f->stream_id_0 = 0;
- f->stream_id_1 = 0;
- f->stream_id_2 = 0;
- f->stream_id_3 = 0;
-
- cl->buf->last = ngx_copy(cl->buf->last, ctx->ping_data, 8);
-
- *ll = cl;
-
- return NGX_OK;
-}
-
-
-static ngx_int_t
-ngx_http_grpc_send_window_update(ngx_http_request_t *r,
- ngx_http_grpc_ctx_t *ctx)
-{
- size_t n;
- ngx_chain_t *cl, **ll;
- ngx_http_grpc_frame_t *f;
-
- ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "grpc send window update: %uz %uz",
- ctx->connection->recv_window, ctx->recv_window);
-
- for (cl = ctx->out, ll = &ctx->out; cl; cl = cl->next) {
- ll = &cl->next;
- }
-
- cl = ngx_http_grpc_get_buf(r, ctx);
- if (cl == NULL) {
- return NGX_ERROR;
- }
-
- f = (ngx_http_grpc_frame_t *) cl->buf->last;
- cl->buf->last += sizeof(ngx_http_grpc_frame_t);
-
- f->length_0 = 0;
- f->length_1 = 0;
- f->length_2 = 4;
- f->type = NGX_HTTP_V2_WINDOW_UPDATE_FRAME;
- f->flags = 0;
- f->stream_id_0 = 0;
- f->stream_id_1 = 0;
- f->stream_id_2 = 0;
- f->stream_id_3 = 0;
-
- n = NGX_HTTP_V2_MAX_WINDOW - ctx->connection->recv_window;
- ctx->connection->recv_window = NGX_HTTP_V2_MAX_WINDOW;
-
- *cl->buf->last++ = (u_char) ((n >> 24) & 0xff);
- *cl->buf->last++ = (u_char) ((n >> 16) & 0xff);
- *cl->buf->last++ = (u_char) ((n >> 8) & 0xff);
- *cl->buf->last++ = (u_char) (n & 0xff);
-
- f = (ngx_http_grpc_frame_t *) cl->buf->last;
- cl->buf->last += sizeof(ngx_http_grpc_frame_t);
-
- f->length_0 = 0;
- f->length_1 = 0;
- f->length_2 = 4;
- f->type = NGX_HTTP_V2_WINDOW_UPDATE_FRAME;
- f->flags = 0;
- f->stream_id_0 = (u_char) ((ctx->id >> 24) & 0xff);
- f->stream_id_1 = (u_char) ((ctx->id >> 16) & 0xff);
- f->stream_id_2 = (u_char) ((ctx->id >> 8) & 0xff);
- f->stream_id_3 = (u_char) (ctx->id & 0xff);
-
- n = NGX_HTTP_V2_MAX_WINDOW - ctx->recv_window;
- ctx->recv_window = NGX_HTTP_V2_MAX_WINDOW;
-
- *cl->buf->last++ = (u_char) ((n >> 24) & 0xff);
- *cl->buf->last++ = (u_char) ((n >> 16) & 0xff);
- *cl->buf->last++ = (u_char) ((n >> 8) & 0xff);
- *cl->buf->last++ = (u_char) (n & 0xff);
-
- *ll = cl;
-
- return NGX_OK;
-}
-
-
-static ngx_chain_t *
-ngx_http_grpc_get_buf(ngx_http_request_t *r, ngx_http_grpc_ctx_t *ctx)
-{
- u_char *start;
- ngx_buf_t *b;
- ngx_chain_t *cl;
-
- cl = ngx_chain_get_free_buf(r->pool, &ctx->free);
- if (cl == NULL) {
- return NULL;
- }
-
- b = cl->buf;
- start = b->start;
-
- if (start == NULL) {
-
- /*
- * each buffer is large enough to hold two window update
- * frames in a row
- */
-
- start = ngx_palloc(r->pool, 2 * sizeof(ngx_http_grpc_frame_t) + 8);
- if (start == NULL) {
- return NULL;
- }
-
- }
-
- ngx_memzero(b, sizeof(ngx_buf_t));
-
- b->start = start;
- b->pos = start;
- b->last = start;
- b->end = start + 2 * sizeof(ngx_http_grpc_frame_t) + 8;
-
- b->tag = (ngx_buf_tag_t) &ngx_http_grpc_body_output_filter;
- b->temporary = 1;
- b->flush = 1;
-
- return cl;
-}
-
-
-static ngx_http_grpc_ctx_t *
-ngx_http_grpc_get_ctx(ngx_http_request_t *r)
-{
- ngx_http_grpc_ctx_t *ctx;
- ngx_http_upstream_t *u;
-
- ctx = ngx_http_get_module_ctx(r, ngx_http_grpc_module);
-
- if (ctx->connection == NULL) {
- u = r->upstream;
-
- if (ngx_http_grpc_get_connection_data(r, ctx, &u->peer) != NGX_OK) {
- return NULL;
- }
- }
-
- return ctx;
-}
-
-
-static ngx_int_t
-ngx_http_grpc_get_connection_data(ngx_http_request_t *r,
- ngx_http_grpc_ctx_t *ctx, ngx_peer_connection_t *pc)
-{
- ngx_connection_t *c;
- ngx_pool_cleanup_t *cln;
-
- c = pc->connection;
-
- if (pc->cached) {
-
- /*
- * for cached connections, connection data can be found
- * in the cleanup handler
- */
-
- for (cln = c->pool->cleanup; cln; cln = cln->next) {
- if (cln->handler == ngx_http_grpc_cleanup) {
- ctx->connection = cln->data;
- break;
- }
- }
-
- if (ctx->connection == NULL) {
- ngx_log_error(NGX_LOG_ERR, c->log, 0,
- "no connection data found for "
- "keepalive http2 connection");
- return NGX_ERROR;
- }
-
- ctx->send_window = ctx->connection->init_window;
- ctx->recv_window = NGX_HTTP_V2_MAX_WINDOW;
-
- ctx->connection->last_stream_id += 2;
- ctx->id = ctx->connection->last_stream_id;
-
- return NGX_OK;
- }
-
- cln = ngx_pool_cleanup_add(c->pool, sizeof(ngx_http_grpc_conn_t));
- if (cln == NULL) {
- return NGX_ERROR;
- }
-
- cln->handler = ngx_http_grpc_cleanup;
- ctx->connection = cln->data;
-
- ctx->connection->init_window = NGX_HTTP_V2_DEFAULT_WINDOW;
- ctx->connection->send_window = NGX_HTTP_V2_DEFAULT_WINDOW;
- ctx->connection->recv_window = NGX_HTTP_V2_MAX_WINDOW;
-
- ctx->send_window = NGX_HTTP_V2_DEFAULT_WINDOW;
- ctx->recv_window = NGX_HTTP_V2_MAX_WINDOW;
-
- ctx->id = 1;
- ctx->connection->last_stream_id = 1;
-
- return NGX_OK;
-}
-
-
-static void
-ngx_http_grpc_cleanup(void *data)
-{
-#if 0
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
- "grpc cleanup");
-#endif
- return;
-}
-
-
-static void
-ngx_http_grpc_abort_request(ngx_http_request_t *r)
-{
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "abort grpc request");
- return;
-}
-
-
-static void
-ngx_http_grpc_finalize_request(ngx_http_request_t *r, ngx_int_t rc)
-{
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "finalize grpc request");
- return;
-}
-
-
-static ngx_int_t
-ngx_http_grpc_internal_trailers_variable(ngx_http_request_t *r,
- ngx_http_variable_value_t *v, uintptr_t data)
-{
- ngx_table_elt_t *te;
-
- te = r->headers_in.te;
-
- if (te == NULL) {
- v->not_found = 1;
- return NGX_OK;
- }
-
- if (ngx_strlcasestrn(te->value.data, te->value.data + te->value.len,
- (u_char *) "trailers", 8 - 1)
- == NULL)
- {
- v->not_found = 1;
- return NGX_OK;
- }
-
- v->valid = 1;
- v->no_cacheable = 0;
- v->not_found = 0;
-
- v->data = (u_char *) "trailers";
- v->len = sizeof("trailers") - 1;
-
- return NGX_OK;
-}
-
-
-static ngx_int_t
-ngx_http_grpc_add_variables(ngx_conf_t *cf)
-{
- ngx_http_variable_t *var, *v;
-
- for (v = ngx_http_grpc_vars; v->name.len; v++) {
- var = ngx_http_add_variable(cf, &v->name, v->flags);
- if (var == NULL) {
- return NGX_ERROR;
- }
-
- var->get_handler = v->get_handler;
- var->data = v->data;
- }
-
- return NGX_OK;
-}
-
-
-static void *
-ngx_http_grpc_create_loc_conf(ngx_conf_t *cf)
-{
- ngx_http_grpc_loc_conf_t *conf;
-
- conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_grpc_loc_conf_t));
- if (conf == NULL) {
- return NULL;
- }
-
- /*
- * set by ngx_pcalloc():
- *
- * conf->upstream.ignore_headers = 0;
- * conf->upstream.next_upstream = 0;
- * conf->upstream.hide_headers_hash = { NULL, 0 };
- * conf->upstream.ssl_name = NULL;
- *
- * conf->headers_source = NULL;
- * conf->headers.lengths = NULL;
- * conf->headers.values = NULL;
- * conf->headers.hash = { NULL, 0 };
- * conf->host = { 0, NULL };
- * conf->host_set = 0;
- * conf->ssl = 0;
- * conf->ssl_protocols = 0;
- * conf->ssl_ciphers = { 0, NULL };
- * conf->ssl_trusted_certificate = { 0, NULL };
- * conf->ssl_crl = { 0, NULL };
- * conf->ssl_certificate = { 0, NULL };
- * conf->ssl_certificate_key = { 0, NULL };
- */
-
- conf->upstream.local = NGX_CONF_UNSET_PTR;
- conf->upstream.next_upstream_tries = NGX_CONF_UNSET_UINT;
- conf->upstream.connect_timeout = NGX_CONF_UNSET_MSEC;
- conf->upstream.send_timeout = NGX_CONF_UNSET_MSEC;
- conf->upstream.read_timeout = NGX_CONF_UNSET_MSEC;
- conf->upstream.next_upstream_timeout = NGX_CONF_UNSET_MSEC;
-
- conf->upstream.buffer_size = NGX_CONF_UNSET_SIZE;
-
- conf->upstream.hide_headers = NGX_CONF_UNSET_PTR;
- conf->upstream.pass_headers = NGX_CONF_UNSET_PTR;
-
- conf->upstream.intercept_errors = NGX_CONF_UNSET;
-
-#if (NGX_HTTP_SSL)
- conf->upstream.ssl_session_reuse = NGX_CONF_UNSET;
- conf->upstream.ssl_server_name = NGX_CONF_UNSET;
- conf->upstream.ssl_verify = NGX_CONF_UNSET;
- conf->ssl_verify_depth = NGX_CONF_UNSET_UINT;
- conf->ssl_passwords = NGX_CONF_UNSET_PTR;
-#endif
-
- /* the hardcoded values */
- conf->upstream.cyclic_temp_file = 0;
- conf->upstream.buffering = 0;
- conf->upstream.ignore_client_abort = 0;
- conf->upstream.send_lowat = 0;
- conf->upstream.bufs.num = 0;
- conf->upstream.busy_buffers_size = 0;
- conf->upstream.max_temp_file_size = 0;
- conf->upstream.temp_file_write_size = 0;
- conf->upstream.pass_request_headers = 1;
- conf->upstream.pass_request_body = 1;
- conf->upstream.force_ranges = 0;
- conf->upstream.pass_trailers = 1;
- conf->upstream.preserve_output = 1;
-
- ngx_str_set(&conf->upstream.module, "grpc");
-
- return conf;
-}
-
-
-static char *
-ngx_http_grpc_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
-{
- ngx_http_grpc_loc_conf_t *prev = parent;
- ngx_http_grpc_loc_conf_t *conf = child;
-
- ngx_int_t rc;
- ngx_hash_init_t hash;
- ngx_http_core_loc_conf_t *clcf;
-
- ngx_conf_merge_ptr_value(conf->upstream.local,
- prev->upstream.local, NULL);
-
- ngx_conf_merge_uint_value(conf->upstream.next_upstream_tries,
- prev->upstream.next_upstream_tries, 0);
-
- ngx_conf_merge_msec_value(conf->upstream.connect_timeout,
- prev->upstream.connect_timeout, 60000);
-
- ngx_conf_merge_msec_value(conf->upstream.send_timeout,
- prev->upstream.send_timeout, 60000);
-
- ngx_conf_merge_msec_value(conf->upstream.read_timeout,
- prev->upstream.read_timeout, 60000);
-
- ngx_conf_merge_msec_value(conf->upstream.next_upstream_timeout,
- prev->upstream.next_upstream_timeout, 0);
-
- ngx_conf_merge_size_value(conf->upstream.buffer_size,
- prev->upstream.buffer_size,
- (size_t) ngx_pagesize);
-
- ngx_conf_merge_bitmask_value(conf->upstream.ignore_headers,
- prev->upstream.ignore_headers,
- NGX_CONF_BITMASK_SET);
-
- ngx_conf_merge_bitmask_value(conf->upstream.next_upstream,
- prev->upstream.next_upstream,
- (NGX_CONF_BITMASK_SET
- |NGX_HTTP_UPSTREAM_FT_ERROR
- |NGX_HTTP_UPSTREAM_FT_TIMEOUT));
-
- if (conf->upstream.next_upstream & NGX_HTTP_UPSTREAM_FT_OFF) {
- conf->upstream.next_upstream = NGX_CONF_BITMASK_SET
- |NGX_HTTP_UPSTREAM_FT_OFF;
- }
-
- ngx_conf_merge_value(conf->upstream.intercept_errors,
- prev->upstream.intercept_errors, 0);
-
-#if (NGX_HTTP_SSL)
-
- ngx_conf_merge_value(conf->upstream.ssl_session_reuse,
- prev->upstream.ssl_session_reuse, 1);
-
- ngx_conf_merge_bitmask_value(conf->ssl_protocols, prev->ssl_protocols,
- (NGX_CONF_BITMASK_SET|NGX_SSL_TLSv1
- |NGX_SSL_TLSv1_1|NGX_SSL_TLSv1_2));
-
- ngx_conf_merge_str_value(conf->ssl_ciphers, prev->ssl_ciphers,
- "DEFAULT");
-
- if (conf->upstream.ssl_name == NULL) {
- conf->upstream.ssl_name = prev->upstream.ssl_name;
- }
-
- ngx_conf_merge_value(conf->upstream.ssl_server_name,
- prev->upstream.ssl_server_name, 0);
- ngx_conf_merge_value(conf->upstream.ssl_verify,
- prev->upstream.ssl_verify, 0);
- ngx_conf_merge_uint_value(conf->ssl_verify_depth,
- prev->ssl_verify_depth, 1);
- ngx_conf_merge_str_value(conf->ssl_trusted_certificate,
- prev->ssl_trusted_certificate, "");
- ngx_conf_merge_str_value(conf->ssl_crl, prev->ssl_crl, "");
-
- ngx_conf_merge_str_value(conf->ssl_certificate,
- prev->ssl_certificate, "");
- ngx_conf_merge_str_value(conf->ssl_certificate_key,
- prev->ssl_certificate_key, "");
- ngx_conf_merge_ptr_value(conf->ssl_passwords, prev->ssl_passwords, NULL);
-
- if (conf->ssl && ngx_http_grpc_set_ssl(cf, conf) != NGX_OK) {
- return NGX_CONF_ERROR;
- }
-
-#endif
-
- hash.max_size = 512;
- hash.bucket_size = ngx_align(64, ngx_cacheline_size);
- hash.name = "grpc_headers_hash";
-
- if (ngx_http_upstream_hide_headers_hash(cf, &conf->upstream,
- &prev->upstream, ngx_http_grpc_hide_headers, &hash)
- != NGX_OK)
- {
- return NGX_CONF_ERROR;
- }
-
- clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);
-
- if (clcf->noname && conf->upstream.upstream == NULL) {
- conf->upstream.upstream = prev->upstream.upstream;
- conf->host = prev->host;
-#if (NGX_HTTP_SSL)
- conf->upstream.ssl = prev->upstream.ssl;
-#endif
- }
-
- if (clcf->lmt_excpt && clcf->handler == NULL && conf->upstream.upstream) {
- clcf->handler = ngx_http_grpc_handler;
- }
-
- if (conf->headers_source == NULL) {
- conf->headers = prev->headers;
- conf->headers_source = prev->headers_source;
- conf->host_set = prev->host_set;
- }
-
- rc = ngx_http_grpc_init_headers(cf, conf, &conf->headers,
- ngx_http_grpc_headers);
- if (rc != NGX_OK) {
- return NGX_CONF_ERROR;
- }
-
- /*
- * special handling to preserve conf->headers in the "http" section
- * to inherit it to all servers
- */
-
- if (prev->headers.hash.buckets == NULL
- && conf->headers_source == prev->headers_source)
- {
- prev->headers = conf->headers;
- prev->host_set = conf->host_set;
- }
-
- return NGX_CONF_OK;
-}
-
-
-static ngx_int_t
-ngx_http_grpc_init_headers(ngx_conf_t *cf, ngx_http_grpc_loc_conf_t *conf,
- ngx_http_grpc_headers_t *headers, ngx_keyval_t *default_headers)
-{
- u_char *p;
- size_t size;
- uintptr_t *code;
- ngx_uint_t i;
- ngx_array_t headers_names, headers_merged;
- ngx_keyval_t *src, *s, *h;
- ngx_hash_key_t *hk;
- ngx_hash_init_t hash;
- ngx_http_script_compile_t sc;
- ngx_http_script_copy_code_t *copy;
-
- if (headers->hash.buckets) {
- return NGX_OK;
- }
-
- if (ngx_array_init(&headers_names, cf->temp_pool, 4, sizeof(ngx_hash_key_t))
- != NGX_OK)
- {
- return NGX_ERROR;
- }
-
- if (ngx_array_init(&headers_merged, cf->temp_pool, 4, sizeof(ngx_keyval_t))
- != NGX_OK)
- {
- return NGX_ERROR;
- }
-
- headers->lengths = ngx_array_create(cf->pool, 64, 1);
- if (headers->lengths == NULL) {
- return NGX_ERROR;
- }
-
- headers->values = ngx_array_create(cf->pool, 512, 1);
- if (headers->values == NULL) {
- return NGX_ERROR;
- }
-
- if (conf->headers_source) {
-
- src = conf->headers_source->elts;
- for (i = 0; i < conf->headers_source->nelts; i++) {
-
- if (src[i].key.len == 4
- && ngx_strncasecmp(src[i].key.data, (u_char *) "Host", 4) == 0)
- {
- conf->host_set = 1;
- }
-
- s = ngx_array_push(&headers_merged);
- if (s == NULL) {
- return NGX_ERROR;
- }
-
- *s = src[i];
- }
- }
-
- h = default_headers;
-
- while (h->key.len) {
-
- src = headers_merged.elts;
- for (i = 0; i < headers_merged.nelts; i++) {
- if (ngx_strcasecmp(h->key.data, src[i].key.data) == 0) {
- goto next;
- }
- }
-
- s = ngx_array_push(&headers_merged);
- if (s == NULL) {
- return NGX_ERROR;
- }
-
- *s = *h;
-
- next:
-
- h++;
- }
-
-
- src = headers_merged.elts;
- for (i = 0; i < headers_merged.nelts; i++) {
-
- hk = ngx_array_push(&headers_names);
- if (hk == NULL) {
- return NGX_ERROR;
- }
-
- hk->key = src[i].key;
- hk->key_hash = ngx_hash_key_lc(src[i].key.data, src[i].key.len);
- hk->value = (void *) 1;
-
- if (src[i].value.len == 0) {
- continue;
- }
-
- copy = ngx_array_push_n(headers->lengths,
- sizeof(ngx_http_script_copy_code_t));
- if (copy == NULL) {
- return NGX_ERROR;
- }
-
- copy->code = (ngx_http_script_code_pt) (void *)
- ngx_http_script_copy_len_code;
- copy->len = src[i].key.len;
-
- size = (sizeof(ngx_http_script_copy_code_t)
- + src[i].key.len + sizeof(uintptr_t) - 1)
- & ~(sizeof(uintptr_t) - 1);
-
- copy = ngx_array_push_n(headers->values, size);
- if (copy == NULL) {
- return NGX_ERROR;
- }
-
- copy->code = ngx_http_script_copy_code;
- copy->len = src[i].key.len;
-
- p = (u_char *) copy + sizeof(ngx_http_script_copy_code_t);
- ngx_memcpy(p, src[i].key.data, src[i].key.len);
-
- ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));
-
- sc.cf = cf;
- sc.source = &src[i].value;
- sc.flushes = &headers->flushes;
- sc.lengths = &headers->lengths;
- sc.values = &headers->values;
-
- if (ngx_http_script_compile(&sc) != NGX_OK) {
- return NGX_ERROR;
- }
-
- code = ngx_array_push_n(headers->lengths, sizeof(uintptr_t));
- if (code == NULL) {
- return NGX_ERROR;
- }
-
- *code = (uintptr_t) NULL;
-
- code = ngx_array_push_n(headers->values, sizeof(uintptr_t));
- if (code == NULL) {
- return NGX_ERROR;
- }
-
- *code = (uintptr_t) NULL;
- }
-
- code = ngx_array_push_n(headers->lengths, sizeof(uintptr_t));
- if (code == NULL) {
- return NGX_ERROR;
- }
-
- *code = (uintptr_t) NULL;
-
-
- hash.hash = &headers->hash;
- hash.key = ngx_hash_key_lc;
- hash.max_size = 512;
- hash.bucket_size = 64;
- hash.name = "grpc_headers_hash";
- hash.pool = cf->pool;
- hash.temp_pool = NULL;
-
- return ngx_hash_init(&hash, headers_names.elts, headers_names.nelts);
-}
-
-
-static char *
-ngx_http_grpc_pass(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
-{
- ngx_http_grpc_loc_conf_t *glcf = conf;
-
- size_t add;
- ngx_str_t *value, *url;
- ngx_url_t u;
- ngx_http_core_loc_conf_t *clcf;
-
- if (glcf->upstream.upstream) {
- return "is duplicate";
- }
-
- value = cf->args->elts;
- url = &value[1];
-
- if (ngx_strncasecmp(url->data, (u_char *) "grpc://", 7) == 0) {
- add = 7;
-
- } else if (ngx_strncasecmp(url->data, (u_char *) "grpcs://", 8) == 0) {
-
-#if (NGX_HTTP_SSL)
- glcf->ssl = 1;
-
- add = 8;
-#else
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "grpcs protocol requires SSL support");
- return NGX_CONF_ERROR;
-#endif
-
- } else {
- add = 0;
- }
-
- ngx_memzero(&u, sizeof(ngx_url_t));
-
- u.url.len = url->len - add;
- u.url.data = url->data + add;
- u.no_resolve = 1;
-
- glcf->upstream.upstream = ngx_http_upstream_add(cf, &u, 0);
- if (glcf->upstream.upstream == NULL) {
- return NGX_CONF_ERROR;
- }
-
- if (u.family != AF_UNIX) {
-
- if (u.no_port) {
- glcf->host = u.host;
-
- } else {
- glcf->host.len = u.host.len + 1 + u.port_text.len;
- glcf->host.data = u.host.data;
- }
-
- } else {
- ngx_str_set(&glcf->host, "localhost");
- }
-
- clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);
-
- clcf->handler = ngx_http_grpc_handler;
-
- if (clcf->name.data[clcf->name.len - 1] == '/') {
- clcf->auto_redirect = 1;
- }
-
- return NGX_CONF_OK;
-}
-
-
-#if (NGX_HTTP_SSL)
-
-static char *
-ngx_http_grpc_ssl_password_file(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
-{
- ngx_http_grpc_loc_conf_t *glcf = conf;
-
- ngx_str_t *value;
-
- if (glcf->ssl_passwords != NGX_CONF_UNSET_PTR) {
- return "is duplicate";
- }
-
- value = cf->args->elts;
-
- glcf->ssl_passwords = ngx_ssl_read_password_file(cf, &value[1]);
-
- if (glcf->ssl_passwords == NULL) {
- return NGX_CONF_ERROR;
- }
-
- return NGX_CONF_OK;
-}
-
-
-static ngx_int_t
-ngx_http_grpc_set_ssl(ngx_conf_t *cf, ngx_http_grpc_loc_conf_t *glcf)
-{
- ngx_pool_cleanup_t *cln;
-
- glcf->upstream.ssl = ngx_pcalloc(cf->pool, sizeof(ngx_ssl_t));
- if (glcf->upstream.ssl == NULL) {
- return NGX_ERROR;
- }
-
- glcf->upstream.ssl->log = cf->log;
-
- if (ngx_ssl_create(glcf->upstream.ssl, glcf->ssl_protocols, NULL)
- != NGX_OK)
- {
- return NGX_ERROR;
- }
-
- cln = ngx_pool_cleanup_add(cf->pool, 0);
- if (cln == NULL) {
- return NGX_ERROR;
- }
-
- cln->handler = ngx_ssl_cleanup_ctx;
- cln->data = glcf->upstream.ssl;
-
- if (glcf->ssl_certificate.len) {
-
- if (glcf->ssl_certificate_key.len == 0) {
- ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
- "no \"grpc_ssl_certificate_key\" is defined "
- "for certificate \"%V\"", &glcf->ssl_certificate);
- return NGX_ERROR;
- }
-
- if (ngx_ssl_certificate(cf, glcf->upstream.ssl, &glcf->ssl_certificate,
- &glcf->ssl_certificate_key, glcf->ssl_passwords)
- != NGX_OK)
- {
- return NGX_ERROR;
- }
- }
-
- if (ngx_ssl_ciphers(cf, glcf->upstream.ssl, &glcf->ssl_ciphers, 0)
- != NGX_OK)
- {
- return NGX_ERROR;
- }
-
- if (glcf->upstream.ssl_verify) {
- if (glcf->ssl_trusted_certificate.len == 0) {
- ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
- "no grpc_ssl_trusted_certificate for grpc_ssl_verify");
- return NGX_ERROR;
- }
-
- if (ngx_ssl_trusted_certificate(cf, glcf->upstream.ssl,
- &glcf->ssl_trusted_certificate,
- glcf->ssl_verify_depth)
- != NGX_OK)
- {
- return NGX_ERROR;
- }
-
- if (ngx_ssl_crl(cf, glcf->upstream.ssl, &glcf->ssl_crl) != NGX_OK) {
- return NGX_ERROR;
- }
- }
-
-#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
-
- if (SSL_CTX_set_alpn_protos(glcf->upstream.ssl->ctx,
- (u_char *) "\x02h2", 3)
- != 0)
- {
- ngx_ssl_error(NGX_LOG_EMERG, cf->log, 0,
- "SSL_CTX_set_alpn_protos() failed");
- return NGX_ERROR;
- }
-
-#endif
-
- return NGX_OK;
-}
-
-#endif
diff --git a/nginx/src/http/modules/ngx_http_gunzip_filter_module.c b/nginx/src/http/modules/ngx_http_gunzip_filter_module.c
deleted file mode 100644
index c1341f5..0000000
--- a/nginx/src/http/modules/ngx_http_gunzip_filter_module.c
+++ /dev/null
@@ -1,687 +0,0 @@
-
-/*
- * Copyright (C) Igor Sysoev
- * Copyright (C) Maxim Dounin
- * Copyright (C) Nginx, Inc.
- */
-
-
-#include <ngx_config.h>
-#include <ngx_core.h>
-#include <ngx_http.h>
-
-#include <zlib.h>
-
-
-typedef struct {
- ngx_flag_t enable;
- ngx_bufs_t bufs;
-} ngx_http_gunzip_conf_t;
-
-
-typedef struct {
- ngx_chain_t *in;
- ngx_chain_t *free;
- ngx_chain_t *busy;
- ngx_chain_t *out;
- ngx_chain_t **last_out;
-
- ngx_buf_t *in_buf;
- ngx_buf_t *out_buf;
- ngx_int_t bufs;
-
- unsigned started:1;
- unsigned flush:4;
- unsigned redo:1;
- unsigned done:1;
- unsigned nomem:1;
-
- z_stream zstream;
- ngx_http_request_t *request;
-} ngx_http_gunzip_ctx_t;
-
-
-static ngx_int_t ngx_http_gunzip_filter_inflate_start(ngx_http_request_t *r,
- ngx_http_gunzip_ctx_t *ctx);
-static ngx_int_t ngx_http_gunzip_filter_add_data(ngx_http_request_t *r,
- ngx_http_gunzip_ctx_t *ctx);
-static ngx_int_t ngx_http_gunzip_filter_get_buf(ngx_http_request_t *r,
- ngx_http_gunzip_ctx_t *ctx);
-static ngx_int_t ngx_http_gunzip_filter_inflate(ngx_http_request_t *r,
- ngx_http_gunzip_ctx_t *ctx);
-static ngx_int_t ngx_http_gunzip_filter_inflate_end(ngx_http_request_t *r,
- ngx_http_gunzip_ctx_t *ctx);
-
-static void *ngx_http_gunzip_filter_alloc(void *opaque, u_int items,
- u_int size);
-static void ngx_http_gunzip_filter_free(void *opaque, void *address);
-
-static ngx_int_t ngx_http_gunzip_filter_init(ngx_conf_t *cf);
-static void *ngx_http_gunzip_create_conf(ngx_conf_t *cf);
-static char *ngx_http_gunzip_merge_conf(ngx_conf_t *cf,
- void *parent, void *child);
-
-
-static ngx_command_t ngx_http_gunzip_filter_commands[] = {
-
- { ngx_string("gunzip"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
- ngx_conf_set_flag_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_gunzip_conf_t, enable),
- NULL },
-
- { ngx_string("gunzip_buffers"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE2,
- ngx_conf_set_bufs_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_gunzip_conf_t, bufs),
- NULL },
-
- ngx_null_command
-};
-
-
-static ngx_http_module_t ngx_http_gunzip_filter_module_ctx = {
- NULL, /* preconfiguration */
- ngx_http_gunzip_filter_init, /* postconfiguration */
-
- NULL, /* create main configuration */
- NULL, /* init main configuration */
-
- NULL, /* create server configuration */
- NULL, /* merge server configuration */
-
- ngx_http_gunzip_create_conf, /* create location configuration */
- ngx_http_gunzip_merge_conf /* merge location configuration */
-};
-
-
-ngx_module_t ngx_http_gunzip_filter_module = {
- NGX_MODULE_V1,
- &ngx_http_gunzip_filter_module_ctx, /* module context */
- ngx_http_gunzip_filter_commands, /* module directives */
- NGX_HTTP_MODULE, /* module type */
- NULL, /* init master */
- NULL, /* init module */
- NULL, /* init process */
- NULL, /* init thread */
- NULL, /* exit thread */
- NULL, /* exit process */
- NULL, /* exit master */
- NGX_MODULE_V1_PADDING
-};
-
-
-static ngx_http_output_header_filter_pt ngx_http_next_header_filter;
-static ngx_http_output_body_filter_pt ngx_http_next_body_filter;
-
-
-static ngx_int_t
-ngx_http_gunzip_header_filter(ngx_http_request_t *r)
-{
- ngx_http_gunzip_ctx_t *ctx;
- ngx_http_gunzip_conf_t *conf;
-
- conf = ngx_http_get_module_loc_conf(r, ngx_http_gunzip_filter_module);
-
- /* TODO support multiple content-codings */
- /* TODO always gunzip - due to configuration or module request */
- /* TODO ignore content encoding? */
-
- if (!conf->enable
- || r->headers_out.content_encoding == NULL
- || r->headers_out.content_encoding->value.len != 4
- || ngx_strncasecmp(r->headers_out.content_encoding->value.data,
- (u_char *) "gzip", 4) != 0)
- {
- return ngx_http_next_header_filter(r);
- }
-
- r->gzip_vary = 1;
-
- if (!r->gzip_tested) {
- if (ngx_http_gzip_ok(r) == NGX_OK) {
- return ngx_http_next_header_filter(r);
- }
-
- } else if (r->gzip_ok) {
- return ngx_http_next_header_filter(r);
- }
-
- ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_gunzip_ctx_t));
- if (ctx == NULL) {
- return NGX_ERROR;
- }
-
- ngx_http_set_ctx(r, ctx, ngx_http_gunzip_filter_module);
-
- ctx->request = r;
-
- r->filter_need_in_memory = 1;
-
- r->headers_out.content_encoding->hash = 0;
- r->headers_out.content_encoding = NULL;
-
- ngx_http_clear_content_length(r);
- ngx_http_clear_accept_ranges(r);
- ngx_http_weak_etag(r);
-
- return ngx_http_next_header_filter(r);
-}
-
-
-static ngx_int_t
-ngx_http_gunzip_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
-{
- int rc;
- ngx_uint_t flush;
- ngx_chain_t *cl;
- ngx_http_gunzip_ctx_t *ctx;
-
- ctx = ngx_http_get_module_ctx(r, ngx_http_gunzip_filter_module);
-
- if (ctx == NULL || ctx->done) {
- return ngx_http_next_body_filter(r, in);
- }
-
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "http gunzip filter");
-
- if (!ctx->started) {
- if (ngx_http_gunzip_filter_inflate_start(r, ctx) != NGX_OK) {
- goto failed;
- }
- }
-
- if (in) {
- if (ngx_chain_add_copy(r->pool, &ctx->in, in) != NGX_OK) {
- goto failed;
- }
- }
-
- if (ctx->nomem) {
-
- /* flush busy buffers */
-
- if (ngx_http_next_body_filter(r, NULL) == NGX_ERROR) {
- goto failed;
- }
-
- cl = NULL;
-
- ngx_chain_update_chains(r->pool, &ctx->free, &ctx->busy, &cl,
- (ngx_buf_tag_t) &ngx_http_gunzip_filter_module);
- ctx->nomem = 0;
- flush = 0;
-
- } else {
- flush = ctx->busy ? 1 : 0;
- }
-
- for ( ;; ) {
-
- /* cycle while we can write to a client */
-
- for ( ;; ) {
-
- /* cycle while there is data to feed zlib and ... */
-
- rc = ngx_http_gunzip_filter_add_data(r, ctx);
-
- if (rc == NGX_DECLINED) {
- break;
- }
-
- if (rc == NGX_AGAIN) {
- continue;
- }
-
-
- /* ... there are buffers to write zlib output */
-
- rc = ngx_http_gunzip_filter_get_buf(r, ctx);
-
- if (rc == NGX_DECLINED) {
- break;
- }
-
- if (rc == NGX_ERROR) {
- goto failed;
- }
-
- rc = ngx_http_gunzip_filter_inflate(r, ctx);
-
- if (rc == NGX_OK) {
- break;
- }
-
- if (rc == NGX_ERROR) {
- goto failed;
- }
-
- /* rc == NGX_AGAIN */
- }
-
- if (ctx->out == NULL && !flush) {
- return ctx->busy ? NGX_AGAIN : NGX_OK;
- }
-
- rc = ngx_http_next_body_filter(r, ctx->out);
-
- if (rc == NGX_ERROR) {
- goto failed;
- }
-
- ngx_chain_update_chains(r->pool, &ctx->free, &ctx->busy, &ctx->out,
- (ngx_buf_tag_t) &ngx_http_gunzip_filter_module);
- ctx->last_out = &ctx->out;
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "gunzip out: %p", ctx->out);
-
- ctx->nomem = 0;
- flush = 0;
-
- if (ctx->done) {
- return rc;
- }
- }
-
- /* unreachable */
-
-failed:
-
- ctx->done = 1;
-
- return NGX_ERROR;
-}
-
-
-static ngx_int_t
-ngx_http_gunzip_filter_inflate_start(ngx_http_request_t *r,
- ngx_http_gunzip_ctx_t *ctx)
-{
- int rc;
-
- ctx->zstream.next_in = Z_NULL;
- ctx->zstream.avail_in = 0;
-
- ctx->zstream.zalloc = ngx_http_gunzip_filter_alloc;
- ctx->zstream.zfree = ngx_http_gunzip_filter_free;
- ctx->zstream.opaque = ctx;
-
- /* windowBits +16 to decode gzip, zlib 1.2.0.4+ */
- rc = inflateInit2(&ctx->zstream, MAX_WBITS + 16);
-
- if (rc != Z_OK) {
- ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
- "inflateInit2() failed: %d", rc);
- return NGX_ERROR;
- }
-
- ctx->started = 1;
-
- ctx->last_out = &ctx->out;
- ctx->flush = Z_NO_FLUSH;
-
- return NGX_OK;
-}
-
-
-static ngx_int_t
-ngx_http_gunzip_filter_add_data(ngx_http_request_t *r,
- ngx_http_gunzip_ctx_t *ctx)
-{
- if (ctx->zstream.avail_in || ctx->flush != Z_NO_FLUSH || ctx->redo) {
- return NGX_OK;
- }
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "gunzip in: %p", ctx->in);
-
- if (ctx->in == NULL) {
- return NGX_DECLINED;
- }
-
- ctx->in_buf = ctx->in->buf;
- ctx->in = ctx->in->next;
-
- ctx->zstream.next_in = ctx->in_buf->pos;
- ctx->zstream.avail_in = ctx->in_buf->last - ctx->in_buf->pos;
-
- ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "gunzip in_buf:%p ni:%p ai:%ud",
- ctx->in_buf,
- ctx->zstream.next_in, ctx->zstream.avail_in);
-
- if (ctx->in_buf->last_buf || ctx->in_buf->last_in_chain) {
- ctx->flush = Z_FINISH;
-
- } else if (ctx->in_buf->flush) {
- ctx->flush = Z_SYNC_FLUSH;
-
- } else if (ctx->zstream.avail_in == 0) {
- /* ctx->flush == Z_NO_FLUSH */
- return NGX_AGAIN;
- }
-
- return NGX_OK;
-}
-
-
-static ngx_int_t
-ngx_http_gunzip_filter_get_buf(ngx_http_request_t *r,
- ngx_http_gunzip_ctx_t *ctx)
-{
- ngx_http_gunzip_conf_t *conf;
-
- if (ctx->zstream.avail_out) {
- return NGX_OK;
- }
-
- conf = ngx_http_get_module_loc_conf(r, ngx_http_gunzip_filter_module);
-
- if (ctx->free) {
- ctx->out_buf = ctx->free->buf;
- ctx->free = ctx->free->next;
-
- ctx->out_buf->flush = 0;
-
- } else if (ctx->bufs < conf->bufs.num) {
-
- ctx->out_buf = ngx_create_temp_buf(r->pool, conf->bufs.size);
- if (ctx->out_buf == NULL) {
- return NGX_ERROR;
- }
-
- ctx->out_buf->tag = (ngx_buf_tag_t) &ngx_http_gunzip_filter_module;
- ctx->out_buf->recycled = 1;
- ctx->bufs++;
-
- } else {
- ctx->nomem = 1;
- return NGX_DECLINED;
- }
-
- ctx->zstream.next_out = ctx->out_buf->pos;
- ctx->zstream.avail_out = conf->bufs.size;
-
- return NGX_OK;
-}
-
-
-static ngx_int_t
-ngx_http_gunzip_filter_inflate(ngx_http_request_t *r,
- ngx_http_gunzip_ctx_t *ctx)
-{
- int rc;
- ngx_buf_t *b;
- ngx_chain_t *cl;
-
- ngx_log_debug6(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "inflate in: ni:%p no:%p ai:%ud ao:%ud fl:%d redo:%d",
- ctx->zstream.next_in, ctx->zstream.next_out,
- ctx->zstream.avail_in, ctx->zstream.avail_out,
- ctx->flush, ctx->redo);
-
- rc = inflate(&ctx->zstream, ctx->flush);
-
- if (rc != Z_OK && rc != Z_STREAM_END && rc != Z_BUF_ERROR) {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "inflate() failed: %d, %d", ctx->flush, rc);
- return NGX_ERROR;
- }
-
- ngx_log_debug5(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "inflate out: ni:%p no:%p ai:%ud ao:%ud rc:%d",
- ctx->zstream.next_in, ctx->zstream.next_out,
- ctx->zstream.avail_in, ctx->zstream.avail_out,
- rc);
-
- ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "gunzip in_buf:%p pos:%p",
- ctx->in_buf, ctx->in_buf->pos);
-
- if (ctx->zstream.next_in) {
- ctx->in_buf->pos = ctx->zstream.next_in;
-
- if (ctx->zstream.avail_in == 0) {
- ctx->zstream.next_in = NULL;
- }
- }
-
- ctx->out_buf->last = ctx->zstream.next_out;
-
- if (ctx->zstream.avail_out == 0) {
-
- /* zlib wants to output some more data */
-
- cl = ngx_alloc_chain_link(r->pool);
- if (cl == NULL) {
- return NGX_ERROR;
- }
-
- cl->buf = ctx->out_buf;
- cl->next = NULL;
- *ctx->last_out = cl;
- ctx->last_out = &cl->next;
-
- ctx->redo = 1;
-
- return NGX_AGAIN;
- }
-
- ctx->redo = 0;
-
- if (ctx->flush == Z_SYNC_FLUSH) {
-
- ctx->flush = Z_NO_FLUSH;
-
- cl = ngx_alloc_chain_link(r->pool);
- if (cl == NULL) {
- return NGX_ERROR;
- }
-
- b = ctx->out_buf;
-
- if (ngx_buf_size(b) == 0) {
-
- b = ngx_calloc_buf(ctx->request->pool);
- if (b == NULL) {
- return NGX_ERROR;
- }
-
- } else {
- ctx->zstream.avail_out = 0;
- }
-
- b->flush = 1;
-
- cl->buf = b;
- cl->next = NULL;
- *ctx->last_out = cl;
- ctx->last_out = &cl->next;
-
- return NGX_OK;
- }
-
- if (ctx->flush == Z_FINISH && ctx->zstream.avail_in == 0) {
-
- if (rc != Z_STREAM_END) {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "inflate() returned %d on response end", rc);
- return NGX_ERROR;
- }
-
- if (ngx_http_gunzip_filter_inflate_end(r, ctx) != NGX_OK) {
- return NGX_ERROR;
- }
-
- return NGX_OK;
- }
-
- if (rc == Z_STREAM_END && ctx->zstream.avail_in > 0) {
-
- rc = inflateReset(&ctx->zstream);
-
- if (rc != Z_OK) {
- ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
- "inflateReset() failed: %d", rc);
- return NGX_ERROR;
- }
-
- ctx->redo = 1;
-
- return NGX_AGAIN;
- }
-
- if (ctx->in == NULL) {
-
- b = ctx->out_buf;
-
- if (ngx_buf_size(b) == 0) {
- return NGX_OK;
- }
-
- cl = ngx_alloc_chain_link(r->pool);
- if (cl == NULL) {
- return NGX_ERROR;
- }
-
- ctx->zstream.avail_out = 0;
-
- cl->buf = b;
- cl->next = NULL;
- *ctx->last_out = cl;
- ctx->last_out = &cl->next;
-
- return NGX_OK;
- }
-
- return NGX_AGAIN;
-}
-
-
-static ngx_int_t
-ngx_http_gunzip_filter_inflate_end(ngx_http_request_t *r,
- ngx_http_gunzip_ctx_t *ctx)
-{
- int rc;
- ngx_buf_t *b;
- ngx_chain_t *cl;
-
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "gunzip inflate end");
-
- rc = inflateEnd(&ctx->zstream);
-
- if (rc != Z_OK) {
- ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
- "inflateEnd() failed: %d", rc);
- return NGX_ERROR;
- }
-
- b = ctx->out_buf;
-
- if (ngx_buf_size(b) == 0) {
-
- b = ngx_calloc_buf(ctx->request->pool);
- if (b == NULL) {
- return NGX_ERROR;
- }
- }
-
- cl = ngx_alloc_chain_link(r->pool);
- if (cl == NULL) {
- return NGX_ERROR;
- }
-
- cl->buf = b;
- cl->next = NULL;
- *ctx->last_out = cl;
- ctx->last_out = &cl->next;
-
- b->last_buf = (r == r->main) ? 1 : 0;
- b->last_in_chain = 1;
- b->sync = 1;
-
- ctx->done = 1;
-
- return NGX_OK;
-}
-
-
-static void *
-ngx_http_gunzip_filter_alloc(void *opaque, u_int items, u_int size)
-{
- ngx_http_gunzip_ctx_t *ctx = opaque;
-
- ngx_log_debug2(NGX_LOG_DEBUG_HTTP, ctx->request->connection->log, 0,
- "gunzip alloc: n:%ud s:%ud",
- items, size);
-
- return ngx_palloc(ctx->request->pool, items * size);
-}
-
-
-static void
-ngx_http_gunzip_filter_free(void *opaque, void *address)
-{
-#if 0
- ngx_http_gunzip_ctx_t *ctx = opaque;
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, ctx->request->connection->log, 0,
- "gunzip free: %p", address);
-#endif
-}
-
-
-static void *
-ngx_http_gunzip_create_conf(ngx_conf_t *cf)
-{
- ngx_http_gunzip_conf_t *conf;
-
- conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_gunzip_conf_t));
- if (conf == NULL) {
- return NULL;
- }
-
- /*
- * set by ngx_pcalloc():
- *
- * conf->bufs.num = 0;
- */
-
- conf->enable = NGX_CONF_UNSET;
-
- return conf;
-}
-
-
-static char *
-ngx_http_gunzip_merge_conf(ngx_conf_t *cf, void *parent, void *child)
-{
- ngx_http_gunzip_conf_t *prev = parent;
- ngx_http_gunzip_conf_t *conf = child;
-
- ngx_conf_merge_value(conf->enable, prev->enable, 0);
-
- ngx_conf_merge_bufs_value(conf->bufs, prev->bufs,
- (128 * 1024) / ngx_pagesize, ngx_pagesize);
-
- return NGX_CONF_OK;
-}
-
-
-static ngx_int_t
-ngx_http_gunzip_filter_init(ngx_conf_t *cf)
-{
- ngx_http_next_header_filter = ngx_http_top_header_filter;
- ngx_http_top_header_filter = ngx_http_gunzip_header_filter;
-
- ngx_http_next_body_filter = ngx_http_top_body_filter;
- ngx_http_top_body_filter = ngx_http_gunzip_body_filter;
-
- return NGX_OK;
-}
diff --git a/nginx/src/http/modules/ngx_http_gzip_filter_module.c b/nginx/src/http/modules/ngx_http_gzip_filter_module.c
deleted file mode 100644
index e4c343c..0000000
--- a/nginx/src/http/modules/ngx_http_gzip_filter_module.c
+++ /dev/null
@@ -1,1273 +0,0 @@
-
-/*
- * Copyright (C) Igor Sysoev
- * Copyright (C) Nginx, Inc.
- */
-
-
-#include <ngx_config.h>
-#include <ngx_core.h>
-#include <ngx_http.h>
-
-#include <zlib.h>
-
-
-typedef struct {
- ngx_flag_t enable;
- ngx_flag_t no_buffer;
-
- ngx_hash_t types;
-
- ngx_bufs_t bufs;
-
- size_t postpone_gzipping;
- ngx_int_t level;
- size_t wbits;
- size_t memlevel;
- ssize_t min_length;
-
- ngx_array_t *types_keys;
-} ngx_http_gzip_conf_t;
-
-
-typedef struct {
- ngx_chain_t *in;
- ngx_chain_t *free;
- ngx_chain_t *busy;
- ngx_chain_t *out;
- ngx_chain_t **last_out;
-
- ngx_chain_t *copied;
- ngx_chain_t *copy_buf;
-
- ngx_buf_t *in_buf;
- ngx_buf_t *out_buf;
- ngx_int_t bufs;
-
- void *preallocated;
- char *free_mem;
- ngx_uint_t allocated;
-
- int wbits;
- int memlevel;
-
- unsigned flush:4;
- unsigned redo:1;
- unsigned done:1;
- unsigned nomem:1;
- unsigned gzheader:1;
- unsigned buffering:1;
- unsigned intel:1;
-
- size_t zin;
- size_t zout;
-
- uint32_t crc32;
- z_stream zstream;
- ngx_http_request_t *request;
-} ngx_http_gzip_ctx_t;
-
-
-#if (NGX_HAVE_LITTLE_ENDIAN && NGX_HAVE_NONALIGNED)
-
-struct gztrailer {
- uint32_t crc32;
- uint32_t zlen;
-};
-
-#else /* NGX_HAVE_BIG_ENDIAN || !NGX_HAVE_NONALIGNED */
-
-struct gztrailer {
- u_char crc32[4];
- u_char zlen[4];
-};
-
-#endif
-
-
-static void ngx_http_gzip_filter_memory(ngx_http_request_t *r,
- ngx_http_gzip_ctx_t *ctx);
-static ngx_int_t ngx_http_gzip_filter_buffer(ngx_http_gzip_ctx_t *ctx,
- ngx_chain_t *in);
-static ngx_int_t ngx_http_gzip_filter_deflate_start(ngx_http_request_t *r,
- ngx_http_gzip_ctx_t *ctx);
-static ngx_int_t ngx_http_gzip_filter_gzheader(ngx_http_request_t *r,
- ngx_http_gzip_ctx_t *ctx);
-static ngx_int_t ngx_http_gzip_filter_add_data(ngx_http_request_t *r,
- ngx_http_gzip_ctx_t *ctx);
-static ngx_int_t ngx_http_gzip_filter_get_buf(ngx_http_request_t *r,
- ngx_http_gzip_ctx_t *ctx);
-static ngx_int_t ngx_http_gzip_filter_deflate(ngx_http_request_t *r,
- ngx_http_gzip_ctx_t *ctx);
-static ngx_int_t ngx_http_gzip_filter_deflate_end(ngx_http_request_t *r,
- ngx_http_gzip_ctx_t *ctx);
-
-static void *ngx_http_gzip_filter_alloc(void *opaque, u_int items,
- u_int size);
-static void ngx_http_gzip_filter_free(void *opaque, void *address);
-static void ngx_http_gzip_filter_free_copy_buf(ngx_http_request_t *r,
- ngx_http_gzip_ctx_t *ctx);
-
-static ngx_int_t ngx_http_gzip_add_variables(ngx_conf_t *cf);
-static ngx_int_t ngx_http_gzip_ratio_variable(ngx_http_request_t *r,
- ngx_http_variable_value_t *v, uintptr_t data);
-
-static ngx_int_t ngx_http_gzip_filter_init(ngx_conf_t *cf);
-static void *ngx_http_gzip_create_conf(ngx_conf_t *cf);
-static char *ngx_http_gzip_merge_conf(ngx_conf_t *cf,
- void *parent, void *child);
-static char *ngx_http_gzip_window(ngx_conf_t *cf, void *post, void *data);
-static char *ngx_http_gzip_hash(ngx_conf_t *cf, void *post, void *data);
-
-
-static ngx_conf_num_bounds_t ngx_http_gzip_comp_level_bounds = {
- ngx_conf_check_num_bounds, 1, 9
-};
-
-static ngx_conf_post_handler_pt ngx_http_gzip_window_p = ngx_http_gzip_window;
-static ngx_conf_post_handler_pt ngx_http_gzip_hash_p = ngx_http_gzip_hash;
-
-
-static ngx_command_t ngx_http_gzip_filter_commands[] = {
-
- { ngx_string("gzip"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF
- |NGX_CONF_FLAG,
- ngx_conf_set_flag_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_gzip_conf_t, enable),
- NULL },
-
- { ngx_string("gzip_buffers"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE2,
- ngx_conf_set_bufs_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_gzip_conf_t, bufs),
- NULL },
-
- { ngx_string("gzip_types"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
- ngx_http_types_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_gzip_conf_t, types_keys),
- &ngx_http_html_default_types[0] },
-
- { ngx_string("gzip_comp_level"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_num_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_gzip_conf_t, level),
- &ngx_http_gzip_comp_level_bounds },
-
- { ngx_string("gzip_window"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_size_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_gzip_conf_t, wbits),
- &ngx_http_gzip_window_p },
-
- { ngx_string("gzip_hash"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_size_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_gzip_conf_t, memlevel),
- &ngx_http_gzip_hash_p },
-
- { ngx_string("postpone_gzipping"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_size_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_gzip_conf_t, postpone_gzipping),
- NULL },
-
- { ngx_string("gzip_no_buffer"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
- ngx_conf_set_flag_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_gzip_conf_t, no_buffer),
- NULL },
-
- { ngx_string("gzip_min_length"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_size_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_gzip_conf_t, min_length),
- NULL },
-
- ngx_null_command
-};
-
-
-static ngx_http_module_t ngx_http_gzip_filter_module_ctx = {
- ngx_http_gzip_add_variables, /* preconfiguration */
- ngx_http_gzip_filter_init, /* postconfiguration */
-
- NULL, /* create main configuration */
- NULL, /* init main configuration */
-
- NULL, /* create server configuration */
- NULL, /* merge server configuration */
-
- ngx_http_gzip_create_conf, /* create location configuration */
- ngx_http_gzip_merge_conf /* merge location configuration */
-};
-
-
-ngx_module_t ngx_http_gzip_filter_module = {
- NGX_MODULE_V1,
- &ngx_http_gzip_filter_module_ctx, /* module context */
- ngx_http_gzip_filter_commands, /* module directives */
- NGX_HTTP_MODULE, /* module type */
- NULL, /* init master */
- NULL, /* init module */
- NULL, /* init process */
- NULL, /* init thread */
- NULL, /* exit thread */
- NULL, /* exit process */
- NULL, /* exit master */
- NGX_MODULE_V1_PADDING
-};
-
-
-static ngx_str_t ngx_http_gzip_ratio = ngx_string("gzip_ratio");
-
-static ngx_http_output_header_filter_pt ngx_http_next_header_filter;
-static ngx_http_output_body_filter_pt ngx_http_next_body_filter;
-
-static ngx_uint_t ngx_http_gzip_assume_intel;
-
-
-static ngx_int_t
-ngx_http_gzip_header_filter(ngx_http_request_t *r)
-{
- ngx_table_elt_t *h;
- ngx_http_gzip_ctx_t *ctx;
- ngx_http_gzip_conf_t *conf;
-
- conf = ngx_http_get_module_loc_conf(r, ngx_http_gzip_filter_module);
-
- if (!conf->enable
- || (r->headers_out.status != NGX_HTTP_OK
- && r->headers_out.status != NGX_HTTP_FORBIDDEN
- && r->headers_out.status != NGX_HTTP_NOT_FOUND)
- || (r->headers_out.content_encoding
- && r->headers_out.content_encoding->value.len)
- || (r->headers_out.content_length_n != -1
- && r->headers_out.content_length_n < conf->min_length)
- || ngx_http_test_content_type(r, &conf->types) == NULL
- || r->header_only)
- {
- return ngx_http_next_header_filter(r);
- }
-
- r->gzip_vary = 1;
-
-#if (NGX_HTTP_DEGRADATION)
- {
- ngx_http_core_loc_conf_t *clcf;
-
- clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
-
- if (clcf->gzip_disable_degradation && ngx_http_degraded(r)) {
- return ngx_http_next_header_filter(r);
- }
- }
-#endif
-
- if (!r->gzip_tested) {
- if (ngx_http_gzip_ok(r) != NGX_OK) {
- return ngx_http_next_header_filter(r);
- }
-
- } else if (!r->gzip_ok) {
- return ngx_http_next_header_filter(r);
- }
-
- ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_gzip_ctx_t));
- if (ctx == NULL) {
- return NGX_ERROR;
- }
-
- ngx_http_set_ctx(r, ctx, ngx_http_gzip_filter_module);
-
- ctx->request = r;
- ctx->buffering = (conf->postpone_gzipping != 0);
-
- ngx_http_gzip_filter_memory(r, ctx);
-
- h = ngx_list_push(&r->headers_out.headers);
- if (h == NULL) {
- return NGX_ERROR;
- }
-
- h->hash = 1;
- ngx_str_set(&h->key, "Content-Encoding");
- ngx_str_set(&h->value, "gzip");
- r->headers_out.content_encoding = h;
-
- r->main_filter_need_in_memory = 1;
-
- ngx_http_clear_content_length(r);
- ngx_http_clear_accept_ranges(r);
- ngx_http_weak_etag(r);
-
- return ngx_http_next_header_filter(r);
-}
-
-
-static ngx_int_t
-ngx_http_gzip_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
-{
- int rc;
- ngx_uint_t flush;
- ngx_chain_t *cl;
- ngx_http_gzip_ctx_t *ctx;
-
- ctx = ngx_http_get_module_ctx(r, ngx_http_gzip_filter_module);
-
- if (ctx == NULL || ctx->done || r->header_only) {
- return ngx_http_next_body_filter(r, in);
- }
-
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "http gzip filter");
-
- if (ctx->buffering) {
-
- /*
- * With default memory settings zlib starts to output gzipped data
- * only after it has got about 90K, so it makes sense to allocate
- * zlib memory (200-400K) only after we have enough data to compress.
- * Although we copy buffers, nevertheless for not big responses
- * this allows to allocate zlib memory, to compress and to output
- * the response in one step using hot CPU cache.
- */
-
- if (in) {
- switch (ngx_http_gzip_filter_buffer(ctx, in)) {
-
- case NGX_OK:
- return NGX_OK;
-
- case NGX_DONE:
- in = NULL;
- break;
-
- default: /* NGX_ERROR */
- goto failed;
- }
-
- } else {
- ctx->buffering = 0;
- }
- }
-
- if (ctx->preallocated == NULL) {
- if (ngx_http_gzip_filter_deflate_start(r, ctx) != NGX_OK) {
- goto failed;
- }
- }
-
- if (in) {
- if (ngx_chain_add_copy(r->pool, &ctx->in, in) != NGX_OK) {
- goto failed;
- }
-
- r->connection->buffered |= NGX_HTTP_GZIP_BUFFERED;
- }
-
- if (ctx->nomem) {
-
- /* flush busy buffers */
-
- if (ngx_http_next_body_filter(r, NULL) == NGX_ERROR) {
- goto failed;
- }
-
- cl = NULL;
-
- ngx_chain_update_chains(r->pool, &ctx->free, &ctx->busy, &cl,
- (ngx_buf_tag_t) &ngx_http_gzip_filter_module);
- ctx->nomem = 0;
- flush = 0;
-
- } else {
- flush = ctx->busy ? 1 : 0;
- }
-
- for ( ;; ) {
-
- /* cycle while we can write to a client */
-
- for ( ;; ) {
-
- /* cycle while there is data to feed zlib and ... */
-
- rc = ngx_http_gzip_filter_add_data(r, ctx);
-
- if (rc == NGX_DECLINED) {
- break;
- }
-
- if (rc == NGX_AGAIN) {
- continue;
- }
-
-
- /* ... there are buffers to write zlib output */
-
- rc = ngx_http_gzip_filter_get_buf(r, ctx);
-
- if (rc == NGX_DECLINED) {
- break;
- }
-
- if (rc == NGX_ERROR) {
- goto failed;
- }
-
-
- rc = ngx_http_gzip_filter_deflate(r, ctx);
-
- if (rc == NGX_OK) {
- break;
- }
-
- if (rc == NGX_ERROR) {
- goto failed;
- }
-
- /* rc == NGX_AGAIN */
- }
-
- if (ctx->out == NULL && !flush) {
- ngx_http_gzip_filter_free_copy_buf(r, ctx);
-
- return ctx->busy ? NGX_AGAIN : NGX_OK;
- }
-
- if (!ctx->gzheader) {
- if (ngx_http_gzip_filter_gzheader(r, ctx) != NGX_OK) {
- goto failed;
- }
- }
-
- rc = ngx_http_next_body_filter(r, ctx->out);
-
- if (rc == NGX_ERROR) {
- goto failed;
- }
-
- ngx_http_gzip_filter_free_copy_buf(r, ctx);
-
- ngx_chain_update_chains(r->pool, &ctx->free, &ctx->busy, &ctx->out,
- (ngx_buf_tag_t) &ngx_http_gzip_filter_module);
- ctx->last_out = &ctx->out;
-
- ctx->nomem = 0;
- flush = 0;
-
- if (ctx->done) {
- return rc;
- }
- }
-
- /* unreachable */
-
-failed:
-
- ctx->done = 1;
-
- if (ctx->preallocated) {
- deflateEnd(&ctx->zstream);
-
- ngx_pfree(r->pool, ctx->preallocated);
- }
-
- ngx_http_gzip_filter_free_copy_buf(r, ctx);
-
- return NGX_ERROR;
-}
-
-
-static void
-ngx_http_gzip_filter_memory(ngx_http_request_t *r, ngx_http_gzip_ctx_t *ctx)
-{
- int wbits, memlevel;
- ngx_http_gzip_conf_t *conf;
-
- conf = ngx_http_get_module_loc_conf(r, ngx_http_gzip_filter_module);
-
- wbits = conf->wbits;
- memlevel = conf->memlevel;
-
- if (r->headers_out.content_length_n > 0) {
-
- /* the actual zlib window size is smaller by 262 bytes */
-
- while (r->headers_out.content_length_n < ((1 << (wbits - 1)) - 262)) {
- wbits--;
- memlevel--;
- }
-
- if (memlevel < 1) {
- memlevel = 1;
- }
- }
-
- ctx->wbits = wbits;
- ctx->memlevel = memlevel;
-
- /*
- * We preallocate a memory for zlib in one buffer (200K-400K), this
- * decreases a number of malloc() and free() calls and also probably
- * decreases a number of syscalls (sbrk()/mmap() and so on).
- * Besides we free the memory as soon as a gzipping will complete
- * and do not wait while a whole response will be sent to a client.
- *
- * 8K is for zlib deflate_state, it takes
- * *) 5816 bytes on i386 and sparc64 (32-bit mode)
- * *) 5920 bytes on amd64 and sparc64
- */
-
- if (!ngx_http_gzip_assume_intel) {
- ctx->allocated = 8192 + (1 << (wbits + 2)) + (1 << (memlevel + 9));
-
- } else {
- /*
- * A zlib variant from Intel, https://github.com/jtkukunas/zlib.
- * It can force window bits to 13 for fast compression level,
- * on processors with SSE 4.2 it uses 64K hash instead of scaling
- * it from the specified memory level, and also introduces
- * 16-byte padding in one out of the two window-sized buffers.
- */
-
- if (conf->level == 1) {
- wbits = ngx_max(wbits, 13);
- }
-
- ctx->allocated = 8192 + 16 + (1 << (wbits + 2))
- + (1 << (ngx_max(memlevel, 8) + 8))
- + (1 << (memlevel + 8));
- ctx->intel = 1;
- }
-}
-
-
-static ngx_int_t
-ngx_http_gzip_filter_buffer(ngx_http_gzip_ctx_t *ctx, ngx_chain_t *in)
-{
- size_t size, buffered;
- ngx_buf_t *b, *buf;
- ngx_chain_t *cl, **ll;
- ngx_http_request_t *r;
- ngx_http_gzip_conf_t *conf;
-
- r = ctx->request;
-
- r->connection->buffered |= NGX_HTTP_GZIP_BUFFERED;
-
- buffered = 0;
- ll = &ctx->in;
-
- for (cl = ctx->in; cl; cl = cl->next) {
- buffered += cl->buf->last - cl->buf->pos;
- ll = &cl->next;
- }
-
- conf = ngx_http_get_module_loc_conf(r, ngx_http_gzip_filter_module);
-
- while (in) {
- cl = ngx_alloc_chain_link(r->pool);
- if (cl == NULL) {
- return NGX_ERROR;
- }
-
- b = in->buf;
-
- size = b->last - b->pos;
- buffered += size;
-
- if (b->flush || b->last_buf || buffered > conf->postpone_gzipping) {
- ctx->buffering = 0;
- }
-
- if (ctx->buffering && size) {
-
- buf = ngx_create_temp_buf(r->pool, size);
- if (buf == NULL) {
- return NGX_ERROR;
- }
-
- buf->last = ngx_cpymem(buf->pos, b->pos, size);
- b->pos = b->last;
-
- buf->last_buf = b->last_buf;
- buf->tag = (ngx_buf_tag_t) &ngx_http_gzip_filter_module;
-
- cl->buf = buf;
-
- } else {
- cl->buf = b;
- }
-
- *ll = cl;
- ll = &cl->next;
- in = in->next;
- }
-
- *ll = NULL;
-
- return ctx->buffering ? NGX_OK : NGX_DONE;
-}
-
-
-static ngx_int_t
-ngx_http_gzip_filter_deflate_start(ngx_http_request_t *r,
- ngx_http_gzip_ctx_t *ctx)
-{
- int rc;
- ngx_http_gzip_conf_t *conf;
-
- conf = ngx_http_get_module_loc_conf(r, ngx_http_gzip_filter_module);
-
- ctx->preallocated = ngx_palloc(r->pool, ctx->allocated);
- if (ctx->preallocated == NULL) {
- return NGX_ERROR;
- }
-
- ctx->free_mem = ctx->preallocated;
-
- ctx->zstream.zalloc = ngx_http_gzip_filter_alloc;
- ctx->zstream.zfree = ngx_http_gzip_filter_free;
- ctx->zstream.opaque = ctx;
-
- rc = deflateInit2(&ctx->zstream, (int) conf->level, Z_DEFLATED,
- - ctx->wbits, ctx->memlevel, Z_DEFAULT_STRATEGY);
-
- if (rc != Z_OK) {
- ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
- "deflateInit2() failed: %d", rc);
- return NGX_ERROR;
- }
-
- ctx->last_out = &ctx->out;
- ctx->crc32 = crc32(0L, Z_NULL, 0);
- ctx->flush = Z_NO_FLUSH;
-
- return NGX_OK;
-}
-
-
-static ngx_int_t
-ngx_http_gzip_filter_gzheader(ngx_http_request_t *r, ngx_http_gzip_ctx_t *ctx)
-{
- ngx_buf_t *b;
- ngx_chain_t *cl;
- static u_char gzheader[10] =
- { 0x1f, 0x8b, Z_DEFLATED, 0, 0, 0, 0, 0, 0, 3 };
-
- b = ngx_calloc_buf(r->pool);
- if (b == NULL) {
- return NGX_ERROR;
- }
-
- b->memory = 1;
- b->pos = gzheader;
- b->last = b->pos + 10;
-
- cl = ngx_alloc_chain_link(r->pool);
- if (cl == NULL) {
- return NGX_ERROR;
- }
-
- cl->buf = b;
- cl->next = ctx->out;
- ctx->out = cl;
-
- ctx->gzheader = 1;
-
- return NGX_OK;
-}
-
-
-static ngx_int_t
-ngx_http_gzip_filter_add_data(ngx_http_request_t *r, ngx_http_gzip_ctx_t *ctx)
-{
- ngx_chain_t *cl;
-
- if (ctx->zstream.avail_in || ctx->flush != Z_NO_FLUSH || ctx->redo) {
- return NGX_OK;
- }
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "gzip in: %p", ctx->in);
-
- if (ctx->in == NULL) {
- return NGX_DECLINED;
- }
-
- if (ctx->copy_buf) {
-
- /*
- * to avoid CPU cache trashing we do not free() just quit buf,
- * but postpone free()ing after zlib compressing and data output
- */
-
- ctx->copy_buf->next = ctx->copied;
- ctx->copied = ctx->copy_buf;
- ctx->copy_buf = NULL;
- }
-
- cl = ctx->in;
- ctx->in_buf = cl->buf;
- ctx->in = cl->next;
-
- if (ctx->in_buf->tag == (ngx_buf_tag_t) &ngx_http_gzip_filter_module) {
- ctx->copy_buf = cl;
-
- } else {
- ngx_free_chain(r->pool, cl);
- }
-
- ctx->zstream.next_in = ctx->in_buf->pos;
- ctx->zstream.avail_in = ctx->in_buf->last - ctx->in_buf->pos;
-
- ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "gzip in_buf:%p ni:%p ai:%ud",
- ctx->in_buf,
- ctx->zstream.next_in, ctx->zstream.avail_in);
-
- if (ctx->in_buf->last_buf) {
- ctx->flush = Z_FINISH;
-
- } else if (ctx->in_buf->flush) {
- ctx->flush = Z_SYNC_FLUSH;
- }
-
- if (ctx->zstream.avail_in) {
-
- ctx->crc32 = crc32(ctx->crc32, ctx->zstream.next_in,
- ctx->zstream.avail_in);
-
- } else if (ctx->flush == Z_NO_FLUSH) {
- return NGX_AGAIN;
- }
-
- return NGX_OK;
-}
-
-
-static ngx_int_t
-ngx_http_gzip_filter_get_buf(ngx_http_request_t *r, ngx_http_gzip_ctx_t *ctx)
-{
- ngx_chain_t *cl;
- ngx_http_gzip_conf_t *conf;
-
- if (ctx->zstream.avail_out) {
- return NGX_OK;
- }
-
- conf = ngx_http_get_module_loc_conf(r, ngx_http_gzip_filter_module);
-
- if (ctx->free) {
-
- cl = ctx->free;
- ctx->out_buf = cl->buf;
- ctx->free = cl->next;
-
- ngx_free_chain(r->pool, cl);
-
- } else if (ctx->bufs < conf->bufs.num) {
-
- ctx->out_buf = ngx_create_temp_buf(r->pool, conf->bufs.size);
- if (ctx->out_buf == NULL) {
- return NGX_ERROR;
- }
-
- ctx->out_buf->tag = (ngx_buf_tag_t) &ngx_http_gzip_filter_module;
- ctx->out_buf->recycled = 1;
- ctx->bufs++;
-
- } else {
- ctx->nomem = 1;
- return NGX_DECLINED;
- }
-
- ctx->zstream.next_out = ctx->out_buf->pos;
- ctx->zstream.avail_out = conf->bufs.size;
-
- return NGX_OK;
-}
-
-
-static ngx_int_t
-ngx_http_gzip_filter_deflate(ngx_http_request_t *r, ngx_http_gzip_ctx_t *ctx)
-{
- int rc;
- ngx_buf_t *b;
- ngx_chain_t *cl;
- ngx_http_gzip_conf_t *conf;
-
- ngx_log_debug6(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "deflate in: ni:%p no:%p ai:%ud ao:%ud fl:%d redo:%d",
- ctx->zstream.next_in, ctx->zstream.next_out,
- ctx->zstream.avail_in, ctx->zstream.avail_out,
- ctx->flush, ctx->redo);
-
- rc = deflate(&ctx->zstream, ctx->flush);
-
- if (rc != Z_OK && rc != Z_STREAM_END && rc != Z_BUF_ERROR) {
- ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
- "deflate() failed: %d, %d", ctx->flush, rc);
- return NGX_ERROR;
- }
-
- ngx_log_debug5(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "deflate out: ni:%p no:%p ai:%ud ao:%ud rc:%d",
- ctx->zstream.next_in, ctx->zstream.next_out,
- ctx->zstream.avail_in, ctx->zstream.avail_out,
- rc);
-
- ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "gzip in_buf:%p pos:%p",
- ctx->in_buf, ctx->in_buf->pos);
-
- if (ctx->zstream.next_in) {
- ctx->in_buf->pos = ctx->zstream.next_in;
-
- if (ctx->zstream.avail_in == 0) {
- ctx->zstream.next_in = NULL;
- }
- }
-
- ctx->out_buf->last = ctx->zstream.next_out;
-
- if (ctx->zstream.avail_out == 0) {
-
- /* zlib wants to output some more gzipped data */
-
- cl = ngx_alloc_chain_link(r->pool);
- if (cl == NULL) {
- return NGX_ERROR;
- }
-
- cl->buf = ctx->out_buf;
- cl->next = NULL;
- *ctx->last_out = cl;
- ctx->last_out = &cl->next;
-
- ctx->redo = 1;
-
- return NGX_AGAIN;
- }
-
- ctx->redo = 0;
-
- if (ctx->flush == Z_SYNC_FLUSH) {
-
- ctx->flush = Z_NO_FLUSH;
-
- cl = ngx_alloc_chain_link(r->pool);
- if (cl == NULL) {
- return NGX_ERROR;
- }
-
- b = ctx->out_buf;
-
- if (ngx_buf_size(b) == 0) {
-
- b = ngx_calloc_buf(ctx->request->pool);
- if (b == NULL) {
- return NGX_ERROR;
- }
-
- } else {
- ctx->zstream.avail_out = 0;
- }
-
- b->flush = 1;
-
- cl->buf = b;
- cl->next = NULL;
- *ctx->last_out = cl;
- ctx->last_out = &cl->next;
-
- r->connection->buffered &= ~NGX_HTTP_GZIP_BUFFERED;
-
- return NGX_OK;
- }
-
- if (rc == Z_STREAM_END) {
-
- if (ngx_http_gzip_filter_deflate_end(r, ctx) != NGX_OK) {
- return NGX_ERROR;
- }
-
- return NGX_OK;
- }
-
- conf = ngx_http_get_module_loc_conf(r, ngx_http_gzip_filter_module);
-
- if (conf->no_buffer && ctx->in == NULL) {
-
- cl = ngx_alloc_chain_link(r->pool);
- if (cl == NULL) {
- return NGX_ERROR;
- }
-
- cl->buf = ctx->out_buf;
- cl->next = NULL;
- *ctx->last_out = cl;
- ctx->last_out = &cl->next;
-
- return NGX_OK;
- }
-
- return NGX_AGAIN;
-}
-
-
-static ngx_int_t
-ngx_http_gzip_filter_deflate_end(ngx_http_request_t *r,
- ngx_http_gzip_ctx_t *ctx)
-{
- int rc;
- ngx_buf_t *b;
- ngx_chain_t *cl;
- struct gztrailer *trailer;
-
- ctx->zin = ctx->zstream.total_in;
- ctx->zout = 10 + ctx->zstream.total_out + 8;
-
- rc = deflateEnd(&ctx->zstream);
-
- if (rc != Z_OK) {
- ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
- "deflateEnd() failed: %d", rc);
- return NGX_ERROR;
- }
-
- ngx_pfree(r->pool, ctx->preallocated);
-
- cl = ngx_alloc_chain_link(r->pool);
- if (cl == NULL) {
- return NGX_ERROR;
- }
-
- cl->buf = ctx->out_buf;
- cl->next = NULL;
- *ctx->last_out = cl;
- ctx->last_out = &cl->next;
-
- if (ctx->zstream.avail_out >= 8) {
- trailer = (struct gztrailer *) ctx->out_buf->last;
- ctx->out_buf->last += 8;
- ctx->out_buf->last_buf = 1;
-
- } else {
- b = ngx_create_temp_buf(r->pool, 8);
- if (b == NULL) {
- return NGX_ERROR;
- }
-
- b->last_buf = 1;
-
- cl = ngx_alloc_chain_link(r->pool);
- if (cl == NULL) {
- return NGX_ERROR;
- }
-
- cl->buf = b;
- cl->next = NULL;
- *ctx->last_out = cl;
- ctx->last_out = &cl->next;
- trailer = (struct gztrailer *) b->pos;
- b->last += 8;
- }
-
-#if (NGX_HAVE_LITTLE_ENDIAN && NGX_HAVE_NONALIGNED)
-
- trailer->crc32 = ctx->crc32;
- trailer->zlen = ctx->zin;
-
-#else
-
- trailer->crc32[0] = (u_char) (ctx->crc32 & 0xff);
- trailer->crc32[1] = (u_char) ((ctx->crc32 >> 8) & 0xff);
- trailer->crc32[2] = (u_char) ((ctx->crc32 >> 16) & 0xff);
- trailer->crc32[3] = (u_char) ((ctx->crc32 >> 24) & 0xff);
-
- trailer->zlen[0] = (u_char) (ctx->zin & 0xff);
- trailer->zlen[1] = (u_char) ((ctx->zin >> 8) & 0xff);
- trailer->zlen[2] = (u_char) ((ctx->zin >> 16) & 0xff);
- trailer->zlen[3] = (u_char) ((ctx->zin >> 24) & 0xff);
-
-#endif
-
- ctx->zstream.avail_in = 0;
- ctx->zstream.avail_out = 0;
-
- ctx->done = 1;
-
- r->connection->buffered &= ~NGX_HTTP_GZIP_BUFFERED;
-
- return NGX_OK;
-}
-
-
-static void *
-ngx_http_gzip_filter_alloc(void *opaque, u_int items, u_int size)
-{
- ngx_http_gzip_ctx_t *ctx = opaque;
-
- void *p;
- ngx_uint_t alloc;
-
- alloc = items * size;
-
- if (items == 1 && alloc % 512 != 0 && alloc < 8192) {
-
- /*
- * The zlib deflate_state allocation, it takes about 6K,
- * we allocate 8K. Other allocations are divisible by 512.
- */
-
- alloc = 8192;
- }
-
- if (alloc <= ctx->allocated) {
- p = ctx->free_mem;
- ctx->free_mem += alloc;
- ctx->allocated -= alloc;
-
- ngx_log_debug4(NGX_LOG_DEBUG_HTTP, ctx->request->connection->log, 0,
- "gzip alloc: n:%ud s:%ud a:%ui p:%p",
- items, size, alloc, p);
-
- return p;
- }
-
- if (ctx->intel) {
- ngx_log_error(NGX_LOG_ALERT, ctx->request->connection->log, 0,
- "gzip filter failed to use preallocated memory: "
- "%ud of %ui", items * size, ctx->allocated);
-
- } else {
- ngx_http_gzip_assume_intel = 1;
- }
-
- p = ngx_palloc(ctx->request->pool, items * size);
-
- return p;
-}
-
-
-static void
-ngx_http_gzip_filter_free(void *opaque, void *address)
-{
-#if 0
- ngx_http_gzip_ctx_t *ctx = opaque;
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, ctx->request->connection->log, 0,
- "gzip free: %p", address);
-#endif
-}
-
-
-static void
-ngx_http_gzip_filter_free_copy_buf(ngx_http_request_t *r,
- ngx_http_gzip_ctx_t *ctx)
-{
- ngx_chain_t *cl;
-
- for (cl = ctx->copied; cl; cl = cl->next) {
- ngx_pfree(r->pool, cl->buf->start);
- }
-
- ctx->copied = NULL;
-}
-
-
-static ngx_int_t
-ngx_http_gzip_add_variables(ngx_conf_t *cf)
-{
- ngx_http_variable_t *var;
-
- var = ngx_http_add_variable(cf, &ngx_http_gzip_ratio, NGX_HTTP_VAR_NOHASH);
- if (var == NULL) {
- return NGX_ERROR;
- }
-
- var->get_handler = ngx_http_gzip_ratio_variable;
-
- return NGX_OK;
-}
-
-
-static ngx_int_t
-ngx_http_gzip_ratio_variable(ngx_http_request_t *r,
- ngx_http_variable_value_t *v, uintptr_t data)
-{
- ngx_uint_t zint, zfrac;
- ngx_http_gzip_ctx_t *ctx;
-
- ctx = ngx_http_get_module_ctx(r, ngx_http_gzip_filter_module);
-
- if (ctx == NULL || ctx->zout == 0) {
- v->not_found = 1;
- return NGX_OK;
- }
-
- v->valid = 1;
- v->no_cacheable = 0;
- v->not_found = 0;
-
- v->data = ngx_pnalloc(r->pool, NGX_INT32_LEN + 3);
- if (v->data == NULL) {
- return NGX_ERROR;
- }
-
- zint = (ngx_uint_t) (ctx->zin / ctx->zout);
- zfrac = (ngx_uint_t) ((ctx->zin * 100 / ctx->zout) % 100);
-
- if ((ctx->zin * 1000 / ctx->zout) % 10 > 4) {
-
- /* the rounding, e.g., 2.125 to 2.13 */
-
- zfrac++;
-
- if (zfrac > 99) {
- zint++;
- zfrac = 0;
- }
- }
-
- v->len = ngx_sprintf(v->data, "%ui.%02ui", zint, zfrac) - v->data;
-
- return NGX_OK;
-}
-
-
-static void *
-ngx_http_gzip_create_conf(ngx_conf_t *cf)
-{
- ngx_http_gzip_conf_t *conf;
-
- conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_gzip_conf_t));
- if (conf == NULL) {
- return NULL;
- }
-
- /*
- * set by ngx_pcalloc():
- *
- * conf->bufs.num = 0;
- * conf->types = { NULL };
- * conf->types_keys = NULL;
- */
-
- conf->enable = NGX_CONF_UNSET;
- conf->no_buffer = NGX_CONF_UNSET;
-
- conf->postpone_gzipping = NGX_CONF_UNSET_SIZE;
- conf->level = NGX_CONF_UNSET;
- conf->wbits = NGX_CONF_UNSET_SIZE;
- conf->memlevel = NGX_CONF_UNSET_SIZE;
- conf->min_length = NGX_CONF_UNSET;
-
- return conf;
-}
-
-
-static char *
-ngx_http_gzip_merge_conf(ngx_conf_t *cf, void *parent, void *child)
-{
- ngx_http_gzip_conf_t *prev = parent;
- ngx_http_gzip_conf_t *conf = child;
-
- ngx_conf_merge_value(conf->enable, prev->enable, 0);
- ngx_conf_merge_value(conf->no_buffer, prev->no_buffer, 0);
-
- ngx_conf_merge_bufs_value(conf->bufs, prev->bufs,
- (128 * 1024) / ngx_pagesize, ngx_pagesize);
-
- ngx_conf_merge_size_value(conf->postpone_gzipping, prev->postpone_gzipping,
- 0);
- ngx_conf_merge_value(conf->level, prev->level, 1);
- ngx_conf_merge_size_value(conf->wbits, prev->wbits, MAX_WBITS);
- ngx_conf_merge_size_value(conf->memlevel, prev->memlevel,
- MAX_MEM_LEVEL - 1);
- ngx_conf_merge_value(conf->min_length, prev->min_length, 20);
-
- if (ngx_http_merge_types(cf, &conf->types_keys, &conf->types,
- &prev->types_keys, &prev->types,
- ngx_http_html_default_types)
- != NGX_OK)
- {
- return NGX_CONF_ERROR;
- }
-
- return NGX_CONF_OK;
-}
-
-
-static ngx_int_t
-ngx_http_gzip_filter_init(ngx_conf_t *cf)
-{
- ngx_http_next_header_filter = ngx_http_top_header_filter;
- ngx_http_top_header_filter = ngx_http_gzip_header_filter;
-
- ngx_http_next_body_filter = ngx_http_top_body_filter;
- ngx_http_top_body_filter = ngx_http_gzip_body_filter;
-
- return NGX_OK;
-}
-
-
-static char *
-ngx_http_gzip_window(ngx_conf_t *cf, void *post, void *data)
-{
- size_t *np = data;
-
- size_t wbits, wsize;
-
- wbits = 15;
-
- for (wsize = 32 * 1024; wsize > 256; wsize >>= 1) {
-
- if (wsize == *np) {
- *np = wbits;
-
- return NGX_CONF_OK;
- }
-
- wbits--;
- }
-
- return "must be 512, 1k, 2k, 4k, 8k, 16k, or 32k";
-}
-
-
-static char *
-ngx_http_gzip_hash(ngx_conf_t *cf, void *post, void *data)
-{
- size_t *np = data;
-
- size_t memlevel, hsize;
-
- memlevel = 9;
-
- for (hsize = 128 * 1024; hsize > 256; hsize >>= 1) {
-
- if (hsize == *np) {
- *np = memlevel;
-
- return NGX_CONF_OK;
- }
-
- memlevel--;
- }
-
- return "must be 512, 1k, 2k, 4k, 8k, 16k, 32k, 64k, or 128k";
-}
diff --git a/nginx/src/http/modules/ngx_http_gzip_static_module.c b/nginx/src/http/modules/ngx_http_gzip_static_module.c
deleted file mode 100644
index 7652a9a..0000000
--- a/nginx/src/http/modules/ngx_http_gzip_static_module.c
+++ /dev/null
@@ -1,331 +0,0 @@
-
-/*
- * Copyright (C) Igor Sysoev
- * Copyright (C) Nginx, Inc.
- */
-
-
-#include <ngx_config.h>
-#include <ngx_core.h>
-#include <ngx_http.h>
-
-
-#define NGX_HTTP_GZIP_STATIC_OFF 0
-#define NGX_HTTP_GZIP_STATIC_ON 1
-#define NGX_HTTP_GZIP_STATIC_ALWAYS 2
-
-
-typedef struct {
- ngx_uint_t enable;
-} ngx_http_gzip_static_conf_t;
-
-
-static ngx_int_t ngx_http_gzip_static_handler(ngx_http_request_t *r);
-static void *ngx_http_gzip_static_create_conf(ngx_conf_t *cf);
-static char *ngx_http_gzip_static_merge_conf(ngx_conf_t *cf, void *parent,
- void *child);
-static ngx_int_t ngx_http_gzip_static_init(ngx_conf_t *cf);
-
-
-static ngx_conf_enum_t ngx_http_gzip_static[] = {
- { ngx_string("off"), NGX_HTTP_GZIP_STATIC_OFF },
- { ngx_string("on"), NGX_HTTP_GZIP_STATIC_ON },
- { ngx_string("always"), NGX_HTTP_GZIP_STATIC_ALWAYS },
- { ngx_null_string, 0 }
-};
-
-
-static ngx_command_t ngx_http_gzip_static_commands[] = {
-
- { ngx_string("gzip_static"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_enum_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_gzip_static_conf_t, enable),
- &ngx_http_gzip_static },
-
- ngx_null_command
-};
-
-
-static ngx_http_module_t ngx_http_gzip_static_module_ctx = {
- NULL, /* preconfiguration */
- ngx_http_gzip_static_init, /* postconfiguration */
-
- NULL, /* create main configuration */
- NULL, /* init main configuration */
-
- NULL, /* create server configuration */
- NULL, /* merge server configuration */
-
- ngx_http_gzip_static_create_conf, /* create location configuration */
- ngx_http_gzip_static_merge_conf /* merge location configuration */
-};
-
-
-ngx_module_t ngx_http_gzip_static_module = {
- NGX_MODULE_V1,
- &ngx_http_gzip_static_module_ctx, /* module context */
- ngx_http_gzip_static_commands, /* module directives */
- NGX_HTTP_MODULE, /* module type */
- NULL, /* init master */
- NULL, /* init module */
- NULL, /* init process */
- NULL, /* init thread */
- NULL, /* exit thread */
- NULL, /* exit process */
- NULL, /* exit master */
- NGX_MODULE_V1_PADDING
-};
-
-
-static ngx_int_t
-ngx_http_gzip_static_handler(ngx_http_request_t *r)
-{
- u_char *p;
- size_t root;
- ngx_str_t path;
- ngx_int_t rc;
- ngx_uint_t level;
- ngx_log_t *log;
- ngx_buf_t *b;
- ngx_chain_t out;
- ngx_table_elt_t *h;
- ngx_open_file_info_t of;
- ngx_http_core_loc_conf_t *clcf;
- ngx_http_gzip_static_conf_t *gzcf;
-
- if (!(r->method & (NGX_HTTP_GET|NGX_HTTP_HEAD))) {
- return NGX_DECLINED;
- }
-
- if (r->uri.data[r->uri.len - 1] == '/') {
- return NGX_DECLINED;
- }
-
- gzcf = ngx_http_get_module_loc_conf(r, ngx_http_gzip_static_module);
-
- if (gzcf->enable == NGX_HTTP_GZIP_STATIC_OFF) {
- return NGX_DECLINED;
- }
-
- if (gzcf->enable == NGX_HTTP_GZIP_STATIC_ON) {
- rc = ngx_http_gzip_ok(r);
-
- } else {
- /* always */
- rc = NGX_OK;
- }
-
- clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
-
- if (!clcf->gzip_vary && rc != NGX_OK) {
- return NGX_DECLINED;
- }
-
- log = r->connection->log;
-
- p = ngx_http_map_uri_to_path(r, &path, &root, sizeof(".gz") - 1);
- if (p == NULL) {
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
-
- *p++ = '.';
- *p++ = 'g';
- *p++ = 'z';
- *p = '\0';
-
- path.len = p - path.data;
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0,
- "http filename: \"%s\"", path.data);
-
- ngx_memzero(&of, sizeof(ngx_open_file_info_t));
-
- of.read_ahead = clcf->read_ahead;
- of.directio = clcf->directio;
- of.valid = clcf->open_file_cache_valid;
- of.min_uses = clcf->open_file_cache_min_uses;
- of.errors = clcf->open_file_cache_errors;
- of.events = clcf->open_file_cache_events;
-
- if (ngx_http_set_disable_symlinks(r, clcf, &path, &of) != NGX_OK) {
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
-
- if (ngx_open_cached_file(clcf->open_file_cache, &path, &of, r->pool)
- != NGX_OK)
- {
- switch (of.err) {
-
- case 0:
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
-
- case NGX_ENOENT:
- case NGX_ENOTDIR:
- case NGX_ENAMETOOLONG:
-
- return NGX_DECLINED;
-
- case NGX_EACCES:
-#if (NGX_HAVE_OPENAT)
- case NGX_EMLINK:
- case NGX_ELOOP:
-#endif
-
- level = NGX_LOG_ERR;
- break;
-
- default:
-
- level = NGX_LOG_CRIT;
- break;
- }
-
- ngx_log_error(level, log, of.err,
- "%s \"%s\" failed", of.failed, path.data);
-
- return NGX_DECLINED;
- }
-
- if (gzcf->enable == NGX_HTTP_GZIP_STATIC_ON) {
- r->gzip_vary = 1;
-
- if (rc != NGX_OK) {
- return NGX_DECLINED;
- }
- }
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0, "http static fd: %d", of.fd);
-
- if (of.is_dir) {
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, log, 0, "http dir");
- return NGX_DECLINED;
- }
-
-#if !(NGX_WIN32) /* the not regular files are probably Unix specific */
-
- if (!of.is_file) {
- ngx_log_error(NGX_LOG_CRIT, log, 0,
- "\"%s\" is not a regular file", path.data);
-
- return NGX_HTTP_NOT_FOUND;
- }
-
-#endif
-
- r->root_tested = !r->error_page;
-
- rc = ngx_http_discard_request_body(r);
-
- if (rc != NGX_OK) {
- return rc;
- }
-
- log->action = "sending response to client";
-
- r->headers_out.status = NGX_HTTP_OK;
- r->headers_out.content_length_n = of.size;
- r->headers_out.last_modified_time = of.mtime;
-
- if (ngx_http_set_etag(r) != NGX_OK) {
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
-
- if (ngx_http_set_content_type(r) != NGX_OK) {
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
-
- h = ngx_list_push(&r->headers_out.headers);
- if (h == NULL) {
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
-
- h->hash = 1;
- ngx_str_set(&h->key, "Content-Encoding");
- ngx_str_set(&h->value, "gzip");
- r->headers_out.content_encoding = h;
-
- /* we need to allocate all before the header would be sent */
-
- b = ngx_calloc_buf(r->pool);
- if (b == NULL) {
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
-
- b->file = ngx_pcalloc(r->pool, sizeof(ngx_file_t));
- if (b->file == NULL) {
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
-
- rc = ngx_http_send_header(r);
-
- if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) {
- return rc;
- }
-
- b->file_pos = 0;
- b->file_last = of.size;
-
- b->in_file = b->file_last ? 1 : 0;
- b->last_buf = (r == r->main) ? 1 : 0;
- b->last_in_chain = 1;
-
- b->file->fd = of.fd;
- b->file->name = path;
- b->file->log = log;
- b->file->directio = of.is_directio;
-
- out.buf = b;
- out.next = NULL;
-
- return ngx_http_output_filter(r, &out);
-}
-
-
-static void *
-ngx_http_gzip_static_create_conf(ngx_conf_t *cf)
-{
- ngx_http_gzip_static_conf_t *conf;
-
- conf = ngx_palloc(cf->pool, sizeof(ngx_http_gzip_static_conf_t));
- if (conf == NULL) {
- return NULL;
- }
-
- conf->enable = NGX_CONF_UNSET_UINT;
-
- return conf;
-}
-
-
-static char *
-ngx_http_gzip_static_merge_conf(ngx_conf_t *cf, void *parent, void *child)
-{
- ngx_http_gzip_static_conf_t *prev = parent;
- ngx_http_gzip_static_conf_t *conf = child;
-
- ngx_conf_merge_uint_value(conf->enable, prev->enable,
- NGX_HTTP_GZIP_STATIC_OFF);
-
- return NGX_CONF_OK;
-}
-
-
-static ngx_int_t
-ngx_http_gzip_static_init(ngx_conf_t *cf)
-{
- ngx_http_handler_pt *h;
- ngx_http_core_main_conf_t *cmcf;
-
- cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);
-
- h = ngx_array_push(&cmcf->phases[NGX_HTTP_CONTENT_PHASE].handlers);
- if (h == NULL) {
- return NGX_ERROR;
- }
-
- *h = ngx_http_gzip_static_handler;
-
- return NGX_OK;
-}
diff --git a/nginx/src/http/modules/ngx_http_headers_filter_module.c b/nginx/src/http/modules/ngx_http_headers_filter_module.c
deleted file mode 100644
index a4c8cc2..0000000
--- a/nginx/src/http/modules/ngx_http_headers_filter_module.c
+++ /dev/null
@@ -1,867 +0,0 @@
-
-/*
- * Copyright (C) Igor Sysoev
- * Copyright (C) Nginx, Inc.
- */
-
-
-#include <ngx_config.h>
-#include <ngx_core.h>
-#include <ngx_http.h>
-
-
-typedef struct ngx_http_header_val_s ngx_http_header_val_t;
-
-typedef ngx_int_t (*ngx_http_set_header_pt)(ngx_http_request_t *r,
- ngx_http_header_val_t *hv, ngx_str_t *value);
-
-
-typedef struct {
- ngx_str_t name;
- ngx_uint_t offset;
- ngx_http_set_header_pt handler;
-} ngx_http_set_header_t;
-
-
-struct ngx_http_header_val_s {
- ngx_http_complex_value_t value;
- ngx_str_t key;
- ngx_http_set_header_pt handler;
- ngx_uint_t offset;
- ngx_uint_t always; /* unsigned always:1 */
-};
-
-
-typedef enum {
- NGX_HTTP_EXPIRES_OFF,
- NGX_HTTP_EXPIRES_EPOCH,
- NGX_HTTP_EXPIRES_MAX,
- NGX_HTTP_EXPIRES_ACCESS,
- NGX_HTTP_EXPIRES_MODIFIED,
- NGX_HTTP_EXPIRES_DAILY,
- NGX_HTTP_EXPIRES_UNSET
-} ngx_http_expires_t;
-
-
-typedef struct {
- ngx_http_expires_t expires;
- time_t expires_time;
- ngx_http_complex_value_t *expires_value;
- ngx_array_t *headers;
- ngx_array_t *trailers;
-} ngx_http_headers_conf_t;
-
-
-static ngx_int_t ngx_http_set_expires(ngx_http_request_t *r,
- ngx_http_headers_conf_t *conf);
-static ngx_int_t ngx_http_parse_expires(ngx_str_t *value,
- ngx_http_expires_t *expires, time_t *expires_time, char **err);
-static ngx_int_t ngx_http_add_multi_header_lines(ngx_http_request_t *r,
- ngx_http_header_val_t *hv, ngx_str_t *value);
-static ngx_int_t ngx_http_add_header(ngx_http_request_t *r,
- ngx_http_header_val_t *hv, ngx_str_t *value);
-static ngx_int_t ngx_http_set_last_modified(ngx_http_request_t *r,
- ngx_http_header_val_t *hv, ngx_str_t *value);
-static ngx_int_t ngx_http_set_response_header(ngx_http_request_t *r,
- ngx_http_header_val_t *hv, ngx_str_t *value);
-
-static void *ngx_http_headers_create_conf(ngx_conf_t *cf);
-static char *ngx_http_headers_merge_conf(ngx_conf_t *cf,
- void *parent, void *child);
-static ngx_int_t ngx_http_headers_filter_init(ngx_conf_t *cf);
-static char *ngx_http_headers_expires(ngx_conf_t *cf, ngx_command_t *cmd,
- void *conf);
-static char *ngx_http_headers_add(ngx_conf_t *cf, ngx_command_t *cmd,
- void *conf);
-
-
-static ngx_http_set_header_t ngx_http_set_headers[] = {
-
- { ngx_string("Cache-Control"),
- offsetof(ngx_http_headers_out_t, cache_control),
- ngx_http_add_multi_header_lines },
-
- { ngx_string("Link"),
- offsetof(ngx_http_headers_out_t, link),
- ngx_http_add_multi_header_lines },
-
- { ngx_string("Last-Modified"),
- offsetof(ngx_http_headers_out_t, last_modified),
- ngx_http_set_last_modified },
-
- { ngx_string("ETag"),
- offsetof(ngx_http_headers_out_t, etag),
- ngx_http_set_response_header },
-
- { ngx_null_string, 0, NULL }
-};
-
-
-static ngx_command_t ngx_http_headers_filter_commands[] = {
-
- { ngx_string("expires"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF
- |NGX_CONF_TAKE12,
- ngx_http_headers_expires,
- NGX_HTTP_LOC_CONF_OFFSET,
- 0,
- NULL },
-
- { ngx_string("add_header"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF
- |NGX_CONF_TAKE23,
- ngx_http_headers_add,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_headers_conf_t, headers),
- NULL },
-
- { ngx_string("add_trailer"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF
- |NGX_CONF_TAKE23,
- ngx_http_headers_add,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_headers_conf_t, trailers),
- NULL },
-
- ngx_null_command
-};
-
-
-static ngx_http_module_t ngx_http_headers_filter_module_ctx = {
- NULL, /* preconfiguration */
- ngx_http_headers_filter_init, /* postconfiguration */
-
- NULL, /* create main configuration */
- NULL, /* init main configuration */
-
- NULL, /* create server configuration */
- NULL, /* merge server configuration */
-
- ngx_http_headers_create_conf, /* create location configuration */
- ngx_http_headers_merge_conf /* merge location configuration */
-};
-
-
-ngx_module_t ngx_http_headers_filter_module = {
- NGX_MODULE_V1,
- &ngx_http_headers_filter_module_ctx, /* module context */
- ngx_http_headers_filter_commands, /* module directives */
- NGX_HTTP_MODULE, /* module type */
- NULL, /* init master */
- NULL, /* init module */
- NULL, /* init process */
- NULL, /* init thread */
- NULL, /* exit thread */
- NULL, /* exit process */
- NULL, /* exit master */
- NGX_MODULE_V1_PADDING
-};
-
-
-static ngx_http_output_header_filter_pt ngx_http_next_header_filter;
-static ngx_http_output_body_filter_pt ngx_http_next_body_filter;
-
-
-static ngx_int_t
-ngx_http_headers_filter(ngx_http_request_t *r)
-{
- ngx_str_t value;
- ngx_uint_t i, safe_status;
- ngx_http_header_val_t *h;
- ngx_http_headers_conf_t *conf;
-
- if (r != r->main) {
- return ngx_http_next_header_filter(r);
- }
-
- conf = ngx_http_get_module_loc_conf(r, ngx_http_headers_filter_module);
-
- if (conf->expires == NGX_HTTP_EXPIRES_OFF
- && conf->headers == NULL
- && conf->trailers == NULL)
- {
- return ngx_http_next_header_filter(r);
- }
-
- switch (r->headers_out.status) {
-
- case NGX_HTTP_OK:
- case NGX_HTTP_CREATED:
- case NGX_HTTP_NO_CONTENT:
- case NGX_HTTP_PARTIAL_CONTENT:
- case NGX_HTTP_MOVED_PERMANENTLY:
- case NGX_HTTP_MOVED_TEMPORARILY:
- case NGX_HTTP_SEE_OTHER:
- case NGX_HTTP_NOT_MODIFIED:
- case NGX_HTTP_TEMPORARY_REDIRECT:
- case NGX_HTTP_PERMANENT_REDIRECT:
- safe_status = 1;
- break;
-
- default:
- safe_status = 0;
- break;
- }
-
- if (conf->expires != NGX_HTTP_EXPIRES_OFF && safe_status) {
- if (ngx_http_set_expires(r, conf) != NGX_OK) {
- return NGX_ERROR;
- }
- }
-
- if (conf->headers) {
- h = conf->headers->elts;
- for (i = 0; i < conf->headers->nelts; i++) {
-
- if (!safe_status && !h[i].always) {
- continue;
- }
-
- if (ngx_http_complex_value(r, &h[i].value, &value) != NGX_OK) {
- return NGX_ERROR;
- }
-
- if (h[i].handler(r, &h[i], &value) != NGX_OK) {
- return NGX_ERROR;
- }
- }
- }
-
- if (conf->trailers) {
- h = conf->trailers->elts;
- for (i = 0; i < conf->trailers->nelts; i++) {
-
- if (!safe_status && !h[i].always) {
- continue;
- }
-
- r->expect_trailers = 1;
- break;
- }
- }
-
- return ngx_http_next_header_filter(r);
-}
-
-
-static ngx_int_t
-ngx_http_trailers_filter(ngx_http_request_t *r, ngx_chain_t *in)
-{
- ngx_str_t value;
- ngx_uint_t i, safe_status;
- ngx_chain_t *cl;
- ngx_table_elt_t *t;
- ngx_http_header_val_t *h;
- ngx_http_headers_conf_t *conf;
-
- conf = ngx_http_get_module_loc_conf(r, ngx_http_headers_filter_module);
-
- if (in == NULL
- || conf->trailers == NULL
- || !r->expect_trailers
- || r->header_only)
- {
- return ngx_http_next_body_filter(r, in);
- }
-
- for (cl = in; cl; cl = cl->next) {
- if (cl->buf->last_buf) {
- break;
- }
- }
-
- if (cl == NULL) {
- return ngx_http_next_body_filter(r, in);
- }
-
- switch (r->headers_out.status) {
-
- case NGX_HTTP_OK:
- case NGX_HTTP_CREATED:
- case NGX_HTTP_NO_CONTENT:
- case NGX_HTTP_PARTIAL_CONTENT:
- case NGX_HTTP_MOVED_PERMANENTLY:
- case NGX_HTTP_MOVED_TEMPORARILY:
- case NGX_HTTP_SEE_OTHER:
- case NGX_HTTP_NOT_MODIFIED:
- case NGX_HTTP_TEMPORARY_REDIRECT:
- case NGX_HTTP_PERMANENT_REDIRECT:
- safe_status = 1;
- break;
-
- default:
- safe_status = 0;
- break;
- }
-
- h = conf->trailers->elts;
- for (i = 0; i < conf->trailers->nelts; i++) {
-
- if (!safe_status && !h[i].always) {
- continue;
- }
-
- if (ngx_http_complex_value(r, &h[i].value, &value) != NGX_OK) {
- return NGX_ERROR;
- }
-
- if (value.len) {
- t = ngx_list_push(&r->headers_out.trailers);
- if (t == NULL) {
- return NGX_ERROR;
- }
-
- t->key = h[i].key;
- t->value = value;
- t->hash = 1;
- }
- }
-
- return ngx_http_next_body_filter(r, in);
-}
-
-
-static ngx_int_t
-ngx_http_set_expires(ngx_http_request_t *r, ngx_http_headers_conf_t *conf)
-{
- char *err;
- size_t len;
- time_t now, expires_time, max_age;
- ngx_str_t value;
- ngx_int_t rc;
- ngx_uint_t i;
- ngx_table_elt_t *e, *cc, **ccp;
- ngx_http_expires_t expires;
-
- expires = conf->expires;
- expires_time = conf->expires_time;
-
- if (conf->expires_value != NULL) {
-
- if (ngx_http_complex_value(r, conf->expires_value, &value) != NGX_OK) {
- return NGX_ERROR;
- }
-
- rc = ngx_http_parse_expires(&value, &expires, &expires_time, &err);
-
- if (rc != NGX_OK) {
- return NGX_OK;
- }
-
- if (expires == NGX_HTTP_EXPIRES_OFF) {
- return NGX_OK;
- }
- }
-
- e = r->headers_out.expires;
-
- if (e == NULL) {
-
- e = ngx_list_push(&r->headers_out.headers);
- if (e == NULL) {
- return NGX_ERROR;
- }
-
- r->headers_out.expires = e;
-
- e->hash = 1;
- ngx_str_set(&e->key, "Expires");
- }
-
- len = sizeof("Mon, 28 Sep 1970 06:00:00 GMT");
- e->value.len = len - 1;
-
- ccp = r->headers_out.cache_control.elts;
-
- if (ccp == NULL) {
-
- if (ngx_array_init(&r->headers_out.cache_control, r->pool,
- 1, sizeof(ngx_table_elt_t *))
- != NGX_OK)
- {
- return NGX_ERROR;
- }
-
- cc = ngx_list_push(&r->headers_out.headers);
- if (cc == NULL) {
- return NGX_ERROR;
- }
-
- cc->hash = 1;
- ngx_str_set(&cc->key, "Cache-Control");
-
- ccp = ngx_array_push(&r->headers_out.cache_control);
- if (ccp == NULL) {
- return NGX_ERROR;
- }
-
- *ccp = cc;
-
- } else {
- for (i = 1; i < r->headers_out.cache_control.nelts; i++) {
- ccp[i]->hash = 0;
- }
-
- cc = ccp[0];
- }
-
- if (expires == NGX_HTTP_EXPIRES_EPOCH) {
- e->value.data = (u_char *) "Thu, 01 Jan 1970 00:00:01 GMT";
- ngx_str_set(&cc->value, "no-cache");
- return NGX_OK;
- }
-
- if (expires == NGX_HTTP_EXPIRES_MAX) {
- e->value.data = (u_char *) "Thu, 31 Dec 2037 23:55:55 GMT";
- /* 10 years */
- ngx_str_set(&cc->value, "max-age=315360000");
- return NGX_OK;
- }
-
- e->value.data = ngx_pnalloc(r->pool, len);
- if (e->value.data == NULL) {
- return NGX_ERROR;
- }
-
- if (expires_time == 0 && expires != NGX_HTTP_EXPIRES_DAILY) {
- ngx_memcpy(e->value.data, ngx_cached_http_time.data,
- ngx_cached_http_time.len + 1);
- ngx_str_set(&cc->value, "max-age=0");
- return NGX_OK;
- }
-
- now = ngx_time();
-
- if (expires == NGX_HTTP_EXPIRES_DAILY) {
- expires_time = ngx_next_time(expires_time);
- max_age = expires_time - now;
-
- } else if (expires == NGX_HTTP_EXPIRES_ACCESS
- || r->headers_out.last_modified_time == -1)
- {
- max_age = expires_time;
- expires_time += now;
-
- } else {
- expires_time += r->headers_out.last_modified_time;
- max_age = expires_time - now;
- }
-
- ngx_http_time(e->value.data, expires_time);
-
- if (conf->expires_time < 0 || max_age < 0) {
- ngx_str_set(&cc->value, "no-cache");
- return NGX_OK;
- }
-
- cc->value.data = ngx_pnalloc(r->pool,
- sizeof("max-age=") + NGX_TIME_T_LEN + 1);
- if (cc->value.data == NULL) {
- return NGX_ERROR;
- }
-
- cc->value.len = ngx_sprintf(cc->value.data, "max-age=%T", max_age)
- - cc->value.data;
-
- return NGX_OK;
-}
-
-
-static ngx_int_t
-ngx_http_parse_expires(ngx_str_t *value, ngx_http_expires_t *expires,
- time_t *expires_time, char **err)
-{
- ngx_uint_t minus;
-
- if (*expires != NGX_HTTP_EXPIRES_MODIFIED) {
-
- if (value->len == 5 && ngx_strncmp(value->data, "epoch", 5) == 0) {
- *expires = NGX_HTTP_EXPIRES_EPOCH;
- return NGX_OK;
- }
-
- if (value->len == 3 && ngx_strncmp(value->data, "max", 3) == 0) {
- *expires = NGX_HTTP_EXPIRES_MAX;
- return NGX_OK;
- }
-
- if (value->len == 3 && ngx_strncmp(value->data, "off", 3) == 0) {
- *expires = NGX_HTTP_EXPIRES_OFF;
- return NGX_OK;
- }
- }
-
- if (value->len && value->data[0] == '@') {
- value->data++;
- value->len--;
- minus = 0;
-
- if (*expires == NGX_HTTP_EXPIRES_MODIFIED) {
- *err = "daily time cannot be used with \"modified\" parameter";
- return NGX_ERROR;
- }
-
- *expires = NGX_HTTP_EXPIRES_DAILY;
-
- } else if (value->len && value->data[0] == '+') {
- value->data++;
- value->len--;
- minus = 0;
-
- } else if (value->len && value->data[0] == '-') {
- value->data++;
- value->len--;
- minus = 1;
-
- } else {
- minus = 0;
- }
-
- *expires_time = ngx_parse_time(value, 1);
-
- if (*expires_time == (time_t) NGX_ERROR) {
- *err = "invalid value";
- return NGX_ERROR;
- }
-
- if (*expires == NGX_HTTP_EXPIRES_DAILY
- && *expires_time > 24 * 60 * 60)
- {
- *err = "daily time value must be less than 24 hours";
- return NGX_ERROR;
- }
-
- if (minus) {
- *expires_time = - *expires_time;
- }
-
- return NGX_OK;
-}
-
-
-static ngx_int_t
-ngx_http_add_header(ngx_http_request_t *r, ngx_http_header_val_t *hv,
- ngx_str_t *value)
-{
- ngx_table_elt_t *h;
-
- if (value->len) {
- h = ngx_list_push(&r->headers_out.headers);
- if (h == NULL) {
- return NGX_ERROR;
- }
-
- h->hash = 1;
- h->key = hv->key;
- h->value = *value;
- }
-
- return NGX_OK;
-}
-
-
-static ngx_int_t
-ngx_http_add_multi_header_lines(ngx_http_request_t *r,
- ngx_http_header_val_t *hv, ngx_str_t *value)
-{
- ngx_array_t *pa;
- ngx_table_elt_t *h, **ph;
-
- if (value->len == 0) {
- return NGX_OK;
- }
-
- pa = (ngx_array_t *) ((char *) &r->headers_out + hv->offset);
-
- if (pa->elts == NULL) {
- if (ngx_array_init(pa, r->pool, 1, sizeof(ngx_table_elt_t *)) != NGX_OK)
- {
- return NGX_ERROR;
- }
- }
-
- h = ngx_list_push(&r->headers_out.headers);
- if (h == NULL) {
- return NGX_ERROR;
- }
-
- h->hash = 1;
- h->key = hv->key;
- h->value = *value;
-
- ph = ngx_array_push(pa);
- if (ph == NULL) {
- return NGX_ERROR;
- }
-
- *ph = h;
-
- return NGX_OK;
-}
-
-
-static ngx_int_t
-ngx_http_set_last_modified(ngx_http_request_t *r, ngx_http_header_val_t *hv,
- ngx_str_t *value)
-{
- if (ngx_http_set_response_header(r, hv, value) != NGX_OK) {
- return NGX_ERROR;
- }
-
- r->headers_out.last_modified_time =
- (value->len) ? ngx_parse_http_time(value->data, value->len) : -1;
-
- return NGX_OK;
-}
-
-
-static ngx_int_t
-ngx_http_set_response_header(ngx_http_request_t *r, ngx_http_header_val_t *hv,
- ngx_str_t *value)
-{
- ngx_table_elt_t *h, **old;
-
- old = (ngx_table_elt_t **) ((char *) &r->headers_out + hv->offset);
-
- if (value->len == 0) {
- if (*old) {
- (*old)->hash = 0;
- *old = NULL;
- }
-
- return NGX_OK;
- }
-
- if (*old) {
- h = *old;
-
- } else {
- h = ngx_list_push(&r->headers_out.headers);
- if (h == NULL) {
- return NGX_ERROR;
- }
-
- *old = h;
- }
-
- h->hash = 1;
- h->key = hv->key;
- h->value = *value;
-
- return NGX_OK;
-}
-
-
-static void *
-ngx_http_headers_create_conf(ngx_conf_t *cf)
-{
- ngx_http_headers_conf_t *conf;
-
- conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_headers_conf_t));
- if (conf == NULL) {
- return NULL;
- }
-
- /*
- * set by ngx_pcalloc():
- *
- * conf->headers = NULL;
- * conf->trailers = NULL;
- * conf->expires_time = 0;
- * conf->expires_value = NULL;
- */
-
- conf->expires = NGX_HTTP_EXPIRES_UNSET;
-
- return conf;
-}
-
-
-static char *
-ngx_http_headers_merge_conf(ngx_conf_t *cf, void *parent, void *child)
-{
- ngx_http_headers_conf_t *prev = parent;
- ngx_http_headers_conf_t *conf = child;
-
- if (conf->expires == NGX_HTTP_EXPIRES_UNSET) {
- conf->expires = prev->expires;
- conf->expires_time = prev->expires_time;
- conf->expires_value = prev->expires_value;
-
- if (conf->expires == NGX_HTTP_EXPIRES_UNSET) {
- conf->expires = NGX_HTTP_EXPIRES_OFF;
- }
- }
-
- if (conf->headers == NULL) {
- conf->headers = prev->headers;
- }
-
- if (conf->trailers == NULL) {
- conf->trailers = prev->trailers;
- }
-
- return NGX_CONF_OK;
-}
-
-
-static ngx_int_t
-ngx_http_headers_filter_init(ngx_conf_t *cf)
-{
- ngx_http_next_header_filter = ngx_http_top_header_filter;
- ngx_http_top_header_filter = ngx_http_headers_filter;
-
- ngx_http_next_body_filter = ngx_http_top_body_filter;
- ngx_http_top_body_filter = ngx_http_trailers_filter;
-
- return NGX_OK;
-}
-
-
-static char *
-ngx_http_headers_expires(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
-{
- ngx_http_headers_conf_t *hcf = conf;
-
- char *err;
- ngx_str_t *value;
- ngx_int_t rc;
- ngx_uint_t n;
- ngx_http_complex_value_t cv;
- ngx_http_compile_complex_value_t ccv;
-
- if (hcf->expires != NGX_HTTP_EXPIRES_UNSET) {
- return "is duplicate";
- }
-
- value = cf->args->elts;
-
- if (cf->args->nelts == 2) {
-
- hcf->expires = NGX_HTTP_EXPIRES_ACCESS;
-
- n = 1;
-
- } else { /* cf->args->nelts == 3 */
-
- if (ngx_strcmp(value[1].data, "modified") != 0) {
- return "invalid value";
- }
-
- hcf->expires = NGX_HTTP_EXPIRES_MODIFIED;
-
- n = 2;
- }
-
- ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));
-
- ccv.cf = cf;
- ccv.value = &value[n];
- ccv.complex_value = &cv;
-
- if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
- return NGX_CONF_ERROR;
- }
-
- if (cv.lengths != NULL) {
-
- hcf->expires_value = ngx_palloc(cf->pool,
- sizeof(ngx_http_complex_value_t));
- if (hcf->expires_value == NULL) {
- return NGX_CONF_ERROR;
- }
-
- *hcf->expires_value = cv;
-
- return NGX_CONF_OK;
- }
-
- rc = ngx_http_parse_expires(&value[n], &hcf->expires, &hcf->expires_time,
- &err);
- if (rc != NGX_OK) {
- return err;
- }
-
- return NGX_CONF_OK;
-}
-
-
-static char *
-ngx_http_headers_add(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
-{
- ngx_http_headers_conf_t *hcf = conf;
-
- ngx_str_t *value;
- ngx_uint_t i;
- ngx_array_t **headers;
- ngx_http_header_val_t *hv;
- ngx_http_set_header_t *set;
- ngx_http_compile_complex_value_t ccv;
-
- value = cf->args->elts;
-
- headers = (ngx_array_t **) ((char *) hcf + cmd->offset);
-
- if (*headers == NULL) {
- *headers = ngx_array_create(cf->pool, 1,
- sizeof(ngx_http_header_val_t));
- if (*headers == NULL) {
- return NGX_CONF_ERROR;
- }
- }
-
- hv = ngx_array_push(*headers);
- if (hv == NULL) {
- return NGX_CONF_ERROR;
- }
-
- hv->key = value[1];
- hv->handler = NULL;
- hv->offset = 0;
- hv->always = 0;
-
- if (headers == &hcf->headers) {
- hv->handler = ngx_http_add_header;
-
- set = ngx_http_set_headers;
- for (i = 0; set[i].name.len; i++) {
- if (ngx_strcasecmp(value[1].data, set[i].name.data) != 0) {
- continue;
- }
-
- hv->offset = set[i].offset;
- hv->handler = set[i].handler;
-
- break;
- }
- }
-
- if (value[2].len == 0) {
- ngx_memzero(&hv->value, sizeof(ngx_http_complex_value_t));
-
- } else {
- ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));
-
- ccv.cf = cf;
- ccv.value = &value[2];
- ccv.complex_value = &hv->value;
-
- if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
- return NGX_CONF_ERROR;
- }
- }
-
- if (cf->args->nelts == 3) {
- return NGX_CONF_OK;
- }
-
- if (ngx_strcmp(value[3].data, "always") != 0) {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "invalid parameter \"%V\"", &value[3]);
- return NGX_CONF_ERROR;
- }
-
- hv->always = 1;
-
- return NGX_CONF_OK;
-}
diff --git a/nginx/src/http/modules/ngx_http_image_filter_module.c b/nginx/src/http/modules/ngx_http_image_filter_module.c
deleted file mode 100644
index 6c03e8a..0000000
--- a/nginx/src/http/modules/ngx_http_image_filter_module.c
+++ /dev/null
@@ -1,1675 +0,0 @@
-
-/*
- * Copyright (C) Igor Sysoev
- * Copyright (C) Nginx, Inc.
- */
-
-
-#include <ngx_config.h>
-#include <ngx_core.h>
-#include <ngx_http.h>
-
-#include <gd.h>
-
-
-#define NGX_HTTP_IMAGE_OFF 0
-#define NGX_HTTP_IMAGE_TEST 1
-#define NGX_HTTP_IMAGE_SIZE 2
-#define NGX_HTTP_IMAGE_RESIZE 3
-#define NGX_HTTP_IMAGE_CROP 4
-#define NGX_HTTP_IMAGE_ROTATE 5
-
-
-#define NGX_HTTP_IMAGE_START 0
-#define NGX_HTTP_IMAGE_READ 1
-#define NGX_HTTP_IMAGE_PROCESS 2
-#define NGX_HTTP_IMAGE_PASS 3
-#define NGX_HTTP_IMAGE_DONE 4
-
-
-#define NGX_HTTP_IMAGE_NONE 0
-#define NGX_HTTP_IMAGE_JPEG 1
-#define NGX_HTTP_IMAGE_GIF 2
-#define NGX_HTTP_IMAGE_PNG 3
-#define NGX_HTTP_IMAGE_WEBP 4
-
-
-#define NGX_HTTP_IMAGE_BUFFERED 0x08
-
-
-typedef struct {
- ngx_uint_t filter;
- ngx_uint_t width;
- ngx_uint_t height;
- ngx_uint_t angle;
- ngx_uint_t jpeg_quality;
- ngx_uint_t webp_quality;
- ngx_uint_t sharpen;
-
- ngx_flag_t transparency;
- ngx_flag_t interlace;
-
- ngx_http_complex_value_t *wcv;
- ngx_http_complex_value_t *hcv;
- ngx_http_complex_value_t *acv;
- ngx_http_complex_value_t *jqcv;
- ngx_http_complex_value_t *wqcv;
- ngx_http_complex_value_t *shcv;
-
- size_t buffer_size;
-} ngx_http_image_filter_conf_t;
-
-
-typedef struct {
- u_char *image;
- u_char *last;
-
- size_t length;
-
- ngx_uint_t width;
- ngx_uint_t height;
- ngx_uint_t max_width;
- ngx_uint_t max_height;
- ngx_uint_t angle;
-
- ngx_uint_t phase;
- ngx_uint_t type;
- ngx_uint_t force;
-} ngx_http_image_filter_ctx_t;
-
-
-static ngx_int_t ngx_http_image_send(ngx_http_request_t *r,
- ngx_http_image_filter_ctx_t *ctx, ngx_chain_t *in);
-static ngx_uint_t ngx_http_image_test(ngx_http_request_t *r, ngx_chain_t *in);
-static ngx_int_t ngx_http_image_read(ngx_http_request_t *r, ngx_chain_t *in);
-static ngx_buf_t *ngx_http_image_process(ngx_http_request_t *r);
-static ngx_buf_t *ngx_http_image_json(ngx_http_request_t *r,
- ngx_http_image_filter_ctx_t *ctx);
-static ngx_buf_t *ngx_http_image_asis(ngx_http_request_t *r,
- ngx_http_image_filter_ctx_t *ctx);
-static void ngx_http_image_length(ngx_http_request_t *r, ngx_buf_t *b);
-static ngx_int_t ngx_http_image_size(ngx_http_request_t *r,
- ngx_http_image_filter_ctx_t *ctx);
-
-static ngx_buf_t *ngx_http_image_resize(ngx_http_request_t *r,
- ngx_http_image_filter_ctx_t *ctx);
-static gdImagePtr ngx_http_image_source(ngx_http_request_t *r,
- ngx_http_image_filter_ctx_t *ctx);
-static gdImagePtr ngx_http_image_new(ngx_http_request_t *r, int w, int h,
- int colors);
-static u_char *ngx_http_image_out(ngx_http_request_t *r, ngx_uint_t type,
- gdImagePtr img, int *size);
-static void ngx_http_image_cleanup(void *data);
-static ngx_uint_t ngx_http_image_filter_get_value(ngx_http_request_t *r,
- ngx_http_complex_value_t *cv, ngx_uint_t v);
-static ngx_uint_t ngx_http_image_filter_value(ngx_str_t *value);
-
-
-static void *ngx_http_image_filter_create_conf(ngx_conf_t *cf);
-static char *ngx_http_image_filter_merge_conf(ngx_conf_t *cf, void *parent,
- 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 char *ngx_http_image_filter_webp_quality(ngx_conf_t *cf,
- ngx_command_t *cmd, void *conf);
-static char *ngx_http_image_filter_sharpen(ngx_conf_t *cf, ngx_command_t *cmd,
- void *conf);
-static ngx_int_t ngx_http_image_filter_init(ngx_conf_t *cf);
-
-
-static ngx_command_t ngx_http_image_filter_commands[] = {
-
- { ngx_string("image_filter"),
- NGX_HTTP_LOC_CONF|NGX_CONF_TAKE123,
- ngx_http_image_filter,
- NGX_HTTP_LOC_CONF_OFFSET,
- 0,
- NULL },
-
- { ngx_string("image_filter_jpeg_quality"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_http_image_filter_jpeg_quality,
- NGX_HTTP_LOC_CONF_OFFSET,
- 0,
- NULL },
-
- { ngx_string("image_filter_webp_quality"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_http_image_filter_webp_quality,
- NGX_HTTP_LOC_CONF_OFFSET,
- 0,
- NULL },
-
- { ngx_string("image_filter_sharpen"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_http_image_filter_sharpen,
- NGX_HTTP_LOC_CONF_OFFSET,
- 0,
- NULL },
-
- { ngx_string("image_filter_transparency"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
- ngx_conf_set_flag_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_image_filter_conf_t, transparency),
- NULL },
-
- { ngx_string("image_filter_interlace"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
- ngx_conf_set_flag_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_image_filter_conf_t, interlace),
- NULL },
-
- { ngx_string("image_filter_buffer"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_size_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_image_filter_conf_t, buffer_size),
- NULL },
-
- ngx_null_command
-};
-
-
-static ngx_http_module_t ngx_http_image_filter_module_ctx = {
- NULL, /* preconfiguration */
- ngx_http_image_filter_init, /* postconfiguration */
-
- NULL, /* create main configuration */
- NULL, /* init main configuration */
-
- NULL, /* create server configuration */
- NULL, /* merge server configuration */
-
- ngx_http_image_filter_create_conf, /* create location configuration */
- ngx_http_image_filter_merge_conf /* merge location configuration */
-};
-
-
-ngx_module_t ngx_http_image_filter_module = {
- NGX_MODULE_V1,
- &ngx_http_image_filter_module_ctx, /* module context */
- ngx_http_image_filter_commands, /* module directives */
- NGX_HTTP_MODULE, /* module type */
- NULL, /* init master */
- NULL, /* init module */
- NULL, /* init process */
- NULL, /* init thread */
- NULL, /* exit thread */
- NULL, /* exit process */
- NULL, /* exit master */
- NGX_MODULE_V1_PADDING
-};
-
-
-static ngx_http_output_header_filter_pt ngx_http_next_header_filter;
-static ngx_http_output_body_filter_pt ngx_http_next_body_filter;
-
-
-static ngx_str_t ngx_http_image_types[] = {
- ngx_string("image/jpeg"),
- ngx_string("image/gif"),
- ngx_string("image/png"),
- ngx_string("image/webp")
-};
-
-
-static ngx_int_t
-ngx_http_image_header_filter(ngx_http_request_t *r)
-{
- off_t len;
- ngx_http_image_filter_ctx_t *ctx;
- ngx_http_image_filter_conf_t *conf;
-
- if (r->headers_out.status == NGX_HTTP_NOT_MODIFIED) {
- return ngx_http_next_header_filter(r);
- }
-
- ctx = ngx_http_get_module_ctx(r, ngx_http_image_filter_module);
-
- if (ctx) {
- ngx_http_set_ctx(r, NULL, ngx_http_image_filter_module);
- return ngx_http_next_header_filter(r);
- }
-
- conf = ngx_http_get_module_loc_conf(r, ngx_http_image_filter_module);
-
- if (conf->filter == NGX_HTTP_IMAGE_OFF) {
- return ngx_http_next_header_filter(r);
- }
-
- if (r->headers_out.content_type.len
- >= sizeof("multipart/x-mixed-replace") - 1
- && ngx_strncasecmp(r->headers_out.content_type.data,
- (u_char *) "multipart/x-mixed-replace",
- sizeof("multipart/x-mixed-replace") - 1)
- == 0)
- {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "image filter: multipart/x-mixed-replace response");
-
- return NGX_ERROR;
- }
-
- ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_image_filter_ctx_t));
- if (ctx == NULL) {
- return NGX_ERROR;
- }
-
- ngx_http_set_ctx(r, ctx, ngx_http_image_filter_module);
-
- len = r->headers_out.content_length_n;
-
- if (len != -1 && len > (off_t) conf->buffer_size) {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "image filter: too big response: %O", len);
-
- return NGX_HTTP_UNSUPPORTED_MEDIA_TYPE;
- }
-
- if (len == -1) {
- ctx->length = conf->buffer_size;
-
- } else {
- ctx->length = (size_t) len;
- }
-
- if (r->headers_out.refresh) {
- r->headers_out.refresh->hash = 0;
- }
-
- r->main_filter_need_in_memory = 1;
- r->allow_ranges = 0;
-
- return NGX_OK;
-}
-
-
-static ngx_int_t
-ngx_http_image_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
-{
- ngx_int_t rc;
- ngx_str_t *ct;
- ngx_chain_t out;
- ngx_http_image_filter_ctx_t *ctx;
- ngx_http_image_filter_conf_t *conf;
-
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "image filter");
-
- if (in == NULL) {
- return ngx_http_next_body_filter(r, in);
- }
-
- ctx = ngx_http_get_module_ctx(r, ngx_http_image_filter_module);
-
- if (ctx == NULL) {
- return ngx_http_next_body_filter(r, in);
- }
-
- switch (ctx->phase) {
-
- case NGX_HTTP_IMAGE_START:
-
- ctx->type = ngx_http_image_test(r, in);
-
- conf = ngx_http_get_module_loc_conf(r, ngx_http_image_filter_module);
-
- if (ctx->type == NGX_HTTP_IMAGE_NONE) {
-
- if (conf->filter == NGX_HTTP_IMAGE_SIZE) {
- out.buf = ngx_http_image_json(r, NULL);
-
- if (out.buf) {
- out.next = NULL;
- ctx->phase = NGX_HTTP_IMAGE_DONE;
-
- return ngx_http_image_send(r, ctx, &out);
- }
- }
-
- return ngx_http_filter_finalize_request(r,
- &ngx_http_image_filter_module,
- NGX_HTTP_UNSUPPORTED_MEDIA_TYPE);
- }
-
- /* override content type */
-
- ct = &ngx_http_image_types[ctx->type - 1];
- r->headers_out.content_type_len = ct->len;
- r->headers_out.content_type = *ct;
- r->headers_out.content_type_lowcase = NULL;
-
- if (conf->filter == NGX_HTTP_IMAGE_TEST) {
- ctx->phase = NGX_HTTP_IMAGE_PASS;
-
- return ngx_http_image_send(r, ctx, in);
- }
-
- ctx->phase = NGX_HTTP_IMAGE_READ;
-
- /* fall through */
-
- case NGX_HTTP_IMAGE_READ:
-
- rc = ngx_http_image_read(r, in);
-
- if (rc == NGX_AGAIN) {
- return NGX_OK;
- }
-
- if (rc == NGX_ERROR) {
- return ngx_http_filter_finalize_request(r,
- &ngx_http_image_filter_module,
- NGX_HTTP_UNSUPPORTED_MEDIA_TYPE);
- }
-
- /* fall through */
-
- case NGX_HTTP_IMAGE_PROCESS:
-
- out.buf = ngx_http_image_process(r);
-
- if (out.buf == NULL) {
- return ngx_http_filter_finalize_request(r,
- &ngx_http_image_filter_module,
- NGX_HTTP_UNSUPPORTED_MEDIA_TYPE);
- }
-
- out.next = NULL;
- ctx->phase = NGX_HTTP_IMAGE_PASS;
-
- return ngx_http_image_send(r, ctx, &out);
-
- case NGX_HTTP_IMAGE_PASS:
-
- return ngx_http_next_body_filter(r, in);
-
- default: /* NGX_HTTP_IMAGE_DONE */
-
- rc = ngx_http_next_body_filter(r, NULL);
-
- /* NGX_ERROR resets any pending data */
- return (rc == NGX_OK) ? NGX_ERROR : rc;
- }
-}
-
-
-static ngx_int_t
-ngx_http_image_send(ngx_http_request_t *r, ngx_http_image_filter_ctx_t *ctx,
- ngx_chain_t *in)
-{
- ngx_int_t rc;
-
- rc = ngx_http_next_header_filter(r);
-
- if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) {
- return NGX_ERROR;
- }
-
- rc = ngx_http_next_body_filter(r, in);
-
- if (ctx->phase == NGX_HTTP_IMAGE_DONE) {
- /* NGX_ERROR resets any pending data */
- return (rc == NGX_OK) ? NGX_ERROR : rc;
- }
-
- return rc;
-}
-
-
-static ngx_uint_t
-ngx_http_image_test(ngx_http_request_t *r, ngx_chain_t *in)
-{
- u_char *p;
-
- p = in->buf->pos;
-
- if (in->buf->last - p < 16) {
- return NGX_HTTP_IMAGE_NONE;
- }
-
- ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "image filter: \"%c%c\"", p[0], p[1]);
-
- if (p[0] == 0xff && p[1] == 0xd8) {
-
- /* JPEG */
-
- return NGX_HTTP_IMAGE_JPEG;
-
- } else if (p[0] == 'G' && p[1] == 'I' && p[2] == 'F' && p[3] == '8'
- && p[5] == 'a')
- {
- if (p[4] == '9' || p[4] == '7') {
- /* GIF */
- return NGX_HTTP_IMAGE_GIF;
- }
-
- } else if (p[0] == 0x89 && p[1] == 'P' && p[2] == 'N' && p[3] == 'G'
- && p[4] == 0x0d && p[5] == 0x0a && p[6] == 0x1a && p[7] == 0x0a)
- {
- /* PNG */
-
- return NGX_HTTP_IMAGE_PNG;
-
- } else if (p[0] == 'R' && p[1] == 'I' && p[2] == 'F' && p[3] == 'F'
- && p[8] == 'W' && p[9] == 'E' && p[10] == 'B' && p[11] == 'P')
- {
- /* WebP */
-
- return NGX_HTTP_IMAGE_WEBP;
- }
-
- return NGX_HTTP_IMAGE_NONE;
-}
-
-
-static ngx_int_t
-ngx_http_image_read(ngx_http_request_t *r, ngx_chain_t *in)
-{
- u_char *p;
- size_t size, rest;
- ngx_buf_t *b;
- ngx_chain_t *cl;
- ngx_http_image_filter_ctx_t *ctx;
-
- ctx = ngx_http_get_module_ctx(r, ngx_http_image_filter_module);
-
- if (ctx->image == NULL) {
- ctx->image = ngx_palloc(r->pool, ctx->length);
- if (ctx->image == NULL) {
- return NGX_ERROR;
- }
-
- ctx->last = ctx->image;
- }
-
- p = ctx->last;
-
- for (cl = in; cl; cl = cl->next) {
-
- b = cl->buf;
- size = b->last - b->pos;
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "image buf: %uz", size);
-
- rest = ctx->image + ctx->length - p;
-
- if (size > rest) {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "image filter: too big response");
- return NGX_ERROR;
- }
-
- p = ngx_cpymem(p, b->pos, size);
- b->pos += size;
-
- if (b->last_buf) {
- ctx->last = p;
- return NGX_OK;
- }
- }
-
- ctx->last = p;
- r->connection->buffered |= NGX_HTTP_IMAGE_BUFFERED;
-
- return NGX_AGAIN;
-}
-
-
-static ngx_buf_t *
-ngx_http_image_process(ngx_http_request_t *r)
-{
- ngx_int_t rc;
- ngx_http_image_filter_ctx_t *ctx;
- ngx_http_image_filter_conf_t *conf;
-
- r->connection->buffered &= ~NGX_HTTP_IMAGE_BUFFERED;
-
- ctx = ngx_http_get_module_ctx(r, ngx_http_image_filter_module);
-
- rc = ngx_http_image_size(r, ctx);
-
- conf = ngx_http_get_module_loc_conf(r, ngx_http_image_filter_module);
-
- if (conf->filter == NGX_HTTP_IMAGE_SIZE) {
- return ngx_http_image_json(r, rc == NGX_OK ? ctx : NULL);
- }
-
- ctx->angle = ngx_http_image_filter_get_value(r, conf->acv, conf->angle);
-
- if (conf->filter == NGX_HTTP_IMAGE_ROTATE) {
-
- if (ctx->angle != 90 && ctx->angle != 180 && ctx->angle != 270) {
- return NULL;
- }
-
- return ngx_http_image_resize(r, ctx);
- }
-
- ctx->max_width = ngx_http_image_filter_get_value(r, conf->wcv, conf->width);
- if (ctx->max_width == 0) {
- return NULL;
- }
-
- ctx->max_height = ngx_http_image_filter_get_value(r, conf->hcv,
- conf->height);
- if (ctx->max_height == 0) {
- return NULL;
- }
-
- if (rc == NGX_OK
- && ctx->width <= ctx->max_width
- && ctx->height <= ctx->max_height
- && ctx->angle == 0
- && !ctx->force)
- {
- return ngx_http_image_asis(r, ctx);
- }
-
- return ngx_http_image_resize(r, ctx);
-}
-
-
-static ngx_buf_t *
-ngx_http_image_json(ngx_http_request_t *r, ngx_http_image_filter_ctx_t *ctx)
-{
- size_t len;
- ngx_buf_t *b;
-
- b = ngx_calloc_buf(r->pool);
- if (b == NULL) {
- return NULL;
- }
-
- b->memory = 1;
- b->last_buf = 1;
-
- ngx_http_clean_header(r);
-
- r->headers_out.status = NGX_HTTP_OK;
- r->headers_out.content_type_len = sizeof("application/json") - 1;
- ngx_str_set(&r->headers_out.content_type, "application/json");
- r->headers_out.content_type_lowcase = NULL;
-
- if (ctx == NULL) {
- b->pos = (u_char *) "{}" CRLF;
- b->last = b->pos + sizeof("{}" CRLF) - 1;
-
- ngx_http_image_length(r, b);
-
- return b;
- }
-
- len = sizeof("{ \"img\" : "
- "{ \"width\": , \"height\": , \"type\": \"jpeg\" } }" CRLF) - 1
- + 2 * NGX_SIZE_T_LEN;
-
- b->pos = ngx_pnalloc(r->pool, len);
- if (b->pos == NULL) {
- return NULL;
- }
-
- b->last = ngx_sprintf(b->pos,
- "{ \"img\" : "
- "{ \"width\": %uz,"
- " \"height\": %uz,"
- " \"type\": \"%s\" } }" CRLF,
- ctx->width, ctx->height,
- ngx_http_image_types[ctx->type - 1].data + 6);
-
- ngx_http_image_length(r, b);
-
- return b;
-}
-
-
-static ngx_buf_t *
-ngx_http_image_asis(ngx_http_request_t *r, ngx_http_image_filter_ctx_t *ctx)
-{
- ngx_buf_t *b;
-
- b = ngx_calloc_buf(r->pool);
- if (b == NULL) {
- return NULL;
- }
-
- b->pos = ctx->image;
- b->last = ctx->last;
- b->memory = 1;
- b->last_buf = 1;
-
- ngx_http_image_length(r, b);
-
- return b;
-}
-
-
-static void
-ngx_http_image_length(ngx_http_request_t *r, ngx_buf_t *b)
-{
- r->headers_out.content_length_n = b->last - b->pos;
-
- if (r->headers_out.content_length) {
- r->headers_out.content_length->hash = 0;
- }
-
- r->headers_out.content_length = NULL;
-}
-
-
-static ngx_int_t
-ngx_http_image_size(ngx_http_request_t *r, ngx_http_image_filter_ctx_t *ctx)
-{
- u_char *p, *last;
- size_t len, app;
- ngx_uint_t width, height;
-
- p = ctx->image;
-
- switch (ctx->type) {
-
- case NGX_HTTP_IMAGE_JPEG:
-
- p += 2;
- last = ctx->image + ctx->length - 10;
- width = 0;
- height = 0;
- app = 0;
-
- while (p < last) {
-
- if (p[0] == 0xff && p[1] != 0xff) {
-
- ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "JPEG: %02xd %02xd", p[0], p[1]);
-
- p++;
-
- if ((*p == 0xc0 || *p == 0xc1 || *p == 0xc2 || *p == 0xc3
- || *p == 0xc9 || *p == 0xca || *p == 0xcb)
- && (width == 0 || height == 0))
- {
- width = p[6] * 256 + p[7];
- height = p[4] * 256 + p[5];
- }
-
- ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "JPEG: %02xd %02xd", p[1], p[2]);
-
- len = p[1] * 256 + p[2];
-
- if (*p >= 0xe1 && *p <= 0xef) {
- /* application data, e.g., EXIF, Adobe XMP, etc. */
- app += len;
- }
-
- p += len;
-
- continue;
- }
-
- p++;
- }
-
- if (width == 0 || height == 0) {
- return NGX_DECLINED;
- }
-
- if (ctx->length / 20 < app) {
- /* force conversion if application data consume more than 5% */
- ctx->force = 1;
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "app data size: %uz", app);
- }
-
- break;
-
- case NGX_HTTP_IMAGE_GIF:
-
- if (ctx->length < 10) {
- return NGX_DECLINED;
- }
-
- width = p[7] * 256 + p[6];
- height = p[9] * 256 + p[8];
-
- break;
-
- case NGX_HTTP_IMAGE_PNG:
-
- if (ctx->length < 24) {
- return NGX_DECLINED;
- }
-
- width = p[18] * 256 + p[19];
- height = p[22] * 256 + p[23];
-
- break;
-
- case NGX_HTTP_IMAGE_WEBP:
-
- if (ctx->length < 30) {
- return NGX_DECLINED;
- }
-
- if (p[12] != 'V' || p[13] != 'P' || p[14] != '8') {
- return NGX_DECLINED;
- }
-
- switch (p[15]) {
-
- case ' ':
- if (p[20] & 1) {
- /* not a key frame */
- return NGX_DECLINED;
- }
-
- if (p[23] != 0x9d || p[24] != 0x01 || p[25] != 0x2a) {
- /* invalid start code */
- return NGX_DECLINED;
- }
-
- width = (p[26] | p[27] << 8) & 0x3fff;
- height = (p[28] | p[29] << 8) & 0x3fff;
-
- break;
-
- case 'L':
- if (p[20] != 0x2f) {
- /* invalid signature */
- return NGX_DECLINED;
- }
-
- width = ((p[21] | p[22] << 8) & 0x3fff) + 1;
- height = ((p[22] >> 6 | p[23] << 2 | p[24] << 10) & 0x3fff) + 1;
-
- break;
-
- case 'X':
- width = (p[24] | p[25] << 8 | p[26] << 16) + 1;
- height = (p[27] | p[28] << 8 | p[29] << 16) + 1;
- break;
-
- default:
- return NGX_DECLINED;
- }
-
- break;
-
- default:
-
- return NGX_DECLINED;
- }
-
- ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "image size: %d x %d", (int) width, (int) height);
-
- ctx->width = width;
- ctx->height = height;
-
- return NGX_OK;
-}
-
-
-static ngx_buf_t *
-ngx_http_image_resize(ngx_http_request_t *r, ngx_http_image_filter_ctx_t *ctx)
-{
- int sx, sy, dx, dy, ox, oy, ax, ay, size,
- colors, palette, transparent, sharpen,
- red, green, blue, t;
- u_char *out;
- ngx_buf_t *b;
- ngx_uint_t resize;
- gdImagePtr src, dst;
- ngx_pool_cleanup_t *cln;
- ngx_http_image_filter_conf_t *conf;
-
- src = ngx_http_image_source(r, ctx);
-
- if (src == NULL) {
- return NULL;
- }
-
- sx = gdImageSX(src);
- sy = gdImageSY(src);
-
- conf = ngx_http_get_module_loc_conf(r, ngx_http_image_filter_module);
-
- if (!ctx->force
- && ctx->angle == 0
- && (ngx_uint_t) sx <= ctx->max_width
- && (ngx_uint_t) sy <= ctx->max_height)
- {
- gdImageDestroy(src);
- return ngx_http_image_asis(r, ctx);
- }
-
- colors = gdImageColorsTotal(src);
-
- if (colors && conf->transparency) {
- transparent = gdImageGetTransparent(src);
-
- if (transparent != -1) {
- palette = colors;
- red = gdImageRed(src, transparent);
- green = gdImageGreen(src, transparent);
- blue = gdImageBlue(src, transparent);
-
- goto transparent;
- }
- }
-
- palette = 0;
- transparent = -1;
- red = 0;
- green = 0;
- blue = 0;
-
-transparent:
-
- gdImageColorTransparent(src, -1);
-
- dx = sx;
- dy = sy;
-
- if (conf->filter == NGX_HTTP_IMAGE_RESIZE) {
-
- if ((ngx_uint_t) dx > ctx->max_width) {
- dy = dy * ctx->max_width / dx;
- dy = dy ? dy : 1;
- dx = ctx->max_width;
- }
-
- if ((ngx_uint_t) dy > ctx->max_height) {
- dx = dx * ctx->max_height / dy;
- dx = dx ? dx : 1;
- dy = ctx->max_height;
- }
-
- resize = 1;
-
- } else if (conf->filter == NGX_HTTP_IMAGE_ROTATE) {
-
- resize = 0;
-
- } else { /* NGX_HTTP_IMAGE_CROP */
-
- resize = 0;
-
- if ((double) dx / dy < (double) ctx->max_width / ctx->max_height) {
- if ((ngx_uint_t) dx > ctx->max_width) {
- dy = dy * ctx->max_width / dx;
- dy = dy ? dy : 1;
- dx = ctx->max_width;
- resize = 1;
- }
-
- } else {
- if ((ngx_uint_t) dy > ctx->max_height) {
- dx = dx * ctx->max_height / dy;
- dx = dx ? dx : 1;
- dy = ctx->max_height;
- resize = 1;
- }
- }
- }
-
- if (resize) {
- dst = ngx_http_image_new(r, dx, dy, palette);
- if (dst == NULL) {
- gdImageDestroy(src);
- return NULL;
- }
-
- if (colors == 0) {
- gdImageSaveAlpha(dst, 1);
- gdImageAlphaBlending(dst, 0);
- }
-
- gdImageCopyResampled(dst, src, 0, 0, 0, 0, dx, dy, sx, sy);
-
- if (colors) {
- gdImageTrueColorToPalette(dst, 1, 256);
- }
-
- gdImageDestroy(src);
-
- } else {
- dst = src;
- }
-
- if (ctx->angle) {
- src = dst;
-
- ax = (dx % 2 == 0) ? 1 : 0;
- ay = (dy % 2 == 0) ? 1 : 0;
-
- switch (ctx->angle) {
-
- case 90:
- case 270:
- dst = ngx_http_image_new(r, dy, dx, palette);
- if (dst == NULL) {
- gdImageDestroy(src);
- return NULL;
- }
- if (ctx->angle == 90) {
- ox = dy / 2 + ay;
- oy = dx / 2 - ax;
-
- } else {
- ox = dy / 2 - ay;
- oy = dx / 2 + ax;
- }
-
- gdImageCopyRotated(dst, src, ox, oy, 0, 0,
- dx + ax, dy + ay, ctx->angle);
- gdImageDestroy(src);
-
- t = dx;
- dx = dy;
- dy = t;
- break;
-
- case 180:
- dst = ngx_http_image_new(r, dx, dy, palette);
- if (dst == NULL) {
- gdImageDestroy(src);
- return NULL;
- }
- gdImageCopyRotated(dst, src, dx / 2 - ax, dy / 2 - ay, 0, 0,
- dx + ax, dy + ay, ctx->angle);
- gdImageDestroy(src);
- break;
- }
- }
-
- if (conf->filter == NGX_HTTP_IMAGE_CROP) {
-
- src = dst;
-
- if ((ngx_uint_t) dx > ctx->max_width) {
- ox = dx - ctx->max_width;
-
- } else {
- ox = 0;
- }
-
- if ((ngx_uint_t) dy > ctx->max_height) {
- oy = dy - ctx->max_height;
-
- } else {
- oy = 0;
- }
-
- if (ox || oy) {
-
- dst = ngx_http_image_new(r, dx - ox, dy - oy, colors);
-
- if (dst == NULL) {
- gdImageDestroy(src);
- return NULL;
- }
-
- ox /= 2;
- oy /= 2;
-
- ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "image crop: %d x %d @ %d x %d",
- dx, dy, ox, oy);
-
- if (colors == 0) {
- gdImageSaveAlpha(dst, 1);
- gdImageAlphaBlending(dst, 0);
- }
-
- gdImageCopy(dst, src, 0, 0, ox, oy, dx - ox, dy - oy);
-
- if (colors) {
- gdImageTrueColorToPalette(dst, 1, 256);
- }
-
- gdImageDestroy(src);
- }
- }
-
- if (transparent != -1 && colors) {
- gdImageColorTransparent(dst, gdImageColorExact(dst, red, green, blue));
- }
-
- sharpen = ngx_http_image_filter_get_value(r, conf->shcv, conf->sharpen);
- if (sharpen > 0) {
- gdImageSharpen(dst, sharpen);
- }
-
- gdImageInterlace(dst, (int) conf->interlace);
-
- out = ngx_http_image_out(r, ctx->type, dst, &size);
-
- ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "image: %d x %d %d", sx, sy, colors);
-
- gdImageDestroy(dst);
- ngx_pfree(r->pool, ctx->image);
-
- if (out == NULL) {
- return NULL;
- }
-
- cln = ngx_pool_cleanup_add(r->pool, 0);
- if (cln == NULL) {
- gdFree(out);
- return NULL;
- }
-
- b = ngx_calloc_buf(r->pool);
- if (b == NULL) {
- gdFree(out);
- return NULL;
- }
-
- cln->handler = ngx_http_image_cleanup;
- cln->data = out;
-
- b->pos = out;
- b->last = out + size;
- b->memory = 1;
- b->last_buf = 1;
-
- ngx_http_image_length(r, b);
- ngx_http_weak_etag(r);
-
- return b;
-}
-
-
-static gdImagePtr
-ngx_http_image_source(ngx_http_request_t *r, ngx_http_image_filter_ctx_t *ctx)
-{
- char *failed;
- gdImagePtr img;
-
- img = NULL;
-
- switch (ctx->type) {
-
- case NGX_HTTP_IMAGE_JPEG:
- img = gdImageCreateFromJpegPtr(ctx->length, ctx->image);
- failed = "gdImageCreateFromJpegPtr() failed";
- break;
-
- case NGX_HTTP_IMAGE_GIF:
- img = gdImageCreateFromGifPtr(ctx->length, ctx->image);
- failed = "gdImageCreateFromGifPtr() failed";
- break;
-
- case NGX_HTTP_IMAGE_PNG:
- img = gdImageCreateFromPngPtr(ctx->length, ctx->image);
- failed = "gdImageCreateFromPngPtr() failed";
- break;
-
- case NGX_HTTP_IMAGE_WEBP:
-#if (NGX_HAVE_GD_WEBP)
- img = gdImageCreateFromWebpPtr(ctx->length, ctx->image);
- failed = "gdImageCreateFromWebpPtr() failed";
-#else
- failed = "nginx was built without GD WebP support";
-#endif
- break;
-
- default:
- failed = "unknown image type";
- break;
- }
-
- if (img == NULL) {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, failed);
- }
-
- return img;
-}
-
-
-static gdImagePtr
-ngx_http_image_new(ngx_http_request_t *r, int w, int h, int colors)
-{
- gdImagePtr img;
-
- if (colors == 0) {
- img = gdImageCreateTrueColor(w, h);
-
- if (img == NULL) {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "gdImageCreateTrueColor() failed");
- return NULL;
- }
-
- } else {
- img = gdImageCreate(w, h);
-
- if (img == NULL) {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "gdImageCreate() failed");
- return NULL;
- }
- }
-
- return img;
-}
-
-
-static u_char *
-ngx_http_image_out(ngx_http_request_t *r, ngx_uint_t type, gdImagePtr img,
- int *size)
-{
- char *failed;
- u_char *out;
- ngx_int_t q;
- ngx_http_image_filter_conf_t *conf;
-
- out = NULL;
-
- switch (type) {
-
- case NGX_HTTP_IMAGE_JPEG:
- conf = ngx_http_get_module_loc_conf(r, ngx_http_image_filter_module);
-
- q = ngx_http_image_filter_get_value(r, conf->jqcv, conf->jpeg_quality);
- if (q <= 0) {
- return NULL;
- }
-
- out = gdImageJpegPtr(img, size, q);
- failed = "gdImageJpegPtr() failed";
- break;
-
- case NGX_HTTP_IMAGE_GIF:
- out = gdImageGifPtr(img, size);
- failed = "gdImageGifPtr() failed";
- break;
-
- case NGX_HTTP_IMAGE_PNG:
- out = gdImagePngPtr(img, size);
- failed = "gdImagePngPtr() failed";
- break;
-
- case NGX_HTTP_IMAGE_WEBP:
-#if (NGX_HAVE_GD_WEBP)
- conf = ngx_http_get_module_loc_conf(r, ngx_http_image_filter_module);
-
- q = ngx_http_image_filter_get_value(r, conf->wqcv, conf->webp_quality);
- if (q <= 0) {
- return NULL;
- }
-
- out = gdImageWebpPtrEx(img, size, q);
- failed = "gdImageWebpPtrEx() failed";
-#else
- failed = "nginx was built without GD WebP support";
-#endif
- break;
-
- default:
- failed = "unknown image type";
- break;
- }
-
- if (out == NULL) {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, failed);
- }
-
- return out;
-}
-
-
-static void
-ngx_http_image_cleanup(void *data)
-{
- gdFree(data);
-}
-
-
-static ngx_uint_t
-ngx_http_image_filter_get_value(ngx_http_request_t *r,
- ngx_http_complex_value_t *cv, ngx_uint_t v)
-{
- ngx_str_t val;
-
- if (cv == NULL) {
- return v;
- }
-
- if (ngx_http_complex_value(r, cv, &val) != NGX_OK) {
- return 0;
- }
-
- return ngx_http_image_filter_value(&val);
-}
-
-
-static ngx_uint_t
-ngx_http_image_filter_value(ngx_str_t *value)
-{
- ngx_int_t n;
-
- if (value->len == 1 && value->data[0] == '-') {
- return (ngx_uint_t) -1;
- }
-
- n = ngx_atoi(value->data, value->len);
-
- if (n > 0) {
- return (ngx_uint_t) n;
- }
-
- return 0;
-}
-
-
-static void *
-ngx_http_image_filter_create_conf(ngx_conf_t *cf)
-{
- ngx_http_image_filter_conf_t *conf;
-
- conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_image_filter_conf_t));
- if (conf == NULL) {
- return NULL;
- }
-
- /*
- * set by ngx_pcalloc():
- *
- * conf->width = 0;
- * conf->height = 0;
- * conf->angle = 0;
- * conf->wcv = NULL;
- * conf->hcv = NULL;
- * conf->acv = NULL;
- * conf->jqcv = NULL;
- * conf->wqcv = NULL;
- * conf->shcv = NULL;
- */
-
- conf->filter = NGX_CONF_UNSET_UINT;
- conf->jpeg_quality = NGX_CONF_UNSET_UINT;
- conf->webp_quality = NGX_CONF_UNSET_UINT;
- conf->sharpen = NGX_CONF_UNSET_UINT;
- conf->transparency = NGX_CONF_UNSET;
- conf->interlace = NGX_CONF_UNSET;
- conf->buffer_size = NGX_CONF_UNSET_SIZE;
-
- return conf;
-}
-
-
-static char *
-ngx_http_image_filter_merge_conf(ngx_conf_t *cf, void *parent, void *child)
-{
- ngx_http_image_filter_conf_t *prev = parent;
- ngx_http_image_filter_conf_t *conf = child;
-
- if (conf->filter == NGX_CONF_UNSET_UINT) {
-
- if (prev->filter == NGX_CONF_UNSET_UINT) {
- conf->filter = NGX_HTTP_IMAGE_OFF;
-
- } else {
- conf->filter = prev->filter;
- conf->width = prev->width;
- conf->height = prev->height;
- conf->angle = prev->angle;
- conf->wcv = prev->wcv;
- conf->hcv = prev->hcv;
- conf->acv = prev->acv;
- }
- }
-
- if (conf->jpeg_quality == NGX_CONF_UNSET_UINT) {
-
- /* 75 is libjpeg default quality */
- ngx_conf_merge_uint_value(conf->jpeg_quality, prev->jpeg_quality, 75);
-
- if (conf->jqcv == NULL) {
- conf->jqcv = prev->jqcv;
- }
- }
-
- if (conf->webp_quality == NGX_CONF_UNSET_UINT) {
-
- /* 80 is libwebp default quality */
- ngx_conf_merge_uint_value(conf->webp_quality, prev->webp_quality, 80);
-
- if (conf->wqcv == NULL) {
- conf->wqcv = prev->wqcv;
- }
- }
-
- if (conf->sharpen == NGX_CONF_UNSET_UINT) {
- ngx_conf_merge_uint_value(conf->sharpen, prev->sharpen, 0);
-
- if (conf->shcv == NULL) {
- conf->shcv = prev->shcv;
- }
- }
-
- ngx_conf_merge_value(conf->transparency, prev->transparency, 1);
-
- ngx_conf_merge_value(conf->interlace, prev->interlace, 0);
-
- ngx_conf_merge_size_value(conf->buffer_size, prev->buffer_size,
- 1 * 1024 * 1024);
-
- return NGX_CONF_OK;
-}
-
-
-static char *
-ngx_http_image_filter(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_uint_t i;
- ngx_http_complex_value_t cv;
- ngx_http_compile_complex_value_t ccv;
-
- value = cf->args->elts;
-
- i = 1;
-
- if (cf->args->nelts == 2) {
- if (ngx_strcmp(value[i].data, "off") == 0) {
- imcf->filter = NGX_HTTP_IMAGE_OFF;
-
- } else if (ngx_strcmp(value[i].data, "test") == 0) {
- imcf->filter = NGX_HTTP_IMAGE_TEST;
-
- } else if (ngx_strcmp(value[i].data, "size") == 0) {
- imcf->filter = NGX_HTTP_IMAGE_SIZE;
-
- } else {
- goto failed;
- }
-
- return NGX_CONF_OK;
-
- } else if (cf->args->nelts == 3) {
-
- if (ngx_strcmp(value[i].data, "rotate") == 0) {
- if (imcf->filter != NGX_HTTP_IMAGE_RESIZE
- && imcf->filter != NGX_HTTP_IMAGE_CROP)
- {
- imcf->filter = NGX_HTTP_IMAGE_ROTATE;
- }
-
- ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));
-
- ccv.cf = cf;
- ccv.value = &value[++i];
- 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[i]);
-
- if (n != 90 && n != 180 && n != 270) {
- goto failed;
- }
-
- imcf->angle = (ngx_uint_t) n;
-
- } else {
- imcf->acv = ngx_palloc(cf->pool,
- sizeof(ngx_http_complex_value_t));
- if (imcf->acv == NULL) {
- return NGX_CONF_ERROR;
- }
-
- *imcf->acv = cv;
- }
-
- return NGX_CONF_OK;
-
- } else {
- goto failed;
- }
- }
-
- if (ngx_strcmp(value[i].data, "resize") == 0) {
- imcf->filter = NGX_HTTP_IMAGE_RESIZE;
-
- } else if (ngx_strcmp(value[i].data, "crop") == 0) {
- imcf->filter = NGX_HTTP_IMAGE_CROP;
-
- } else {
- goto failed;
- }
-
- ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));
-
- ccv.cf = cf;
- ccv.value = &value[++i];
- 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[i]);
-
- if (n == 0) {
- goto failed;
- }
-
- imcf->width = (ngx_uint_t) n;
-
- } else {
- imcf->wcv = ngx_palloc(cf->pool, sizeof(ngx_http_complex_value_t));
- if (imcf->wcv == NULL) {
- return NGX_CONF_ERROR;
- }
-
- *imcf->wcv = cv;
- }
-
- ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));
-
- ccv.cf = cf;
- ccv.value = &value[++i];
- 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[i]);
-
- if (n == 0) {
- goto failed;
- }
-
- imcf->height = (ngx_uint_t) n;
-
- } else {
- imcf->hcv = ngx_palloc(cf->pool, sizeof(ngx_http_complex_value_t));
- if (imcf->hcv == NULL) {
- return NGX_CONF_ERROR;
- }
-
- *imcf->hcv = cv;
- }
-
- return NGX_CONF_OK;
-
-failed:
-
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid parameter \"%V\"",
- &value[i]);
-
- return NGX_CONF_ERROR;
-}
-
-
-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 value \"%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 char *
-ngx_http_image_filter_webp_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 value \"%V\"", &value[1]);
- return NGX_CONF_ERROR;
- }
-
- imcf->webp_quality = (ngx_uint_t) n;
-
- } else {
- imcf->wqcv = ngx_palloc(cf->pool, sizeof(ngx_http_complex_value_t));
- if (imcf->wqcv == NULL) {
- return NGX_CONF_ERROR;
- }
-
- *imcf->wqcv = cv;
- }
-
- return NGX_CONF_OK;
-}
-
-
-static char *
-ngx_http_image_filter_sharpen(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 value \"%V\"", &value[1]);
- return NGX_CONF_ERROR;
- }
-
- imcf->sharpen = (ngx_uint_t) n;
-
- } else {
- imcf->shcv = ngx_palloc(cf->pool, sizeof(ngx_http_complex_value_t));
- if (imcf->shcv == NULL) {
- return NGX_CONF_ERROR;
- }
-
- *imcf->shcv = cv;
- }
-
- return NGX_CONF_OK;
-}
-
-
-static ngx_int_t
-ngx_http_image_filter_init(ngx_conf_t *cf)
-{
- ngx_http_next_header_filter = ngx_http_top_header_filter;
- ngx_http_top_header_filter = ngx_http_image_header_filter;
-
- ngx_http_next_body_filter = ngx_http_top_body_filter;
- ngx_http_top_body_filter = ngx_http_image_body_filter;
-
- return NGX_OK;
-}
diff --git a/nginx/src/http/modules/ngx_http_index_module.c b/nginx/src/http/modules/ngx_http_index_module.c
deleted file mode 100644
index c144b31..0000000
--- a/nginx/src/http/modules/ngx_http_index_module.c
+++ /dev/null
@@ -1,540 +0,0 @@
-
-/*
- * Copyright (C) Igor Sysoev
- * Copyright (C) Nginx, Inc.
- */
-
-
-#include <ngx_config.h>
-#include <ngx_core.h>
-#include <ngx_http.h>
-
-
-typedef struct {
- ngx_str_t name;
- ngx_array_t *lengths;
- ngx_array_t *values;
-} ngx_http_index_t;
-
-
-typedef struct {
- ngx_array_t *indices; /* array of ngx_http_index_t */
- size_t max_index_len;
-} ngx_http_index_loc_conf_t;
-
-
-#define NGX_HTTP_DEFAULT_INDEX "index.html"
-
-
-static ngx_int_t ngx_http_index_test_dir(ngx_http_request_t *r,
- ngx_http_core_loc_conf_t *clcf, u_char *path, u_char *last);
-static ngx_int_t ngx_http_index_error(ngx_http_request_t *r,
- ngx_http_core_loc_conf_t *clcf, u_char *file, ngx_err_t err);
-
-static ngx_int_t ngx_http_index_init(ngx_conf_t *cf);
-static void *ngx_http_index_create_loc_conf(ngx_conf_t *cf);
-static char *ngx_http_index_merge_loc_conf(ngx_conf_t *cf,
- void *parent, void *child);
-static char *ngx_http_index_set_index(ngx_conf_t *cf, ngx_command_t *cmd,
- void *conf);
-
-
-static ngx_command_t ngx_http_index_commands[] = {
-
- { ngx_string("index"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
- ngx_http_index_set_index,
- NGX_HTTP_LOC_CONF_OFFSET,
- 0,
- NULL },
-
- ngx_null_command
-};
-
-
-static ngx_http_module_t ngx_http_index_module_ctx = {
- NULL, /* preconfiguration */
- ngx_http_index_init, /* postconfiguration */
-
- NULL, /* create main configuration */
- NULL, /* init main configuration */
-
- NULL, /* create server configuration */
- NULL, /* merge server configuration */
-
- ngx_http_index_create_loc_conf, /* create location configuration */
- ngx_http_index_merge_loc_conf /* merge location configuration */
-};
-
-
-ngx_module_t ngx_http_index_module = {
- NGX_MODULE_V1,
- &ngx_http_index_module_ctx, /* module context */
- ngx_http_index_commands, /* module directives */
- NGX_HTTP_MODULE, /* module type */
- NULL, /* init master */
- NULL, /* init module */
- NULL, /* init process */
- NULL, /* init thread */
- NULL, /* exit thread */
- NULL, /* exit process */
- NULL, /* exit master */
- NGX_MODULE_V1_PADDING
-};
-
-
-/*
- * Try to open/test the first index file before the test of directory
- * existence because valid requests should prevail over invalid ones.
- * If open()/stat() of a file will fail then stat() of a directory
- * should be faster because kernel may have already cached some data.
- * Besides, Win32 may return ERROR_PATH_NOT_FOUND (NGX_ENOTDIR) at once.
- * Unix has ENOTDIR error; however, it's less helpful than Win32's one:
- * it only indicates that path points to a regular file, not a directory.
- */
-
-static ngx_int_t
-ngx_http_index_handler(ngx_http_request_t *r)
-{
- u_char *p, *name;
- size_t len, root, reserve, allocated;
- ngx_int_t rc;
- ngx_str_t path, uri;
- ngx_uint_t i, dir_tested;
- ngx_http_index_t *index;
- ngx_open_file_info_t of;
- ngx_http_script_code_pt code;
- ngx_http_script_engine_t e;
- ngx_http_core_loc_conf_t *clcf;
- ngx_http_index_loc_conf_t *ilcf;
- ngx_http_script_len_code_pt lcode;
-
- if (r->uri.data[r->uri.len - 1] != '/') {
- return NGX_DECLINED;
- }
-
- if (!(r->method & (NGX_HTTP_GET|NGX_HTTP_HEAD|NGX_HTTP_POST))) {
- return NGX_DECLINED;
- }
-
- ilcf = ngx_http_get_module_loc_conf(r, ngx_http_index_module);
- clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
-
- allocated = 0;
- root = 0;
- dir_tested = 0;
- name = NULL;
- /* suppress MSVC warning */
- path.data = NULL;
-
- index = ilcf->indices->elts;
- for (i = 0; i < ilcf->indices->nelts; i++) {
-
- if (index[i].lengths == NULL) {
-
- if (index[i].name.data[0] == '/') {
- return ngx_http_internal_redirect(r, &index[i].name, &r->args);
- }
-
- reserve = ilcf->max_index_len;
- len = index[i].name.len;
-
- } else {
- ngx_memzero(&e, sizeof(ngx_http_script_engine_t));
-
- e.ip = index[i].lengths->elts;
- e.request = r;
- e.flushed = 1;
-
- /* 1 is for terminating '\0' as in static names */
- len = 1;
-
- while (*(uintptr_t *) e.ip) {
- lcode = *(ngx_http_script_len_code_pt *) e.ip;
- len += lcode(&e);
- }
-
- /* 16 bytes are preallocation */
-
- reserve = len + 16;
- }
-
- if (reserve > allocated) {
-
- name = ngx_http_map_uri_to_path(r, &path, &root, reserve);
- if (name == NULL) {
- return NGX_ERROR;
- }
-
- allocated = path.data + path.len - name;
- }
-
- if (index[i].values == NULL) {
-
- /* index[i].name.len includes the terminating '\0' */
-
- ngx_memcpy(name, index[i].name.data, index[i].name.len);
-
- path.len = (name + index[i].name.len - 1) - path.data;
-
- } else {
- e.ip = index[i].values->elts;
- e.pos = name;
-
- while (*(uintptr_t *) e.ip) {
- code = *(ngx_http_script_code_pt *) e.ip;
- code((ngx_http_script_engine_t *) &e);
- }
-
- if (*name == '/') {
- uri.len = len - 1;
- uri.data = name;
- return ngx_http_internal_redirect(r, &uri, &r->args);
- }
-
- path.len = e.pos - path.data;
-
- *e.pos = '\0';
- }
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "open index \"%V\"", &path);
-
- ngx_memzero(&of, sizeof(ngx_open_file_info_t));
-
- of.read_ahead = clcf->read_ahead;
- of.directio = clcf->directio;
- of.valid = clcf->open_file_cache_valid;
- of.min_uses = clcf->open_file_cache_min_uses;
- of.test_only = 1;
- of.errors = clcf->open_file_cache_errors;
- of.events = clcf->open_file_cache_events;
-
- if (ngx_http_set_disable_symlinks(r, clcf, &path, &of) != NGX_OK) {
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
-
- if (ngx_open_cached_file(clcf->open_file_cache, &path, &of, r->pool)
- != NGX_OK)
- {
- if (of.err == 0) {
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
-
- ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, of.err,
- "%s \"%s\" failed", of.failed, path.data);
-
-#if (NGX_HAVE_OPENAT)
- if (of.err == NGX_EMLINK
- || of.err == NGX_ELOOP)
- {
- return NGX_HTTP_FORBIDDEN;
- }
-#endif
-
- if (of.err == NGX_ENOTDIR
- || of.err == NGX_ENAMETOOLONG
- || of.err == NGX_EACCES)
- {
- return ngx_http_index_error(r, clcf, path.data, of.err);
- }
-
- if (!dir_tested) {
- rc = ngx_http_index_test_dir(r, clcf, path.data, name - 1);
-
- if (rc != NGX_OK) {
- return rc;
- }
-
- dir_tested = 1;
- }
-
- if (of.err == NGX_ENOENT) {
- continue;
- }
-
- ngx_log_error(NGX_LOG_CRIT, r->connection->log, of.err,
- "%s \"%s\" failed", of.failed, path.data);
-
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
-
- uri.len = r->uri.len + len - 1;
-
- if (!clcf->alias) {
- uri.data = path.data + root;
-
- } else {
- uri.data = ngx_pnalloc(r->pool, uri.len);
- if (uri.data == NULL) {
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
-
- p = ngx_copy(uri.data, r->uri.data, r->uri.len);
- ngx_memcpy(p, name, len - 1);
- }
-
- return ngx_http_internal_redirect(r, &uri, &r->args);
- }
-
- return NGX_DECLINED;
-}
-
-
-static ngx_int_t
-ngx_http_index_test_dir(ngx_http_request_t *r, ngx_http_core_loc_conf_t *clcf,
- u_char *path, u_char *last)
-{
- u_char c;
- ngx_str_t dir;
- ngx_open_file_info_t of;
-
- c = *last;
- if (c != '/' || path == last) {
- /* "alias" without trailing slash */
- c = *(++last);
- }
- *last = '\0';
-
- dir.len = last - path;
- dir.data = path;
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "http index check dir: \"%V\"", &dir);
-
- ngx_memzero(&of, sizeof(ngx_open_file_info_t));
-
- of.test_dir = 1;
- of.test_only = 1;
- of.valid = clcf->open_file_cache_valid;
- of.errors = clcf->open_file_cache_errors;
-
- if (ngx_http_set_disable_symlinks(r, clcf, &dir, &of) != NGX_OK) {
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
-
- if (ngx_open_cached_file(clcf->open_file_cache, &dir, &of, r->pool)
- != NGX_OK)
- {
- if (of.err) {
-
-#if (NGX_HAVE_OPENAT)
- if (of.err == NGX_EMLINK
- || of.err == NGX_ELOOP)
- {
- return NGX_HTTP_FORBIDDEN;
- }
-#endif
-
- if (of.err == NGX_ENOENT) {
- *last = c;
- return ngx_http_index_error(r, clcf, dir.data, NGX_ENOENT);
- }
-
- if (of.err == NGX_EACCES) {
-
- *last = c;
-
- /*
- * ngx_http_index_test_dir() is called after the first index
- * file testing has returned an error distinct from NGX_EACCES.
- * This means that directory searching is allowed.
- */
-
- return NGX_OK;
- }
-
- ngx_log_error(NGX_LOG_CRIT, r->connection->log, of.err,
- "%s \"%s\" failed", of.failed, dir.data);
- }
-
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
-
- *last = c;
-
- if (of.is_dir) {
- return NGX_OK;
- }
-
- ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
- "\"%s\" is not a directory", dir.data);
-
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
-}
-
-
-static ngx_int_t
-ngx_http_index_error(ngx_http_request_t *r, ngx_http_core_loc_conf_t *clcf,
- u_char *file, ngx_err_t err)
-{
- if (err == NGX_EACCES) {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, err,
- "\"%s\" is forbidden", file);
-
- return NGX_HTTP_FORBIDDEN;
- }
-
- if (clcf->log_not_found) {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, err,
- "\"%s\" is not found", file);
- }
-
- return NGX_HTTP_NOT_FOUND;
-}
-
-
-static void *
-ngx_http_index_create_loc_conf(ngx_conf_t *cf)
-{
- ngx_http_index_loc_conf_t *conf;
-
- conf = ngx_palloc(cf->pool, sizeof(ngx_http_index_loc_conf_t));
- if (conf == NULL) {
- return NULL;
- }
-
- conf->indices = NULL;
- conf->max_index_len = 0;
-
- return conf;
-}
-
-
-static char *
-ngx_http_index_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
-{
- ngx_http_index_loc_conf_t *prev = parent;
- ngx_http_index_loc_conf_t *conf = child;
-
- ngx_http_index_t *index;
-
- if (conf->indices == NULL) {
- conf->indices = prev->indices;
- conf->max_index_len = prev->max_index_len;
- }
-
- if (conf->indices == NULL) {
- conf->indices = ngx_array_create(cf->pool, 1, sizeof(ngx_http_index_t));
- if (conf->indices == NULL) {
- return NGX_CONF_ERROR;
- }
-
- index = ngx_array_push(conf->indices);
- if (index == NULL) {
- return NGX_CONF_ERROR;
- }
-
- index->name.len = sizeof(NGX_HTTP_DEFAULT_INDEX);
- index->name.data = (u_char *) NGX_HTTP_DEFAULT_INDEX;
- index->lengths = NULL;
- index->values = NULL;
-
- conf->max_index_len = sizeof(NGX_HTTP_DEFAULT_INDEX);
-
- return NGX_CONF_OK;
- }
-
- return NGX_CONF_OK;
-}
-
-
-static ngx_int_t
-ngx_http_index_init(ngx_conf_t *cf)
-{
- ngx_http_handler_pt *h;
- ngx_http_core_main_conf_t *cmcf;
-
- cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);
-
- h = ngx_array_push(&cmcf->phases[NGX_HTTP_CONTENT_PHASE].handlers);
- if (h == NULL) {
- return NGX_ERROR;
- }
-
- *h = ngx_http_index_handler;
-
- return NGX_OK;
-}
-
-
-/* TODO: warn about duplicate indices */
-
-static char *
-ngx_http_index_set_index(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
-{
- ngx_http_index_loc_conf_t *ilcf = conf;
-
- ngx_str_t *value;
- ngx_uint_t i, n;
- ngx_http_index_t *index;
- ngx_http_script_compile_t sc;
-
- if (ilcf->indices == NULL) {
- ilcf->indices = ngx_array_create(cf->pool, 2, sizeof(ngx_http_index_t));
- if (ilcf->indices == NULL) {
- return NGX_CONF_ERROR;
- }
- }
-
- value = cf->args->elts;
-
- for (i = 1; i < cf->args->nelts; i++) {
-
- if (value[i].data[0] == '/' && i != cf->args->nelts - 1) {
- ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
- "only the last index in \"index\" directive "
- "should be absolute");
- }
-
- if (value[i].len == 0) {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "index \"%V\" in \"index\" directive is invalid",
- &value[1]);
- return NGX_CONF_ERROR;
- }
-
- index = ngx_array_push(ilcf->indices);
- if (index == NULL) {
- return NGX_CONF_ERROR;
- }
-
- index->name.len = value[i].len;
- index->name.data = value[i].data;
- index->lengths = NULL;
- index->values = NULL;
-
- n = ngx_http_script_variables_count(&value[i]);
-
- if (n == 0) {
- if (ilcf->max_index_len < index->name.len) {
- ilcf->max_index_len = index->name.len;
- }
-
- if (index->name.data[0] == '/') {
- continue;
- }
-
- /* include the terminating '\0' to the length to use ngx_memcpy() */
- index->name.len++;
-
- continue;
- }
-
- ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));
-
- sc.cf = cf;
- sc.source = &value[i];
- sc.lengths = &index->lengths;
- sc.values = &index->values;
- sc.variables = n;
- sc.complete_lengths = 1;
- sc.complete_values = 1;
-
- if (ngx_http_script_compile(&sc) != NGX_OK) {
- return NGX_CONF_ERROR;
- }
- }
-
- return NGX_CONF_OK;
-}
diff --git a/nginx/src/http/modules/ngx_http_limit_conn_module.c b/nginx/src/http/modules/ngx_http_limit_conn_module.c
deleted file mode 100644
index 913d599..0000000
--- a/nginx/src/http/modules/ngx_http_limit_conn_module.c
+++ /dev/null
@@ -1,670 +0,0 @@
-
-/*
- * Copyright (C) Igor Sysoev
- * Copyright (C) Nginx, Inc.
- */
-
-
-#include <ngx_config.h>
-#include <ngx_core.h>
-#include <ngx_http.h>
-
-
-typedef struct {
- u_char color;
- u_char len;
- u_short conn;
- u_char data[1];
-} ngx_http_limit_conn_node_t;
-
-
-typedef struct {
- ngx_shm_zone_t *shm_zone;
- ngx_rbtree_node_t *node;
-} ngx_http_limit_conn_cleanup_t;
-
-
-typedef struct {
- ngx_rbtree_t *rbtree;
- ngx_http_complex_value_t key;
-} ngx_http_limit_conn_ctx_t;
-
-
-typedef struct {
- ngx_shm_zone_t *shm_zone;
- ngx_uint_t conn;
-} ngx_http_limit_conn_limit_t;
-
-
-typedef struct {
- ngx_array_t limits;
- ngx_uint_t log_level;
- ngx_uint_t status_code;
-} ngx_http_limit_conn_conf_t;
-
-
-static ngx_rbtree_node_t *ngx_http_limit_conn_lookup(ngx_rbtree_t *rbtree,
- ngx_str_t *key, uint32_t hash);
-static void ngx_http_limit_conn_cleanup(void *data);
-static ngx_inline void ngx_http_limit_conn_cleanup_all(ngx_pool_t *pool);
-
-static void *ngx_http_limit_conn_create_conf(ngx_conf_t *cf);
-static char *ngx_http_limit_conn_merge_conf(ngx_conf_t *cf, void *parent,
- void *child);
-static char *ngx_http_limit_conn_zone(ngx_conf_t *cf, ngx_command_t *cmd,
- void *conf);
-static char *ngx_http_limit_conn(ngx_conf_t *cf, ngx_command_t *cmd,
- void *conf);
-static ngx_int_t ngx_http_limit_conn_init(ngx_conf_t *cf);
-
-
-static ngx_conf_enum_t ngx_http_limit_conn_log_levels[] = {
- { ngx_string("info"), NGX_LOG_INFO },
- { ngx_string("notice"), NGX_LOG_NOTICE },
- { ngx_string("warn"), NGX_LOG_WARN },
- { ngx_string("error"), NGX_LOG_ERR },
- { ngx_null_string, 0 }
-};
-
-
-static ngx_conf_num_bounds_t ngx_http_limit_conn_status_bounds = {
- ngx_conf_check_num_bounds, 400, 599
-};
-
-
-static ngx_command_t ngx_http_limit_conn_commands[] = {
-
- { ngx_string("limit_conn_zone"),
- NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE2,
- ngx_http_limit_conn_zone,
- 0,
- 0,
- NULL },
-
- { ngx_string("limit_conn"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE2,
- ngx_http_limit_conn,
- NGX_HTTP_LOC_CONF_OFFSET,
- 0,
- NULL },
-
- { ngx_string("limit_conn_log_level"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_enum_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_limit_conn_conf_t, log_level),
- &ngx_http_limit_conn_log_levels },
-
- { ngx_string("limit_conn_status"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_num_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_limit_conn_conf_t, status_code),
- &ngx_http_limit_conn_status_bounds },
-
- ngx_null_command
-};
-
-
-static ngx_http_module_t ngx_http_limit_conn_module_ctx = {
- NULL, /* preconfiguration */
- ngx_http_limit_conn_init, /* postconfiguration */
-
- NULL, /* create main configuration */
- NULL, /* init main configuration */
-
- NULL, /* create server configuration */
- NULL, /* merge server configuration */
-
- ngx_http_limit_conn_create_conf, /* create location configuration */
- ngx_http_limit_conn_merge_conf /* merge location configuration */
-};
-
-
-ngx_module_t ngx_http_limit_conn_module = {
- NGX_MODULE_V1,
- &ngx_http_limit_conn_module_ctx, /* module context */
- ngx_http_limit_conn_commands, /* module directives */
- NGX_HTTP_MODULE, /* module type */
- NULL, /* init master */
- NULL, /* init module */
- NULL, /* init process */
- NULL, /* init thread */
- NULL, /* exit thread */
- NULL, /* exit process */
- NULL, /* exit master */
- NGX_MODULE_V1_PADDING
-};
-
-
-static ngx_int_t
-ngx_http_limit_conn_handler(ngx_http_request_t *r)
-{
- size_t n;
- uint32_t hash;
- ngx_str_t key;
- ngx_uint_t i;
- ngx_slab_pool_t *shpool;
- ngx_rbtree_node_t *node;
- ngx_pool_cleanup_t *cln;
- ngx_http_limit_conn_ctx_t *ctx;
- ngx_http_limit_conn_node_t *lc;
- ngx_http_limit_conn_conf_t *lccf;
- ngx_http_limit_conn_limit_t *limits;
- ngx_http_limit_conn_cleanup_t *lccln;
-
- if (r->main->limit_conn_set) {
- return NGX_DECLINED;
- }
-
- lccf = ngx_http_get_module_loc_conf(r, ngx_http_limit_conn_module);
- limits = lccf->limits.elts;
-
- for (i = 0; i < lccf->limits.nelts; i++) {
- ctx = limits[i].shm_zone->data;
-
- if (ngx_http_complex_value(r, &ctx->key, &key) != NGX_OK) {
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
-
- if (key.len == 0) {
- continue;
- }
-
- if (key.len > 255) {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "the value of the \"%V\" key "
- "is more than 255 bytes: \"%V\"",
- &ctx->key.value, &key);
- continue;
- }
-
- r->main->limit_conn_set = 1;
-
- hash = ngx_crc32_short(key.data, key.len);
-
- shpool = (ngx_slab_pool_t *) limits[i].shm_zone->shm.addr;
-
- ngx_shmtx_lock(&shpool->mutex);
-
- node = ngx_http_limit_conn_lookup(ctx->rbtree, &key, hash);
-
- if (node == NULL) {
-
- n = offsetof(ngx_rbtree_node_t, color)
- + offsetof(ngx_http_limit_conn_node_t, data)
- + key.len;
-
- node = ngx_slab_alloc_locked(shpool, n);
-
- if (node == NULL) {
- ngx_shmtx_unlock(&shpool->mutex);
- ngx_http_limit_conn_cleanup_all(r->pool);
- return lccf->status_code;
- }
-
- lc = (ngx_http_limit_conn_node_t *) &node->color;
-
- node->key = hash;
- lc->len = (u_char) key.len;
- lc->conn = 1;
- ngx_memcpy(lc->data, key.data, key.len);
-
- ngx_rbtree_insert(ctx->rbtree, node);
-
- } else {
-
- lc = (ngx_http_limit_conn_node_t *) &node->color;
-
- if ((ngx_uint_t) lc->conn >= limits[i].conn) {
-
- ngx_shmtx_unlock(&shpool->mutex);
-
- ngx_log_error(lccf->log_level, r->connection->log, 0,
- "limiting connections by zone \"%V\"",
- &limits[i].shm_zone->shm.name);
-
- ngx_http_limit_conn_cleanup_all(r->pool);
- return lccf->status_code;
- }
-
- lc->conn++;
- }
-
- ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "limit conn: %08Xi %d", node->key, lc->conn);
-
- ngx_shmtx_unlock(&shpool->mutex);
-
- cln = ngx_pool_cleanup_add(r->pool,
- sizeof(ngx_http_limit_conn_cleanup_t));
- if (cln == NULL) {
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
-
- cln->handler = ngx_http_limit_conn_cleanup;
- lccln = cln->data;
-
- lccln->shm_zone = limits[i].shm_zone;
- lccln->node = node;
- }
-
- return NGX_DECLINED;
-}
-
-
-static void
-ngx_http_limit_conn_rbtree_insert_value(ngx_rbtree_node_t *temp,
- ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel)
-{
- ngx_rbtree_node_t **p;
- ngx_http_limit_conn_node_t *lcn, *lcnt;
-
- for ( ;; ) {
-
- if (node->key < temp->key) {
-
- p = &temp->left;
-
- } else if (node->key > temp->key) {
-
- p = &temp->right;
-
- } else { /* node->key == temp->key */
-
- lcn = (ngx_http_limit_conn_node_t *) &node->color;
- lcnt = (ngx_http_limit_conn_node_t *) &temp->color;
-
- p = (ngx_memn2cmp(lcn->data, lcnt->data, lcn->len, lcnt->len) < 0)
- ? &temp->left : &temp->right;
- }
-
- if (*p == sentinel) {
- break;
- }
-
- temp = *p;
- }
-
- *p = node;
- node->parent = temp;
- node->left = sentinel;
- node->right = sentinel;
- ngx_rbt_red(node);
-}
-
-
-static ngx_rbtree_node_t *
-ngx_http_limit_conn_lookup(ngx_rbtree_t *rbtree, ngx_str_t *key, uint32_t hash)
-{
- ngx_int_t rc;
- ngx_rbtree_node_t *node, *sentinel;
- ngx_http_limit_conn_node_t *lcn;
-
- node = rbtree->root;
- sentinel = rbtree->sentinel;
-
- while (node != sentinel) {
-
- if (hash < node->key) {
- node = node->left;
- continue;
- }
-
- if (hash > node->key) {
- node = node->right;
- continue;
- }
-
- /* hash == node->key */
-
- lcn = (ngx_http_limit_conn_node_t *) &node->color;
-
- rc = ngx_memn2cmp(key->data, lcn->data, key->len, (size_t) lcn->len);
-
- if (rc == 0) {
- return node;
- }
-
- node = (rc < 0) ? node->left : node->right;
- }
-
- return NULL;
-}
-
-
-static void
-ngx_http_limit_conn_cleanup(void *data)
-{
- ngx_http_limit_conn_cleanup_t *lccln = data;
-
- ngx_slab_pool_t *shpool;
- ngx_rbtree_node_t *node;
- ngx_http_limit_conn_ctx_t *ctx;
- ngx_http_limit_conn_node_t *lc;
-
- ctx = lccln->shm_zone->data;
- shpool = (ngx_slab_pool_t *) lccln->shm_zone->shm.addr;
- node = lccln->node;
- lc = (ngx_http_limit_conn_node_t *) &node->color;
-
- ngx_shmtx_lock(&shpool->mutex);
-
- ngx_log_debug2(NGX_LOG_DEBUG_HTTP, lccln->shm_zone->shm.log, 0,
- "limit conn cleanup: %08Xi %d", node->key, lc->conn);
-
- lc->conn--;
-
- if (lc->conn == 0) {
- ngx_rbtree_delete(ctx->rbtree, node);
- ngx_slab_free_locked(shpool, node);
- }
-
- ngx_shmtx_unlock(&shpool->mutex);
-}
-
-
-static ngx_inline void
-ngx_http_limit_conn_cleanup_all(ngx_pool_t *pool)
-{
- ngx_pool_cleanup_t *cln;
-
- cln = pool->cleanup;
-
- while (cln && cln->handler == ngx_http_limit_conn_cleanup) {
- ngx_http_limit_conn_cleanup(cln->data);
- cln = cln->next;
- }
-
- pool->cleanup = cln;
-}
-
-
-static ngx_int_t
-ngx_http_limit_conn_init_zone(ngx_shm_zone_t *shm_zone, void *data)
-{
- ngx_http_limit_conn_ctx_t *octx = data;
-
- size_t len;
- ngx_slab_pool_t *shpool;
- ngx_rbtree_node_t *sentinel;
- ngx_http_limit_conn_ctx_t *ctx;
-
- ctx = shm_zone->data;
-
- if (octx) {
- if (ctx->key.value.len != octx->key.value.len
- || ngx_strncmp(ctx->key.value.data, octx->key.value.data,
- ctx->key.value.len)
- != 0)
- {
- ngx_log_error(NGX_LOG_EMERG, shm_zone->shm.log, 0,
- "limit_conn_zone \"%V\" uses the \"%V\" key "
- "while previously it used the \"%V\" key",
- &shm_zone->shm.name, &ctx->key.value,
- &octx->key.value);
- return NGX_ERROR;
- }
-
- ctx->rbtree = octx->rbtree;
-
- return NGX_OK;
- }
-
- shpool = (ngx_slab_pool_t *) shm_zone->shm.addr;
-
- if (shm_zone->shm.exists) {
- ctx->rbtree = shpool->data;
-
- return NGX_OK;
- }
-
- ctx->rbtree = ngx_slab_alloc(shpool, sizeof(ngx_rbtree_t));
- if (ctx->rbtree == NULL) {
- return NGX_ERROR;
- }
-
- shpool->data = ctx->rbtree;
-
- sentinel = ngx_slab_alloc(shpool, sizeof(ngx_rbtree_node_t));
- if (sentinel == NULL) {
- return NGX_ERROR;
- }
-
- ngx_rbtree_init(ctx->rbtree, sentinel,
- ngx_http_limit_conn_rbtree_insert_value);
-
- len = sizeof(" in limit_conn_zone \"\"") + shm_zone->shm.name.len;
-
- shpool->log_ctx = ngx_slab_alloc(shpool, len);
- if (shpool->log_ctx == NULL) {
- return NGX_ERROR;
- }
-
- ngx_sprintf(shpool->log_ctx, " in limit_conn_zone \"%V\"%Z",
- &shm_zone->shm.name);
-
- return NGX_OK;
-}
-
-
-static void *
-ngx_http_limit_conn_create_conf(ngx_conf_t *cf)
-{
- ngx_http_limit_conn_conf_t *conf;
-
- conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_limit_conn_conf_t));
- if (conf == NULL) {
- return NULL;
- }
-
- /*
- * set by ngx_pcalloc():
- *
- * conf->limits.elts = NULL;
- */
-
- conf->log_level = NGX_CONF_UNSET_UINT;
- conf->status_code = NGX_CONF_UNSET_UINT;
-
- return conf;
-}
-
-
-static char *
-ngx_http_limit_conn_merge_conf(ngx_conf_t *cf, void *parent, void *child)
-{
- ngx_http_limit_conn_conf_t *prev = parent;
- ngx_http_limit_conn_conf_t *conf = child;
-
- if (conf->limits.elts == NULL) {
- conf->limits = prev->limits;
- }
-
- ngx_conf_merge_uint_value(conf->log_level, prev->log_level, NGX_LOG_ERR);
- ngx_conf_merge_uint_value(conf->status_code, prev->status_code,
- NGX_HTTP_SERVICE_UNAVAILABLE);
-
- return NGX_CONF_OK;
-}
-
-
-static char *
-ngx_http_limit_conn_zone(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
-{
- u_char *p;
- ssize_t size;
- ngx_str_t *value, name, s;
- ngx_uint_t i;
- ngx_shm_zone_t *shm_zone;
- ngx_http_limit_conn_ctx_t *ctx;
- ngx_http_compile_complex_value_t ccv;
-
- value = cf->args->elts;
-
- ctx = ngx_pcalloc(cf->pool, sizeof(ngx_http_limit_conn_ctx_t));
- if (ctx == NULL) {
- return NGX_CONF_ERROR;
- }
-
- ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));
-
- ccv.cf = cf;
- ccv.value = &value[1];
- ccv.complex_value = &ctx->key;
-
- if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
- return NGX_CONF_ERROR;
- }
-
- size = 0;
- name.len = 0;
-
- for (i = 2; i < cf->args->nelts; i++) {
-
- if (ngx_strncmp(value[i].data, "zone=", 5) == 0) {
-
- name.data = value[i].data + 5;
-
- p = (u_char *) ngx_strchr(name.data, ':');
-
- if (p == NULL) {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "invalid zone size \"%V\"", &value[i]);
- return NGX_CONF_ERROR;
- }
-
- name.len = p - name.data;
-
- s.data = p + 1;
- s.len = value[i].data + value[i].len - s.data;
-
- size = ngx_parse_size(&s);
-
- if (size == NGX_ERROR) {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "invalid zone size \"%V\"", &value[i]);
- return NGX_CONF_ERROR;
- }
-
- if (size < (ssize_t) (8 * ngx_pagesize)) {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "zone \"%V\" is too small", &value[i]);
- return NGX_CONF_ERROR;
- }
-
- continue;
- }
-
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "invalid parameter \"%V\"", &value[i]);
- return NGX_CONF_ERROR;
- }
-
- if (name.len == 0) {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "\"%V\" must have \"zone\" parameter",
- &cmd->name);
- return NGX_CONF_ERROR;
- }
-
- shm_zone = ngx_shared_memory_add(cf, &name, size,
- &ngx_http_limit_conn_module);
- if (shm_zone == NULL) {
- return NGX_CONF_ERROR;
- }
-
- if (shm_zone->data) {
- ctx = shm_zone->data;
-
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "%V \"%V\" is already bound to key \"%V\"",
- &cmd->name, &name, &ctx->key.value);
- return NGX_CONF_ERROR;
- }
-
- shm_zone->init = ngx_http_limit_conn_init_zone;
- shm_zone->data = ctx;
-
- return NGX_CONF_OK;
-}
-
-
-static char *
-ngx_http_limit_conn(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
-{
- ngx_shm_zone_t *shm_zone;
- ngx_http_limit_conn_conf_t *lccf = conf;
- ngx_http_limit_conn_limit_t *limit, *limits;
-
- ngx_str_t *value;
- ngx_int_t n;
- ngx_uint_t i;
-
- value = cf->args->elts;
-
- shm_zone = ngx_shared_memory_add(cf, &value[1], 0,
- &ngx_http_limit_conn_module);
- if (shm_zone == NULL) {
- return NGX_CONF_ERROR;
- }
-
- limits = lccf->limits.elts;
-
- if (limits == NULL) {
- if (ngx_array_init(&lccf->limits, cf->pool, 1,
- sizeof(ngx_http_limit_conn_limit_t))
- != NGX_OK)
- {
- return NGX_CONF_ERROR;
- }
- }
-
- for (i = 0; i < lccf->limits.nelts; i++) {
- if (shm_zone == limits[i].shm_zone) {
- return "is duplicate";
- }
- }
-
- n = ngx_atoi(value[2].data, value[2].len);
- if (n <= 0) {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "invalid number of connections \"%V\"", &value[2]);
- return NGX_CONF_ERROR;
- }
-
- if (n > 65535) {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "connection limit must be less 65536");
- return NGX_CONF_ERROR;
- }
-
- limit = ngx_array_push(&lccf->limits);
- if (limit == NULL) {
- return NGX_CONF_ERROR;
- }
-
- limit->conn = n;
- limit->shm_zone = shm_zone;
-
- return NGX_CONF_OK;
-}
-
-
-static ngx_int_t
-ngx_http_limit_conn_init(ngx_conf_t *cf)
-{
- ngx_http_handler_pt *h;
- ngx_http_core_main_conf_t *cmcf;
-
- cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);
-
- h = ngx_array_push(&cmcf->phases[NGX_HTTP_PREACCESS_PHASE].handlers);
- if (h == NULL) {
- return NGX_ERROR;
- }
-
- *h = ngx_http_limit_conn_handler;
-
- return NGX_OK;
-}
diff --git a/nginx/src/http/modules/ngx_http_limit_req_module.c b/nginx/src/http/modules/ngx_http_limit_req_module.c
deleted file mode 100644
index 579b13c..0000000
--- a/nginx/src/http/modules/ngx_http_limit_req_module.c
+++ /dev/null
@@ -1,960 +0,0 @@
-
-/*
- * Copyright (C) Igor Sysoev
- * Copyright (C) Nginx, Inc.
- */
-
-
-#include <ngx_config.h>
-#include <ngx_core.h>
-#include <ngx_http.h>
-
-
-typedef struct {
- u_char color;
- u_char dummy;
- u_short len;
- ngx_queue_t queue;
- ngx_msec_t last;
- /* integer value, 1 corresponds to 0.001 r/s */
- ngx_uint_t excess;
- ngx_uint_t count;
- u_char data[1];
-} ngx_http_limit_req_node_t;
-
-
-typedef struct {
- ngx_rbtree_t rbtree;
- ngx_rbtree_node_t sentinel;
- ngx_queue_t queue;
-} ngx_http_limit_req_shctx_t;
-
-
-typedef struct {
- ngx_http_limit_req_shctx_t *sh;
- ngx_slab_pool_t *shpool;
- /* integer value, 1 corresponds to 0.001 r/s */
- ngx_uint_t rate;
- ngx_http_complex_value_t key;
- ngx_http_limit_req_node_t *node;
-} ngx_http_limit_req_ctx_t;
-
-
-typedef struct {
- ngx_shm_zone_t *shm_zone;
- /* integer value, 1 corresponds to 0.001 r/s */
- ngx_uint_t burst;
- ngx_uint_t nodelay; /* unsigned nodelay:1 */
-} ngx_http_limit_req_limit_t;
-
-
-typedef struct {
- ngx_array_t limits;
- ngx_uint_t limit_log_level;
- ngx_uint_t delay_log_level;
- ngx_uint_t status_code;
-} ngx_http_limit_req_conf_t;
-
-
-static void ngx_http_limit_req_delay(ngx_http_request_t *r);
-static ngx_int_t ngx_http_limit_req_lookup(ngx_http_limit_req_limit_t *limit,
- ngx_uint_t hash, ngx_str_t *key, ngx_uint_t *ep, ngx_uint_t account);
-static ngx_msec_t ngx_http_limit_req_account(ngx_http_limit_req_limit_t *limits,
- ngx_uint_t n, ngx_uint_t *ep, ngx_http_limit_req_limit_t **limit);
-static void ngx_http_limit_req_expire(ngx_http_limit_req_ctx_t *ctx,
- ngx_uint_t n);
-
-static void *ngx_http_limit_req_create_conf(ngx_conf_t *cf);
-static char *ngx_http_limit_req_merge_conf(ngx_conf_t *cf, void *parent,
- void *child);
-static char *ngx_http_limit_req_zone(ngx_conf_t *cf, ngx_command_t *cmd,
- void *conf);
-static char *ngx_http_limit_req(ngx_conf_t *cf, ngx_command_t *cmd,
- void *conf);
-static ngx_int_t ngx_http_limit_req_init(ngx_conf_t *cf);
-
-
-static ngx_conf_enum_t ngx_http_limit_req_log_levels[] = {
- { ngx_string("info"), NGX_LOG_INFO },
- { ngx_string("notice"), NGX_LOG_NOTICE },
- { ngx_string("warn"), NGX_LOG_WARN },
- { ngx_string("error"), NGX_LOG_ERR },
- { ngx_null_string, 0 }
-};
-
-
-static ngx_conf_num_bounds_t ngx_http_limit_req_status_bounds = {
- ngx_conf_check_num_bounds, 400, 599
-};
-
-
-static ngx_command_t ngx_http_limit_req_commands[] = {
-
- { ngx_string("limit_req_zone"),
- NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE3,
- ngx_http_limit_req_zone,
- 0,
- 0,
- NULL },
-
- { ngx_string("limit_req"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE123,
- ngx_http_limit_req,
- NGX_HTTP_LOC_CONF_OFFSET,
- 0,
- NULL },
-
- { ngx_string("limit_req_log_level"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_enum_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_limit_req_conf_t, limit_log_level),
- &ngx_http_limit_req_log_levels },
-
- { ngx_string("limit_req_status"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_num_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_limit_req_conf_t, status_code),
- &ngx_http_limit_req_status_bounds },
-
- ngx_null_command
-};
-
-
-static ngx_http_module_t ngx_http_limit_req_module_ctx = {
- NULL, /* preconfiguration */
- ngx_http_limit_req_init, /* postconfiguration */
-
- NULL, /* create main configuration */
- NULL, /* init main configuration */
-
- NULL, /* create server configuration */
- NULL, /* merge server configuration */
-
- ngx_http_limit_req_create_conf, /* create location configuration */
- ngx_http_limit_req_merge_conf /* merge location configuration */
-};
-
-
-ngx_module_t ngx_http_limit_req_module = {
- NGX_MODULE_V1,
- &ngx_http_limit_req_module_ctx, /* module context */
- ngx_http_limit_req_commands, /* module directives */
- NGX_HTTP_MODULE, /* module type */
- NULL, /* init master */
- NULL, /* init module */
- NULL, /* init process */
- NULL, /* init thread */
- NULL, /* exit thread */
- NULL, /* exit process */
- NULL, /* exit master */
- NGX_MODULE_V1_PADDING
-};
-
-
-static ngx_int_t
-ngx_http_limit_req_handler(ngx_http_request_t *r)
-{
- uint32_t hash;
- ngx_str_t key;
- ngx_int_t rc;
- ngx_uint_t n, excess;
- ngx_msec_t delay;
- ngx_http_limit_req_ctx_t *ctx;
- ngx_http_limit_req_conf_t *lrcf;
- ngx_http_limit_req_limit_t *limit, *limits;
-
- if (r->main->limit_req_set) {
- return NGX_DECLINED;
- }
-
- lrcf = ngx_http_get_module_loc_conf(r, ngx_http_limit_req_module);
- limits = lrcf->limits.elts;
-
- excess = 0;
-
- rc = NGX_DECLINED;
-
-#if (NGX_SUPPRESS_WARN)
- limit = NULL;
-#endif
-
- for (n = 0; n < lrcf->limits.nelts; n++) {
-
- limit = &limits[n];
-
- ctx = limit->shm_zone->data;
-
- if (ngx_http_complex_value(r, &ctx->key, &key) != NGX_OK) {
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
-
- if (key.len == 0) {
- continue;
- }
-
- if (key.len > 65535) {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "the value of the \"%V\" key "
- "is more than 65535 bytes: \"%V\"",
- &ctx->key.value, &key);
- continue;
- }
-
- hash = ngx_crc32_short(key.data, key.len);
-
- ngx_shmtx_lock(&ctx->shpool->mutex);
-
- rc = ngx_http_limit_req_lookup(limit, hash, &key, &excess,
- (n == lrcf->limits.nelts - 1));
-
- ngx_shmtx_unlock(&ctx->shpool->mutex);
-
- ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "limit_req[%ui]: %i %ui.%03ui",
- n, rc, excess / 1000, excess % 1000);
-
- if (rc != NGX_AGAIN) {
- break;
- }
- }
-
- if (rc == NGX_DECLINED) {
- return NGX_DECLINED;
- }
-
- r->main->limit_req_set = 1;
-
- if (rc == NGX_BUSY || rc == NGX_ERROR) {
-
- if (rc == NGX_BUSY) {
- ngx_log_error(lrcf->limit_log_level, r->connection->log, 0,
- "limiting requests, excess: %ui.%03ui by zone \"%V\"",
- excess / 1000, excess % 1000,
- &limit->shm_zone->shm.name);
- }
-
- while (n--) {
- ctx = limits[n].shm_zone->data;
-
- if (ctx->node == NULL) {
- continue;
- }
-
- ngx_shmtx_lock(&ctx->shpool->mutex);
-
- ctx->node->count--;
-
- ngx_shmtx_unlock(&ctx->shpool->mutex);
-
- ctx->node = NULL;
- }
-
- return lrcf->status_code;
- }
-
- /* rc == NGX_AGAIN || rc == NGX_OK */
-
- if (rc == NGX_AGAIN) {
- excess = 0;
- }
-
- delay = ngx_http_limit_req_account(limits, n, &excess, &limit);
-
- if (!delay) {
- return NGX_DECLINED;
- }
-
- ngx_log_error(lrcf->delay_log_level, r->connection->log, 0,
- "delaying request, excess: %ui.%03ui, by zone \"%V\"",
- excess / 1000, excess % 1000, &limit->shm_zone->shm.name);
-
- if (ngx_handle_read_event(r->connection->read, 0) != NGX_OK) {
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
-
- r->read_event_handler = ngx_http_test_reading;
- r->write_event_handler = ngx_http_limit_req_delay;
-
- r->connection->write->delayed = 1;
- ngx_add_timer(r->connection->write, delay);
-
- return NGX_AGAIN;
-}
-
-
-static void
-ngx_http_limit_req_delay(ngx_http_request_t *r)
-{
- ngx_event_t *wev;
-
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "limit_req delay");
-
- wev = r->connection->write;
-
- if (wev->delayed) {
-
- if (ngx_handle_write_event(wev, 0) != NGX_OK) {
- ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
- }
-
- return;
- }
-
- if (ngx_handle_read_event(r->connection->read, 0) != NGX_OK) {
- ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
- return;
- }
-
- r->read_event_handler = ngx_http_block_reading;
- r->write_event_handler = ngx_http_core_run_phases;
-
- ngx_http_core_run_phases(r);
-}
-
-
-static void
-ngx_http_limit_req_rbtree_insert_value(ngx_rbtree_node_t *temp,
- ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel)
-{
- ngx_rbtree_node_t **p;
- ngx_http_limit_req_node_t *lrn, *lrnt;
-
- for ( ;; ) {
-
- if (node->key < temp->key) {
-
- p = &temp->left;
-
- } else if (node->key > temp->key) {
-
- p = &temp->right;
-
- } else { /* node->key == temp->key */
-
- lrn = (ngx_http_limit_req_node_t *) &node->color;
- lrnt = (ngx_http_limit_req_node_t *) &temp->color;
-
- p = (ngx_memn2cmp(lrn->data, lrnt->data, lrn->len, lrnt->len) < 0)
- ? &temp->left : &temp->right;
- }
-
- if (*p == sentinel) {
- break;
- }
-
- temp = *p;
- }
-
- *p = node;
- node->parent = temp;
- node->left = sentinel;
- node->right = sentinel;
- ngx_rbt_red(node);
-}
-
-
-static ngx_int_t
-ngx_http_limit_req_lookup(ngx_http_limit_req_limit_t *limit, ngx_uint_t hash,
- ngx_str_t *key, ngx_uint_t *ep, ngx_uint_t account)
-{
- size_t size;
- ngx_int_t rc, excess;
- ngx_msec_t now;
- ngx_msec_int_t ms;
- ngx_rbtree_node_t *node, *sentinel;
- ngx_http_limit_req_ctx_t *ctx;
- ngx_http_limit_req_node_t *lr;
-
- now = ngx_current_msec;
-
- ctx = limit->shm_zone->data;
-
- node = ctx->sh->rbtree.root;
- sentinel = ctx->sh->rbtree.sentinel;
-
- while (node != sentinel) {
-
- if (hash < node->key) {
- node = node->left;
- continue;
- }
-
- if (hash > node->key) {
- node = node->right;
- continue;
- }
-
- /* hash == node->key */
-
- lr = (ngx_http_limit_req_node_t *) &node->color;
-
- rc = ngx_memn2cmp(key->data, lr->data, key->len, (size_t) lr->len);
-
- if (rc == 0) {
- ngx_queue_remove(&lr->queue);
- ngx_queue_insert_head(&ctx->sh->queue, &lr->queue);
-
- ms = (ngx_msec_int_t) (now - lr->last);
-
- excess = lr->excess - ctx->rate * ngx_abs(ms) / 1000 + 1000;
-
- if (excess < 0) {
- excess = 0;
- }
-
- *ep = excess;
-
- if ((ngx_uint_t) excess > limit->burst) {
- return NGX_BUSY;
- }
-
- if (account) {
- lr->excess = excess;
- lr->last = now;
- return NGX_OK;
- }
-
- lr->count++;
-
- ctx->node = lr;
-
- return NGX_AGAIN;
- }
-
- node = (rc < 0) ? node->left : node->right;
- }
-
- *ep = 0;
-
- size = offsetof(ngx_rbtree_node_t, color)
- + offsetof(ngx_http_limit_req_node_t, data)
- + key->len;
-
- ngx_http_limit_req_expire(ctx, 1);
-
- node = ngx_slab_alloc_locked(ctx->shpool, size);
-
- if (node == NULL) {
- ngx_http_limit_req_expire(ctx, 0);
-
- node = ngx_slab_alloc_locked(ctx->shpool, size);
- if (node == NULL) {
- ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, 0,
- "could not allocate node%s", ctx->shpool->log_ctx);
- return NGX_ERROR;
- }
- }
-
- node->key = hash;
-
- lr = (ngx_http_limit_req_node_t *) &node->color;
-
- lr->len = (u_short) key->len;
- lr->excess = 0;
-
- ngx_memcpy(lr->data, key->data, key->len);
-
- ngx_rbtree_insert(&ctx->sh->rbtree, node);
-
- ngx_queue_insert_head(&ctx->sh->queue, &lr->queue);
-
- if (account) {
- lr->last = now;
- lr->count = 0;
- return NGX_OK;
- }
-
- lr->last = 0;
- lr->count = 1;
-
- ctx->node = lr;
-
- return NGX_AGAIN;
-}
-
-
-static ngx_msec_t
-ngx_http_limit_req_account(ngx_http_limit_req_limit_t *limits, ngx_uint_t n,
- ngx_uint_t *ep, ngx_http_limit_req_limit_t **limit)
-{
- ngx_int_t excess;
- ngx_msec_t now, delay, max_delay;
- ngx_msec_int_t ms;
- ngx_http_limit_req_ctx_t *ctx;
- ngx_http_limit_req_node_t *lr;
-
- excess = *ep;
-
- if (excess == 0 || (*limit)->nodelay) {
- max_delay = 0;
-
- } else {
- ctx = (*limit)->shm_zone->data;
- max_delay = excess * 1000 / ctx->rate;
- }
-
- while (n--) {
- ctx = limits[n].shm_zone->data;
- lr = ctx->node;
-
- if (lr == NULL) {
- continue;
- }
-
- ngx_shmtx_lock(&ctx->shpool->mutex);
-
- now = ngx_current_msec;
- ms = (ngx_msec_int_t) (now - lr->last);
-
- excess = lr->excess - ctx->rate * ngx_abs(ms) / 1000 + 1000;
-
- if (excess < 0) {
- excess = 0;
- }
-
- lr->last = now;
- lr->excess = excess;
- lr->count--;
-
- ngx_shmtx_unlock(&ctx->shpool->mutex);
-
- ctx->node = NULL;
-
- if (limits[n].nodelay) {
- continue;
- }
-
- delay = excess * 1000 / ctx->rate;
-
- if (delay > max_delay) {
- max_delay = delay;
- *ep = excess;
- *limit = &limits[n];
- }
- }
-
- return max_delay;
-}
-
-
-static void
-ngx_http_limit_req_expire(ngx_http_limit_req_ctx_t *ctx, ngx_uint_t n)
-{
- ngx_int_t excess;
- ngx_msec_t now;
- ngx_queue_t *q;
- ngx_msec_int_t ms;
- ngx_rbtree_node_t *node;
- ngx_http_limit_req_node_t *lr;
-
- now = ngx_current_msec;
-
- /*
- * n == 1 deletes one or two zero rate entries
- * n == 0 deletes oldest entry by force
- * and one or two zero rate entries
- */
-
- while (n < 3) {
-
- if (ngx_queue_empty(&ctx->sh->queue)) {
- return;
- }
-
- q = ngx_queue_last(&ctx->sh->queue);
-
- lr = ngx_queue_data(q, ngx_http_limit_req_node_t, queue);
-
- if (lr->count) {
-
- /*
- * There is not much sense in looking further,
- * because we bump nodes on the lookup stage.
- */
-
- return;
- }
-
- if (n++ != 0) {
-
- ms = (ngx_msec_int_t) (now - lr->last);
- ms = ngx_abs(ms);
-
- if (ms < 60000) {
- return;
- }
-
- excess = lr->excess - ctx->rate * ms / 1000;
-
- if (excess > 0) {
- return;
- }
- }
-
- ngx_queue_remove(q);
-
- node = (ngx_rbtree_node_t *)
- ((u_char *) lr - offsetof(ngx_rbtree_node_t, color));
-
- ngx_rbtree_delete(&ctx->sh->rbtree, node);
-
- ngx_slab_free_locked(ctx->shpool, node);
- }
-}
-
-
-static ngx_int_t
-ngx_http_limit_req_init_zone(ngx_shm_zone_t *shm_zone, void *data)
-{
- ngx_http_limit_req_ctx_t *octx = data;
-
- size_t len;
- ngx_http_limit_req_ctx_t *ctx;
-
- ctx = shm_zone->data;
-
- if (octx) {
- if (ctx->key.value.len != octx->key.value.len
- || ngx_strncmp(ctx->key.value.data, octx->key.value.data,
- ctx->key.value.len)
- != 0)
- {
- ngx_log_error(NGX_LOG_EMERG, shm_zone->shm.log, 0,
- "limit_req \"%V\" uses the \"%V\" key "
- "while previously it used the \"%V\" key",
- &shm_zone->shm.name, &ctx->key.value,
- &octx->key.value);
- return NGX_ERROR;
- }
-
- ctx->sh = octx->sh;
- ctx->shpool = octx->shpool;
-
- return NGX_OK;
- }
-
- ctx->shpool = (ngx_slab_pool_t *) shm_zone->shm.addr;
-
- if (shm_zone->shm.exists) {
- ctx->sh = ctx->shpool->data;
-
- return NGX_OK;
- }
-
- ctx->sh = ngx_slab_alloc(ctx->shpool, sizeof(ngx_http_limit_req_shctx_t));
- if (ctx->sh == NULL) {
- return NGX_ERROR;
- }
-
- ctx->shpool->data = ctx->sh;
-
- ngx_rbtree_init(&ctx->sh->rbtree, &ctx->sh->sentinel,
- ngx_http_limit_req_rbtree_insert_value);
-
- ngx_queue_init(&ctx->sh->queue);
-
- len = sizeof(" in limit_req zone \"\"") + shm_zone->shm.name.len;
-
- ctx->shpool->log_ctx = ngx_slab_alloc(ctx->shpool, len);
- if (ctx->shpool->log_ctx == NULL) {
- return NGX_ERROR;
- }
-
- ngx_sprintf(ctx->shpool->log_ctx, " in limit_req zone \"%V\"%Z",
- &shm_zone->shm.name);
-
- ctx->shpool->log_nomem = 0;
-
- return NGX_OK;
-}
-
-
-static void *
-ngx_http_limit_req_create_conf(ngx_conf_t *cf)
-{
- ngx_http_limit_req_conf_t *conf;
-
- conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_limit_req_conf_t));
- if (conf == NULL) {
- return NULL;
- }
-
- /*
- * set by ngx_pcalloc():
- *
- * conf->limits.elts = NULL;
- */
-
- conf->limit_log_level = NGX_CONF_UNSET_UINT;
- conf->status_code = NGX_CONF_UNSET_UINT;
-
- return conf;
-}
-
-
-static char *
-ngx_http_limit_req_merge_conf(ngx_conf_t *cf, void *parent, void *child)
-{
- ngx_http_limit_req_conf_t *prev = parent;
- ngx_http_limit_req_conf_t *conf = child;
-
- if (conf->limits.elts == NULL) {
- conf->limits = prev->limits;
- }
-
- ngx_conf_merge_uint_value(conf->limit_log_level, prev->limit_log_level,
- NGX_LOG_ERR);
-
- conf->delay_log_level = (conf->limit_log_level == NGX_LOG_INFO) ?
- NGX_LOG_INFO : conf->limit_log_level + 1;
-
- ngx_conf_merge_uint_value(conf->status_code, prev->status_code,
- NGX_HTTP_SERVICE_UNAVAILABLE);
-
- return NGX_CONF_OK;
-}
-
-
-static char *
-ngx_http_limit_req_zone(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
-{
- u_char *p;
- size_t len;
- ssize_t size;
- ngx_str_t *value, name, s;
- ngx_int_t rate, scale;
- ngx_uint_t i;
- ngx_shm_zone_t *shm_zone;
- ngx_http_limit_req_ctx_t *ctx;
- ngx_http_compile_complex_value_t ccv;
-
- value = cf->args->elts;
-
- ctx = ngx_pcalloc(cf->pool, sizeof(ngx_http_limit_req_ctx_t));
- if (ctx == NULL) {
- return NGX_CONF_ERROR;
- }
-
- ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));
-
- ccv.cf = cf;
- ccv.value = &value[1];
- ccv.complex_value = &ctx->key;
-
- if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
- return NGX_CONF_ERROR;
- }
-
- size = 0;
- rate = 1;
- scale = 1;
- name.len = 0;
-
- for (i = 2; i < cf->args->nelts; i++) {
-
- if (ngx_strncmp(value[i].data, "zone=", 5) == 0) {
-
- name.data = value[i].data + 5;
-
- p = (u_char *) ngx_strchr(name.data, ':');
-
- if (p == NULL) {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "invalid zone size \"%V\"", &value[i]);
- return NGX_CONF_ERROR;
- }
-
- name.len = p - name.data;
-
- s.data = p + 1;
- s.len = value[i].data + value[i].len - s.data;
-
- size = ngx_parse_size(&s);
-
- if (size == NGX_ERROR) {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "invalid zone size \"%V\"", &value[i]);
- return NGX_CONF_ERROR;
- }
-
- if (size < (ssize_t) (8 * ngx_pagesize)) {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "zone \"%V\" is too small", &value[i]);
- return NGX_CONF_ERROR;
- }
-
- continue;
- }
-
- if (ngx_strncmp(value[i].data, "rate=", 5) == 0) {
-
- len = value[i].len;
- p = value[i].data + len - 3;
-
- if (ngx_strncmp(p, "r/s", 3) == 0) {
- scale = 1;
- len -= 3;
-
- } else if (ngx_strncmp(p, "r/m", 3) == 0) {
- scale = 60;
- len -= 3;
- }
-
- rate = ngx_atoi(value[i].data + 5, len - 5);
- if (rate <= 0) {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "invalid rate \"%V\"", &value[i]);
- return NGX_CONF_ERROR;
- }
-
- continue;
- }
-
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "invalid parameter \"%V\"", &value[i]);
- return NGX_CONF_ERROR;
- }
-
- if (name.len == 0) {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "\"%V\" must have \"zone\" parameter",
- &cmd->name);
- return NGX_CONF_ERROR;
- }
-
- ctx->rate = rate * 1000 / scale;
-
- shm_zone = ngx_shared_memory_add(cf, &name, size,
- &ngx_http_limit_req_module);
- if (shm_zone == NULL) {
- return NGX_CONF_ERROR;
- }
-
- if (shm_zone->data) {
- ctx = shm_zone->data;
-
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "%V \"%V\" is already bound to key \"%V\"",
- &cmd->name, &name, &ctx->key.value);
- return NGX_CONF_ERROR;
- }
-
- shm_zone->init = ngx_http_limit_req_init_zone;
- shm_zone->data = ctx;
-
- return NGX_CONF_OK;
-}
-
-
-static char *
-ngx_http_limit_req(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
-{
- ngx_http_limit_req_conf_t *lrcf = conf;
-
- ngx_int_t burst;
- ngx_str_t *value, s;
- ngx_uint_t i, nodelay;
- ngx_shm_zone_t *shm_zone;
- ngx_http_limit_req_limit_t *limit, *limits;
-
- value = cf->args->elts;
-
- shm_zone = NULL;
- burst = 0;
- nodelay = 0;
-
- for (i = 1; i < cf->args->nelts; i++) {
-
- if (ngx_strncmp(value[i].data, "zone=", 5) == 0) {
-
- s.len = value[i].len - 5;
- s.data = value[i].data + 5;
-
- shm_zone = ngx_shared_memory_add(cf, &s, 0,
- &ngx_http_limit_req_module);
- if (shm_zone == NULL) {
- return NGX_CONF_ERROR;
- }
-
- continue;
- }
-
- if (ngx_strncmp(value[i].data, "burst=", 6) == 0) {
-
- burst = ngx_atoi(value[i].data + 6, value[i].len - 6);
- if (burst <= 0) {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "invalid burst rate \"%V\"", &value[i]);
- return NGX_CONF_ERROR;
- }
-
- continue;
- }
-
- if (ngx_strcmp(value[i].data, "nodelay") == 0) {
- nodelay = 1;
- continue;
- }
-
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "invalid parameter \"%V\"", &value[i]);
- return NGX_CONF_ERROR;
- }
-
- if (shm_zone == NULL) {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "\"%V\" must have \"zone\" parameter",
- &cmd->name);
- return NGX_CONF_ERROR;
- }
-
- limits = lrcf->limits.elts;
-
- if (limits == NULL) {
- if (ngx_array_init(&lrcf->limits, cf->pool, 1,
- sizeof(ngx_http_limit_req_limit_t))
- != NGX_OK)
- {
- return NGX_CONF_ERROR;
- }
- }
-
- for (i = 0; i < lrcf->limits.nelts; i++) {
- if (shm_zone == limits[i].shm_zone) {
- return "is duplicate";
- }
- }
-
- limit = ngx_array_push(&lrcf->limits);
- if (limit == NULL) {
- return NGX_CONF_ERROR;
- }
-
- limit->shm_zone = shm_zone;
- limit->burst = burst * 1000;
- limit->nodelay = nodelay;
-
- return NGX_CONF_OK;
-}
-
-
-static ngx_int_t
-ngx_http_limit_req_init(ngx_conf_t *cf)
-{
- ngx_http_handler_pt *h;
- ngx_http_core_main_conf_t *cmcf;
-
- cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);
-
- h = ngx_array_push(&cmcf->phases[NGX_HTTP_PREACCESS_PHASE].handlers);
- if (h == NULL) {
- return NGX_ERROR;
- }
-
- *h = ngx_http_limit_req_handler;
-
- return NGX_OK;
-}
diff --git a/nginx/src/http/modules/ngx_http_log_module.c b/nginx/src/http/modules/ngx_http_log_module.c
deleted file mode 100644
index f7c4bd2..0000000
--- a/nginx/src/http/modules/ngx_http_log_module.c
+++ /dev/null
@@ -1,1909 +0,0 @@
-
-/*
- * Copyright (C) Igor Sysoev
- * Copyright (C) Nginx, Inc.
- */
-
-
-#include <ngx_config.h>
-#include <ngx_core.h>
-#include <ngx_http.h>
-
-#if (NGX_ZLIB)
-#include <zlib.h>
-#endif
-
-
-typedef struct ngx_http_log_op_s ngx_http_log_op_t;
-
-typedef u_char *(*ngx_http_log_op_run_pt) (ngx_http_request_t *r, u_char *buf,
- ngx_http_log_op_t *op);
-
-typedef size_t (*ngx_http_log_op_getlen_pt) (ngx_http_request_t *r,
- uintptr_t data);
-
-
-struct ngx_http_log_op_s {
- size_t len;
- ngx_http_log_op_getlen_pt getlen;
- ngx_http_log_op_run_pt run;
- uintptr_t data;
-};
-
-
-typedef struct {
- ngx_str_t name;
- ngx_array_t *flushes;
- ngx_array_t *ops; /* array of ngx_http_log_op_t */
-} ngx_http_log_fmt_t;
-
-
-typedef struct {
- ngx_array_t formats; /* array of ngx_http_log_fmt_t */
- ngx_uint_t combined_used; /* unsigned combined_used:1 */
-} ngx_http_log_main_conf_t;
-
-
-typedef struct {
- u_char *start;
- u_char *pos;
- u_char *last;
-
- ngx_event_t *event;
- ngx_msec_t flush;
- ngx_int_t gzip;
-} ngx_http_log_buf_t;
-
-
-typedef struct {
- ngx_array_t *lengths;
- ngx_array_t *values;
-} ngx_http_log_script_t;
-
-
-typedef struct {
- ngx_open_file_t *file;
- ngx_http_log_script_t *script;
- time_t disk_full_time;
- time_t error_log_time;
- ngx_syslog_peer_t *syslog_peer;
- ngx_http_log_fmt_t *format;
- ngx_http_complex_value_t *filter;
-} ngx_http_log_t;
-
-
-typedef struct {
- ngx_array_t *logs; /* array of ngx_http_log_t */
-
- ngx_open_file_cache_t *open_file_cache;
- time_t open_file_cache_valid;
- ngx_uint_t open_file_cache_min_uses;
-
- ngx_uint_t off; /* unsigned off:1 */
-} ngx_http_log_loc_conf_t;
-
-
-typedef struct {
- ngx_str_t name;
- size_t len;
- ngx_http_log_op_run_pt run;
-} ngx_http_log_var_t;
-
-
-#define NGX_HTTP_LOG_ESCAPE_DEFAULT 0
-#define NGX_HTTP_LOG_ESCAPE_JSON 1
-#define NGX_HTTP_LOG_ESCAPE_NONE 2
-
-
-static void ngx_http_log_write(ngx_http_request_t *r, ngx_http_log_t *log,
- u_char *buf, size_t len);
-static ssize_t ngx_http_log_script_write(ngx_http_request_t *r,
- ngx_http_log_script_t *script, u_char **name, u_char *buf, size_t len);
-
-#if (NGX_ZLIB)
-static ssize_t ngx_http_log_gzip(ngx_fd_t fd, u_char *buf, size_t len,
- ngx_int_t level, ngx_log_t *log);
-
-static void *ngx_http_log_gzip_alloc(void *opaque, u_int items, u_int size);
-static void ngx_http_log_gzip_free(void *opaque, void *address);
-#endif
-
-static void ngx_http_log_flush(ngx_open_file_t *file, ngx_log_t *log);
-static void ngx_http_log_flush_handler(ngx_event_t *ev);
-
-static u_char *ngx_http_log_pipe(ngx_http_request_t *r, u_char *buf,
- ngx_http_log_op_t *op);
-static u_char *ngx_http_log_time(ngx_http_request_t *r, u_char *buf,
- ngx_http_log_op_t *op);
-static u_char *ngx_http_log_iso8601(ngx_http_request_t *r, u_char *buf,
- ngx_http_log_op_t *op);
-static u_char *ngx_http_log_msec(ngx_http_request_t *r, u_char *buf,
- ngx_http_log_op_t *op);
-static u_char *ngx_http_log_request_time(ngx_http_request_t *r, u_char *buf,
- ngx_http_log_op_t *op);
-static u_char *ngx_http_log_status(ngx_http_request_t *r, u_char *buf,
- ngx_http_log_op_t *op);
-static u_char *ngx_http_log_bytes_sent(ngx_http_request_t *r, u_char *buf,
- ngx_http_log_op_t *op);
-static u_char *ngx_http_log_body_bytes_sent(ngx_http_request_t *r,
- u_char *buf, ngx_http_log_op_t *op);
-static u_char *ngx_http_log_request_length(ngx_http_request_t *r, u_char *buf,
- ngx_http_log_op_t *op);
-
-static ngx_int_t ngx_http_log_variable_compile(ngx_conf_t *cf,
- ngx_http_log_op_t *op, ngx_str_t *value, ngx_uint_t escape);
-static size_t ngx_http_log_variable_getlen(ngx_http_request_t *r,
- uintptr_t data);
-static u_char *ngx_http_log_variable(ngx_http_request_t *r, u_char *buf,
- ngx_http_log_op_t *op);
-static uintptr_t ngx_http_log_escape(u_char *dst, u_char *src, size_t size);
-static size_t ngx_http_log_json_variable_getlen(ngx_http_request_t *r,
- uintptr_t data);
-static u_char *ngx_http_log_json_variable(ngx_http_request_t *r, u_char *buf,
- ngx_http_log_op_t *op);
-static size_t ngx_http_log_unescaped_variable_getlen(ngx_http_request_t *r,
- uintptr_t data);
-static u_char *ngx_http_log_unescaped_variable(ngx_http_request_t *r,
- u_char *buf, ngx_http_log_op_t *op);
-
-
-static void *ngx_http_log_create_main_conf(ngx_conf_t *cf);
-static void *ngx_http_log_create_loc_conf(ngx_conf_t *cf);
-static char *ngx_http_log_merge_loc_conf(ngx_conf_t *cf, void *parent,
- void *child);
-static char *ngx_http_log_set_log(ngx_conf_t *cf, ngx_command_t *cmd,
- void *conf);
-static char *ngx_http_log_set_format(ngx_conf_t *cf, ngx_command_t *cmd,
- void *conf);
-static char *ngx_http_log_compile_format(ngx_conf_t *cf,
- ngx_array_t *flushes, ngx_array_t *ops, ngx_array_t *args, ngx_uint_t s);
-static char *ngx_http_log_open_file_cache(ngx_conf_t *cf, ngx_command_t *cmd,
- void *conf);
-static ngx_int_t ngx_http_log_init(ngx_conf_t *cf);
-
-
-static ngx_command_t ngx_http_log_commands[] = {
-
- { ngx_string("log_format"),
- NGX_HTTP_MAIN_CONF|NGX_CONF_2MORE,
- ngx_http_log_set_format,
- NGX_HTTP_MAIN_CONF_OFFSET,
- 0,
- NULL },
-
- { ngx_string("access_log"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF
- |NGX_HTTP_LMT_CONF|NGX_CONF_1MORE,
- ngx_http_log_set_log,
- NGX_HTTP_LOC_CONF_OFFSET,
- 0,
- NULL },
-
- { ngx_string("open_log_file_cache"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1234,
- ngx_http_log_open_file_cache,
- NGX_HTTP_LOC_CONF_OFFSET,
- 0,
- NULL },
-
- ngx_null_command
-};
-
-
-static ngx_http_module_t ngx_http_log_module_ctx = {
- NULL, /* preconfiguration */
- ngx_http_log_init, /* postconfiguration */
-
- ngx_http_log_create_main_conf, /* create main configuration */
- NULL, /* init main configuration */
-
- NULL, /* create server configuration */
- NULL, /* merge server configuration */
-
- ngx_http_log_create_loc_conf, /* create location configuration */
- ngx_http_log_merge_loc_conf /* merge location configuration */
-};
-
-
-ngx_module_t ngx_http_log_module = {
- NGX_MODULE_V1,
- &ngx_http_log_module_ctx, /* module context */
- ngx_http_log_commands, /* module directives */
- NGX_HTTP_MODULE, /* module type */
- NULL, /* init master */
- NULL, /* init module */
- NULL, /* init process */
- NULL, /* init thread */
- NULL, /* exit thread */
- NULL, /* exit process */
- NULL, /* exit master */
- NGX_MODULE_V1_PADDING
-};
-
-
-static ngx_str_t ngx_http_access_log = ngx_string(NGX_HTTP_LOG_PATH);
-
-
-static ngx_str_t ngx_http_combined_fmt =
- ngx_string("$remote_addr - $remote_user [$time_local] "
- "\"$request\" $status $body_bytes_sent "
- "\"$http_referer\" \"$http_user_agent\"");
-
-
-static ngx_http_log_var_t ngx_http_log_vars[] = {
- { ngx_string("pipe"), 1, ngx_http_log_pipe },
- { ngx_string("time_local"), sizeof("28/Sep/1970:12:00:00 +0600") - 1,
- ngx_http_log_time },
- { ngx_string("time_iso8601"), sizeof("1970-09-28T12:00:00+06:00") - 1,
- ngx_http_log_iso8601 },
- { ngx_string("msec"), NGX_TIME_T_LEN + 4, ngx_http_log_msec },
- { ngx_string("request_time"), NGX_TIME_T_LEN + 4,
- ngx_http_log_request_time },
- { ngx_string("status"), NGX_INT_T_LEN, ngx_http_log_status },
- { ngx_string("bytes_sent"), NGX_OFF_T_LEN, ngx_http_log_bytes_sent },
- { ngx_string("body_bytes_sent"), NGX_OFF_T_LEN,
- ngx_http_log_body_bytes_sent },
- { ngx_string("request_length"), NGX_SIZE_T_LEN,
- ngx_http_log_request_length },
-
- { ngx_null_string, 0, NULL }
-};
-
-
-static ngx_int_t
-ngx_http_log_handler(ngx_http_request_t *r)
-{
- u_char *line, *p;
- size_t len, size;
- ssize_t n;
- ngx_str_t val;
- ngx_uint_t i, l;
- ngx_http_log_t *log;
- ngx_http_log_op_t *op;
- ngx_http_log_buf_t *buffer;
- ngx_http_log_loc_conf_t *lcf;
-
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "http log handler");
-
- lcf = ngx_http_get_module_loc_conf(r, ngx_http_log_module);
-
- if (lcf->off) {
- return NGX_OK;
- }
-
- log = lcf->logs->elts;
- for (l = 0; l < lcf->logs->nelts; l++) {
-
- if (log[l].filter) {
- if (ngx_http_complex_value(r, log[l].filter, &val) != NGX_OK) {
- return NGX_ERROR;
- }
-
- if (val.len == 0 || (val.len == 1 && val.data[0] == '0')) {
- continue;
- }
- }
-
- if (ngx_time() == log[l].disk_full_time) {
-
- /*
- * on FreeBSD writing to a full filesystem with enabled softupdates
- * may block process for much longer time than writing to non-full
- * filesystem, so we skip writing to a log for one second
- */
-
- continue;
- }
-
- ngx_http_script_flush_no_cacheable_variables(r, log[l].format->flushes);
-
- len = 0;
- op = log[l].format->ops->elts;
- for (i = 0; i < log[l].format->ops->nelts; i++) {
- if (op[i].len == 0) {
- len += op[i].getlen(r, op[i].data);
-
- } else {
- len += op[i].len;
- }
- }
-
- if (log[l].syslog_peer) {
-
- /* length of syslog's PRI and HEADER message parts */
- len += sizeof("<255>Jan 01 00:00:00 ") - 1
- + ngx_cycle->hostname.len + 1
- + log[l].syslog_peer->tag.len + 2;
-
- goto alloc_line;
- }
-
- len += NGX_LINEFEED_SIZE;
-
- buffer = log[l].file ? log[l].file->data : NULL;
-
- if (buffer) {
-
- if (len > (size_t) (buffer->last - buffer->pos)) {
-
- ngx_http_log_write(r, &log[l], buffer->start,
- buffer->pos - buffer->start);
-
- buffer->pos = buffer->start;
- }
-
- if (len <= (size_t) (buffer->last - buffer->pos)) {
-
- p = buffer->pos;
-
- if (buffer->event && p == buffer->start) {
- ngx_add_timer(buffer->event, buffer->flush);
- }
-
- for (i = 0; i < log[l].format->ops->nelts; i++) {
- p = op[i].run(r, p, &op[i]);
- }
-
- ngx_linefeed(p);
-
- buffer->pos = p;
-
- continue;
- }
-
- if (buffer->event && buffer->event->timer_set) {
- ngx_del_timer(buffer->event);
- }
- }
-
- alloc_line:
-
- line = ngx_pnalloc(r->pool, len);
- if (line == NULL) {
- return NGX_ERROR;
- }
-
- p = line;
-
- if (log[l].syslog_peer) {
- p = ngx_syslog_add_header(log[l].syslog_peer, line);
- }
-
- for (i = 0; i < log[l].format->ops->nelts; i++) {
- p = op[i].run(r, p, &op[i]);
- }
-
- if (log[l].syslog_peer) {
-
- size = p - line;
-
- n = ngx_syslog_send(log[l].syslog_peer, line, size);
-
- if (n < 0) {
- ngx_log_error(NGX_LOG_WARN, r->connection->log, 0,
- "send() to syslog failed");
-
- } else if ((size_t) n != size) {
- ngx_log_error(NGX_LOG_WARN, r->connection->log, 0,
- "send() to syslog has written only %z of %uz",
- n, size);
- }
-
- continue;
- }
-
- ngx_linefeed(p);
-
- ngx_http_log_write(r, &log[l], line, p - line);
- }
-
- return NGX_OK;
-}
-
-
-static void
-ngx_http_log_write(ngx_http_request_t *r, ngx_http_log_t *log, u_char *buf,
- size_t len)
-{
- u_char *name;
- time_t now;
- ssize_t n;
- ngx_err_t err;
-#if (NGX_ZLIB)
- ngx_http_log_buf_t *buffer;
-#endif
-
- if (log->script == NULL) {
- name = log->file->name.data;
-
-#if (NGX_ZLIB)
- buffer = log->file->data;
-
- if (buffer && buffer->gzip) {
- n = ngx_http_log_gzip(log->file->fd, buf, len, buffer->gzip,
- r->connection->log);
- } else {
- n = ngx_write_fd(log->file->fd, buf, len);
- }
-#else
- n = ngx_write_fd(log->file->fd, buf, len);
-#endif
-
- } else {
- name = NULL;
- n = ngx_http_log_script_write(r, log->script, &name, buf, len);
- }
-
- if (n == (ssize_t) len) {
- return;
- }
-
- now = ngx_time();
-
- if (n == -1) {
- err = ngx_errno;
-
- if (err == NGX_ENOSPC) {
- log->disk_full_time = now;
- }
-
- if (now - log->error_log_time > 59) {
- ngx_log_error(NGX_LOG_ALERT, r->connection->log, err,
- ngx_write_fd_n " to \"%s\" failed", name);
-
- log->error_log_time = now;
- }
-
- return;
- }
-
- if (now - log->error_log_time > 59) {
- ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
- ngx_write_fd_n " to \"%s\" was incomplete: %z of %uz",
- name, n, len);
-
- log->error_log_time = now;
- }
-}
-
-
-static ssize_t
-ngx_http_log_script_write(ngx_http_request_t *r, ngx_http_log_script_t *script,
- u_char **name, u_char *buf, size_t len)
-{
- size_t root;
- ssize_t n;
- ngx_str_t log, path;
- ngx_open_file_info_t of;
- ngx_http_log_loc_conf_t *llcf;
- ngx_http_core_loc_conf_t *clcf;
-
- clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
-
- if (!r->root_tested) {
-
- /* test root directory existence */
-
- if (ngx_http_map_uri_to_path(r, &path, &root, 0) == NULL) {
- /* simulate successful logging */
- return len;
- }
-
- path.data[root] = '\0';
-
- ngx_memzero(&of, sizeof(ngx_open_file_info_t));
-
- of.valid = clcf->open_file_cache_valid;
- of.min_uses = clcf->open_file_cache_min_uses;
- of.test_dir = 1;
- of.test_only = 1;
- of.errors = clcf->open_file_cache_errors;
- of.events = clcf->open_file_cache_events;
-
- if (ngx_http_set_disable_symlinks(r, clcf, &path, &of) != NGX_OK) {
- /* simulate successful logging */
- return len;
- }
-
- if (ngx_open_cached_file(clcf->open_file_cache, &path, &of, r->pool)
- != NGX_OK)
- {
- if (of.err == 0) {
- /* simulate successful logging */
- return len;
- }
-
- ngx_log_error(NGX_LOG_ERR, r->connection->log, of.err,
- "testing \"%s\" existence failed", path.data);
-
- /* simulate successful logging */
- return len;
- }
-
- if (!of.is_dir) {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, NGX_ENOTDIR,
- "testing \"%s\" existence failed", path.data);
-
- /* simulate successful logging */
- return len;
- }
- }
-
- if (ngx_http_script_run(r, &log, script->lengths->elts, 1,
- script->values->elts)
- == NULL)
- {
- /* simulate successful logging */
- return len;
- }
-
- log.data[log.len - 1] = '\0';
- *name = log.data;
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "http log \"%s\"", log.data);
-
- llcf = ngx_http_get_module_loc_conf(r, ngx_http_log_module);
-
- ngx_memzero(&of, sizeof(ngx_open_file_info_t));
-
- of.log = 1;
- of.valid = llcf->open_file_cache_valid;
- of.min_uses = llcf->open_file_cache_min_uses;
- of.directio = NGX_OPEN_FILE_DIRECTIO_OFF;
-
- if (ngx_http_set_disable_symlinks(r, clcf, &log, &of) != NGX_OK) {
- /* simulate successful logging */
- return len;
- }
-
- if (ngx_open_cached_file(llcf->open_file_cache, &log, &of, r->pool)
- != NGX_OK)
- {
- if (of.err == 0) {
- /* simulate successful logging */
- return len;
- }
-
- ngx_log_error(NGX_LOG_CRIT, r->connection->log, ngx_errno,
- "%s \"%s\" failed", of.failed, log.data);
- /* simulate successful logging */
- return len;
- }
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "http log #%d", of.fd);
-
- n = ngx_write_fd(of.fd, buf, len);
-
- return n;
-}
-
-
-#if (NGX_ZLIB)
-
-static ssize_t
-ngx_http_log_gzip(ngx_fd_t fd, u_char *buf, size_t len, ngx_int_t level,
- ngx_log_t *log)
-{
- int rc, wbits, memlevel;
- u_char *out;
- size_t size;
- ssize_t n;
- z_stream zstream;
- ngx_err_t err;
- ngx_pool_t *pool;
-
- wbits = MAX_WBITS;
- memlevel = MAX_MEM_LEVEL - 1;
-
- while ((ssize_t) len < ((1 << (wbits - 1)) - 262)) {
- wbits--;
- memlevel--;
- }
-
- /*
- * This is a formula from deflateBound() for conservative upper bound of
- * compressed data plus 18 bytes of gzip wrapper.
- */
-
- size = len + ((len + 7) >> 3) + ((len + 63) >> 6) + 5 + 18;
-
- ngx_memzero(&zstream, sizeof(z_stream));
-
- pool = ngx_create_pool(256, log);
- if (pool == NULL) {
- /* simulate successful logging */
- return len;
- }
-
- pool->log = log;
-
- zstream.zalloc = ngx_http_log_gzip_alloc;
- zstream.zfree = ngx_http_log_gzip_free;
- zstream.opaque = pool;
-
- out = ngx_pnalloc(pool, size);
- if (out == NULL) {
- goto done;
- }
-
- zstream.next_in = buf;
- zstream.avail_in = len;
- zstream.next_out = out;
- zstream.avail_out = size;
-
- rc = deflateInit2(&zstream, (int) level, Z_DEFLATED, wbits + 16, memlevel,
- Z_DEFAULT_STRATEGY);
-
- if (rc != Z_OK) {
- ngx_log_error(NGX_LOG_ALERT, log, 0, "deflateInit2() failed: %d", rc);
- goto done;
- }
-
- ngx_log_debug4(NGX_LOG_DEBUG_HTTP, log, 0,
- "deflate in: ni:%p no:%p ai:%ud ao:%ud",
- zstream.next_in, zstream.next_out,
- zstream.avail_in, zstream.avail_out);
-
- rc = deflate(&zstream, Z_FINISH);
-
- if (rc != Z_STREAM_END) {
- ngx_log_error(NGX_LOG_ALERT, log, 0,
- "deflate(Z_FINISH) failed: %d", rc);
- goto done;
- }
-
- ngx_log_debug5(NGX_LOG_DEBUG_HTTP, log, 0,
- "deflate out: ni:%p no:%p ai:%ud ao:%ud rc:%d",
- zstream.next_in, zstream.next_out,
- zstream.avail_in, zstream.avail_out,
- rc);
-
- size -= zstream.avail_out;
-
- rc = deflateEnd(&zstream);
-
- if (rc != Z_OK) {
- ngx_log_error(NGX_LOG_ALERT, log, 0, "deflateEnd() failed: %d", rc);
- goto done;
- }
-
- n = ngx_write_fd(fd, out, size);
-
- if (n != (ssize_t) size) {
- err = (n == -1) ? ngx_errno : 0;
-
- ngx_destroy_pool(pool);
-
- ngx_set_errno(err);
- return -1;
- }
-
-done:
-
- ngx_destroy_pool(pool);
-
- /* simulate successful logging */
- return len;
-}
-
-
-static void *
-ngx_http_log_gzip_alloc(void *opaque, u_int items, u_int size)
-{
- ngx_pool_t *pool = opaque;
-
- ngx_log_debug2(NGX_LOG_DEBUG_HTTP, pool->log, 0,
- "gzip alloc: n:%ud s:%ud", items, size);
-
- return ngx_palloc(pool, items * size);
-}
-
-
-static void
-ngx_http_log_gzip_free(void *opaque, void *address)
-{
-#if 0
- ngx_pool_t *pool = opaque;
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, pool->log, 0, "gzip free: %p", address);
-#endif
-}
-
-#endif
-
-
-static void
-ngx_http_log_flush(ngx_open_file_t *file, ngx_log_t *log)
-{
- size_t len;
- ssize_t n;
- ngx_http_log_buf_t *buffer;
-
- buffer = file->data;
-
- len = buffer->pos - buffer->start;
-
- if (len == 0) {
- return;
- }
-
-#if (NGX_ZLIB)
- if (buffer->gzip) {
- n = ngx_http_log_gzip(file->fd, buffer->start, len, buffer->gzip, log);
- } else {
- n = ngx_write_fd(file->fd, buffer->start, len);
- }
-#else
- n = ngx_write_fd(file->fd, buffer->start, len);
-#endif
-
- if (n == -1) {
- ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
- ngx_write_fd_n " to \"%s\" failed",
- file->name.data);
-
- } else if ((size_t) n != len) {
- ngx_log_error(NGX_LOG_ALERT, log, 0,
- ngx_write_fd_n " to \"%s\" was incomplete: %z of %uz",
- file->name.data, n, len);
- }
-
- buffer->pos = buffer->start;
-
- if (buffer->event && buffer->event->timer_set) {
- ngx_del_timer(buffer->event);
- }
-}
-
-
-static void
-ngx_http_log_flush_handler(ngx_event_t *ev)
-{
- ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ev->log, 0,
- "http log buffer flush handler");
-
- ngx_http_log_flush(ev->data, ev->log);
-}
-
-
-static u_char *
-ngx_http_log_copy_short(ngx_http_request_t *r, u_char *buf,
- ngx_http_log_op_t *op)
-{
- size_t len;
- uintptr_t data;
-
- len = op->len;
- data = op->data;
-
- while (len--) {
- *buf++ = (u_char) (data & 0xff);
- data >>= 8;
- }
-
- return buf;
-}
-
-
-static u_char *
-ngx_http_log_copy_long(ngx_http_request_t *r, u_char *buf,
- ngx_http_log_op_t *op)
-{
- return ngx_cpymem(buf, (u_char *) op->data, op->len);
-}
-
-
-static u_char *
-ngx_http_log_pipe(ngx_http_request_t *r, u_char *buf, ngx_http_log_op_t *op)
-{
- if (r->pipeline) {
- *buf = 'p';
- } else {
- *buf = '.';
- }
-
- return buf + 1;
-}
-
-
-static u_char *
-ngx_http_log_time(ngx_http_request_t *r, u_char *buf, ngx_http_log_op_t *op)
-{
- return ngx_cpymem(buf, ngx_cached_http_log_time.data,
- ngx_cached_http_log_time.len);
-}
-
-static u_char *
-ngx_http_log_iso8601(ngx_http_request_t *r, u_char *buf, ngx_http_log_op_t *op)
-{
- return ngx_cpymem(buf, ngx_cached_http_log_iso8601.data,
- ngx_cached_http_log_iso8601.len);
-}
-
-static u_char *
-ngx_http_log_msec(ngx_http_request_t *r, u_char *buf, ngx_http_log_op_t *op)
-{
- ngx_time_t *tp;
-
- tp = ngx_timeofday();
-
- return ngx_sprintf(buf, "%T.%03M", tp->sec, tp->msec);
-}
-
-
-static u_char *
-ngx_http_log_request_time(ngx_http_request_t *r, u_char *buf,
- ngx_http_log_op_t *op)
-{
- ngx_time_t *tp;
- ngx_msec_int_t ms;
-
- tp = ngx_timeofday();
-
- ms = (ngx_msec_int_t)
- ((tp->sec - r->start_sec) * 1000 + (tp->msec - r->start_msec));
- ms = ngx_max(ms, 0);
-
- return ngx_sprintf(buf, "%T.%03M", (time_t) ms / 1000, ms % 1000);
-}
-
-
-static u_char *
-ngx_http_log_status(ngx_http_request_t *r, u_char *buf, ngx_http_log_op_t *op)
-{
- ngx_uint_t status;
-
- if (r->err_status) {
- status = r->err_status;
-
- } else if (r->headers_out.status) {
- status = r->headers_out.status;
-
- } else if (r->http_version == NGX_HTTP_VERSION_9) {
- status = 9;
-
- } else {
- status = 0;
- }
-
- return ngx_sprintf(buf, "%03ui", status);
-}
-
-
-static u_char *
-ngx_http_log_bytes_sent(ngx_http_request_t *r, u_char *buf,
- ngx_http_log_op_t *op)
-{
- return ngx_sprintf(buf, "%O", r->connection->sent);
-}
-
-
-/*
- * although there is a real $body_bytes_sent variable,
- * this log operation code function is more optimized for logging
- */
-
-static u_char *
-ngx_http_log_body_bytes_sent(ngx_http_request_t *r, u_char *buf,
- ngx_http_log_op_t *op)
-{
- off_t length;
-
- length = r->connection->sent - r->header_size;
-
- if (length > 0) {
- return ngx_sprintf(buf, "%O", length);
- }
-
- *buf = '0';
-
- return buf + 1;
-}
-
-
-static u_char *
-ngx_http_log_request_length(ngx_http_request_t *r, u_char *buf,
- ngx_http_log_op_t *op)
-{
- return ngx_sprintf(buf, "%O", r->request_length);
-}
-
-
-static ngx_int_t
-ngx_http_log_variable_compile(ngx_conf_t *cf, ngx_http_log_op_t *op,
- ngx_str_t *value, ngx_uint_t escape)
-{
- ngx_int_t index;
-
- index = ngx_http_get_variable_index(cf, value);
- if (index == NGX_ERROR) {
- return NGX_ERROR;
- }
-
- op->len = 0;
-
- switch (escape) {
- case NGX_HTTP_LOG_ESCAPE_JSON:
- op->getlen = ngx_http_log_json_variable_getlen;
- op->run = ngx_http_log_json_variable;
- break;
-
- case NGX_HTTP_LOG_ESCAPE_NONE:
- op->getlen = ngx_http_log_unescaped_variable_getlen;
- op->run = ngx_http_log_unescaped_variable;
- break;
-
- default: /* NGX_HTTP_LOG_ESCAPE_DEFAULT */
- op->getlen = ngx_http_log_variable_getlen;
- op->run = ngx_http_log_variable;
- }
-
- op->data = index;
-
- return NGX_OK;
-}
-
-
-static size_t
-ngx_http_log_variable_getlen(ngx_http_request_t *r, uintptr_t data)
-{
- uintptr_t len;
- ngx_http_variable_value_t *value;
-
- value = ngx_http_get_indexed_variable(r, data);
-
- if (value == NULL || value->not_found) {
- return 1;
- }
-
- len = ngx_http_log_escape(NULL, value->data, value->len);
-
- value->escape = len ? 1 : 0;
-
- return value->len + len * 3;
-}
-
-
-static u_char *
-ngx_http_log_variable(ngx_http_request_t *r, u_char *buf, ngx_http_log_op_t *op)
-{
- ngx_http_variable_value_t *value;
-
- value = ngx_http_get_indexed_variable(r, op->data);
-
- if (value == NULL || value->not_found) {
- *buf = '-';
- return buf + 1;
- }
-
- if (value->escape == 0) {
- return ngx_cpymem(buf, value->data, value->len);
-
- } else {
- return (u_char *) ngx_http_log_escape(buf, value->data, value->len);
- }
-}
-
-
-static uintptr_t
-ngx_http_log_escape(u_char *dst, u_char *src, size_t size)
-{
- ngx_uint_t n;
- static u_char hex[] = "0123456789ABCDEF";
-
- static uint32_t escape[] = {
- 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */
-
- /* ?>=< ;:98 7654 3210 /.-, +*)( '&%$ #"! */
- 0x00000004, /* 0000 0000 0000 0000 0000 0000 0000 0100 */
-
- /* _^]\ [ZYX WVUT SRQP ONML KJIH GFED CBA@ */
- 0x10000000, /* 0001 0000 0000 0000 0000 0000 0000 0000 */
-
- /* ~}| {zyx wvut srqp onml kjih gfed cba` */
- 0x80000000, /* 1000 0000 0000 0000 0000 0000 0000 0000 */
-
- 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */
- 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */
- 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */
- 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */
- };
-
-
- if (dst == NULL) {
-
- /* find the number of the characters to be escaped */
-
- n = 0;
-
- while (size) {
- if (escape[*src >> 5] & (1U << (*src & 0x1f))) {
- n++;
- }
- src++;
- size--;
- }
-
- return (uintptr_t) n;
- }
-
- while (size) {
- if (escape[*src >> 5] & (1U << (*src & 0x1f))) {
- *dst++ = '\\';
- *dst++ = 'x';
- *dst++ = hex[*src >> 4];
- *dst++ = hex[*src & 0xf];
- src++;
-
- } else {
- *dst++ = *src++;
- }
- size--;
- }
-
- return (uintptr_t) dst;
-}
-
-
-static size_t
-ngx_http_log_json_variable_getlen(ngx_http_request_t *r, uintptr_t data)
-{
- uintptr_t len;
- ngx_http_variable_value_t *value;
-
- value = ngx_http_get_indexed_variable(r, data);
-
- if (value == NULL || value->not_found) {
- return 0;
- }
-
- len = ngx_escape_json(NULL, value->data, value->len);
-
- value->escape = len ? 1 : 0;
-
- return value->len + len;
-}
-
-
-static u_char *
-ngx_http_log_json_variable(ngx_http_request_t *r, u_char *buf,
- ngx_http_log_op_t *op)
-{
- ngx_http_variable_value_t *value;
-
- value = ngx_http_get_indexed_variable(r, op->data);
-
- if (value == NULL || value->not_found) {
- return buf;
- }
-
- if (value->escape == 0) {
- return ngx_cpymem(buf, value->data, value->len);
-
- } else {
- return (u_char *) ngx_escape_json(buf, value->data, value->len);
- }
-}
-
-
-static size_t
-ngx_http_log_unescaped_variable_getlen(ngx_http_request_t *r, uintptr_t data)
-{
- ngx_http_variable_value_t *value;
-
- value = ngx_http_get_indexed_variable(r, data);
-
- if (value == NULL || value->not_found) {
- return 0;
- }
-
- value->escape = 0;
-
- return value->len;
-}
-
-
-static u_char *
-ngx_http_log_unescaped_variable(ngx_http_request_t *r, u_char *buf,
- ngx_http_log_op_t *op)
-{
- ngx_http_variable_value_t *value;
-
- value = ngx_http_get_indexed_variable(r, op->data);
-
- if (value == NULL || value->not_found) {
- return buf;
- }
-
- return ngx_cpymem(buf, value->data, value->len);
-}
-
-
-static void *
-ngx_http_log_create_main_conf(ngx_conf_t *cf)
-{
- ngx_http_log_main_conf_t *conf;
-
- ngx_http_log_fmt_t *fmt;
-
- conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_log_main_conf_t));
- if (conf == NULL) {
- return NULL;
- }
-
- if (ngx_array_init(&conf->formats, cf->pool, 4, sizeof(ngx_http_log_fmt_t))
- != NGX_OK)
- {
- return NULL;
- }
-
- fmt = ngx_array_push(&conf->formats);
- if (fmt == NULL) {
- return NULL;
- }
-
- ngx_str_set(&fmt->name, "combined");
-
- fmt->flushes = NULL;
-
- fmt->ops = ngx_array_create(cf->pool, 16, sizeof(ngx_http_log_op_t));
- if (fmt->ops == NULL) {
- return NULL;
- }
-
- return conf;
-}
-
-
-static void *
-ngx_http_log_create_loc_conf(ngx_conf_t *cf)
-{
- ngx_http_log_loc_conf_t *conf;
-
- conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_log_loc_conf_t));
- if (conf == NULL) {
- return NULL;
- }
-
- conf->open_file_cache = NGX_CONF_UNSET_PTR;
-
- return conf;
-}
-
-
-static char *
-ngx_http_log_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
-{
- ngx_http_log_loc_conf_t *prev = parent;
- ngx_http_log_loc_conf_t *conf = child;
-
- ngx_http_log_t *log;
- ngx_http_log_fmt_t *fmt;
- ngx_http_log_main_conf_t *lmcf;
-
- if (conf->open_file_cache == NGX_CONF_UNSET_PTR) {
-
- conf->open_file_cache = prev->open_file_cache;
- conf->open_file_cache_valid = prev->open_file_cache_valid;
- conf->open_file_cache_min_uses = prev->open_file_cache_min_uses;
-
- if (conf->open_file_cache == NGX_CONF_UNSET_PTR) {
- conf->open_file_cache = NULL;
- }
- }
-
- if (conf->logs || conf->off) {
- return NGX_CONF_OK;
- }
-
- conf->logs = prev->logs;
- conf->off = prev->off;
-
- if (conf->logs || conf->off) {
- return NGX_CONF_OK;
- }
-
- conf->logs = ngx_array_create(cf->pool, 2, sizeof(ngx_http_log_t));
- if (conf->logs == NULL) {
- return NGX_CONF_ERROR;
- }
-
- log = ngx_array_push(conf->logs);
- if (log == NULL) {
- return NGX_CONF_ERROR;
- }
-
- ngx_memzero(log, sizeof(ngx_http_log_t));
-
- log->file = ngx_conf_open_file(cf->cycle, &ngx_http_access_log);
- if (log->file == NULL) {
- return NGX_CONF_ERROR;
- }
-
- lmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_log_module);
- fmt = lmcf->formats.elts;
-
- /* the default "combined" format */
- log->format = &fmt[0];
- lmcf->combined_used = 1;
-
- return NGX_CONF_OK;
-}
-
-
-static char *
-ngx_http_log_set_log(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
-{
- ngx_http_log_loc_conf_t *llcf = conf;
-
- ssize_t size;
- ngx_int_t gzip;
- ngx_uint_t i, n;
- ngx_msec_t flush;
- ngx_str_t *value, name, s;
- ngx_http_log_t *log;
- ngx_syslog_peer_t *peer;
- ngx_http_log_buf_t *buffer;
- ngx_http_log_fmt_t *fmt;
- ngx_http_log_main_conf_t *lmcf;
- ngx_http_script_compile_t sc;
- ngx_http_compile_complex_value_t ccv;
-
- value = cf->args->elts;
-
- if (ngx_strcmp(value[1].data, "off") == 0) {
- llcf->off = 1;
- if (cf->args->nelts == 2) {
- return NGX_CONF_OK;
- }
-
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "invalid parameter \"%V\"", &value[2]);
- return NGX_CONF_ERROR;
- }
-
- if (llcf->logs == NULL) {
- llcf->logs = ngx_array_create(cf->pool, 2, sizeof(ngx_http_log_t));
- if (llcf->logs == NULL) {
- return NGX_CONF_ERROR;
- }
- }
-
- lmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_log_module);
-
- log = ngx_array_push(llcf->logs);
- if (log == NULL) {
- return NGX_CONF_ERROR;
- }
-
- ngx_memzero(log, sizeof(ngx_http_log_t));
-
-
- if (ngx_strncmp(value[1].data, "syslog:", 7) == 0) {
-
- peer = ngx_pcalloc(cf->pool, sizeof(ngx_syslog_peer_t));
- if (peer == NULL) {
- return NGX_CONF_ERROR;
- }
-
- if (ngx_syslog_process_conf(cf, peer) != NGX_CONF_OK) {
- return NGX_CONF_ERROR;
- }
-
- log->syslog_peer = peer;
-
- goto process_formats;
- }
-
- n = ngx_http_script_variables_count(&value[1]);
-
- if (n == 0) {
- log->file = ngx_conf_open_file(cf->cycle, &value[1]);
- if (log->file == NULL) {
- return NGX_CONF_ERROR;
- }
-
- } else {
- if (ngx_conf_full_name(cf->cycle, &value[1], 0) != NGX_OK) {
- return NGX_CONF_ERROR;
- }
-
- log->script = ngx_pcalloc(cf->pool, sizeof(ngx_http_log_script_t));
- if (log->script == NULL) {
- return NGX_CONF_ERROR;
- }
-
- ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));
-
- sc.cf = cf;
- sc.source = &value[1];
- sc.lengths = &log->script->lengths;
- sc.values = &log->script->values;
- sc.variables = n;
- sc.complete_lengths = 1;
- sc.complete_values = 1;
-
- if (ngx_http_script_compile(&sc) != NGX_OK) {
- return NGX_CONF_ERROR;
- }
- }
-
-process_formats:
-
- if (cf->args->nelts >= 3) {
- name = value[2];
-
- if (ngx_strcmp(name.data, "combined") == 0) {
- lmcf->combined_used = 1;
- }
-
- } else {
- ngx_str_set(&name, "combined");
- lmcf->combined_used = 1;
- }
-
- fmt = lmcf->formats.elts;
- for (i = 0; i < lmcf->formats.nelts; i++) {
- if (fmt[i].name.len == name.len
- && ngx_strcasecmp(fmt[i].name.data, name.data) == 0)
- {
- log->format = &fmt[i];
- break;
- }
- }
-
- if (log->format == NULL) {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "unknown log format \"%V\"", &name);
- return NGX_CONF_ERROR;
- }
-
- size = 0;
- flush = 0;
- gzip = 0;
-
- for (i = 3; i < cf->args->nelts; i++) {
-
- if (ngx_strncmp(value[i].data, "buffer=", 7) == 0) {
- s.len = value[i].len - 7;
- s.data = value[i].data + 7;
-
- size = ngx_parse_size(&s);
-
- if (size == NGX_ERROR || size == 0) {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "invalid buffer size \"%V\"", &s);
- return NGX_CONF_ERROR;
- }
-
- continue;
- }
-
- if (ngx_strncmp(value[i].data, "flush=", 6) == 0) {
- s.len = value[i].len - 6;
- s.data = value[i].data + 6;
-
- flush = ngx_parse_time(&s, 0);
-
- if (flush == (ngx_msec_t) NGX_ERROR || flush == 0) {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "invalid flush time \"%V\"", &s);
- return NGX_CONF_ERROR;
- }
-
- continue;
- }
-
- if (ngx_strncmp(value[i].data, "gzip", 4) == 0
- && (value[i].len == 4 || value[i].data[4] == '='))
- {
-#if (NGX_ZLIB)
- if (size == 0) {
- size = 64 * 1024;
- }
-
- if (value[i].len == 4) {
- gzip = Z_BEST_SPEED;
- continue;
- }
-
- s.len = value[i].len - 5;
- s.data = value[i].data + 5;
-
- gzip = ngx_atoi(s.data, s.len);
-
- if (gzip < 1 || gzip > 9) {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "invalid compression level \"%V\"", &s);
- return NGX_CONF_ERROR;
- }
-
- continue;
-
-#else
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "nginx was built without zlib support");
- return NGX_CONF_ERROR;
-#endif
- }
-
- if (ngx_strncmp(value[i].data, "if=", 3) == 0) {
- s.len = value[i].len - 3;
- s.data = value[i].data + 3;
-
- ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));
-
- ccv.cf = cf;
- ccv.value = &s;
- ccv.complex_value = ngx_palloc(cf->pool,
- sizeof(ngx_http_complex_value_t));
- if (ccv.complex_value == NULL) {
- return NGX_CONF_ERROR;
- }
-
- if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
- return NGX_CONF_ERROR;
- }
-
- log->filter = ccv.complex_value;
-
- continue;
- }
-
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "invalid parameter \"%V\"", &value[i]);
- return NGX_CONF_ERROR;
- }
-
- if (flush && size == 0) {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "no buffer is defined for access_log \"%V\"",
- &value[1]);
- return NGX_CONF_ERROR;
- }
-
- if (size) {
-
- if (log->script) {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "buffered logs cannot have variables in name");
- return NGX_CONF_ERROR;
- }
-
- if (log->syslog_peer) {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "logs to syslog cannot be buffered");
- return NGX_CONF_ERROR;
- }
-
- if (log->file->data) {
- buffer = log->file->data;
-
- if (buffer->last - buffer->start != size
- || buffer->flush != flush
- || buffer->gzip != gzip)
- {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "access_log \"%V\" already defined "
- "with conflicting parameters",
- &value[1]);
- return NGX_CONF_ERROR;
- }
-
- return NGX_CONF_OK;
- }
-
- buffer = ngx_pcalloc(cf->pool, sizeof(ngx_http_log_buf_t));
- if (buffer == NULL) {
- return NGX_CONF_ERROR;
- }
-
- buffer->start = ngx_pnalloc(cf->pool, size);
- if (buffer->start == NULL) {
- return NGX_CONF_ERROR;
- }
-
- buffer->pos = buffer->start;
- buffer->last = buffer->start + size;
-
- if (flush) {
- buffer->event = ngx_pcalloc(cf->pool, sizeof(ngx_event_t));
- if (buffer->event == NULL) {
- return NGX_CONF_ERROR;
- }
-
- buffer->event->data = log->file;
- buffer->event->handler = ngx_http_log_flush_handler;
- buffer->event->log = &cf->cycle->new_log;
- buffer->event->cancelable = 1;
-
- buffer->flush = flush;
- }
-
- buffer->gzip = gzip;
-
- log->file->flush = ngx_http_log_flush;
- log->file->data = buffer;
- }
-
- return NGX_CONF_OK;
-}
-
-
-static char *
-ngx_http_log_set_format(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
-{
- ngx_http_log_main_conf_t *lmcf = conf;
-
- ngx_str_t *value;
- ngx_uint_t i;
- ngx_http_log_fmt_t *fmt;
-
- value = cf->args->elts;
-
- fmt = lmcf->formats.elts;
- for (i = 0; i < lmcf->formats.nelts; i++) {
- if (fmt[i].name.len == value[1].len
- && ngx_strcmp(fmt[i].name.data, value[1].data) == 0)
- {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "duplicate \"log_format\" name \"%V\"",
- &value[1]);
- return NGX_CONF_ERROR;
- }
- }
-
- fmt = ngx_array_push(&lmcf->formats);
- if (fmt == NULL) {
- return NGX_CONF_ERROR;
- }
-
- fmt->name = value[1];
-
- fmt->flushes = ngx_array_create(cf->pool, 4, sizeof(ngx_int_t));
- if (fmt->flushes == NULL) {
- return NGX_CONF_ERROR;
- }
-
- fmt->ops = ngx_array_create(cf->pool, 16, sizeof(ngx_http_log_op_t));
- if (fmt->ops == NULL) {
- return NGX_CONF_ERROR;
- }
-
- return ngx_http_log_compile_format(cf, fmt->flushes, fmt->ops, cf->args, 2);
-}
-
-
-static char *
-ngx_http_log_compile_format(ngx_conf_t *cf, ngx_array_t *flushes,
- ngx_array_t *ops, ngx_array_t *args, ngx_uint_t s)
-{
- u_char *data, *p, ch;
- size_t i, len;
- ngx_str_t *value, var;
- ngx_int_t *flush;
- ngx_uint_t bracket, escape;
- ngx_http_log_op_t *op;
- ngx_http_log_var_t *v;
-
- escape = NGX_HTTP_LOG_ESCAPE_DEFAULT;
- value = args->elts;
-
- if (s < args->nelts && ngx_strncmp(value[s].data, "escape=", 7) == 0) {
- data = value[s].data + 7;
-
- if (ngx_strcmp(data, "json") == 0) {
- escape = NGX_HTTP_LOG_ESCAPE_JSON;
-
- } else if (ngx_strcmp(data, "none") == 0) {
- escape = NGX_HTTP_LOG_ESCAPE_NONE;
-
- } else if (ngx_strcmp(data, "default") != 0) {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "unknown log format escaping \"%s\"", data);
- return NGX_CONF_ERROR;
- }
-
- s++;
- }
-
- for ( /* void */ ; s < args->nelts; s++) {
-
- i = 0;
-
- while (i < value[s].len) {
-
- op = ngx_array_push(ops);
- if (op == NULL) {
- return NGX_CONF_ERROR;
- }
-
- data = &value[s].data[i];
-
- if (value[s].data[i] == '$') {
-
- if (++i == value[s].len) {
- goto invalid;
- }
-
- if (value[s].data[i] == '{') {
- bracket = 1;
-
- if (++i == value[s].len) {
- goto invalid;
- }
-
- var.data = &value[s].data[i];
-
- } else {
- bracket = 0;
- var.data = &value[s].data[i];
- }
-
- for (var.len = 0; i < value[s].len; i++, var.len++) {
- ch = value[s].data[i];
-
- if (ch == '}' && bracket) {
- i++;
- bracket = 0;
- break;
- }
-
- if ((ch >= 'A' && ch <= 'Z')
- || (ch >= 'a' && ch <= 'z')
- || (ch >= '0' && ch <= '9')
- || ch == '_')
- {
- continue;
- }
-
- break;
- }
-
- if (bracket) {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "the closing bracket in \"%V\" "
- "variable is missing", &var);
- return NGX_CONF_ERROR;
- }
-
- if (var.len == 0) {
- goto invalid;
- }
-
- for (v = ngx_http_log_vars; v->name.len; v++) {
-
- if (v->name.len == var.len
- && ngx_strncmp(v->name.data, var.data, var.len) == 0)
- {
- op->len = v->len;
- op->getlen = NULL;
- op->run = v->run;
- op->data = 0;
-
- goto found;
- }
- }
-
- if (ngx_http_log_variable_compile(cf, op, &var, escape)
- != NGX_OK)
- {
- return NGX_CONF_ERROR;
- }
-
- if (flushes) {
-
- flush = ngx_array_push(flushes);
- if (flush == NULL) {
- return NGX_CONF_ERROR;
- }
-
- *flush = op->data; /* variable index */
- }
-
- found:
-
- continue;
- }
-
- i++;
-
- while (i < value[s].len && value[s].data[i] != '$') {
- i++;
- }
-
- len = &value[s].data[i] - data;
-
- if (len) {
-
- op->len = len;
- op->getlen = NULL;
-
- if (len <= sizeof(uintptr_t)) {
- op->run = ngx_http_log_copy_short;
- op->data = 0;
-
- while (len--) {
- op->data <<= 8;
- op->data |= data[len];
- }
-
- } else {
- op->run = ngx_http_log_copy_long;
-
- p = ngx_pnalloc(cf->pool, len);
- if (p == NULL) {
- return NGX_CONF_ERROR;
- }
-
- ngx_memcpy(p, data, len);
- op->data = (uintptr_t) p;
- }
- }
- }
- }
-
- return NGX_CONF_OK;
-
-invalid:
-
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid parameter \"%s\"", data);
-
- return NGX_CONF_ERROR;
-}
-
-
-static char *
-ngx_http_log_open_file_cache(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
-{
- ngx_http_log_loc_conf_t *llcf = conf;
-
- time_t inactive, valid;
- ngx_str_t *value, s;
- ngx_int_t max, min_uses;
- ngx_uint_t i;
-
- if (llcf->open_file_cache != NGX_CONF_UNSET_PTR) {
- return "is duplicate";
- }
-
- value = cf->args->elts;
-
- max = 0;
- inactive = 10;
- valid = 60;
- min_uses = 1;
-
- for (i = 1; i < cf->args->nelts; i++) {
-
- if (ngx_strncmp(value[i].data, "max=", 4) == 0) {
-
- max = ngx_atoi(value[i].data + 4, value[i].len - 4);
- if (max == NGX_ERROR) {
- goto failed;
- }
-
- continue;
- }
-
- if (ngx_strncmp(value[i].data, "inactive=", 9) == 0) {
-
- s.len = value[i].len - 9;
- s.data = value[i].data + 9;
-
- inactive = ngx_parse_time(&s, 1);
- if (inactive == (time_t) NGX_ERROR) {
- goto failed;
- }
-
- continue;
- }
-
- if (ngx_strncmp(value[i].data, "min_uses=", 9) == 0) {
-
- min_uses = ngx_atoi(value[i].data + 9, value[i].len - 9);
- if (min_uses == NGX_ERROR) {
- goto failed;
- }
-
- continue;
- }
-
- if (ngx_strncmp(value[i].data, "valid=", 6) == 0) {
-
- s.len = value[i].len - 6;
- s.data = value[i].data + 6;
-
- valid = ngx_parse_time(&s, 1);
- if (valid == (time_t) NGX_ERROR) {
- goto failed;
- }
-
- continue;
- }
-
- if (ngx_strcmp(value[i].data, "off") == 0) {
-
- llcf->open_file_cache = NULL;
-
- continue;
- }
-
- failed:
-
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "invalid \"open_log_file_cache\" parameter \"%V\"",
- &value[i]);
- return NGX_CONF_ERROR;
- }
-
- if (llcf->open_file_cache == NULL) {
- return NGX_CONF_OK;
- }
-
- if (max == 0) {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "\"open_log_file_cache\" must have \"max\" parameter");
- return NGX_CONF_ERROR;
- }
-
- llcf->open_file_cache = ngx_open_file_cache_init(cf->pool, max, inactive);
-
- if (llcf->open_file_cache) {
-
- llcf->open_file_cache_valid = valid;
- llcf->open_file_cache_min_uses = min_uses;
-
- return NGX_CONF_OK;
- }
-
- return NGX_CONF_ERROR;
-}
-
-
-static ngx_int_t
-ngx_http_log_init(ngx_conf_t *cf)
-{
- ngx_str_t *value;
- ngx_array_t a;
- ngx_http_handler_pt *h;
- ngx_http_log_fmt_t *fmt;
- ngx_http_log_main_conf_t *lmcf;
- ngx_http_core_main_conf_t *cmcf;
-
- lmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_log_module);
-
- if (lmcf->combined_used) {
- if (ngx_array_init(&a, cf->pool, 1, sizeof(ngx_str_t)) != NGX_OK) {
- return NGX_ERROR;
- }
-
- value = ngx_array_push(&a);
- if (value == NULL) {
- return NGX_ERROR;
- }
-
- *value = ngx_http_combined_fmt;
- fmt = lmcf->formats.elts;
-
- if (ngx_http_log_compile_format(cf, NULL, fmt->ops, &a, 0)
- != NGX_CONF_OK)
- {
- return NGX_ERROR;
- }
- }
-
- cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);
-
- h = ngx_array_push(&cmcf->phases[NGX_HTTP_LOG_PHASE].handlers);
- if (h == NULL) {
- return NGX_ERROR;
- }
-
- *h = ngx_http_log_handler;
-
- return NGX_OK;
-}
diff --git a/nginx/src/http/modules/ngx_http_map_module.c b/nginx/src/http/modules/ngx_http_map_module.c
deleted file mode 100644
index 2fc9be9..0000000
--- a/nginx/src/http/modules/ngx_http_map_module.c
+++ /dev/null
@@ -1,589 +0,0 @@
-
-/*
- * Copyright (C) Igor Sysoev
- * Copyright (C) Nginx, Inc.
- */
-
-
-#include <ngx_config.h>
-#include <ngx_core.h>
-#include <ngx_http.h>
-
-
-typedef struct {
- ngx_uint_t hash_max_size;
- ngx_uint_t hash_bucket_size;
-} ngx_http_map_conf_t;
-
-
-typedef struct {
- ngx_hash_keys_arrays_t keys;
-
- ngx_array_t *values_hash;
-#if (NGX_PCRE)
- ngx_array_t regexes;
-#endif
-
- ngx_http_variable_value_t *default_value;
- ngx_conf_t *cf;
- unsigned hostnames:1;
- unsigned no_cacheable:1;
-} ngx_http_map_conf_ctx_t;
-
-
-typedef struct {
- ngx_http_map_t map;
- ngx_http_complex_value_t value;
- ngx_http_variable_value_t *default_value;
- ngx_uint_t hostnames; /* unsigned hostnames:1 */
-} ngx_http_map_ctx_t;
-
-
-static int ngx_libc_cdecl ngx_http_map_cmp_dns_wildcards(const void *one,
- const void *two);
-static void *ngx_http_map_create_conf(ngx_conf_t *cf);
-static char *ngx_http_map_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
-static char *ngx_http_map(ngx_conf_t *cf, ngx_command_t *dummy, void *conf);
-
-
-static ngx_command_t ngx_http_map_commands[] = {
-
- { ngx_string("map"),
- NGX_HTTP_MAIN_CONF|NGX_CONF_BLOCK|NGX_CONF_TAKE2,
- ngx_http_map_block,
- NGX_HTTP_MAIN_CONF_OFFSET,
- 0,
- NULL },
-
- { ngx_string("map_hash_max_size"),
- NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_num_slot,
- NGX_HTTP_MAIN_CONF_OFFSET,
- offsetof(ngx_http_map_conf_t, hash_max_size),
- NULL },
-
- { ngx_string("map_hash_bucket_size"),
- NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_num_slot,
- NGX_HTTP_MAIN_CONF_OFFSET,
- offsetof(ngx_http_map_conf_t, hash_bucket_size),
- NULL },
-
- ngx_null_command
-};
-
-
-static ngx_http_module_t ngx_http_map_module_ctx = {
- NULL, /* preconfiguration */
- NULL, /* postconfiguration */
-
- ngx_http_map_create_conf, /* create main configuration */
- NULL, /* init main configuration */
-
- NULL, /* create server configuration */
- NULL, /* merge server configuration */
-
- NULL, /* create location configuration */
- NULL /* merge location configuration */
-};
-
-
-ngx_module_t ngx_http_map_module = {
- NGX_MODULE_V1,
- &ngx_http_map_module_ctx, /* module context */
- ngx_http_map_commands, /* module directives */
- NGX_HTTP_MODULE, /* module type */
- NULL, /* init master */
- NULL, /* init module */
- NULL, /* init process */
- NULL, /* init thread */
- NULL, /* exit thread */
- NULL, /* exit process */
- NULL, /* exit master */
- NGX_MODULE_V1_PADDING
-};
-
-
-static ngx_int_t
-ngx_http_map_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v,
- uintptr_t data)
-{
- ngx_http_map_ctx_t *map = (ngx_http_map_ctx_t *) data;
-
- ngx_str_t val, str;
- ngx_http_complex_value_t *cv;
- ngx_http_variable_value_t *value;
-
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "http map started");
-
- if (ngx_http_complex_value(r, &map->value, &val) != NGX_OK) {
- return NGX_ERROR;
- }
-
- if (map->hostnames && val.len > 0 && val.data[val.len - 1] == '.') {
- val.len--;
- }
-
- value = ngx_http_map_find(r, &map->map, &val);
-
- if (value == NULL) {
- value = map->default_value;
- }
-
- if (!value->valid) {
- cv = (ngx_http_complex_value_t *) value->data;
-
- if (ngx_http_complex_value(r, cv, &str) != NGX_OK) {
- return NGX_ERROR;
- }
-
- v->valid = 1;
- v->no_cacheable = 0;
- v->not_found = 0;
- v->len = str.len;
- v->data = str.data;
-
- } else {
- *v = *value;
- }
-
- ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "http map: \"%V\" \"%v\"", &val, v);
-
- return NGX_OK;
-}
-
-
-static void *
-ngx_http_map_create_conf(ngx_conf_t *cf)
-{
- ngx_http_map_conf_t *mcf;
-
- mcf = ngx_palloc(cf->pool, sizeof(ngx_http_map_conf_t));
- if (mcf == NULL) {
- return NULL;
- }
-
- mcf->hash_max_size = NGX_CONF_UNSET_UINT;
- mcf->hash_bucket_size = NGX_CONF_UNSET_UINT;
-
- return mcf;
-}
-
-
-static char *
-ngx_http_map_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
-{
- ngx_http_map_conf_t *mcf = conf;
-
- char *rv;
- ngx_str_t *value, name;
- ngx_conf_t save;
- ngx_pool_t *pool;
- ngx_hash_init_t hash;
- ngx_http_map_ctx_t *map;
- ngx_http_variable_t *var;
- ngx_http_map_conf_ctx_t ctx;
- ngx_http_compile_complex_value_t ccv;
-
- if (mcf->hash_max_size == NGX_CONF_UNSET_UINT) {
- mcf->hash_max_size = 2048;
- }
-
- if (mcf->hash_bucket_size == NGX_CONF_UNSET_UINT) {
- mcf->hash_bucket_size = ngx_cacheline_size;
-
- } else {
- mcf->hash_bucket_size = ngx_align(mcf->hash_bucket_size,
- ngx_cacheline_size);
- }
-
- map = ngx_pcalloc(cf->pool, sizeof(ngx_http_map_ctx_t));
- if (map == NULL) {
- return NGX_CONF_ERROR;
- }
-
- value = cf->args->elts;
-
- ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));
-
- ccv.cf = cf;
- ccv.value = &value[1];
- ccv.complex_value = &map->value;
-
- if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
- return NGX_CONF_ERROR;
- }
-
- name = value[2];
-
- if (name.data[0] != '$') {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "invalid variable name \"%V\"", &name);
- return NGX_CONF_ERROR;
- }
-
- name.len--;
- name.data++;
-
- var = ngx_http_add_variable(cf, &name, NGX_HTTP_VAR_CHANGEABLE);
- if (var == NULL) {
- return NGX_CONF_ERROR;
- }
-
- var->get_handler = ngx_http_map_variable;
- var->data = (uintptr_t) map;
-
- pool = ngx_create_pool(NGX_DEFAULT_POOL_SIZE, cf->log);
- if (pool == NULL) {
- return NGX_CONF_ERROR;
- }
-
- ctx.keys.pool = cf->pool;
- ctx.keys.temp_pool = pool;
-
- if (ngx_hash_keys_array_init(&ctx.keys, NGX_HASH_LARGE) != NGX_OK) {
- ngx_destroy_pool(pool);
- return NGX_CONF_ERROR;
- }
-
- ctx.values_hash = ngx_pcalloc(pool, sizeof(ngx_array_t) * ctx.keys.hsize);
- if (ctx.values_hash == NULL) {
- ngx_destroy_pool(pool);
- return NGX_CONF_ERROR;
- }
-
-#if (NGX_PCRE)
- if (ngx_array_init(&ctx.regexes, cf->pool, 2, sizeof(ngx_http_map_regex_t))
- != NGX_OK)
- {
- ngx_destroy_pool(pool);
- return NGX_CONF_ERROR;
- }
-#endif
-
- ctx.default_value = NULL;
- ctx.cf = &save;
- ctx.hostnames = 0;
- ctx.no_cacheable = 0;
-
- save = *cf;
- cf->pool = pool;
- cf->ctx = &ctx;
- cf->handler = ngx_http_map;
- cf->handler_conf = conf;
-
- rv = ngx_conf_parse(cf, NULL);
-
- *cf = save;
-
- if (rv != NGX_CONF_OK) {
- ngx_destroy_pool(pool);
- return rv;
- }
-
- if (ctx.no_cacheable) {
- var->flags |= NGX_HTTP_VAR_NOCACHEABLE;
- }
-
- map->default_value = ctx.default_value ? ctx.default_value:
- &ngx_http_variable_null_value;
-
- map->hostnames = ctx.hostnames;
-
- hash.key = ngx_hash_key_lc;
- hash.max_size = mcf->hash_max_size;
- hash.bucket_size = mcf->hash_bucket_size;
- hash.name = "map_hash";
- hash.pool = cf->pool;
-
- if (ctx.keys.keys.nelts) {
- hash.hash = &map->map.hash.hash;
- hash.temp_pool = NULL;
-
- if (ngx_hash_init(&hash, ctx.keys.keys.elts, ctx.keys.keys.nelts)
- != NGX_OK)
- {
- ngx_destroy_pool(pool);
- return NGX_CONF_ERROR;
- }
- }
-
- if (ctx.keys.dns_wc_head.nelts) {
-
- ngx_qsort(ctx.keys.dns_wc_head.elts,
- (size_t) ctx.keys.dns_wc_head.nelts,
- sizeof(ngx_hash_key_t), ngx_http_map_cmp_dns_wildcards);
-
- hash.hash = NULL;
- hash.temp_pool = pool;
-
- if (ngx_hash_wildcard_init(&hash, ctx.keys.dns_wc_head.elts,
- ctx.keys.dns_wc_head.nelts)
- != NGX_OK)
- {
- ngx_destroy_pool(pool);
- return NGX_CONF_ERROR;
- }
-
- map->map.hash.wc_head = (ngx_hash_wildcard_t *) hash.hash;
- }
-
- if (ctx.keys.dns_wc_tail.nelts) {
-
- ngx_qsort(ctx.keys.dns_wc_tail.elts,
- (size_t) ctx.keys.dns_wc_tail.nelts,
- sizeof(ngx_hash_key_t), ngx_http_map_cmp_dns_wildcards);
-
- hash.hash = NULL;
- hash.temp_pool = pool;
-
- if (ngx_hash_wildcard_init(&hash, ctx.keys.dns_wc_tail.elts,
- ctx.keys.dns_wc_tail.nelts)
- != NGX_OK)
- {
- ngx_destroy_pool(pool);
- return NGX_CONF_ERROR;
- }
-
- map->map.hash.wc_tail = (ngx_hash_wildcard_t *) hash.hash;
- }
-
-#if (NGX_PCRE)
-
- if (ctx.regexes.nelts) {
- map->map.regex = ctx.regexes.elts;
- map->map.nregex = ctx.regexes.nelts;
- }
-
-#endif
-
- ngx_destroy_pool(pool);
-
- return rv;
-}
-
-
-static int ngx_libc_cdecl
-ngx_http_map_cmp_dns_wildcards(const void *one, const void *two)
-{
- ngx_hash_key_t *first, *second;
-
- first = (ngx_hash_key_t *) one;
- second = (ngx_hash_key_t *) two;
-
- return ngx_dns_strcmp(first->key.data, second->key.data);
-}
-
-
-static char *
-ngx_http_map(ngx_conf_t *cf, ngx_command_t *dummy, void *conf)
-{
- u_char *data;
- size_t len;
- ngx_int_t rv;
- ngx_str_t *value, v;
- ngx_uint_t i, key;
- ngx_http_map_conf_ctx_t *ctx;
- ngx_http_complex_value_t cv, *cvp;
- ngx_http_variable_value_t *var, **vp;
- ngx_http_compile_complex_value_t ccv;
-
- ctx = cf->ctx;
-
- value = cf->args->elts;
-
- if (cf->args->nelts == 1
- && ngx_strcmp(value[0].data, "hostnames") == 0)
- {
- ctx->hostnames = 1;
- return NGX_CONF_OK;
- }
-
- if (cf->args->nelts == 1
- && ngx_strcmp(value[0].data, "volatile") == 0)
- {
- ctx->no_cacheable = 1;
- return NGX_CONF_OK;
- }
-
- if (cf->args->nelts != 2) {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "invalid number of the map parameters");
- return NGX_CONF_ERROR;
- }
-
- if (ngx_strcmp(value[0].data, "include") == 0) {
- return ngx_conf_include(cf, dummy, conf);
- }
-
- key = 0;
-
- for (i = 0; i < value[1].len; i++) {
- key = ngx_hash(key, value[1].data[i]);
- }
-
- key %= ctx->keys.hsize;
-
- vp = ctx->values_hash[key].elts;
-
- if (vp) {
- for (i = 0; i < ctx->values_hash[key].nelts; i++) {
-
- if (vp[i]->valid) {
- data = vp[i]->data;
- len = vp[i]->len;
-
- } else {
- cvp = (ngx_http_complex_value_t *) vp[i]->data;
- data = cvp->value.data;
- len = cvp->value.len;
- }
-
- if (value[1].len != len) {
- continue;
- }
-
- if (ngx_strncmp(value[1].data, data, len) == 0) {
- var = vp[i];
- goto found;
- }
- }
-
- } else {
- if (ngx_array_init(&ctx->values_hash[key], cf->pool, 4,
- sizeof(ngx_http_variable_value_t *))
- != NGX_OK)
- {
- return NGX_CONF_ERROR;
- }
- }
-
- var = ngx_palloc(ctx->keys.pool, sizeof(ngx_http_variable_value_t));
- if (var == NULL) {
- return NGX_CONF_ERROR;
- }
-
- v.len = value[1].len;
- v.data = ngx_pstrdup(ctx->keys.pool, &value[1]);
- if (v.data == NULL) {
- return NGX_CONF_ERROR;
- }
-
- ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));
-
- ccv.cf = ctx->cf;
- ccv.value = &v;
- ccv.complex_value = &cv;
-
- if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
- return NGX_CONF_ERROR;
- }
-
- if (cv.lengths != NULL) {
- cvp = ngx_palloc(ctx->keys.pool, sizeof(ngx_http_complex_value_t));
- if (cvp == NULL) {
- return NGX_CONF_ERROR;
- }
-
- *cvp = cv;
-
- var->len = 0;
- var->data = (u_char *) cvp;
- var->valid = 0;
-
- } else {
- var->len = v.len;
- var->data = v.data;
- var->valid = 1;
- }
-
- var->no_cacheable = 0;
- var->not_found = 0;
-
- vp = ngx_array_push(&ctx->values_hash[key]);
- if (vp == NULL) {
- return NGX_CONF_ERROR;
- }
-
- *vp = var;
-
-found:
-
- if (ngx_strcmp(value[0].data, "default") == 0) {
-
- if (ctx->default_value) {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "duplicate default map parameter");
- return NGX_CONF_ERROR;
- }
-
- ctx->default_value = var;
-
- return NGX_CONF_OK;
- }
-
-#if (NGX_PCRE)
-
- if (value[0].len && value[0].data[0] == '~') {
- ngx_regex_compile_t rc;
- ngx_http_map_regex_t *regex;
- u_char errstr[NGX_MAX_CONF_ERRSTR];
-
- regex = ngx_array_push(&ctx->regexes);
- if (regex == NULL) {
- return NGX_CONF_ERROR;
- }
-
- value[0].len--;
- value[0].data++;
-
- ngx_memzero(&rc, sizeof(ngx_regex_compile_t));
-
- if (value[0].data[0] == '*') {
- value[0].len--;
- value[0].data++;
- rc.options = NGX_REGEX_CASELESS;
- }
-
- rc.pattern = value[0];
- rc.err.len = NGX_MAX_CONF_ERRSTR;
- rc.err.data = errstr;
-
- regex->regex = ngx_http_regex_compile(ctx->cf, &rc);
- if (regex->regex == NULL) {
- return NGX_CONF_ERROR;
- }
-
- regex->value = var;
-
- return NGX_CONF_OK;
- }
-
-#endif
-
- if (value[0].len && value[0].data[0] == '\\') {
- value[0].len--;
- value[0].data++;
- }
-
- rv = ngx_hash_add_key(&ctx->keys, &value[0], var,
- (ctx->hostnames) ? NGX_HASH_WILDCARD_KEY : 0);
-
- if (rv == NGX_OK) {
- return NGX_CONF_OK;
- }
-
- if (rv == NGX_DECLINED) {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "invalid hostname or wildcard \"%V\"", &value[0]);
- }
-
- if (rv == NGX_BUSY) {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "conflicting parameter \"%V\"", &value[0]);
- }
-
- return NGX_CONF_ERROR;
-}
diff --git a/nginx/src/http/modules/ngx_http_memcached_module.c b/nginx/src/http/modules/ngx_http_memcached_module.c
deleted file mode 100644
index 82fa713..0000000
--- a/nginx/src/http/modules/ngx_http_memcached_module.c
+++ /dev/null
@@ -1,721 +0,0 @@
-
-/*
- * Copyright (C) Igor Sysoev
- * Copyright (C) Nginx, Inc.
- */
-
-
-#include <ngx_config.h>
-#include <ngx_core.h>
-#include <ngx_http.h>
-
-
-typedef struct {
- ngx_http_upstream_conf_t upstream;
- ngx_int_t index;
- ngx_uint_t gzip_flag;
-} ngx_http_memcached_loc_conf_t;
-
-
-typedef struct {
- size_t rest;
- ngx_http_request_t *request;
- ngx_str_t key;
-} ngx_http_memcached_ctx_t;
-
-
-static ngx_int_t ngx_http_memcached_create_request(ngx_http_request_t *r);
-static ngx_int_t ngx_http_memcached_reinit_request(ngx_http_request_t *r);
-static ngx_int_t ngx_http_memcached_process_header(ngx_http_request_t *r);
-static ngx_int_t ngx_http_memcached_filter_init(void *data);
-static ngx_int_t ngx_http_memcached_filter(void *data, ssize_t bytes);
-static void ngx_http_memcached_abort_request(ngx_http_request_t *r);
-static void ngx_http_memcached_finalize_request(ngx_http_request_t *r,
- ngx_int_t rc);
-
-static void *ngx_http_memcached_create_loc_conf(ngx_conf_t *cf);
-static char *ngx_http_memcached_merge_loc_conf(ngx_conf_t *cf,
- void *parent, void *child);
-
-static char *ngx_http_memcached_pass(ngx_conf_t *cf, ngx_command_t *cmd,
- void *conf);
-
-
-static ngx_conf_bitmask_t ngx_http_memcached_next_upstream_masks[] = {
- { ngx_string("error"), NGX_HTTP_UPSTREAM_FT_ERROR },
- { ngx_string("timeout"), NGX_HTTP_UPSTREAM_FT_TIMEOUT },
- { ngx_string("invalid_response"), NGX_HTTP_UPSTREAM_FT_INVALID_HEADER },
- { ngx_string("not_found"), NGX_HTTP_UPSTREAM_FT_HTTP_404 },
- { ngx_string("off"), NGX_HTTP_UPSTREAM_FT_OFF },
- { ngx_null_string, 0 }
-};
-
-
-static ngx_command_t ngx_http_memcached_commands[] = {
-
- { ngx_string("memcached_pass"),
- NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_TAKE1,
- ngx_http_memcached_pass,
- NGX_HTTP_LOC_CONF_OFFSET,
- 0,
- NULL },
-
- { ngx_string("memcached_bind"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE12,
- ngx_http_upstream_bind_set_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_memcached_loc_conf_t, upstream.local),
- NULL },
-
- { ngx_string("memcached_connect_timeout"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_msec_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_memcached_loc_conf_t, upstream.connect_timeout),
- NULL },
-
- { ngx_string("memcached_send_timeout"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_msec_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_memcached_loc_conf_t, upstream.send_timeout),
- NULL },
-
- { ngx_string("memcached_buffer_size"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_size_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_memcached_loc_conf_t, upstream.buffer_size),
- NULL },
-
- { ngx_string("memcached_read_timeout"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_msec_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_memcached_loc_conf_t, upstream.read_timeout),
- NULL },
-
- { ngx_string("memcached_next_upstream"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
- ngx_conf_set_bitmask_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_memcached_loc_conf_t, upstream.next_upstream),
- &ngx_http_memcached_next_upstream_masks },
-
- { ngx_string("memcached_next_upstream_tries"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_num_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_memcached_loc_conf_t, upstream.next_upstream_tries),
- NULL },
-
- { ngx_string("memcached_next_upstream_timeout"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_msec_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_memcached_loc_conf_t, upstream.next_upstream_timeout),
- NULL },
-
- { ngx_string("memcached_gzip_flag"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_num_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_memcached_loc_conf_t, gzip_flag),
- NULL },
-
- ngx_null_command
-};
-
-
-static ngx_http_module_t ngx_http_memcached_module_ctx = {
- NULL, /* preconfiguration */
- NULL, /* postconfiguration */
-
- NULL, /* create main configuration */
- NULL, /* init main configuration */
-
- NULL, /* create server configuration */
- NULL, /* merge server configuration */
-
- ngx_http_memcached_create_loc_conf, /* create location configuration */
- ngx_http_memcached_merge_loc_conf /* merge location configuration */
-};
-
-
-ngx_module_t ngx_http_memcached_module = {
- NGX_MODULE_V1,
- &ngx_http_memcached_module_ctx, /* module context */
- ngx_http_memcached_commands, /* module directives */
- NGX_HTTP_MODULE, /* module type */
- NULL, /* init master */
- NULL, /* init module */
- NULL, /* init process */
- NULL, /* init thread */
- NULL, /* exit thread */
- NULL, /* exit process */
- NULL, /* exit master */
- NGX_MODULE_V1_PADDING
-};
-
-
-static ngx_str_t ngx_http_memcached_key = ngx_string("memcached_key");
-
-
-#define NGX_HTTP_MEMCACHED_END (sizeof(ngx_http_memcached_end) - 1)
-static u_char ngx_http_memcached_end[] = CRLF "END" CRLF;
-
-
-static ngx_int_t
-ngx_http_memcached_handler(ngx_http_request_t *r)
-{
- ngx_int_t rc;
- ngx_http_upstream_t *u;
- ngx_http_memcached_ctx_t *ctx;
- ngx_http_memcached_loc_conf_t *mlcf;
-
- if (!(r->method & (NGX_HTTP_GET|NGX_HTTP_HEAD))) {
- return NGX_HTTP_NOT_ALLOWED;
- }
-
- rc = ngx_http_discard_request_body(r);
-
- if (rc != NGX_OK) {
- return rc;
- }
-
- if (ngx_http_set_content_type(r) != NGX_OK) {
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
-
- if (ngx_http_upstream_create(r) != NGX_OK) {
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
-
- u = r->upstream;
-
- ngx_str_set(&u->schema, "memcached://");
- u->output.tag = (ngx_buf_tag_t) &ngx_http_memcached_module;
-
- mlcf = ngx_http_get_module_loc_conf(r, ngx_http_memcached_module);
-
- u->conf = &mlcf->upstream;
-
- u->create_request = ngx_http_memcached_create_request;
- u->reinit_request = ngx_http_memcached_reinit_request;
- u->process_header = ngx_http_memcached_process_header;
- u->abort_request = ngx_http_memcached_abort_request;
- u->finalize_request = ngx_http_memcached_finalize_request;
-
- ctx = ngx_palloc(r->pool, sizeof(ngx_http_memcached_ctx_t));
- if (ctx == NULL) {
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
-
- ctx->request = r;
-
- ngx_http_set_ctx(r, ctx, ngx_http_memcached_module);
-
- u->input_filter_init = ngx_http_memcached_filter_init;
- u->input_filter = ngx_http_memcached_filter;
- u->input_filter_ctx = ctx;
-
- r->main->count++;
-
- ngx_http_upstream_init(r);
-
- return NGX_DONE;
-}
-
-
-static ngx_int_t
-ngx_http_memcached_create_request(ngx_http_request_t *r)
-{
- size_t len;
- uintptr_t escape;
- ngx_buf_t *b;
- ngx_chain_t *cl;
- ngx_http_memcached_ctx_t *ctx;
- ngx_http_variable_value_t *vv;
- ngx_http_memcached_loc_conf_t *mlcf;
-
- mlcf = ngx_http_get_module_loc_conf(r, ngx_http_memcached_module);
-
- vv = ngx_http_get_indexed_variable(r, mlcf->index);
-
- if (vv == NULL || vv->not_found || vv->len == 0) {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "the \"$memcached_key\" variable is not set");
- return NGX_ERROR;
- }
-
- escape = 2 * ngx_escape_uri(NULL, vv->data, vv->len, NGX_ESCAPE_MEMCACHED);
-
- len = sizeof("get ") - 1 + vv->len + escape + sizeof(CRLF) - 1;
-
- b = ngx_create_temp_buf(r->pool, len);
- if (b == NULL) {
- return NGX_ERROR;
- }
-
- cl = ngx_alloc_chain_link(r->pool);
- if (cl == NULL) {
- return NGX_ERROR;
- }
-
- cl->buf = b;
- cl->next = NULL;
-
- r->upstream->request_bufs = cl;
-
- *b->last++ = 'g'; *b->last++ = 'e'; *b->last++ = 't'; *b->last++ = ' ';
-
- ctx = ngx_http_get_module_ctx(r, ngx_http_memcached_module);
-
- ctx->key.data = b->last;
-
- if (escape == 0) {
- b->last = ngx_copy(b->last, vv->data, vv->len);
-
- } else {
- b->last = (u_char *) ngx_escape_uri(b->last, vv->data, vv->len,
- NGX_ESCAPE_MEMCACHED);
- }
-
- ctx->key.len = b->last - ctx->key.data;
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "http memcached request: \"%V\"", &ctx->key);
-
- *b->last++ = CR; *b->last++ = LF;
-
- return NGX_OK;
-}
-
-
-static ngx_int_t
-ngx_http_memcached_reinit_request(ngx_http_request_t *r)
-{
- return NGX_OK;
-}
-
-
-static ngx_int_t
-ngx_http_memcached_process_header(ngx_http_request_t *r)
-{
- u_char *p, *start;
- ngx_str_t line;
- ngx_uint_t flags;
- ngx_table_elt_t *h;
- ngx_http_upstream_t *u;
- ngx_http_memcached_ctx_t *ctx;
- ngx_http_memcached_loc_conf_t *mlcf;
-
- u = r->upstream;
-
- for (p = u->buffer.pos; p < u->buffer.last; p++) {
- if (*p == LF) {
- goto found;
- }
- }
-
- return NGX_AGAIN;
-
-found:
-
- line.data = u->buffer.pos;
- line.len = p - u->buffer.pos;
-
- if (line.len == 0 || *(p - 1) != CR) {
- goto no_valid;
- }
-
- *p = '\0';
- line.len--;
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "memcached: \"%V\"", &line);
-
- p = u->buffer.pos;
-
- ctx = ngx_http_get_module_ctx(r, ngx_http_memcached_module);
- mlcf = ngx_http_get_module_loc_conf(r, ngx_http_memcached_module);
-
- if (ngx_strncmp(p, "VALUE ", sizeof("VALUE ") - 1) == 0) {
-
- p += sizeof("VALUE ") - 1;
-
- if (ngx_strncmp(p, ctx->key.data, ctx->key.len) != 0) {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "memcached sent invalid key in response \"%V\" "
- "for key \"%V\"",
- &line, &ctx->key);
-
- return NGX_HTTP_UPSTREAM_INVALID_HEADER;
- }
-
- p += ctx->key.len;
-
- if (*p++ != ' ') {
- goto no_valid;
- }
-
- /* flags */
-
- start = p;
-
- while (*p) {
- if (*p++ == ' ') {
- if (mlcf->gzip_flag) {
- goto flags;
- } else {
- goto length;
- }
- }
- }
-
- goto no_valid;
-
- flags:
-
- flags = ngx_atoi(start, p - start - 1);
-
- if (flags == (ngx_uint_t) NGX_ERROR) {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "memcached sent invalid flags in response \"%V\" "
- "for key \"%V\"",
- &line, &ctx->key);
- return NGX_HTTP_UPSTREAM_INVALID_HEADER;
- }
-
- if (flags & mlcf->gzip_flag) {
- h = ngx_list_push(&r->headers_out.headers);
- if (h == NULL) {
- return NGX_ERROR;
- }
-
- h->hash = 1;
- ngx_str_set(&h->key, "Content-Encoding");
- ngx_str_set(&h->value, "gzip");
- r->headers_out.content_encoding = h;
- }
-
- length:
-
- start = p;
- p = line.data + line.len;
-
- u->headers_in.content_length_n = ngx_atoof(start, p - start);
- if (u->headers_in.content_length_n == NGX_ERROR) {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "memcached sent invalid length in response \"%V\" "
- "for key \"%V\"",
- &line, &ctx->key);
- return NGX_HTTP_UPSTREAM_INVALID_HEADER;
- }
-
- u->headers_in.status_n = 200;
- u->state->status = 200;
- u->buffer.pos = p + sizeof(CRLF) - 1;
-
- return NGX_OK;
- }
-
- if (ngx_strcmp(p, "END\x0d") == 0) {
- ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
- "key: \"%V\" was not found by memcached", &ctx->key);
-
- u->headers_in.content_length_n = 0;
- u->headers_in.status_n = 404;
- u->state->status = 404;
- u->buffer.pos = p + sizeof("END" CRLF) - 1;
- u->keepalive = 1;
-
- return NGX_OK;
- }
-
-no_valid:
-
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "memcached sent invalid response: \"%V\"", &line);
-
- return NGX_HTTP_UPSTREAM_INVALID_HEADER;
-}
-
-
-static ngx_int_t
-ngx_http_memcached_filter_init(void *data)
-{
- ngx_http_memcached_ctx_t *ctx = data;
-
- ngx_http_upstream_t *u;
-
- u = ctx->request->upstream;
-
- if (u->headers_in.status_n != 404) {
- u->length = u->headers_in.content_length_n + NGX_HTTP_MEMCACHED_END;
- ctx->rest = NGX_HTTP_MEMCACHED_END;
-
- } else {
- u->length = 0;
- }
-
- return NGX_OK;
-}
-
-
-static ngx_int_t
-ngx_http_memcached_filter(void *data, ssize_t bytes)
-{
- ngx_http_memcached_ctx_t *ctx = data;
-
- u_char *last;
- ngx_buf_t *b;
- ngx_chain_t *cl, **ll;
- ngx_http_upstream_t *u;
-
- u = ctx->request->upstream;
- b = &u->buffer;
-
- if (u->length == (ssize_t) ctx->rest) {
-
- if (ngx_strncmp(b->last,
- ngx_http_memcached_end + NGX_HTTP_MEMCACHED_END - ctx->rest,
- bytes)
- != 0)
- {
- ngx_log_error(NGX_LOG_ERR, ctx->request->connection->log, 0,
- "memcached sent invalid trailer");
-
- u->length = 0;
- ctx->rest = 0;
-
- return NGX_OK;
- }
-
- u->length -= bytes;
- ctx->rest -= bytes;
-
- if (u->length == 0) {
- u->keepalive = 1;
- }
-
- return NGX_OK;
- }
-
- for (cl = u->out_bufs, ll = &u->out_bufs; cl; cl = cl->next) {
- ll = &cl->next;
- }
-
- cl = ngx_chain_get_free_buf(ctx->request->pool, &u->free_bufs);
- if (cl == NULL) {
- return NGX_ERROR;
- }
-
- cl->buf->flush = 1;
- cl->buf->memory = 1;
-
- *ll = cl;
-
- last = b->last;
- cl->buf->pos = last;
- b->last += bytes;
- cl->buf->last = b->last;
- cl->buf->tag = u->output.tag;
-
- ngx_log_debug4(NGX_LOG_DEBUG_HTTP, ctx->request->connection->log, 0,
- "memcached filter bytes:%z size:%z length:%O rest:%z",
- bytes, b->last - b->pos, u->length, ctx->rest);
-
- if (bytes <= (ssize_t) (u->length - NGX_HTTP_MEMCACHED_END)) {
- u->length -= bytes;
- return NGX_OK;
- }
-
- last += (size_t) (u->length - NGX_HTTP_MEMCACHED_END);
-
- if (ngx_strncmp(last, ngx_http_memcached_end, b->last - last) != 0) {
- ngx_log_error(NGX_LOG_ERR, ctx->request->connection->log, 0,
- "memcached sent invalid trailer");
-
- b->last = last;
- cl->buf->last = last;
- u->length = 0;
- ctx->rest = 0;
-
- return NGX_OK;
- }
-
- ctx->rest -= b->last - last;
- b->last = last;
- cl->buf->last = last;
- u->length = ctx->rest;
-
- if (u->length == 0) {
- u->keepalive = 1;
- }
-
- return NGX_OK;
-}
-
-
-static void
-ngx_http_memcached_abort_request(ngx_http_request_t *r)
-{
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "abort http memcached request");
- return;
-}
-
-
-static void
-ngx_http_memcached_finalize_request(ngx_http_request_t *r, ngx_int_t rc)
-{
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "finalize http memcached request");
- return;
-}
-
-
-static void *
-ngx_http_memcached_create_loc_conf(ngx_conf_t *cf)
-{
- ngx_http_memcached_loc_conf_t *conf;
-
- conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_memcached_loc_conf_t));
- if (conf == NULL) {
- return NULL;
- }
-
- /*
- * set by ngx_pcalloc():
- *
- * conf->upstream.bufs.num = 0;
- * conf->upstream.next_upstream = 0;
- * conf->upstream.temp_path = NULL;
- */
-
- conf->upstream.local = NGX_CONF_UNSET_PTR;
- conf->upstream.next_upstream_tries = NGX_CONF_UNSET_UINT;
- conf->upstream.connect_timeout = NGX_CONF_UNSET_MSEC;
- conf->upstream.send_timeout = NGX_CONF_UNSET_MSEC;
- conf->upstream.read_timeout = NGX_CONF_UNSET_MSEC;
- conf->upstream.next_upstream_timeout = NGX_CONF_UNSET_MSEC;
-
- conf->upstream.buffer_size = NGX_CONF_UNSET_SIZE;
-
- /* the hardcoded values */
- conf->upstream.cyclic_temp_file = 0;
- conf->upstream.buffering = 0;
- conf->upstream.ignore_client_abort = 0;
- conf->upstream.send_lowat = 0;
- conf->upstream.bufs.num = 0;
- conf->upstream.busy_buffers_size = 0;
- conf->upstream.max_temp_file_size = 0;
- conf->upstream.temp_file_write_size = 0;
- conf->upstream.intercept_errors = 1;
- conf->upstream.intercept_404 = 1;
- conf->upstream.pass_request_headers = 0;
- conf->upstream.pass_request_body = 0;
- conf->upstream.force_ranges = 1;
-
- conf->index = NGX_CONF_UNSET;
- conf->gzip_flag = NGX_CONF_UNSET_UINT;
-
- return conf;
-}
-
-
-static char *
-ngx_http_memcached_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
-{
- ngx_http_memcached_loc_conf_t *prev = parent;
- ngx_http_memcached_loc_conf_t *conf = child;
-
- ngx_conf_merge_ptr_value(conf->upstream.local,
- prev->upstream.local, NULL);
-
- ngx_conf_merge_uint_value(conf->upstream.next_upstream_tries,
- prev->upstream.next_upstream_tries, 0);
-
- ngx_conf_merge_msec_value(conf->upstream.connect_timeout,
- prev->upstream.connect_timeout, 60000);
-
- ngx_conf_merge_msec_value(conf->upstream.send_timeout,
- prev->upstream.send_timeout, 60000);
-
- ngx_conf_merge_msec_value(conf->upstream.read_timeout,
- prev->upstream.read_timeout, 60000);
-
- ngx_conf_merge_msec_value(conf->upstream.next_upstream_timeout,
- prev->upstream.next_upstream_timeout, 0);
-
- ngx_conf_merge_size_value(conf->upstream.buffer_size,
- prev->upstream.buffer_size,
- (size_t) ngx_pagesize);
-
- ngx_conf_merge_bitmask_value(conf->upstream.next_upstream,
- prev->upstream.next_upstream,
- (NGX_CONF_BITMASK_SET
- |NGX_HTTP_UPSTREAM_FT_ERROR
- |NGX_HTTP_UPSTREAM_FT_TIMEOUT));
-
- if (conf->upstream.next_upstream & NGX_HTTP_UPSTREAM_FT_OFF) {
- conf->upstream.next_upstream = NGX_CONF_BITMASK_SET
- |NGX_HTTP_UPSTREAM_FT_OFF;
- }
-
- if (conf->upstream.upstream == NULL) {
- conf->upstream.upstream = prev->upstream.upstream;
- }
-
- if (conf->index == NGX_CONF_UNSET) {
- conf->index = prev->index;
- }
-
- ngx_conf_merge_uint_value(conf->gzip_flag, prev->gzip_flag, 0);
-
- return NGX_CONF_OK;
-}
-
-
-static char *
-ngx_http_memcached_pass(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
-{
- ngx_http_memcached_loc_conf_t *mlcf = conf;
-
- ngx_str_t *value;
- ngx_url_t u;
- ngx_http_core_loc_conf_t *clcf;
-
- if (mlcf->upstream.upstream) {
- return "is duplicate";
- }
-
- value = cf->args->elts;
-
- ngx_memzero(&u, sizeof(ngx_url_t));
-
- u.url = value[1];
- u.no_resolve = 1;
-
- mlcf->upstream.upstream = ngx_http_upstream_add(cf, &u, 0);
- if (mlcf->upstream.upstream == NULL) {
- return NGX_CONF_ERROR;
- }
-
- clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);
-
- clcf->handler = ngx_http_memcached_handler;
-
- if (clcf->name.data[clcf->name.len - 1] == '/') {
- clcf->auto_redirect = 1;
- }
-
- mlcf->index = ngx_http_get_variable_index(cf, &ngx_http_memcached_key);
-
- if (mlcf->index == NGX_ERROR) {
- return NGX_CONF_ERROR;
- }
-
- return NGX_CONF_OK;
-}
diff --git a/nginx/src/http/modules/ngx_http_mirror_module.c b/nginx/src/http/modules/ngx_http_mirror_module.c
deleted file mode 100644
index 787adb3..0000000
--- a/nginx/src/http/modules/ngx_http_mirror_module.c
+++ /dev/null
@@ -1,264 +0,0 @@
-
-/*
- * Copyright (C) Roman Arutyunyan
- * Copyright (C) Nginx, Inc.
- */
-
-
-#include <ngx_config.h>
-#include <ngx_core.h>
-#include <ngx_http.h>
-
-
-typedef struct {
- ngx_array_t *mirror;
- ngx_flag_t request_body;
-} ngx_http_mirror_loc_conf_t;
-
-
-typedef struct {
- ngx_int_t status;
-} ngx_http_mirror_ctx_t;
-
-
-static ngx_int_t ngx_http_mirror_handler(ngx_http_request_t *r);
-static void ngx_http_mirror_body_handler(ngx_http_request_t *r);
-static ngx_int_t ngx_http_mirror_handler_internal(ngx_http_request_t *r);
-static void *ngx_http_mirror_create_loc_conf(ngx_conf_t *cf);
-static char *ngx_http_mirror_merge_loc_conf(ngx_conf_t *cf, void *parent,
- void *child);
-static char *ngx_http_mirror(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
-static ngx_int_t ngx_http_mirror_init(ngx_conf_t *cf);
-
-
-static ngx_command_t ngx_http_mirror_commands[] = {
-
- { ngx_string("mirror"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_http_mirror,
- NGX_HTTP_LOC_CONF_OFFSET,
- 0,
- NULL },
-
- { ngx_string("mirror_request_body"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
- ngx_conf_set_flag_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_mirror_loc_conf_t, request_body),
- NULL },
-
- ngx_null_command
-};
-
-
-static ngx_http_module_t ngx_http_mirror_module_ctx = {
- NULL, /* preconfiguration */
- ngx_http_mirror_init, /* postconfiguration */
-
- NULL, /* create main configuration */
- NULL, /* init main configuration */
-
- NULL, /* create server configuration */
- NULL, /* merge server configuration */
-
- ngx_http_mirror_create_loc_conf, /* create location configuration */
- ngx_http_mirror_merge_loc_conf /* merge location configuration */
-};
-
-
-ngx_module_t ngx_http_mirror_module = {
- NGX_MODULE_V1,
- &ngx_http_mirror_module_ctx, /* module context */
- ngx_http_mirror_commands, /* module directives */
- NGX_HTTP_MODULE, /* module type */
- NULL, /* init master */
- NULL, /* init module */
- NULL, /* init process */
- NULL, /* init thread */
- NULL, /* exit thread */
- NULL, /* exit process */
- NULL, /* exit master */
- NGX_MODULE_V1_PADDING
-};
-
-
-static ngx_int_t
-ngx_http_mirror_handler(ngx_http_request_t *r)
-{
- ngx_int_t rc;
- ngx_http_mirror_ctx_t *ctx;
- ngx_http_mirror_loc_conf_t *mlcf;
-
- if (r != r->main) {
- return NGX_DECLINED;
- }
-
- mlcf = ngx_http_get_module_loc_conf(r, ngx_http_mirror_module);
-
- if (mlcf->mirror == NULL) {
- return NGX_DECLINED;
- }
-
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "mirror handler");
-
- if (mlcf->request_body) {
- ctx = ngx_http_get_module_ctx(r, ngx_http_mirror_module);
-
- if (ctx) {
- return ctx->status;
- }
-
- ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_mirror_ctx_t));
- if (ctx == NULL) {
- return NGX_ERROR;
- }
-
- ctx->status = NGX_DONE;
-
- ngx_http_set_ctx(r, ctx, ngx_http_mirror_module);
-
- rc = ngx_http_read_client_request_body(r, ngx_http_mirror_body_handler);
- if (rc >= NGX_HTTP_SPECIAL_RESPONSE) {
- return rc;
- }
-
- ngx_http_finalize_request(r, NGX_DONE);
- return NGX_DONE;
- }
-
- return ngx_http_mirror_handler_internal(r);
-}
-
-
-static void
-ngx_http_mirror_body_handler(ngx_http_request_t *r)
-{
- ngx_http_mirror_ctx_t *ctx;
-
- ctx = ngx_http_get_module_ctx(r, ngx_http_mirror_module);
-
- ctx->status = ngx_http_mirror_handler_internal(r);
-
- r->preserve_body = 1;
-
- r->write_event_handler = ngx_http_core_run_phases;
- ngx_http_core_run_phases(r);
-}
-
-
-static ngx_int_t
-ngx_http_mirror_handler_internal(ngx_http_request_t *r)
-{
- ngx_str_t *name;
- ngx_uint_t i;
- ngx_http_request_t *sr;
- ngx_http_mirror_loc_conf_t *mlcf;
-
- mlcf = ngx_http_get_module_loc_conf(r, ngx_http_mirror_module);
-
- name = mlcf->mirror->elts;
-
- for (i = 0; i < mlcf->mirror->nelts; i++) {
- if (ngx_http_subrequest(r, &name[i], &r->args, &sr, NULL,
- NGX_HTTP_SUBREQUEST_BACKGROUND)
- != NGX_OK)
- {
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
-
- sr->header_only = 1;
- sr->method = r->method;
- sr->method_name = r->method_name;
- }
-
- return NGX_DECLINED;
-}
-
-
-static void *
-ngx_http_mirror_create_loc_conf(ngx_conf_t *cf)
-{
- ngx_http_mirror_loc_conf_t *mlcf;
-
- mlcf = ngx_pcalloc(cf->pool, sizeof(ngx_http_mirror_loc_conf_t));
- if (mlcf == NULL) {
- return NULL;
- }
-
- mlcf->mirror = NGX_CONF_UNSET_PTR;
- mlcf->request_body = NGX_CONF_UNSET;
-
- return mlcf;
-}
-
-
-static char *
-ngx_http_mirror_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
-{
- ngx_http_mirror_loc_conf_t *prev = parent;
- ngx_http_mirror_loc_conf_t *conf = child;
-
- ngx_conf_merge_ptr_value(conf->mirror, prev->mirror, NULL);
- ngx_conf_merge_value(conf->request_body, prev->request_body, 1);
-
- return NGX_CONF_OK;
-}
-
-
-static char *
-ngx_http_mirror(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
-{
- ngx_http_mirror_loc_conf_t *mlcf = conf;
-
- ngx_str_t *value, *s;
-
- value = cf->args->elts;
-
- if (ngx_strcmp(value[1].data, "off") == 0) {
- if (mlcf->mirror != NGX_CONF_UNSET_PTR) {
- return "is duplicate";
- }
-
- mlcf->mirror = NULL;
- return NGX_CONF_OK;
- }
-
- if (mlcf->mirror == NULL) {
- return "is duplicate";
- }
-
- if (mlcf->mirror == NGX_CONF_UNSET_PTR) {
- mlcf->mirror = ngx_array_create(cf->pool, 4, sizeof(ngx_str_t));
- if (mlcf->mirror == NULL) {
- return NGX_CONF_ERROR;
- }
- }
-
- s = ngx_array_push(mlcf->mirror);
- if (s == NULL) {
- return NGX_CONF_ERROR;
- }
-
- *s = value[1];
-
- return NGX_CONF_OK;
-}
-
-
-static ngx_int_t
-ngx_http_mirror_init(ngx_conf_t *cf)
-{
- ngx_http_handler_pt *h;
- ngx_http_core_main_conf_t *cmcf;
-
- cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);
-
- h = ngx_array_push(&cmcf->phases[NGX_HTTP_PRECONTENT_PHASE].handlers);
- if (h == NULL) {
- return NGX_ERROR;
- }
-
- *h = ngx_http_mirror_handler;
-
- return NGX_OK;
-}
diff --git a/nginx/src/http/modules/ngx_http_mp4_module.c b/nginx/src/http/modules/ngx_http_mp4_module.c
deleted file mode 100644
index 618bf78..0000000
--- a/nginx/src/http/modules/ngx_http_mp4_module.c
+++ /dev/null
@@ -1,3562 +0,0 @@
-
-/*
- * Copyright (C) Igor Sysoev
- * Copyright (C) Nginx, Inc.
- */
-
-#include <ngx_config.h>
-#include <ngx_core.h>
-#include <ngx_http.h>
-
-
-#define NGX_HTTP_MP4_TRAK_ATOM 0
-#define NGX_HTTP_MP4_TKHD_ATOM 1
-#define NGX_HTTP_MP4_MDIA_ATOM 2
-#define NGX_HTTP_MP4_MDHD_ATOM 3
-#define NGX_HTTP_MP4_HDLR_ATOM 4
-#define NGX_HTTP_MP4_MINF_ATOM 5
-#define NGX_HTTP_MP4_VMHD_ATOM 6
-#define NGX_HTTP_MP4_SMHD_ATOM 7
-#define NGX_HTTP_MP4_DINF_ATOM 8
-#define NGX_HTTP_MP4_STBL_ATOM 9
-#define NGX_HTTP_MP4_STSD_ATOM 10
-#define NGX_HTTP_MP4_STTS_ATOM 11
-#define NGX_HTTP_MP4_STTS_DATA 12
-#define NGX_HTTP_MP4_STSS_ATOM 13
-#define NGX_HTTP_MP4_STSS_DATA 14
-#define NGX_HTTP_MP4_CTTS_ATOM 15
-#define NGX_HTTP_MP4_CTTS_DATA 16
-#define NGX_HTTP_MP4_STSC_ATOM 17
-#define NGX_HTTP_MP4_STSC_START 18
-#define NGX_HTTP_MP4_STSC_DATA 19
-#define NGX_HTTP_MP4_STSC_END 20
-#define NGX_HTTP_MP4_STSZ_ATOM 21
-#define NGX_HTTP_MP4_STSZ_DATA 22
-#define NGX_HTTP_MP4_STCO_ATOM 23
-#define NGX_HTTP_MP4_STCO_DATA 24
-#define NGX_HTTP_MP4_CO64_ATOM 25
-#define NGX_HTTP_MP4_CO64_DATA 26
-
-#define NGX_HTTP_MP4_LAST_ATOM NGX_HTTP_MP4_CO64_DATA
-
-
-typedef struct {
- size_t buffer_size;
- size_t max_buffer_size;
-} ngx_http_mp4_conf_t;
-
-
-typedef struct {
- u_char chunk[4];
- u_char samples[4];
- u_char id[4];
-} ngx_mp4_stsc_entry_t;
-
-
-typedef struct {
- uint32_t timescale;
- uint32_t time_to_sample_entries;
- uint32_t sample_to_chunk_entries;
- uint32_t sync_samples_entries;
- uint32_t composition_offset_entries;
- uint32_t sample_sizes_entries;
- uint32_t chunks;
-
- ngx_uint_t start_sample;
- ngx_uint_t end_sample;
- ngx_uint_t start_chunk;
- ngx_uint_t end_chunk;
- ngx_uint_t start_chunk_samples;
- ngx_uint_t end_chunk_samples;
- uint64_t start_chunk_samples_size;
- uint64_t end_chunk_samples_size;
- off_t start_offset;
- off_t end_offset;
-
- size_t tkhd_size;
- size_t mdhd_size;
- size_t hdlr_size;
- size_t vmhd_size;
- size_t smhd_size;
- size_t dinf_size;
- size_t size;
-
- ngx_chain_t out[NGX_HTTP_MP4_LAST_ATOM + 1];
-
- ngx_buf_t trak_atom_buf;
- ngx_buf_t tkhd_atom_buf;
- ngx_buf_t mdia_atom_buf;
- ngx_buf_t mdhd_atom_buf;
- ngx_buf_t hdlr_atom_buf;
- ngx_buf_t minf_atom_buf;
- ngx_buf_t vmhd_atom_buf;
- ngx_buf_t smhd_atom_buf;
- ngx_buf_t dinf_atom_buf;
- ngx_buf_t stbl_atom_buf;
- ngx_buf_t stsd_atom_buf;
- ngx_buf_t stts_atom_buf;
- ngx_buf_t stts_data_buf;
- ngx_buf_t stss_atom_buf;
- ngx_buf_t stss_data_buf;
- ngx_buf_t ctts_atom_buf;
- ngx_buf_t ctts_data_buf;
- ngx_buf_t stsc_atom_buf;
- ngx_buf_t stsc_start_chunk_buf;
- ngx_buf_t stsc_end_chunk_buf;
- ngx_buf_t stsc_data_buf;
- ngx_buf_t stsz_atom_buf;
- ngx_buf_t stsz_data_buf;
- ngx_buf_t stco_atom_buf;
- ngx_buf_t stco_data_buf;
- ngx_buf_t co64_atom_buf;
- ngx_buf_t co64_data_buf;
-
- ngx_mp4_stsc_entry_t stsc_start_chunk_entry;
- ngx_mp4_stsc_entry_t stsc_end_chunk_entry;
-} ngx_http_mp4_trak_t;
-
-
-typedef struct {
- ngx_file_t file;
-
- u_char *buffer;
- u_char *buffer_start;
- u_char *buffer_pos;
- u_char *buffer_end;
- size_t buffer_size;
-
- off_t offset;
- off_t end;
- off_t content_length;
- ngx_uint_t start;
- ngx_uint_t length;
- uint32_t timescale;
- ngx_http_request_t *request;
- ngx_array_t trak;
- ngx_http_mp4_trak_t traks[2];
-
- size_t ftyp_size;
- size_t moov_size;
-
- ngx_chain_t *out;
- ngx_chain_t ftyp_atom;
- ngx_chain_t moov_atom;
- ngx_chain_t mvhd_atom;
- ngx_chain_t mdat_atom;
- ngx_chain_t mdat_data;
-
- ngx_buf_t ftyp_atom_buf;
- ngx_buf_t moov_atom_buf;
- ngx_buf_t mvhd_atom_buf;
- ngx_buf_t mdat_atom_buf;
- ngx_buf_t mdat_data_buf;
-
- u_char moov_atom_header[8];
- u_char mdat_atom_header[16];
-} ngx_http_mp4_file_t;
-
-
-typedef struct {
- char *name;
- ngx_int_t (*handler)(ngx_http_mp4_file_t *mp4,
- uint64_t atom_data_size);
-} ngx_http_mp4_atom_handler_t;
-
-
-#define ngx_mp4_atom_header(mp4) (mp4->buffer_pos - 8)
-#define ngx_mp4_atom_data(mp4) mp4->buffer_pos
-#define ngx_mp4_atom_data_size(t) (uint64_t) (sizeof(t) - 8)
-
-
-#define ngx_mp4_atom_next(mp4, n) \
- \
- if (n > (size_t) (mp4->buffer_end - mp4->buffer_pos)) { \
- mp4->buffer_pos = mp4->buffer_end; \
- \
- } else { \
- mp4->buffer_pos += (size_t) n; \
- } \
- \
- mp4->offset += n
-
-
-#define ngx_mp4_set_atom_name(p, n1, n2, n3, n4) \
- ((u_char *) (p))[4] = n1; \
- ((u_char *) (p))[5] = n2; \
- ((u_char *) (p))[6] = n3; \
- ((u_char *) (p))[7] = n4
-
-#define ngx_mp4_get_32value(p) \
- ( ((uint32_t) ((u_char *) (p))[0] << 24) \
- + ( ((u_char *) (p))[1] << 16) \
- + ( ((u_char *) (p))[2] << 8) \
- + ( ((u_char *) (p))[3]) )
-
-#define ngx_mp4_set_32value(p, n) \
- ((u_char *) (p))[0] = (u_char) ((n) >> 24); \
- ((u_char *) (p))[1] = (u_char) ((n) >> 16); \
- ((u_char *) (p))[2] = (u_char) ((n) >> 8); \
- ((u_char *) (p))[3] = (u_char) (n)
-
-#define ngx_mp4_get_64value(p) \
- ( ((uint64_t) ((u_char *) (p))[0] << 56) \
- + ((uint64_t) ((u_char *) (p))[1] << 48) \
- + ((uint64_t) ((u_char *) (p))[2] << 40) \
- + ((uint64_t) ((u_char *) (p))[3] << 32) \
- + ((uint64_t) ((u_char *) (p))[4] << 24) \
- + ( ((u_char *) (p))[5] << 16) \
- + ( ((u_char *) (p))[6] << 8) \
- + ( ((u_char *) (p))[7]) )
-
-#define ngx_mp4_set_64value(p, n) \
- ((u_char *) (p))[0] = (u_char) ((uint64_t) (n) >> 56); \
- ((u_char *) (p))[1] = (u_char) ((uint64_t) (n) >> 48); \
- ((u_char *) (p))[2] = (u_char) ((uint64_t) (n) >> 40); \
- ((u_char *) (p))[3] = (u_char) ((uint64_t) (n) >> 32); \
- ((u_char *) (p))[4] = (u_char) ( (n) >> 24); \
- ((u_char *) (p))[5] = (u_char) ( (n) >> 16); \
- ((u_char *) (p))[6] = (u_char) ( (n) >> 8); \
- ((u_char *) (p))[7] = (u_char) (n)
-
-#define ngx_mp4_last_trak(mp4) \
- &((ngx_http_mp4_trak_t *) mp4->trak.elts)[mp4->trak.nelts - 1]
-
-
-static ngx_int_t ngx_http_mp4_handler(ngx_http_request_t *r);
-static ngx_int_t ngx_http_mp4_atofp(u_char *line, size_t n, size_t point);
-
-static ngx_int_t ngx_http_mp4_process(ngx_http_mp4_file_t *mp4);
-static ngx_int_t ngx_http_mp4_read_atom(ngx_http_mp4_file_t *mp4,
- ngx_http_mp4_atom_handler_t *atom, uint64_t atom_data_size);
-static ngx_int_t ngx_http_mp4_read(ngx_http_mp4_file_t *mp4, size_t size);
-static ngx_int_t ngx_http_mp4_read_ftyp_atom(ngx_http_mp4_file_t *mp4,
- uint64_t atom_data_size);
-static ngx_int_t ngx_http_mp4_read_moov_atom(ngx_http_mp4_file_t *mp4,
- uint64_t atom_data_size);
-static ngx_int_t ngx_http_mp4_read_mdat_atom(ngx_http_mp4_file_t *mp4,
- uint64_t atom_data_size);
-static size_t ngx_http_mp4_update_mdat_atom(ngx_http_mp4_file_t *mp4,
- off_t start_offset, off_t end_offset);
-static ngx_int_t ngx_http_mp4_read_mvhd_atom(ngx_http_mp4_file_t *mp4,
- uint64_t atom_data_size);
-static ngx_int_t ngx_http_mp4_read_trak_atom(ngx_http_mp4_file_t *mp4,
- uint64_t atom_data_size);
-static void ngx_http_mp4_update_trak_atom(ngx_http_mp4_file_t *mp4,
- ngx_http_mp4_trak_t *trak);
-static ngx_int_t ngx_http_mp4_read_cmov_atom(ngx_http_mp4_file_t *mp4,
- uint64_t atom_data_size);
-static ngx_int_t ngx_http_mp4_read_tkhd_atom(ngx_http_mp4_file_t *mp4,
- uint64_t atom_data_size);
-static ngx_int_t ngx_http_mp4_read_mdia_atom(ngx_http_mp4_file_t *mp4,
- uint64_t atom_data_size);
-static void ngx_http_mp4_update_mdia_atom(ngx_http_mp4_file_t *mp4,
- ngx_http_mp4_trak_t *trak);
-static ngx_int_t ngx_http_mp4_read_mdhd_atom(ngx_http_mp4_file_t *mp4,
- uint64_t atom_data_size);
-static ngx_int_t ngx_http_mp4_read_hdlr_atom(ngx_http_mp4_file_t *mp4,
- uint64_t atom_data_size);
-static ngx_int_t ngx_http_mp4_read_minf_atom(ngx_http_mp4_file_t *mp4,
- uint64_t atom_data_size);
-static void ngx_http_mp4_update_minf_atom(ngx_http_mp4_file_t *mp4,
- ngx_http_mp4_trak_t *trak);
-static ngx_int_t ngx_http_mp4_read_dinf_atom(ngx_http_mp4_file_t *mp4,
- uint64_t atom_data_size);
-static ngx_int_t ngx_http_mp4_read_vmhd_atom(ngx_http_mp4_file_t *mp4,
- uint64_t atom_data_size);
-static ngx_int_t ngx_http_mp4_read_smhd_atom(ngx_http_mp4_file_t *mp4,
- uint64_t atom_data_size);
-static ngx_int_t ngx_http_mp4_read_stbl_atom(ngx_http_mp4_file_t *mp4,
- uint64_t atom_data_size);
-static void ngx_http_mp4_update_stbl_atom(ngx_http_mp4_file_t *mp4,
- ngx_http_mp4_trak_t *trak);
-static ngx_int_t ngx_http_mp4_read_stsd_atom(ngx_http_mp4_file_t *mp4,
- uint64_t atom_data_size);
-static ngx_int_t ngx_http_mp4_read_stts_atom(ngx_http_mp4_file_t *mp4,
- uint64_t atom_data_size);
-static ngx_int_t ngx_http_mp4_update_stts_atom(ngx_http_mp4_file_t *mp4,
- ngx_http_mp4_trak_t *trak);
-static ngx_int_t ngx_http_mp4_crop_stts_data(ngx_http_mp4_file_t *mp4,
- ngx_http_mp4_trak_t *trak, ngx_uint_t start);
-static ngx_int_t ngx_http_mp4_read_stss_atom(ngx_http_mp4_file_t *mp4,
- uint64_t atom_data_size);
-static ngx_int_t ngx_http_mp4_update_stss_atom(ngx_http_mp4_file_t *mp4,
- ngx_http_mp4_trak_t *trak);
-static void ngx_http_mp4_crop_stss_data(ngx_http_mp4_file_t *mp4,
- ngx_http_mp4_trak_t *trak, ngx_uint_t start);
-static ngx_int_t ngx_http_mp4_read_ctts_atom(ngx_http_mp4_file_t *mp4,
- uint64_t atom_data_size);
-static void ngx_http_mp4_update_ctts_atom(ngx_http_mp4_file_t *mp4,
- ngx_http_mp4_trak_t *trak);
-static void ngx_http_mp4_crop_ctts_data(ngx_http_mp4_file_t *mp4,
- ngx_http_mp4_trak_t *trak, ngx_uint_t start);
-static ngx_int_t ngx_http_mp4_read_stsc_atom(ngx_http_mp4_file_t *mp4,
- uint64_t atom_data_size);
-static ngx_int_t ngx_http_mp4_update_stsc_atom(ngx_http_mp4_file_t *mp4,
- ngx_http_mp4_trak_t *trak);
-static ngx_int_t ngx_http_mp4_crop_stsc_data(ngx_http_mp4_file_t *mp4,
- ngx_http_mp4_trak_t *trak, ngx_uint_t start);
-static ngx_int_t ngx_http_mp4_read_stsz_atom(ngx_http_mp4_file_t *mp4,
- uint64_t atom_data_size);
-static ngx_int_t ngx_http_mp4_update_stsz_atom(ngx_http_mp4_file_t *mp4,
- ngx_http_mp4_trak_t *trak);
-static ngx_int_t ngx_http_mp4_read_stco_atom(ngx_http_mp4_file_t *mp4,
- uint64_t atom_data_size);
-static ngx_int_t ngx_http_mp4_update_stco_atom(ngx_http_mp4_file_t *mp4,
- ngx_http_mp4_trak_t *trak);
-static void ngx_http_mp4_adjust_stco_atom(ngx_http_mp4_file_t *mp4,
- ngx_http_mp4_trak_t *trak, int32_t adjustment);
-static ngx_int_t ngx_http_mp4_read_co64_atom(ngx_http_mp4_file_t *mp4,
- uint64_t atom_data_size);
-static ngx_int_t ngx_http_mp4_update_co64_atom(ngx_http_mp4_file_t *mp4,
- ngx_http_mp4_trak_t *trak);
-static void ngx_http_mp4_adjust_co64_atom(ngx_http_mp4_file_t *mp4,
- ngx_http_mp4_trak_t *trak, off_t adjustment);
-
-static char *ngx_http_mp4(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
-static void *ngx_http_mp4_create_conf(ngx_conf_t *cf);
-static char *ngx_http_mp4_merge_conf(ngx_conf_t *cf, void *parent, void *child);
-
-
-static ngx_command_t ngx_http_mp4_commands[] = {
-
- { ngx_string("mp4"),
- NGX_HTTP_LOC_CONF|NGX_CONF_NOARGS,
- ngx_http_mp4,
- 0,
- 0,
- NULL },
-
- { ngx_string("mp4_buffer_size"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_size_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_mp4_conf_t, buffer_size),
- NULL },
-
- { ngx_string("mp4_max_buffer_size"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_size_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_mp4_conf_t, max_buffer_size),
- NULL },
-
- ngx_null_command
-};
-
-
-static ngx_http_module_t ngx_http_mp4_module_ctx = {
- NULL, /* preconfiguration */
- NULL, /* postconfiguration */
-
- NULL, /* create main configuration */
- NULL, /* init main configuration */
-
- NULL, /* create server configuration */
- NULL, /* merge server configuration */
-
- ngx_http_mp4_create_conf, /* create location configuration */
- ngx_http_mp4_merge_conf /* merge location configuration */
-};
-
-
-ngx_module_t ngx_http_mp4_module = {
- NGX_MODULE_V1,
- &ngx_http_mp4_module_ctx, /* module context */
- ngx_http_mp4_commands, /* module directives */
- NGX_HTTP_MODULE, /* module type */
- NULL, /* init master */
- NULL, /* init module */
- NULL, /* init process */
- NULL, /* init thread */
- NULL, /* exit thread */
- NULL, /* exit process */
- NULL, /* exit master */
- NGX_MODULE_V1_PADDING
-};
-
-
-static ngx_http_mp4_atom_handler_t ngx_http_mp4_atoms[] = {
- { "ftyp", ngx_http_mp4_read_ftyp_atom },
- { "moov", ngx_http_mp4_read_moov_atom },
- { "mdat", ngx_http_mp4_read_mdat_atom },
- { NULL, NULL }
-};
-
-static ngx_http_mp4_atom_handler_t ngx_http_mp4_moov_atoms[] = {
- { "mvhd", ngx_http_mp4_read_mvhd_atom },
- { "trak", ngx_http_mp4_read_trak_atom },
- { "cmov", ngx_http_mp4_read_cmov_atom },
- { NULL, NULL }
-};
-
-static ngx_http_mp4_atom_handler_t ngx_http_mp4_trak_atoms[] = {
- { "tkhd", ngx_http_mp4_read_tkhd_atom },
- { "mdia", ngx_http_mp4_read_mdia_atom },
- { NULL, NULL }
-};
-
-static ngx_http_mp4_atom_handler_t ngx_http_mp4_mdia_atoms[] = {
- { "mdhd", ngx_http_mp4_read_mdhd_atom },
- { "hdlr", ngx_http_mp4_read_hdlr_atom },
- { "minf", ngx_http_mp4_read_minf_atom },
- { NULL, NULL }
-};
-
-static ngx_http_mp4_atom_handler_t ngx_http_mp4_minf_atoms[] = {
- { "vmhd", ngx_http_mp4_read_vmhd_atom },
- { "smhd", ngx_http_mp4_read_smhd_atom },
- { "dinf", ngx_http_mp4_read_dinf_atom },
- { "stbl", ngx_http_mp4_read_stbl_atom },
- { NULL, NULL }
-};
-
-static ngx_http_mp4_atom_handler_t ngx_http_mp4_stbl_atoms[] = {
- { "stsd", ngx_http_mp4_read_stsd_atom },
- { "stts", ngx_http_mp4_read_stts_atom },
- { "stss", ngx_http_mp4_read_stss_atom },
- { "ctts", ngx_http_mp4_read_ctts_atom },
- { "stsc", ngx_http_mp4_read_stsc_atom },
- { "stsz", ngx_http_mp4_read_stsz_atom },
- { "stco", ngx_http_mp4_read_stco_atom },
- { "co64", ngx_http_mp4_read_co64_atom },
- { NULL, NULL }
-};
-
-
-static ngx_int_t
-ngx_http_mp4_handler(ngx_http_request_t *r)
-{
- u_char *last;
- size_t root;
- ngx_int_t rc, start, end;
- ngx_uint_t level, length;
- ngx_str_t path, value;
- ngx_log_t *log;
- ngx_buf_t *b;
- ngx_chain_t out;
- ngx_http_mp4_file_t *mp4;
- ngx_open_file_info_t of;
- ngx_http_core_loc_conf_t *clcf;
-
- if (!(r->method & (NGX_HTTP_GET|NGX_HTTP_HEAD))) {
- return NGX_HTTP_NOT_ALLOWED;
- }
-
- if (r->uri.data[r->uri.len - 1] == '/') {
- return NGX_DECLINED;
- }
-
- rc = ngx_http_discard_request_body(r);
-
- if (rc != NGX_OK) {
- return rc;
- }
-
- last = ngx_http_map_uri_to_path(r, &path, &root, 0);
- if (last == NULL) {
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
-
- log = r->connection->log;
-
- path.len = last - path.data;
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0,
- "http mp4 filename: \"%V\"", &path);
-
- clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
-
- ngx_memzero(&of, sizeof(ngx_open_file_info_t));
-
- of.read_ahead = clcf->read_ahead;
- of.directio = NGX_MAX_OFF_T_VALUE;
- of.valid = clcf->open_file_cache_valid;
- of.min_uses = clcf->open_file_cache_min_uses;
- of.errors = clcf->open_file_cache_errors;
- of.events = clcf->open_file_cache_events;
-
- if (ngx_http_set_disable_symlinks(r, clcf, &path, &of) != NGX_OK) {
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
-
- if (ngx_open_cached_file(clcf->open_file_cache, &path, &of, r->pool)
- != NGX_OK)
- {
- switch (of.err) {
-
- case 0:
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
-
- case NGX_ENOENT:
- case NGX_ENOTDIR:
- case NGX_ENAMETOOLONG:
-
- level = NGX_LOG_ERR;
- rc = NGX_HTTP_NOT_FOUND;
- break;
-
- case NGX_EACCES:
-#if (NGX_HAVE_OPENAT)
- case NGX_EMLINK:
- case NGX_ELOOP:
-#endif
-
- level = NGX_LOG_ERR;
- rc = NGX_HTTP_FORBIDDEN;
- break;
-
- default:
-
- level = NGX_LOG_CRIT;
- rc = NGX_HTTP_INTERNAL_SERVER_ERROR;
- break;
- }
-
- if (rc != NGX_HTTP_NOT_FOUND || clcf->log_not_found) {
- ngx_log_error(level, log, of.err,
- "%s \"%s\" failed", of.failed, path.data);
- }
-
- return rc;
- }
-
- if (!of.is_file) {
-
- if (ngx_close_file(of.fd) == NGX_FILE_ERROR) {
- ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
- ngx_close_file_n " \"%s\" failed", path.data);
- }
-
- return NGX_DECLINED;
- }
-
- r->root_tested = !r->error_page;
- r->allow_ranges = 1;
-
- start = -1;
- length = 0;
- r->headers_out.content_length_n = of.size;
- mp4 = NULL;
- b = NULL;
-
- if (r->args.len) {
-
- if (ngx_http_arg(r, (u_char *) "start", 5, &value) == NGX_OK) {
-
- /*
- * A Flash player may send start value with a lot of digits
- * after dot so a custom function is used instead of ngx_atofp().
- */
-
- start = ngx_http_mp4_atofp(value.data, value.len, 3);
- }
-
- if (ngx_http_arg(r, (u_char *) "end", 3, &value) == NGX_OK) {
-
- end = ngx_http_mp4_atofp(value.data, value.len, 3);
-
- if (end > 0) {
- if (start < 0) {
- start = 0;
- }
-
- if (end > start) {
- length = end - start;
- }
- }
- }
- }
-
- if (start >= 0) {
- r->single_range = 1;
-
- mp4 = ngx_pcalloc(r->pool, sizeof(ngx_http_mp4_file_t));
- if (mp4 == NULL) {
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
-
- mp4->file.fd = of.fd;
- mp4->file.name = path;
- mp4->file.log = r->connection->log;
- mp4->end = of.size;
- mp4->start = (ngx_uint_t) start;
- mp4->length = length;
- mp4->request = r;
-
- switch (ngx_http_mp4_process(mp4)) {
-
- case NGX_DECLINED:
- if (mp4->buffer) {
- ngx_pfree(r->pool, mp4->buffer);
- }
-
- ngx_pfree(r->pool, mp4);
- mp4 = NULL;
-
- break;
-
- case NGX_OK:
- r->headers_out.content_length_n = mp4->content_length;
- break;
-
- default: /* NGX_ERROR */
- if (mp4->buffer) {
- ngx_pfree(r->pool, mp4->buffer);
- }
-
- ngx_pfree(r->pool, mp4);
-
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
- }
-
- log->action = "sending mp4 to client";
-
- if (clcf->directio <= of.size) {
-
- /*
- * DIRECTIO is set on transfer only
- * to allow kernel to cache "moov" atom
- */
-
- if (ngx_directio_on(of.fd) == NGX_FILE_ERROR) {
- ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
- ngx_directio_on_n " \"%s\" failed", path.data);
- }
-
- of.is_directio = 1;
-
- if (mp4) {
- mp4->file.directio = 1;
- }
- }
-
- r->headers_out.status = NGX_HTTP_OK;
- r->headers_out.last_modified_time = of.mtime;
-
- if (ngx_http_set_etag(r) != NGX_OK) {
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
-
- if (ngx_http_set_content_type(r) != NGX_OK) {
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
-
- if (mp4 == NULL) {
- b = ngx_calloc_buf(r->pool);
- if (b == NULL) {
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
-
- b->file = ngx_pcalloc(r->pool, sizeof(ngx_file_t));
- if (b->file == NULL) {
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
- }
-
- rc = ngx_http_send_header(r);
-
- if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) {
- return rc;
- }
-
- if (mp4) {
- return ngx_http_output_filter(r, mp4->out);
- }
-
- b->file_pos = 0;
- b->file_last = of.size;
-
- b->in_file = b->file_last ? 1 : 0;
- b->last_buf = (r == r->main) ? 1 : 0;
- b->last_in_chain = 1;
-
- b->file->fd = of.fd;
- b->file->name = path;
- b->file->log = log;
- b->file->directio = of.is_directio;
-
- out.buf = b;
- out.next = NULL;
-
- return ngx_http_output_filter(r, &out);
-}
-
-
-static ngx_int_t
-ngx_http_mp4_atofp(u_char *line, size_t n, size_t point)
-{
- ngx_int_t value, cutoff, cutlim;
- ngx_uint_t dot;
-
- /* same as ngx_atofp(), but allows additional digits */
-
- if (n == 0) {
- return NGX_ERROR;
- }
-
- cutoff = NGX_MAX_INT_T_VALUE / 10;
- cutlim = NGX_MAX_INT_T_VALUE % 10;
-
- dot = 0;
-
- for (value = 0; n--; line++) {
-
- if (*line == '.') {
- if (dot) {
- return NGX_ERROR;
- }
-
- dot = 1;
- continue;
- }
-
- if (*line < '0' || *line > '9') {
- return NGX_ERROR;
- }
-
- if (point == 0) {
- continue;
- }
-
- if (value >= cutoff && (value > cutoff || *line - '0' > cutlim)) {
- return NGX_ERROR;
- }
-
- value = value * 10 + (*line - '0');
- point -= dot;
- }
-
- while (point--) {
- if (value > cutoff) {
- return NGX_ERROR;
- }
-
- value = value * 10;
- }
-
- return value;
-}
-
-
-static ngx_int_t
-ngx_http_mp4_process(ngx_http_mp4_file_t *mp4)
-{
- off_t start_offset, end_offset, adjustment;
- ngx_int_t rc;
- ngx_uint_t i, j;
- ngx_chain_t **prev;
- ngx_http_mp4_trak_t *trak;
- ngx_http_mp4_conf_t *conf;
-
- ngx_log_debug2(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
- "mp4 start:%ui, length:%ui", mp4->start, mp4->length);
-
- conf = ngx_http_get_module_loc_conf(mp4->request, ngx_http_mp4_module);
-
- mp4->buffer_size = conf->buffer_size;
-
- rc = ngx_http_mp4_read_atom(mp4, ngx_http_mp4_atoms, mp4->end);
- if (rc != NGX_OK) {
- return rc;
- }
-
- if (mp4->trak.nelts == 0) {
- ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
- "no mp4 trak atoms were found in \"%s\"",
- mp4->file.name.data);
- return NGX_ERROR;
- }
-
- if (mp4->mdat_atom.buf == NULL) {
- ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
- "no mp4 mdat atom was found in \"%s\"",
- mp4->file.name.data);
- return NGX_ERROR;
- }
-
- prev = &mp4->out;
-
- if (mp4->ftyp_atom.buf) {
- *prev = &mp4->ftyp_atom;
- prev = &mp4->ftyp_atom.next;
- }
-
- *prev = &mp4->moov_atom;
- prev = &mp4->moov_atom.next;
-
- if (mp4->mvhd_atom.buf) {
- mp4->moov_size += mp4->mvhd_atom_buf.last - mp4->mvhd_atom_buf.pos;
- *prev = &mp4->mvhd_atom;
- prev = &mp4->mvhd_atom.next;
- }
-
- start_offset = mp4->end;
- end_offset = 0;
- trak = mp4->trak.elts;
-
- for (i = 0; i < mp4->trak.nelts; i++) {
-
- if (ngx_http_mp4_update_stts_atom(mp4, &trak[i]) != NGX_OK) {
- return NGX_ERROR;
- }
-
- if (ngx_http_mp4_update_stss_atom(mp4, &trak[i]) != NGX_OK) {
- return NGX_ERROR;
- }
-
- ngx_http_mp4_update_ctts_atom(mp4, &trak[i]);
-
- if (ngx_http_mp4_update_stsc_atom(mp4, &trak[i]) != NGX_OK) {
- return NGX_ERROR;
- }
-
- if (ngx_http_mp4_update_stsz_atom(mp4, &trak[i]) != NGX_OK) {
- return NGX_ERROR;
- }
-
- if (trak[i].out[NGX_HTTP_MP4_CO64_DATA].buf) {
- if (ngx_http_mp4_update_co64_atom(mp4, &trak[i]) != NGX_OK) {
- return NGX_ERROR;
- }
-
- } else {
- if (ngx_http_mp4_update_stco_atom(mp4, &trak[i]) != NGX_OK) {
- return NGX_ERROR;
- }
- }
-
- ngx_http_mp4_update_stbl_atom(mp4, &trak[i]);
- ngx_http_mp4_update_minf_atom(mp4, &trak[i]);
- trak[i].size += trak[i].mdhd_size;
- trak[i].size += trak[i].hdlr_size;
- ngx_http_mp4_update_mdia_atom(mp4, &trak[i]);
- trak[i].size += trak[i].tkhd_size;
- ngx_http_mp4_update_trak_atom(mp4, &trak[i]);
-
- mp4->moov_size += trak[i].size;
-
- if (start_offset > trak[i].start_offset) {
- start_offset = trak[i].start_offset;
- }
-
- if (end_offset < trak[i].end_offset) {
- end_offset = trak[i].end_offset;
- }
-
- *prev = &trak[i].out[NGX_HTTP_MP4_TRAK_ATOM];
- prev = &trak[i].out[NGX_HTTP_MP4_TRAK_ATOM].next;
-
- for (j = 0; j < NGX_HTTP_MP4_LAST_ATOM + 1; j++) {
- if (trak[i].out[j].buf) {
- *prev = &trak[i].out[j];
- prev = &trak[i].out[j].next;
- }
- }
- }
-
- if (end_offset < start_offset) {
- end_offset = start_offset;
- }
-
- mp4->moov_size += 8;
-
- ngx_mp4_set_32value(mp4->moov_atom_header, mp4->moov_size);
- ngx_mp4_set_atom_name(mp4->moov_atom_header, 'm', 'o', 'o', 'v');
- mp4->content_length += mp4->moov_size;
-
- *prev = &mp4->mdat_atom;
-
- if (start_offset > mp4->mdat_data.buf->file_last) {
- ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
- "start time is out mp4 mdat atom in \"%s\"",
- mp4->file.name.data);
- return NGX_ERROR;
- }
-
- adjustment = mp4->ftyp_size + mp4->moov_size
- + ngx_http_mp4_update_mdat_atom(mp4, start_offset, end_offset)
- - start_offset;
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
- "mp4 adjustment:%O", adjustment);
-
- for (i = 0; i < mp4->trak.nelts; i++) {
- if (trak[i].out[NGX_HTTP_MP4_CO64_DATA].buf) {
- ngx_http_mp4_adjust_co64_atom(mp4, &trak[i], adjustment);
- } else {
- ngx_http_mp4_adjust_stco_atom(mp4, &trak[i], (int32_t) adjustment);
- }
- }
-
- return NGX_OK;
-}
-
-
-typedef struct {
- u_char size[4];
- u_char name[4];
-} ngx_mp4_atom_header_t;
-
-typedef struct {
- u_char size[4];
- u_char name[4];
- u_char size64[8];
-} ngx_mp4_atom_header64_t;
-
-
-static ngx_int_t
-ngx_http_mp4_read_atom(ngx_http_mp4_file_t *mp4,
- ngx_http_mp4_atom_handler_t *atom, uint64_t atom_data_size)
-{
- off_t end;
- size_t atom_header_size;
- u_char *atom_header, *atom_name;
- uint64_t atom_size;
- ngx_int_t rc;
- ngx_uint_t n;
-
- end = mp4->offset + atom_data_size;
-
- while (mp4->offset < end) {
-
- if (ngx_http_mp4_read(mp4, sizeof(uint32_t)) != NGX_OK) {
- return NGX_ERROR;
- }
-
- atom_header = mp4->buffer_pos;
- atom_size = ngx_mp4_get_32value(atom_header);
- atom_header_size = sizeof(ngx_mp4_atom_header_t);
-
- if (atom_size == 0) {
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
- "mp4 atom end");
- return NGX_OK;
- }
-
- if (atom_size < sizeof(ngx_mp4_atom_header_t)) {
-
- if (atom_size == 1) {
-
- if (ngx_http_mp4_read(mp4, sizeof(ngx_mp4_atom_header64_t))
- != NGX_OK)
- {
- return NGX_ERROR;
- }
-
- /* 64-bit atom size */
- atom_header = mp4->buffer_pos;
- atom_size = ngx_mp4_get_64value(atom_header + 8);
- atom_header_size = sizeof(ngx_mp4_atom_header64_t);
-
- if (atom_size < sizeof(ngx_mp4_atom_header64_t)) {
- ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
- "\"%s\" mp4 atom is too small:%uL",
- mp4->file.name.data, atom_size);
- return NGX_ERROR;
- }
-
- } else {
- ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
- "\"%s\" mp4 atom is too small:%uL",
- mp4->file.name.data, atom_size);
- return NGX_ERROR;
- }
- }
-
- if (ngx_http_mp4_read(mp4, sizeof(ngx_mp4_atom_header_t)) != NGX_OK) {
- return NGX_ERROR;
- }
-
- atom_header = mp4->buffer_pos;
- atom_name = atom_header + sizeof(uint32_t);
-
- ngx_log_debug4(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
- "mp4 atom: %*s @%O:%uL",
- (size_t) 4, atom_name, mp4->offset, atom_size);
-
- if (atom_size > (uint64_t) (NGX_MAX_OFF_T_VALUE - mp4->offset)
- || mp4->offset + (off_t) atom_size > end)
- {
- ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
- "\"%s\" mp4 atom too large:%uL",
- mp4->file.name.data, atom_size);
- return NGX_ERROR;
- }
-
- for (n = 0; atom[n].name; n++) {
-
- if (ngx_strncmp(atom_name, atom[n].name, 4) == 0) {
-
- ngx_mp4_atom_next(mp4, atom_header_size);
-
- rc = atom[n].handler(mp4, atom_size - atom_header_size);
- if (rc != NGX_OK) {
- return rc;
- }
-
- goto next;
- }
- }
-
- ngx_mp4_atom_next(mp4, atom_size);
-
- next:
- continue;
- }
-
- return NGX_OK;
-}
-
-
-static ngx_int_t
-ngx_http_mp4_read(ngx_http_mp4_file_t *mp4, size_t size)
-{
- ssize_t n;
-
- if (mp4->buffer_pos + size <= mp4->buffer_end) {
- return NGX_OK;
- }
-
- if (mp4->offset + (off_t) mp4->buffer_size > mp4->end) {
- mp4->buffer_size = (size_t) (mp4->end - mp4->offset);
- }
-
- if (mp4->buffer_size < size) {
- ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
- "\"%s\" mp4 file truncated", mp4->file.name.data);
- return NGX_ERROR;
- }
-
- if (mp4->buffer == NULL) {
- mp4->buffer = ngx_palloc(mp4->request->pool, mp4->buffer_size);
- if (mp4->buffer == NULL) {
- return NGX_ERROR;
- }
-
- mp4->buffer_start = mp4->buffer;
- }
-
- n = ngx_read_file(&mp4->file, mp4->buffer_start, mp4->buffer_size,
- mp4->offset);
-
- if (n == NGX_ERROR) {
- return NGX_ERROR;
- }
-
- if ((size_t) n != mp4->buffer_size) {
- ngx_log_error(NGX_LOG_CRIT, mp4->file.log, 0,
- ngx_read_file_n " read only %z of %z from \"%s\"",
- n, mp4->buffer_size, mp4->file.name.data);
- return NGX_ERROR;
- }
-
- mp4->buffer_pos = mp4->buffer_start;
- mp4->buffer_end = mp4->buffer_start + mp4->buffer_size;
-
- return NGX_OK;
-}
-
-
-static ngx_int_t
-ngx_http_mp4_read_ftyp_atom(ngx_http_mp4_file_t *mp4, uint64_t atom_data_size)
-{
- u_char *ftyp_atom;
- size_t atom_size;
- ngx_buf_t *atom;
-
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, "mp4 ftyp atom");
-
- if (atom_data_size > 1024
- || ngx_mp4_atom_data(mp4) + (size_t) atom_data_size > mp4->buffer_end)
- {
- ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
- "\"%s\" mp4 ftyp atom is too large:%uL",
- mp4->file.name.data, atom_data_size);
- return NGX_ERROR;
- }
-
- atom_size = sizeof(ngx_mp4_atom_header_t) + (size_t) atom_data_size;
-
- ftyp_atom = ngx_palloc(mp4->request->pool, atom_size);
- if (ftyp_atom == NULL) {
- return NGX_ERROR;
- }
-
- ngx_mp4_set_32value(ftyp_atom, atom_size);
- ngx_mp4_set_atom_name(ftyp_atom, 'f', 't', 'y', 'p');
-
- /*
- * only moov atom content is guaranteed to be in mp4->buffer
- * during sending response, so ftyp atom content should be copied
- */
- ngx_memcpy(ftyp_atom + sizeof(ngx_mp4_atom_header_t),
- ngx_mp4_atom_data(mp4), (size_t) atom_data_size);
-
- atom = &mp4->ftyp_atom_buf;
- atom->temporary = 1;
- atom->pos = ftyp_atom;
- atom->last = ftyp_atom + atom_size;
-
- mp4->ftyp_atom.buf = atom;
- mp4->ftyp_size = atom_size;
- mp4->content_length = atom_size;
-
- ngx_mp4_atom_next(mp4, atom_data_size);
-
- return NGX_OK;
-}
-
-
-/*
- * Small excess buffer to process atoms after moov atom, mp4->buffer_start
- * will be set to this buffer part after moov atom processing.
- */
-#define NGX_HTTP_MP4_MOOV_BUFFER_EXCESS (4 * 1024)
-
-static ngx_int_t
-ngx_http_mp4_read_moov_atom(ngx_http_mp4_file_t *mp4, uint64_t atom_data_size)
-{
- ngx_int_t rc;
- ngx_uint_t no_mdat;
- ngx_buf_t *atom;
- ngx_http_mp4_conf_t *conf;
-
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, "mp4 moov atom");
-
- no_mdat = (mp4->mdat_atom.buf == NULL);
-
- if (no_mdat && mp4->start == 0 && mp4->length == 0) {
- /*
- * send original file if moov atom resides before
- * mdat atom and client requests integral file
- */
- return NGX_DECLINED;
- }
-
- conf = ngx_http_get_module_loc_conf(mp4->request, ngx_http_mp4_module);
-
- if (atom_data_size > mp4->buffer_size) {
-
- if (atom_data_size > conf->max_buffer_size) {
- ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
- "\"%s\" mp4 moov atom is too large:%uL, "
- "you may want to increase mp4_max_buffer_size",
- mp4->file.name.data, atom_data_size);
- return NGX_ERROR;
- }
-
- ngx_pfree(mp4->request->pool, mp4->buffer);
- mp4->buffer = NULL;
- mp4->buffer_pos = NULL;
- mp4->buffer_end = NULL;
-
- mp4->buffer_size = (size_t) atom_data_size
- + NGX_HTTP_MP4_MOOV_BUFFER_EXCESS * no_mdat;
- }
-
- if (ngx_http_mp4_read(mp4, (size_t) atom_data_size) != NGX_OK) {
- return NGX_ERROR;
- }
-
- mp4->trak.elts = &mp4->traks;
- mp4->trak.size = sizeof(ngx_http_mp4_trak_t);
- mp4->trak.nalloc = 2;
- mp4->trak.pool = mp4->request->pool;
-
- atom = &mp4->moov_atom_buf;
- atom->temporary = 1;
- atom->pos = mp4->moov_atom_header;
- atom->last = mp4->moov_atom_header + 8;
-
- mp4->moov_atom.buf = &mp4->moov_atom_buf;
-
- rc = ngx_http_mp4_read_atom(mp4, ngx_http_mp4_moov_atoms, atom_data_size);
-
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, "mp4 moov atom done");
-
- if (no_mdat) {
- mp4->buffer_start = mp4->buffer_pos;
- mp4->buffer_size = NGX_HTTP_MP4_MOOV_BUFFER_EXCESS;
-
- if (mp4->buffer_start + mp4->buffer_size > mp4->buffer_end) {
- mp4->buffer = NULL;
- mp4->buffer_pos = NULL;
- mp4->buffer_end = NULL;
- }
-
- } else {
- /* skip atoms after moov atom */
- mp4->offset = mp4->end;
- }
-
- return rc;
-}
-
-
-static ngx_int_t
-ngx_http_mp4_read_mdat_atom(ngx_http_mp4_file_t *mp4, uint64_t atom_data_size)
-{
- ngx_buf_t *data;
-
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, "mp4 mdat atom");
-
- data = &mp4->mdat_data_buf;
- data->file = &mp4->file;
- data->in_file = 1;
- data->last_buf = (mp4->request == mp4->request->main) ? 1 : 0;
- data->last_in_chain = 1;
- data->file_last = mp4->offset + atom_data_size;
-
- mp4->mdat_atom.buf = &mp4->mdat_atom_buf;
- mp4->mdat_atom.next = &mp4->mdat_data;
- mp4->mdat_data.buf = data;
-
- if (mp4->trak.nelts) {
- /* skip atoms after mdat atom */
- mp4->offset = mp4->end;
-
- } else {
- ngx_mp4_atom_next(mp4, atom_data_size);
- }
-
- return NGX_OK;
-}
-
-
-static size_t
-ngx_http_mp4_update_mdat_atom(ngx_http_mp4_file_t *mp4, off_t start_offset,
- off_t end_offset)
-{
- off_t atom_data_size;
- u_char *atom_header;
- uint32_t atom_header_size;
- uint64_t atom_size;
- ngx_buf_t *atom;
-
- atom_data_size = end_offset - start_offset;
- mp4->mdat_data.buf->file_pos = start_offset;
- mp4->mdat_data.buf->file_last = end_offset;
-
- ngx_log_debug2(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
- "mdat new offset @%O:%O", start_offset, atom_data_size);
-
- atom_header = mp4->mdat_atom_header;
-
- if ((uint64_t) atom_data_size
- > (uint64_t) 0xffffffff - sizeof(ngx_mp4_atom_header_t))
- {
- atom_size = 1;
- atom_header_size = sizeof(ngx_mp4_atom_header64_t);
- ngx_mp4_set_64value(atom_header + sizeof(ngx_mp4_atom_header_t),
- sizeof(ngx_mp4_atom_header64_t) + atom_data_size);
- } else {
- atom_size = sizeof(ngx_mp4_atom_header_t) + atom_data_size;
- atom_header_size = sizeof(ngx_mp4_atom_header_t);
- }
-
- mp4->content_length += atom_header_size + atom_data_size;
-
- ngx_mp4_set_32value(atom_header, atom_size);
- ngx_mp4_set_atom_name(atom_header, 'm', 'd', 'a', 't');
-
- atom = &mp4->mdat_atom_buf;
- atom->temporary = 1;
- atom->pos = atom_header;
- atom->last = atom_header + atom_header_size;
-
- return atom_header_size;
-}
-
-
-typedef struct {
- u_char size[4];
- u_char name[4];
- u_char version[1];
- u_char flags[3];
- u_char creation_time[4];
- u_char modification_time[4];
- u_char timescale[4];
- u_char duration[4];
- u_char rate[4];
- u_char volume[2];
- u_char reserved[10];
- u_char matrix[36];
- u_char preview_time[4];
- u_char preview_duration[4];
- u_char poster_time[4];
- u_char selection_time[4];
- u_char selection_duration[4];
- u_char current_time[4];
- u_char next_track_id[4];
-} ngx_mp4_mvhd_atom_t;
-
-typedef struct {
- u_char size[4];
- u_char name[4];
- u_char version[1];
- u_char flags[3];
- u_char creation_time[8];
- u_char modification_time[8];
- u_char timescale[4];
- u_char duration[8];
- u_char rate[4];
- u_char volume[2];
- u_char reserved[10];
- u_char matrix[36];
- u_char preview_time[4];
- u_char preview_duration[4];
- u_char poster_time[4];
- u_char selection_time[4];
- u_char selection_duration[4];
- u_char current_time[4];
- u_char next_track_id[4];
-} ngx_mp4_mvhd64_atom_t;
-
-
-static ngx_int_t
-ngx_http_mp4_read_mvhd_atom(ngx_http_mp4_file_t *mp4, uint64_t atom_data_size)
-{
- u_char *atom_header;
- size_t atom_size;
- uint32_t timescale;
- uint64_t duration, start_time, length_time;
- ngx_buf_t *atom;
- ngx_mp4_mvhd_atom_t *mvhd_atom;
- ngx_mp4_mvhd64_atom_t *mvhd64_atom;
-
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, "mp4 mvhd atom");
-
- atom_header = ngx_mp4_atom_header(mp4);
- mvhd_atom = (ngx_mp4_mvhd_atom_t *) atom_header;
- mvhd64_atom = (ngx_mp4_mvhd64_atom_t *) atom_header;
- ngx_mp4_set_atom_name(atom_header, 'm', 'v', 'h', 'd');
-
- if (ngx_mp4_atom_data_size(ngx_mp4_mvhd_atom_t) > atom_data_size) {
- ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
- "\"%s\" mp4 mvhd atom too small", mp4->file.name.data);
- return NGX_ERROR;
- }
-
- if (mvhd_atom->version[0] == 0) {
- /* version 0: 32-bit duration */
- timescale = ngx_mp4_get_32value(mvhd_atom->timescale);
- duration = ngx_mp4_get_32value(mvhd_atom->duration);
-
- } else {
- /* version 1: 64-bit duration */
-
- if (ngx_mp4_atom_data_size(ngx_mp4_mvhd64_atom_t) > atom_data_size) {
- ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
- "\"%s\" mp4 mvhd atom too small",
- mp4->file.name.data);
- return NGX_ERROR;
- }
-
- timescale = ngx_mp4_get_32value(mvhd64_atom->timescale);
- duration = ngx_mp4_get_64value(mvhd64_atom->duration);
- }
-
- mp4->timescale = timescale;
-
- ngx_log_debug3(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
- "mvhd timescale:%uD, duration:%uL, time:%.3fs",
- timescale, duration, (double) duration / timescale);
-
- start_time = (uint64_t) mp4->start * timescale / 1000;
-
- if (duration < start_time) {
- ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
- "\"%s\" mp4 start time exceeds file duration",
- mp4->file.name.data);
- return NGX_ERROR;
- }
-
- duration -= start_time;
-
- if (mp4->length) {
- length_time = (uint64_t) mp4->length * timescale / 1000;
-
- if (duration > length_time) {
- duration = length_time;
- }
- }
-
- ngx_log_debug2(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
- "mvhd new duration:%uL, time:%.3fs",
- duration, (double) duration / timescale);
-
- atom_size = sizeof(ngx_mp4_atom_header_t) + (size_t) atom_data_size;
- ngx_mp4_set_32value(mvhd_atom->size, atom_size);
-
- if (mvhd_atom->version[0] == 0) {
- ngx_mp4_set_32value(mvhd_atom->duration, duration);
-
- } else {
- ngx_mp4_set_64value(mvhd64_atom->duration, duration);
- }
-
- atom = &mp4->mvhd_atom_buf;
- atom->temporary = 1;
- atom->pos = atom_header;
- atom->last = atom_header + atom_size;
-
- mp4->mvhd_atom.buf = atom;
-
- ngx_mp4_atom_next(mp4, atom_data_size);
-
- return NGX_OK;
-}
-
-
-static ngx_int_t
-ngx_http_mp4_read_trak_atom(ngx_http_mp4_file_t *mp4, uint64_t atom_data_size)
-{
- u_char *atom_header, *atom_end;
- off_t atom_file_end;
- ngx_int_t rc;
- ngx_buf_t *atom;
- ngx_http_mp4_trak_t *trak;
-
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, "mp4 trak atom");
-
- trak = ngx_array_push(&mp4->trak);
- if (trak == NULL) {
- return NGX_ERROR;
- }
-
- ngx_memzero(trak, sizeof(ngx_http_mp4_trak_t));
-
- atom_header = ngx_mp4_atom_header(mp4);
- ngx_mp4_set_atom_name(atom_header, 't', 'r', 'a', 'k');
-
- atom = &trak->trak_atom_buf;
- atom->temporary = 1;
- atom->pos = atom_header;
- atom->last = atom_header + sizeof(ngx_mp4_atom_header_t);
-
- trak->out[NGX_HTTP_MP4_TRAK_ATOM].buf = atom;
-
- atom_end = mp4->buffer_pos + (size_t) atom_data_size;
- atom_file_end = mp4->offset + atom_data_size;
-
- rc = ngx_http_mp4_read_atom(mp4, ngx_http_mp4_trak_atoms, atom_data_size);
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
- "mp4 trak atom: %i", rc);
-
- if (rc == NGX_DECLINED) {
- /* skip this trak */
- ngx_memzero(trak, sizeof(ngx_http_mp4_trak_t));
- mp4->trak.nelts--;
- mp4->buffer_pos = atom_end;
- mp4->offset = atom_file_end;
- return NGX_OK;
- }
-
- return rc;
-}
-
-
-static void
-ngx_http_mp4_update_trak_atom(ngx_http_mp4_file_t *mp4,
- ngx_http_mp4_trak_t *trak)
-{
- ngx_buf_t *atom;
-
- trak->size += sizeof(ngx_mp4_atom_header_t);
- atom = &trak->trak_atom_buf;
- ngx_mp4_set_32value(atom->pos, trak->size);
-}
-
-
-static ngx_int_t
-ngx_http_mp4_read_cmov_atom(ngx_http_mp4_file_t *mp4, uint64_t atom_data_size)
-{
- ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
- "\"%s\" mp4 compressed moov atom (cmov) is not supported",
- mp4->file.name.data);
-
- return NGX_ERROR;
-}
-
-
-typedef struct {
- u_char size[4];
- u_char name[4];
- u_char version[1];
- u_char flags[3];
- u_char creation_time[4];
- u_char modification_time[4];
- u_char track_id[4];
- u_char reserved1[4];
- u_char duration[4];
- u_char reserved2[8];
- u_char layer[2];
- u_char group[2];
- u_char volume[2];
- u_char reserved3[2];
- u_char matrix[36];
- u_char width[4];
- u_char height[4];
-} ngx_mp4_tkhd_atom_t;
-
-typedef struct {
- u_char size[4];
- u_char name[4];
- u_char version[1];
- u_char flags[3];
- u_char creation_time[8];
- u_char modification_time[8];
- u_char track_id[4];
- u_char reserved1[4];
- u_char duration[8];
- u_char reserved2[8];
- u_char layer[2];
- u_char group[2];
- u_char volume[2];
- u_char reserved3[2];
- u_char matrix[36];
- u_char width[4];
- u_char height[4];
-} ngx_mp4_tkhd64_atom_t;
-
-
-static ngx_int_t
-ngx_http_mp4_read_tkhd_atom(ngx_http_mp4_file_t *mp4, uint64_t atom_data_size)
-{
- u_char *atom_header;
- size_t atom_size;
- uint64_t duration, start_time, length_time;
- ngx_buf_t *atom;
- ngx_http_mp4_trak_t *trak;
- ngx_mp4_tkhd_atom_t *tkhd_atom;
- ngx_mp4_tkhd64_atom_t *tkhd64_atom;
-
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, "mp4 tkhd atom");
-
- atom_header = ngx_mp4_atom_header(mp4);
- tkhd_atom = (ngx_mp4_tkhd_atom_t *) atom_header;
- tkhd64_atom = (ngx_mp4_tkhd64_atom_t *) atom_header;
- ngx_mp4_set_atom_name(tkhd_atom, 't', 'k', 'h', 'd');
-
- if (ngx_mp4_atom_data_size(ngx_mp4_tkhd_atom_t) > atom_data_size) {
- ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
- "\"%s\" mp4 tkhd atom too small", mp4->file.name.data);
- return NGX_ERROR;
- }
-
- if (tkhd_atom->version[0] == 0) {
- /* version 0: 32-bit duration */
- duration = ngx_mp4_get_32value(tkhd_atom->duration);
-
- } else {
- /* version 1: 64-bit duration */
-
- if (ngx_mp4_atom_data_size(ngx_mp4_tkhd64_atom_t) > atom_data_size) {
- ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
- "\"%s\" mp4 tkhd atom too small",
- mp4->file.name.data);
- return NGX_ERROR;
- }
-
- duration = ngx_mp4_get_64value(tkhd64_atom->duration);
- }
-
- ngx_log_debug2(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
- "tkhd duration:%uL, time:%.3fs",
- duration, (double) duration / mp4->timescale);
-
- start_time = (uint64_t) mp4->start * mp4->timescale / 1000;
-
- if (duration <= start_time) {
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
- "tkhd duration is less than start time");
- return NGX_DECLINED;
- }
-
- duration -= start_time;
-
- if (mp4->length) {
- length_time = (uint64_t) mp4->length * mp4->timescale / 1000;
-
- if (duration > length_time) {
- duration = length_time;
- }
- }
-
- ngx_log_debug2(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
- "tkhd new duration:%uL, time:%.3fs",
- duration, (double) duration / mp4->timescale);
-
- atom_size = sizeof(ngx_mp4_atom_header_t) + (size_t) atom_data_size;
-
- trak = ngx_mp4_last_trak(mp4);
- trak->tkhd_size = atom_size;
-
- ngx_mp4_set_32value(tkhd_atom->size, atom_size);
-
- if (tkhd_atom->version[0] == 0) {
- ngx_mp4_set_32value(tkhd_atom->duration, duration);
-
- } else {
- ngx_mp4_set_64value(tkhd64_atom->duration, duration);
- }
-
- atom = &trak->tkhd_atom_buf;
- atom->temporary = 1;
- atom->pos = atom_header;
- atom->last = atom_header + atom_size;
-
- trak->out[NGX_HTTP_MP4_TKHD_ATOM].buf = atom;
-
- ngx_mp4_atom_next(mp4, atom_data_size);
-
- return NGX_OK;
-}
-
-
-static ngx_int_t
-ngx_http_mp4_read_mdia_atom(ngx_http_mp4_file_t *mp4, uint64_t atom_data_size)
-{
- u_char *atom_header;
- ngx_buf_t *atom;
- ngx_http_mp4_trak_t *trak;
-
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, "process mdia atom");
-
- atom_header = ngx_mp4_atom_header(mp4);
- ngx_mp4_set_atom_name(atom_header, 'm', 'd', 'i', 'a');
-
- trak = ngx_mp4_last_trak(mp4);
-
- atom = &trak->mdia_atom_buf;
- atom->temporary = 1;
- atom->pos = atom_header;
- atom->last = atom_header + sizeof(ngx_mp4_atom_header_t);
-
- trak->out[NGX_HTTP_MP4_MDIA_ATOM].buf = atom;
-
- return ngx_http_mp4_read_atom(mp4, ngx_http_mp4_mdia_atoms, atom_data_size);
-}
-
-
-static void
-ngx_http_mp4_update_mdia_atom(ngx_http_mp4_file_t *mp4,
- ngx_http_mp4_trak_t *trak)
-{
- ngx_buf_t *atom;
-
- trak->size += sizeof(ngx_mp4_atom_header_t);
- atom = &trak->mdia_atom_buf;
- ngx_mp4_set_32value(atom->pos, trak->size);
-}
-
-
-typedef struct {
- u_char size[4];
- u_char name[4];
- u_char version[1];
- u_char flags[3];
- u_char creation_time[4];
- u_char modification_time[4];
- u_char timescale[4];
- u_char duration[4];
- u_char language[2];
- u_char quality[2];
-} ngx_mp4_mdhd_atom_t;
-
-typedef struct {
- u_char size[4];
- u_char name[4];
- u_char version[1];
- u_char flags[3];
- u_char creation_time[8];
- u_char modification_time[8];
- u_char timescale[4];
- u_char duration[8];
- u_char language[2];
- u_char quality[2];
-} ngx_mp4_mdhd64_atom_t;
-
-
-static ngx_int_t
-ngx_http_mp4_read_mdhd_atom(ngx_http_mp4_file_t *mp4, uint64_t atom_data_size)
-{
- u_char *atom_header;
- size_t atom_size;
- uint32_t timescale;
- uint64_t duration, start_time, length_time;
- ngx_buf_t *atom;
- ngx_http_mp4_trak_t *trak;
- ngx_mp4_mdhd_atom_t *mdhd_atom;
- ngx_mp4_mdhd64_atom_t *mdhd64_atom;
-
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, "mp4 mdhd atom");
-
- atom_header = ngx_mp4_atom_header(mp4);
- mdhd_atom = (ngx_mp4_mdhd_atom_t *) atom_header;
- mdhd64_atom = (ngx_mp4_mdhd64_atom_t *) atom_header;
- ngx_mp4_set_atom_name(mdhd_atom, 'm', 'd', 'h', 'd');
-
- if (ngx_mp4_atom_data_size(ngx_mp4_mdhd_atom_t) > atom_data_size) {
- ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
- "\"%s\" mp4 mdhd atom too small", mp4->file.name.data);
- return NGX_ERROR;
- }
-
- if (mdhd_atom->version[0] == 0) {
- /* version 0: everything is 32-bit */
- timescale = ngx_mp4_get_32value(mdhd_atom->timescale);
- duration = ngx_mp4_get_32value(mdhd_atom->duration);
-
- } else {
- /* version 1: 64-bit duration and 32-bit timescale */
-
- if (ngx_mp4_atom_data_size(ngx_mp4_mdhd64_atom_t) > atom_data_size) {
- ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
- "\"%s\" mp4 mdhd atom too small",
- mp4->file.name.data);
- return NGX_ERROR;
- }
-
- timescale = ngx_mp4_get_32value(mdhd64_atom->timescale);
- duration = ngx_mp4_get_64value(mdhd64_atom->duration);
- }
-
- ngx_log_debug3(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
- "mdhd timescale:%uD, duration:%uL, time:%.3fs",
- timescale, duration, (double) duration / timescale);
-
- start_time = (uint64_t) mp4->start * timescale / 1000;
-
- if (duration <= start_time) {
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
- "mdhd duration is less than start time");
- return NGX_DECLINED;
- }
-
- duration -= start_time;
-
- if (mp4->length) {
- length_time = (uint64_t) mp4->length * timescale / 1000;
-
- if (duration > length_time) {
- duration = length_time;
- }
- }
-
- ngx_log_debug2(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
- "mdhd new duration:%uL, time:%.3fs",
- duration, (double) duration / timescale);
-
- atom_size = sizeof(ngx_mp4_atom_header_t) + (size_t) atom_data_size;
-
- trak = ngx_mp4_last_trak(mp4);
- trak->mdhd_size = atom_size;
- trak->timescale = timescale;
-
- ngx_mp4_set_32value(mdhd_atom->size, atom_size);
-
- if (mdhd_atom->version[0] == 0) {
- ngx_mp4_set_32value(mdhd_atom->duration, duration);
-
- } else {
- ngx_mp4_set_64value(mdhd64_atom->duration, duration);
- }
-
- atom = &trak->mdhd_atom_buf;
- atom->temporary = 1;
- atom->pos = atom_header;
- atom->last = atom_header + atom_size;
-
- trak->out[NGX_HTTP_MP4_MDHD_ATOM].buf = atom;
-
- ngx_mp4_atom_next(mp4, atom_data_size);
-
- return NGX_OK;
-}
-
-
-static ngx_int_t
-ngx_http_mp4_read_hdlr_atom(ngx_http_mp4_file_t *mp4, uint64_t atom_data_size)
-{
- u_char *atom_header;
- size_t atom_size;
- ngx_buf_t *atom;
- ngx_http_mp4_trak_t *trak;
-
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, "mp4 hdlr atom");
-
- atom_header = ngx_mp4_atom_header(mp4);
- atom_size = sizeof(ngx_mp4_atom_header_t) + (size_t) atom_data_size;
- ngx_mp4_set_32value(atom_header, atom_size);
- ngx_mp4_set_atom_name(atom_header, 'h', 'd', 'l', 'r');
-
- trak = ngx_mp4_last_trak(mp4);
-
- atom = &trak->hdlr_atom_buf;
- atom->temporary = 1;
- atom->pos = atom_header;
- atom->last = atom_header + atom_size;
-
- trak->hdlr_size = atom_size;
- trak->out[NGX_HTTP_MP4_HDLR_ATOM].buf = atom;
-
- ngx_mp4_atom_next(mp4, atom_data_size);
-
- return NGX_OK;
-}
-
-
-static ngx_int_t
-ngx_http_mp4_read_minf_atom(ngx_http_mp4_file_t *mp4, uint64_t atom_data_size)
-{
- u_char *atom_header;
- ngx_buf_t *atom;
- ngx_http_mp4_trak_t *trak;
-
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, "process minf atom");
-
- atom_header = ngx_mp4_atom_header(mp4);
- ngx_mp4_set_atom_name(atom_header, 'm', 'i', 'n', 'f');
-
- trak = ngx_mp4_last_trak(mp4);
-
- atom = &trak->minf_atom_buf;
- atom->temporary = 1;
- atom->pos = atom_header;
- atom->last = atom_header + sizeof(ngx_mp4_atom_header_t);
-
- trak->out[NGX_HTTP_MP4_MINF_ATOM].buf = atom;
-
- return ngx_http_mp4_read_atom(mp4, ngx_http_mp4_minf_atoms, atom_data_size);
-}
-
-
-static void
-ngx_http_mp4_update_minf_atom(ngx_http_mp4_file_t *mp4,
- ngx_http_mp4_trak_t *trak)
-{
- ngx_buf_t *atom;
-
- trak->size += sizeof(ngx_mp4_atom_header_t)
- + trak->vmhd_size
- + trak->smhd_size
- + trak->dinf_size;
- atom = &trak->minf_atom_buf;
- ngx_mp4_set_32value(atom->pos, trak->size);
-}
-
-
-static ngx_int_t
-ngx_http_mp4_read_vmhd_atom(ngx_http_mp4_file_t *mp4, uint64_t atom_data_size)
-{
- u_char *atom_header;
- size_t atom_size;
- ngx_buf_t *atom;
- ngx_http_mp4_trak_t *trak;
-
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, "mp4 vmhd atom");
-
- atom_header = ngx_mp4_atom_header(mp4);
- atom_size = sizeof(ngx_mp4_atom_header_t) + (size_t) atom_data_size;
- ngx_mp4_set_32value(atom_header, atom_size);
- ngx_mp4_set_atom_name(atom_header, 'v', 'm', 'h', 'd');
-
- trak = ngx_mp4_last_trak(mp4);
-
- atom = &trak->vmhd_atom_buf;
- atom->temporary = 1;
- atom->pos = atom_header;
- atom->last = atom_header + atom_size;
-
- trak->vmhd_size += atom_size;
- trak->out[NGX_HTTP_MP4_VMHD_ATOM].buf = atom;
-
- ngx_mp4_atom_next(mp4, atom_data_size);
-
- return NGX_OK;
-}
-
-
-static ngx_int_t
-ngx_http_mp4_read_smhd_atom(ngx_http_mp4_file_t *mp4, uint64_t atom_data_size)
-{
- u_char *atom_header;
- size_t atom_size;
- ngx_buf_t *atom;
- ngx_http_mp4_trak_t *trak;
-
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, "mp4 smhd atom");
-
- atom_header = ngx_mp4_atom_header(mp4);
- atom_size = sizeof(ngx_mp4_atom_header_t) + (size_t) atom_data_size;
- ngx_mp4_set_32value(atom_header, atom_size);
- ngx_mp4_set_atom_name(atom_header, 's', 'm', 'h', 'd');
-
- trak = ngx_mp4_last_trak(mp4);
-
- atom = &trak->smhd_atom_buf;
- atom->temporary = 1;
- atom->pos = atom_header;
- atom->last = atom_header + atom_size;
-
- trak->smhd_size += atom_size;
- trak->out[NGX_HTTP_MP4_SMHD_ATOM].buf = atom;
-
- ngx_mp4_atom_next(mp4, atom_data_size);
-
- return NGX_OK;
-}
-
-
-static ngx_int_t
-ngx_http_mp4_read_dinf_atom(ngx_http_mp4_file_t *mp4, uint64_t atom_data_size)
-{
- u_char *atom_header;
- size_t atom_size;
- ngx_buf_t *atom;
- ngx_http_mp4_trak_t *trak;
-
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, "mp4 dinf atom");
-
- atom_header = ngx_mp4_atom_header(mp4);
- atom_size = sizeof(ngx_mp4_atom_header_t) + (size_t) atom_data_size;
- ngx_mp4_set_32value(atom_header, atom_size);
- ngx_mp4_set_atom_name(atom_header, 'd', 'i', 'n', 'f');
-
- trak = ngx_mp4_last_trak(mp4);
-
- atom = &trak->dinf_atom_buf;
- atom->temporary = 1;
- atom->pos = atom_header;
- atom->last = atom_header + atom_size;
-
- trak->dinf_size += atom_size;
- trak->out[NGX_HTTP_MP4_DINF_ATOM].buf = atom;
-
- ngx_mp4_atom_next(mp4, atom_data_size);
-
- return NGX_OK;
-}
-
-
-static ngx_int_t
-ngx_http_mp4_read_stbl_atom(ngx_http_mp4_file_t *mp4, uint64_t atom_data_size)
-{
- u_char *atom_header;
- ngx_buf_t *atom;
- ngx_http_mp4_trak_t *trak;
-
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, "process stbl atom");
-
- atom_header = ngx_mp4_atom_header(mp4);
- ngx_mp4_set_atom_name(atom_header, 's', 't', 'b', 'l');
-
- trak = ngx_mp4_last_trak(mp4);
-
- atom = &trak->stbl_atom_buf;
- atom->temporary = 1;
- atom->pos = atom_header;
- atom->last = atom_header + sizeof(ngx_mp4_atom_header_t);
-
- trak->out[NGX_HTTP_MP4_STBL_ATOM].buf = atom;
-
- return ngx_http_mp4_read_atom(mp4, ngx_http_mp4_stbl_atoms, atom_data_size);
-}
-
-
-static void
-ngx_http_mp4_update_stbl_atom(ngx_http_mp4_file_t *mp4,
- ngx_http_mp4_trak_t *trak)
-{
- ngx_buf_t *atom;
-
- trak->size += sizeof(ngx_mp4_atom_header_t);
- atom = &trak->stbl_atom_buf;
- ngx_mp4_set_32value(atom->pos, trak->size);
-}
-
-
-typedef struct {
- u_char size[4];
- u_char name[4];
- u_char version[1];
- u_char flags[3];
- u_char entries[4];
-
- u_char media_size[4];
- u_char media_name[4];
-} ngx_mp4_stsd_atom_t;
-
-
-static ngx_int_t
-ngx_http_mp4_read_stsd_atom(ngx_http_mp4_file_t *mp4, uint64_t atom_data_size)
-{
- u_char *atom_header, *atom_table;
- size_t atom_size;
- ngx_buf_t *atom;
- ngx_mp4_stsd_atom_t *stsd_atom;
- ngx_http_mp4_trak_t *trak;
-
- /* sample description atom */
-
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, "mp4 stsd atom");
-
- atom_header = ngx_mp4_atom_header(mp4);
- stsd_atom = (ngx_mp4_stsd_atom_t *) atom_header;
- atom_size = sizeof(ngx_mp4_atom_header_t) + (size_t) atom_data_size;
- atom_table = atom_header + atom_size;
- ngx_mp4_set_32value(stsd_atom->size, atom_size);
- ngx_mp4_set_atom_name(stsd_atom, 's', 't', 's', 'd');
-
- if (ngx_mp4_atom_data_size(ngx_mp4_stsd_atom_t) > atom_data_size) {
- ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
- "\"%s\" mp4 stsd atom too small", mp4->file.name.data);
- return NGX_ERROR;
- }
-
- ngx_log_debug3(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
- "stsd entries:%uD, media:%*s",
- ngx_mp4_get_32value(stsd_atom->entries),
- (size_t) 4, stsd_atom->media_name);
-
- trak = ngx_mp4_last_trak(mp4);
-
- atom = &trak->stsd_atom_buf;
- atom->temporary = 1;
- atom->pos = atom_header;
- atom->last = atom_table;
-
- trak->out[NGX_HTTP_MP4_STSD_ATOM].buf = atom;
- trak->size += atom_size;
-
- ngx_mp4_atom_next(mp4, atom_data_size);
-
- return NGX_OK;
-}
-
-
-typedef struct {
- u_char size[4];
- u_char name[4];
- u_char version[1];
- u_char flags[3];
- u_char entries[4];
-} ngx_mp4_stts_atom_t;
-
-typedef struct {
- u_char count[4];
- u_char duration[4];
-} ngx_mp4_stts_entry_t;
-
-
-static ngx_int_t
-ngx_http_mp4_read_stts_atom(ngx_http_mp4_file_t *mp4, uint64_t atom_data_size)
-{
- u_char *atom_header, *atom_table, *atom_end;
- uint32_t entries;
- ngx_buf_t *atom, *data;
- ngx_mp4_stts_atom_t *stts_atom;
- ngx_http_mp4_trak_t *trak;
-
- /* time-to-sample atom */
-
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, "mp4 stts atom");
-
- atom_header = ngx_mp4_atom_header(mp4);
- stts_atom = (ngx_mp4_stts_atom_t *) atom_header;
- ngx_mp4_set_atom_name(stts_atom, 's', 't', 't', 's');
-
- if (ngx_mp4_atom_data_size(ngx_mp4_stts_atom_t) > atom_data_size) {
- ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
- "\"%s\" mp4 stts atom too small", mp4->file.name.data);
- return NGX_ERROR;
- }
-
- entries = ngx_mp4_get_32value(stts_atom->entries);
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
- "mp4 time-to-sample entries:%uD", entries);
-
- if (ngx_mp4_atom_data_size(ngx_mp4_stts_atom_t)
- + entries * sizeof(ngx_mp4_stts_entry_t) > atom_data_size)
- {
- ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
- "\"%s\" mp4 stts atom too small", mp4->file.name.data);
- return NGX_ERROR;
- }
-
- atom_table = atom_header + sizeof(ngx_mp4_stts_atom_t);
- atom_end = atom_table + entries * sizeof(ngx_mp4_stts_entry_t);
-
- trak = ngx_mp4_last_trak(mp4);
- trak->time_to_sample_entries = entries;
-
- atom = &trak->stts_atom_buf;
- atom->temporary = 1;
- atom->pos = atom_header;
- atom->last = atom_table;
-
- data = &trak->stts_data_buf;
- data->temporary = 1;
- data->pos = atom_table;
- data->last = atom_end;
-
- trak->out[NGX_HTTP_MP4_STTS_ATOM].buf = atom;
- trak->out[NGX_HTTP_MP4_STTS_DATA].buf = data;
-
- ngx_mp4_atom_next(mp4, atom_data_size);
-
- return NGX_OK;
-}
-
-
-static ngx_int_t
-ngx_http_mp4_update_stts_atom(ngx_http_mp4_file_t *mp4,
- ngx_http_mp4_trak_t *trak)
-{
- size_t atom_size;
- ngx_buf_t *atom, *data;
- ngx_mp4_stts_atom_t *stts_atom;
-
- /*
- * mdia.minf.stbl.stts updating requires trak->timescale
- * from mdia.mdhd atom which may reside after mdia.minf
- */
-
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
- "mp4 stts atom update");
-
- data = trak->out[NGX_HTTP_MP4_STTS_DATA].buf;
-
- if (data == NULL) {
- ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
- "no mp4 stts atoms were found in \"%s\"",
- mp4->file.name.data);
- return NGX_ERROR;
- }
-
- if (ngx_http_mp4_crop_stts_data(mp4, trak, 1) != NGX_OK) {
- return NGX_ERROR;
- }
-
- if (ngx_http_mp4_crop_stts_data(mp4, trak, 0) != NGX_OK) {
- return NGX_ERROR;
- }
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
- "time-to-sample entries:%uD", trak->time_to_sample_entries);
-
- atom_size = sizeof(ngx_mp4_stts_atom_t) + (data->last - data->pos);
- trak->size += atom_size;
-
- atom = trak->out[NGX_HTTP_MP4_STTS_ATOM].buf;
- stts_atom = (ngx_mp4_stts_atom_t *) atom->pos;
- ngx_mp4_set_32value(stts_atom->size, atom_size);
- ngx_mp4_set_32value(stts_atom->entries, trak->time_to_sample_entries);
-
- return NGX_OK;
-}
-
-
-static ngx_int_t
-ngx_http_mp4_crop_stts_data(ngx_http_mp4_file_t *mp4,
- ngx_http_mp4_trak_t *trak, ngx_uint_t start)
-{
- uint32_t count, duration, rest;
- uint64_t start_time;
- ngx_buf_t *data;
- ngx_uint_t start_sample, entries, start_sec;
- ngx_mp4_stts_entry_t *entry, *end;
-
- if (start) {
- start_sec = mp4->start;
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
- "mp4 stts crop start_time:%ui", start_sec);
-
- } else if (mp4->length) {
- start_sec = mp4->length;
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
- "mp4 stts crop end_time:%ui", start_sec);
-
- } else {
- return NGX_OK;
- }
-
- data = trak->out[NGX_HTTP_MP4_STTS_DATA].buf;
-
- start_time = (uint64_t) start_sec * trak->timescale / 1000;
-
- entries = trak->time_to_sample_entries;
- start_sample = 0;
- entry = (ngx_mp4_stts_entry_t *) data->pos;
- end = (ngx_mp4_stts_entry_t *) data->last;
-
- while (entry < end) {
- count = ngx_mp4_get_32value(entry->count);
- duration = ngx_mp4_get_32value(entry->duration);
-
- ngx_log_debug3(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
- "time:%uL, count:%uD, duration:%uD",
- start_time, count, duration);
-
- if (start_time < (uint64_t) count * duration) {
- start_sample += (ngx_uint_t) (start_time / duration);
- rest = (uint32_t) (start_time / duration);
- goto found;
- }
-
- start_sample += count;
- start_time -= count * duration;
- entries--;
- entry++;
- }
-
- if (start) {
- ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
- "start time is out mp4 stts samples in \"%s\"",
- mp4->file.name.data);
-
- return NGX_ERROR;
-
- } else {
- trak->end_sample = trak->start_sample + start_sample;
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
- "end_sample:%ui", trak->end_sample);
-
- return NGX_OK;
- }
-
-found:
-
- if (start) {
- ngx_mp4_set_32value(entry->count, count - rest);
- data->pos = (u_char *) entry;
- trak->time_to_sample_entries = entries;
- trak->start_sample = start_sample;
-
- ngx_log_debug2(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
- "start_sample:%ui, new count:%uD",
- trak->start_sample, count - rest);
-
- } else {
- ngx_mp4_set_32value(entry->count, rest);
- data->last = (u_char *) (entry + 1);
- trak->time_to_sample_entries -= entries - 1;
- trak->end_sample = trak->start_sample + start_sample;
-
- ngx_log_debug2(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
- "end_sample:%ui, new count:%uD",
- trak->end_sample, rest);
- }
-
- return NGX_OK;
-}
-
-
-typedef struct {
- u_char size[4];
- u_char name[4];
- u_char version[1];
- u_char flags[3];
- u_char entries[4];
-} ngx_http_mp4_stss_atom_t;
-
-
-static ngx_int_t
-ngx_http_mp4_read_stss_atom(ngx_http_mp4_file_t *mp4, uint64_t atom_data_size)
-{
- u_char *atom_header, *atom_table, *atom_end;
- uint32_t entries;
- ngx_buf_t *atom, *data;
- ngx_http_mp4_trak_t *trak;
- ngx_http_mp4_stss_atom_t *stss_atom;
-
- /* sync samples atom */
-
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, "mp4 stss atom");
-
- atom_header = ngx_mp4_atom_header(mp4);
- stss_atom = (ngx_http_mp4_stss_atom_t *) atom_header;
- ngx_mp4_set_atom_name(stss_atom, 's', 't', 's', 's');
-
- if (ngx_mp4_atom_data_size(ngx_http_mp4_stss_atom_t) > atom_data_size) {
- ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
- "\"%s\" mp4 stss atom too small", mp4->file.name.data);
- return NGX_ERROR;
- }
-
- entries = ngx_mp4_get_32value(stss_atom->entries);
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
- "sync sample entries:%uD", entries);
-
- trak = ngx_mp4_last_trak(mp4);
- trak->sync_samples_entries = entries;
-
- atom_table = atom_header + sizeof(ngx_http_mp4_stss_atom_t);
-
- atom = &trak->stss_atom_buf;
- atom->temporary = 1;
- atom->pos = atom_header;
- atom->last = atom_table;
-
- if (ngx_mp4_atom_data_size(ngx_http_mp4_stss_atom_t)
- + entries * sizeof(uint32_t) > atom_data_size)
- {
- ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
- "\"%s\" mp4 stss atom too small", mp4->file.name.data);
- return NGX_ERROR;
- }
-
- atom_end = atom_table + entries * sizeof(uint32_t);
-
- data = &trak->stss_data_buf;
- data->temporary = 1;
- data->pos = atom_table;
- data->last = atom_end;
-
- trak->out[NGX_HTTP_MP4_STSS_ATOM].buf = atom;
- trak->out[NGX_HTTP_MP4_STSS_DATA].buf = data;
-
- ngx_mp4_atom_next(mp4, atom_data_size);
-
- return NGX_OK;
-}
-
-
-static ngx_int_t
-ngx_http_mp4_update_stss_atom(ngx_http_mp4_file_t *mp4,
- ngx_http_mp4_trak_t *trak)
-{
- size_t atom_size;
- uint32_t sample, start_sample, *entry, *end;
- ngx_buf_t *atom, *data;
- ngx_http_mp4_stss_atom_t *stss_atom;
-
- /*
- * mdia.minf.stbl.stss updating requires trak->start_sample
- * from mdia.minf.stbl.stts which depends on value from mdia.mdhd
- * atom which may reside after mdia.minf
- */
-
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
- "mp4 stss atom update");
-
- data = trak->out[NGX_HTTP_MP4_STSS_DATA].buf;
-
- if (data == NULL) {
- return NGX_OK;
- }
-
- ngx_http_mp4_crop_stss_data(mp4, trak, 1);
- ngx_http_mp4_crop_stss_data(mp4, trak, 0);
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
- "sync sample entries:%uD", trak->sync_samples_entries);
-
- if (trak->sync_samples_entries) {
- entry = (uint32_t *) data->pos;
- end = (uint32_t *) data->last;
-
- start_sample = trak->start_sample;
-
- while (entry < end) {
- sample = ngx_mp4_get_32value(entry);
- sample -= start_sample;
- ngx_mp4_set_32value(entry, sample);
- entry++;
- }
-
- } else {
- trak->out[NGX_HTTP_MP4_STSS_DATA].buf = NULL;
- }
-
- atom_size = sizeof(ngx_http_mp4_stss_atom_t) + (data->last - data->pos);
- trak->size += atom_size;
-
- atom = trak->out[NGX_HTTP_MP4_STSS_ATOM].buf;
- stss_atom = (ngx_http_mp4_stss_atom_t *) atom->pos;
-
- ngx_mp4_set_32value(stss_atom->size, atom_size);
- ngx_mp4_set_32value(stss_atom->entries, trak->sync_samples_entries);
-
- return NGX_OK;
-}
-
-
-static void
-ngx_http_mp4_crop_stss_data(ngx_http_mp4_file_t *mp4,
- ngx_http_mp4_trak_t *trak, ngx_uint_t start)
-{
- uint32_t sample, start_sample, *entry, *end;
- ngx_buf_t *data;
- ngx_uint_t entries;
-
- /* sync samples starts from 1 */
-
- if (start) {
- start_sample = trak->start_sample + 1;
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
- "mp4 stss crop start_sample:%uD", start_sample);
-
- } else if (mp4->length) {
- start_sample = trak->end_sample + 1;
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
- "mp4 stss crop end_sample:%uD", start_sample);
-
- } else {
- return;
- }
-
- data = trak->out[NGX_HTTP_MP4_STSS_DATA].buf;
-
- entries = trak->sync_samples_entries;
- entry = (uint32_t *) data->pos;
- end = (uint32_t *) data->last;
-
- while (entry < end) {
- sample = ngx_mp4_get_32value(entry);
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
- "sync:%uD", sample);
-
- if (sample >= start_sample) {
- goto found;
- }
-
- entries--;
- entry++;
- }
-
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
- "sample is out of mp4 stss atom");
-
-found:
-
- if (start) {
- data->pos = (u_char *) entry;
- trak->sync_samples_entries = entries;
-
- } else {
- data->last = (u_char *) entry;
- trak->sync_samples_entries -= entries;
- }
-}
-
-
-typedef struct {
- u_char size[4];
- u_char name[4];
- u_char version[1];
- u_char flags[3];
- u_char entries[4];
-} ngx_mp4_ctts_atom_t;
-
-typedef struct {
- u_char count[4];
- u_char offset[4];
-} ngx_mp4_ctts_entry_t;
-
-
-static ngx_int_t
-ngx_http_mp4_read_ctts_atom(ngx_http_mp4_file_t *mp4, uint64_t atom_data_size)
-{
- u_char *atom_header, *atom_table, *atom_end;
- uint32_t entries;
- ngx_buf_t *atom, *data;
- ngx_mp4_ctts_atom_t *ctts_atom;
- ngx_http_mp4_trak_t *trak;
-
- /* composition offsets atom */
-
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, "mp4 ctts atom");
-
- atom_header = ngx_mp4_atom_header(mp4);
- ctts_atom = (ngx_mp4_ctts_atom_t *) atom_header;
- ngx_mp4_set_atom_name(ctts_atom, 'c', 't', 't', 's');
-
- if (ngx_mp4_atom_data_size(ngx_mp4_ctts_atom_t) > atom_data_size) {
- ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
- "\"%s\" mp4 ctts atom too small", mp4->file.name.data);
- return NGX_ERROR;
- }
-
- entries = ngx_mp4_get_32value(ctts_atom->entries);
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
- "composition offset entries:%uD", entries);
-
- trak = ngx_mp4_last_trak(mp4);
- trak->composition_offset_entries = entries;
-
- atom_table = atom_header + sizeof(ngx_mp4_ctts_atom_t);
-
- atom = &trak->ctts_atom_buf;
- atom->temporary = 1;
- atom->pos = atom_header;
- atom->last = atom_table;
-
- if (ngx_mp4_atom_data_size(ngx_mp4_ctts_atom_t)
- + entries * sizeof(ngx_mp4_ctts_entry_t) > atom_data_size)
- {
- ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
- "\"%s\" mp4 ctts atom too small", mp4->file.name.data);
- return NGX_ERROR;
- }
-
- atom_end = atom_table + entries * sizeof(ngx_mp4_ctts_entry_t);
-
- data = &trak->ctts_data_buf;
- data->temporary = 1;
- data->pos = atom_table;
- data->last = atom_end;
-
- trak->out[NGX_HTTP_MP4_CTTS_ATOM].buf = atom;
- trak->out[NGX_HTTP_MP4_CTTS_DATA].buf = data;
-
- ngx_mp4_atom_next(mp4, atom_data_size);
-
- return NGX_OK;
-}
-
-
-static void
-ngx_http_mp4_update_ctts_atom(ngx_http_mp4_file_t *mp4,
- ngx_http_mp4_trak_t *trak)
-{
- size_t atom_size;
- ngx_buf_t *atom, *data;
- ngx_mp4_ctts_atom_t *ctts_atom;
-
- /*
- * mdia.minf.stbl.ctts updating requires trak->start_sample
- * from mdia.minf.stbl.stts which depends on value from mdia.mdhd
- * atom which may reside after mdia.minf
- */
-
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
- "mp4 ctts atom update");
-
- data = trak->out[NGX_HTTP_MP4_CTTS_DATA].buf;
-
- if (data == NULL) {
- return;
- }
-
- ngx_http_mp4_crop_ctts_data(mp4, trak, 1);
- ngx_http_mp4_crop_ctts_data(mp4, trak, 0);
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
- "composition offset entries:%uD",
- trak->composition_offset_entries);
-
- if (trak->composition_offset_entries == 0) {
- trak->out[NGX_HTTP_MP4_CTTS_ATOM].buf = NULL;
- trak->out[NGX_HTTP_MP4_CTTS_DATA].buf = NULL;
- return;
- }
-
- atom_size = sizeof(ngx_mp4_ctts_atom_t) + (data->last - data->pos);
- trak->size += atom_size;
-
- atom = trak->out[NGX_HTTP_MP4_CTTS_ATOM].buf;
- ctts_atom = (ngx_mp4_ctts_atom_t *) atom->pos;
-
- ngx_mp4_set_32value(ctts_atom->size, atom_size);
- ngx_mp4_set_32value(ctts_atom->entries, trak->composition_offset_entries);
-
- return;
-}
-
-
-static void
-ngx_http_mp4_crop_ctts_data(ngx_http_mp4_file_t *mp4,
- ngx_http_mp4_trak_t *trak, ngx_uint_t start)
-{
- uint32_t count, start_sample, rest;
- ngx_buf_t *data;
- ngx_uint_t entries;
- ngx_mp4_ctts_entry_t *entry, *end;
-
- /* sync samples starts from 1 */
-
- if (start) {
- start_sample = trak->start_sample + 1;
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
- "mp4 ctts crop start_sample:%uD", start_sample);
-
- } else if (mp4->length) {
- start_sample = trak->end_sample - trak->start_sample + 1;
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
- "mp4 ctts crop end_sample:%uD", start_sample);
-
- } else {
- return;
- }
-
- data = trak->out[NGX_HTTP_MP4_CTTS_DATA].buf;
-
- entries = trak->composition_offset_entries;
- entry = (ngx_mp4_ctts_entry_t *) data->pos;
- end = (ngx_mp4_ctts_entry_t *) data->last;
-
- while (entry < end) {
- count = ngx_mp4_get_32value(entry->count);
-
- ngx_log_debug3(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
- "sample:%uD, count:%uD, offset:%uD",
- start_sample, count, ngx_mp4_get_32value(entry->offset));
-
- if (start_sample <= count) {
- rest = start_sample - 1;
- goto found;
- }
-
- start_sample -= count;
- entries--;
- entry++;
- }
-
- if (start) {
- data->pos = (u_char *) end;
- trak->composition_offset_entries = 0;
- }
-
- return;
-
-found:
-
- if (start) {
- ngx_mp4_set_32value(entry->count, count - rest);
- data->pos = (u_char *) entry;
- trak->composition_offset_entries = entries;
-
- } else {
- ngx_mp4_set_32value(entry->count, rest);
- data->last = (u_char *) (entry + 1);
- trak->composition_offset_entries -= entries - 1;
- }
-}
-
-
-typedef struct {
- u_char size[4];
- u_char name[4];
- u_char version[1];
- u_char flags[3];
- u_char entries[4];
-} ngx_mp4_stsc_atom_t;
-
-
-static ngx_int_t
-ngx_http_mp4_read_stsc_atom(ngx_http_mp4_file_t *mp4, uint64_t atom_data_size)
-{
- u_char *atom_header, *atom_table, *atom_end;
- uint32_t entries;
- ngx_buf_t *atom, *data;
- ngx_mp4_stsc_atom_t *stsc_atom;
- ngx_http_mp4_trak_t *trak;
-
- /* sample-to-chunk atom */
-
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, "mp4 stsc atom");
-
- atom_header = ngx_mp4_atom_header(mp4);
- stsc_atom = (ngx_mp4_stsc_atom_t *) atom_header;
- ngx_mp4_set_atom_name(stsc_atom, 's', 't', 's', 'c');
-
- if (ngx_mp4_atom_data_size(ngx_mp4_stsc_atom_t) > atom_data_size) {
- ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
- "\"%s\" mp4 stsc atom too small", mp4->file.name.data);
- return NGX_ERROR;
- }
-
- entries = ngx_mp4_get_32value(stsc_atom->entries);
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
- "sample-to-chunk entries:%uD", entries);
-
- if (ngx_mp4_atom_data_size(ngx_mp4_stsc_atom_t)
- + entries * sizeof(ngx_mp4_stsc_entry_t) > atom_data_size)
- {
- ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
- "\"%s\" mp4 stsc atom too small", mp4->file.name.data);
- return NGX_ERROR;
- }
-
- atom_table = atom_header + sizeof(ngx_mp4_stsc_atom_t);
- atom_end = atom_table + entries * sizeof(ngx_mp4_stsc_entry_t);
-
- trak = ngx_mp4_last_trak(mp4);
- trak->sample_to_chunk_entries = entries;
-
- atom = &trak->stsc_atom_buf;
- atom->temporary = 1;
- atom->pos = atom_header;
- atom->last = atom_table;
-
- data = &trak->stsc_data_buf;
- data->temporary = 1;
- data->pos = atom_table;
- data->last = atom_end;
-
- trak->out[NGX_HTTP_MP4_STSC_ATOM].buf = atom;
- trak->out[NGX_HTTP_MP4_STSC_DATA].buf = data;
-
- ngx_mp4_atom_next(mp4, atom_data_size);
-
- return NGX_OK;
-}
-
-
-static ngx_int_t
-ngx_http_mp4_update_stsc_atom(ngx_http_mp4_file_t *mp4,
- ngx_http_mp4_trak_t *trak)
-{
- size_t atom_size;
- uint32_t chunk;
- ngx_buf_t *atom, *data;
- ngx_mp4_stsc_atom_t *stsc_atom;
- ngx_mp4_stsc_entry_t *entry, *end;
-
- /*
- * mdia.minf.stbl.stsc updating requires trak->start_sample
- * from mdia.minf.stbl.stts which depends on value from mdia.mdhd
- * atom which may reside after mdia.minf
- */
-
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
- "mp4 stsc atom update");
-
- data = trak->out[NGX_HTTP_MP4_STSC_DATA].buf;
-
- if (data == NULL) {
- ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
- "no mp4 stsc atoms were found in \"%s\"",
- mp4->file.name.data);
- return NGX_ERROR;
- }
-
- if (trak->sample_to_chunk_entries == 0) {
- ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
- "zero number of entries in stsc atom in \"%s\"",
- mp4->file.name.data);
- return NGX_ERROR;
- }
-
- if (ngx_http_mp4_crop_stsc_data(mp4, trak, 1) != NGX_OK) {
- return NGX_ERROR;
- }
-
- if (ngx_http_mp4_crop_stsc_data(mp4, trak, 0) != NGX_OK) {
- return NGX_ERROR;
- }
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
- "sample-to-chunk entries:%uD",
- trak->sample_to_chunk_entries);
-
- entry = (ngx_mp4_stsc_entry_t *) data->pos;
- end = (ngx_mp4_stsc_entry_t *) data->last;
-
- while (entry < end) {
- chunk = ngx_mp4_get_32value(entry->chunk);
- chunk -= trak->start_chunk;
- ngx_mp4_set_32value(entry->chunk, chunk);
- entry++;
- }
-
- atom_size = sizeof(ngx_mp4_stsc_atom_t)
- + trak->sample_to_chunk_entries * sizeof(ngx_mp4_stsc_entry_t);
-
- trak->size += atom_size;
-
- atom = trak->out[NGX_HTTP_MP4_STSC_ATOM].buf;
- stsc_atom = (ngx_mp4_stsc_atom_t *) atom->pos;
-
- ngx_mp4_set_32value(stsc_atom->size, atom_size);
- ngx_mp4_set_32value(stsc_atom->entries, trak->sample_to_chunk_entries);
-
- return NGX_OK;
-}
-
-
-static ngx_int_t
-ngx_http_mp4_crop_stsc_data(ngx_http_mp4_file_t *mp4,
- ngx_http_mp4_trak_t *trak, ngx_uint_t start)
-{
- uint32_t start_sample, chunk, samples, id, next_chunk, n,
- prev_samples;
- ngx_buf_t *data, *buf;
- ngx_uint_t entries, target_chunk, chunk_samples;
- ngx_mp4_stsc_entry_t *entry, *end, *first;
-
- entries = trak->sample_to_chunk_entries - 1;
-
- if (start) {
- start_sample = (uint32_t) trak->start_sample;
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
- "mp4 stsc crop start_sample:%uD", start_sample);
-
- } else if (mp4->length) {
- start_sample = (uint32_t) (trak->end_sample - trak->start_sample);
- samples = 0;
-
- data = trak->out[NGX_HTTP_MP4_STSC_START].buf;
-
- if (data) {
- entry = (ngx_mp4_stsc_entry_t *) data->pos;
- samples = ngx_mp4_get_32value(entry->samples);
- entries--;
-
- if (samples > start_sample) {
- samples = start_sample;
- ngx_mp4_set_32value(entry->samples, samples);
- }
-
- start_sample -= samples;
- }
-
- ngx_log_debug2(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
- "mp4 stsc crop end_sample:%uD, ext_samples:%uD",
- start_sample, samples);
-
- } else {
- return NGX_OK;
- }
-
- data = trak->out[NGX_HTTP_MP4_STSC_DATA].buf;
-
- entry = (ngx_mp4_stsc_entry_t *) data->pos;
- end = (ngx_mp4_stsc_entry_t *) data->last;
-
- chunk = ngx_mp4_get_32value(entry->chunk);
- samples = ngx_mp4_get_32value(entry->samples);
- id = ngx_mp4_get_32value(entry->id);
- prev_samples = 0;
- entry++;
-
- while (entry < end) {
-
- next_chunk = ngx_mp4_get_32value(entry->chunk);
-
- ngx_log_debug5(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
- "sample:%uD, chunk:%uD, chunks:%uD, "
- "samples:%uD, id:%uD",
- start_sample, chunk, next_chunk - chunk, samples, id);
-
- n = (next_chunk - chunk) * samples;
-
- if (start_sample < n) {
- goto found;
- }
-
- start_sample -= n;
-
- prev_samples = samples;
- chunk = next_chunk;
- samples = ngx_mp4_get_32value(entry->samples);
- id = ngx_mp4_get_32value(entry->id);
- entries--;
- entry++;
- }
-
- next_chunk = trak->chunks + 1;
-
- ngx_log_debug4(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
- "sample:%uD, chunk:%uD, chunks:%uD, samples:%uD",
- start_sample, chunk, next_chunk - chunk, samples);
-
- n = (next_chunk - chunk) * samples;
-
- if (start_sample > n) {
- ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
- "%s time is out mp4 stsc chunks in \"%s\"",
- start ? "start" : "end", mp4->file.name.data);
- return NGX_ERROR;
- }
-
-found:
-
- entries++;
- entry--;
-
- if (samples == 0) {
- ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
- "zero number of samples in \"%s\"",
- mp4->file.name.data);
- return NGX_ERROR;
- }
-
- target_chunk = chunk - 1;
- target_chunk += start_sample / samples;
- chunk_samples = start_sample % samples;
-
- if (start) {
- data->pos = (u_char *) entry;
-
- trak->sample_to_chunk_entries = entries;
- trak->start_chunk = target_chunk;
- trak->start_chunk_samples = chunk_samples;
-
- ngx_mp4_set_32value(entry->chunk, trak->start_chunk + 1);
-
- samples -= chunk_samples;
-
- ngx_log_debug2(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
- "start_chunk:%ui, start_chunk_samples:%ui",
- trak->start_chunk, trak->start_chunk_samples);
-
- } else {
- if (start_sample) {
- data->last = (u_char *) (entry + 1);
- trak->sample_to_chunk_entries -= entries - 1;
- trak->end_chunk_samples = samples;
-
- } else {
- data->last = (u_char *) entry;
- trak->sample_to_chunk_entries -= entries;
- trak->end_chunk_samples = prev_samples;
- }
-
- if (chunk_samples) {
- trak->end_chunk = target_chunk + 1;
- trak->end_chunk_samples = chunk_samples;
-
- } else {
- trak->end_chunk = target_chunk;
- }
-
- samples = chunk_samples;
- next_chunk = chunk + 1;
-
- ngx_log_debug2(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
- "end_chunk:%ui, end_chunk_samples:%ui",
- trak->end_chunk, trak->end_chunk_samples);
- }
-
- if (chunk_samples && next_chunk - target_chunk == 2) {
-
- ngx_mp4_set_32value(entry->samples, samples);
-
- } else if (chunk_samples && start) {
-
- first = &trak->stsc_start_chunk_entry;
- ngx_mp4_set_32value(first->chunk, 1);
- ngx_mp4_set_32value(first->samples, samples);
- ngx_mp4_set_32value(first->id, id);
-
- buf = &trak->stsc_start_chunk_buf;
- buf->temporary = 1;
- buf->pos = (u_char *) first;
- buf->last = (u_char *) first + sizeof(ngx_mp4_stsc_entry_t);
-
- trak->out[NGX_HTTP_MP4_STSC_START].buf = buf;
-
- ngx_mp4_set_32value(entry->chunk, trak->start_chunk + 2);
-
- trak->sample_to_chunk_entries++;
-
- } else if (chunk_samples) {
-
- first = &trak->stsc_end_chunk_entry;
- ngx_mp4_set_32value(first->chunk, trak->end_chunk - trak->start_chunk);
- ngx_mp4_set_32value(first->samples, samples);
- ngx_mp4_set_32value(first->id, id);
-
- buf = &trak->stsc_end_chunk_buf;
- buf->temporary = 1;
- buf->pos = (u_char *) first;
- buf->last = (u_char *) first + sizeof(ngx_mp4_stsc_entry_t);
-
- trak->out[NGX_HTTP_MP4_STSC_END].buf = buf;
-
- trak->sample_to_chunk_entries++;
- }
-
- return NGX_OK;
-}
-
-
-typedef struct {
- u_char size[4];
- u_char name[4];
- u_char version[1];
- u_char flags[3];
- u_char uniform_size[4];
- u_char entries[4];
-} ngx_mp4_stsz_atom_t;
-
-
-static ngx_int_t
-ngx_http_mp4_read_stsz_atom(ngx_http_mp4_file_t *mp4, uint64_t atom_data_size)
-{
- u_char *atom_header, *atom_table, *atom_end;
- size_t atom_size;
- uint32_t entries, size;
- ngx_buf_t *atom, *data;
- ngx_mp4_stsz_atom_t *stsz_atom;
- ngx_http_mp4_trak_t *trak;
-
- /* sample sizes atom */
-
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, "mp4 stsz atom");
-
- atom_header = ngx_mp4_atom_header(mp4);
- stsz_atom = (ngx_mp4_stsz_atom_t *) atom_header;
- ngx_mp4_set_atom_name(stsz_atom, 's', 't', 's', 'z');
-
- if (ngx_mp4_atom_data_size(ngx_mp4_stsz_atom_t) > atom_data_size) {
- ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
- "\"%s\" mp4 stsz atom too small", mp4->file.name.data);
- return NGX_ERROR;
- }
-
- size = ngx_mp4_get_32value(stsz_atom->uniform_size);
- entries = ngx_mp4_get_32value(stsz_atom->entries);
-
- ngx_log_debug2(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
- "sample uniform size:%uD, entries:%uD", size, entries);
-
- trak = ngx_mp4_last_trak(mp4);
- trak->sample_sizes_entries = entries;
-
- atom_table = atom_header + sizeof(ngx_mp4_stsz_atom_t);
-
- atom = &trak->stsz_atom_buf;
- atom->temporary = 1;
- atom->pos = atom_header;
- atom->last = atom_table;
-
- trak->out[NGX_HTTP_MP4_STSZ_ATOM].buf = atom;
-
- if (size == 0) {
- if (ngx_mp4_atom_data_size(ngx_mp4_stsz_atom_t)
- + entries * sizeof(uint32_t) > atom_data_size)
- {
- ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
- "\"%s\" mp4 stsz atom too small",
- mp4->file.name.data);
- return NGX_ERROR;
- }
-
- atom_end = atom_table + entries * sizeof(uint32_t);
-
- data = &trak->stsz_data_buf;
- data->temporary = 1;
- data->pos = atom_table;
- data->last = atom_end;
-
- trak->out[NGX_HTTP_MP4_STSZ_DATA].buf = data;
-
- } else {
- /* if size != 0 then all samples are the same size */
- /* TODO : chunk samples */
- atom_size = sizeof(ngx_mp4_atom_header_t) + (size_t) atom_data_size;
- ngx_mp4_set_32value(atom_header, atom_size);
- trak->size += atom_size;
- }
-
- ngx_mp4_atom_next(mp4, atom_data_size);
-
- return NGX_OK;
-}
-
-
-static ngx_int_t
-ngx_http_mp4_update_stsz_atom(ngx_http_mp4_file_t *mp4,
- ngx_http_mp4_trak_t *trak)
-{
- size_t atom_size;
- uint32_t *pos, *end, entries;
- ngx_buf_t *atom, *data;
- ngx_mp4_stsz_atom_t *stsz_atom;
-
- /*
- * mdia.minf.stbl.stsz updating requires trak->start_sample
- * from mdia.minf.stbl.stts which depends on value from mdia.mdhd
- * atom which may reside after mdia.minf
- */
-
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
- "mp4 stsz atom update");
-
- data = trak->out[NGX_HTTP_MP4_STSZ_DATA].buf;
-
- if (data) {
- entries = trak->sample_sizes_entries;
-
- if (trak->start_sample > entries) {
- ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
- "start time is out mp4 stsz samples in \"%s\"",
- mp4->file.name.data);
- return NGX_ERROR;
- }
-
- entries -= trak->start_sample;
- data->pos += trak->start_sample * sizeof(uint32_t);
- end = (uint32_t *) data->pos;
-
- for (pos = end - trak->start_chunk_samples; pos < end; pos++) {
- trak->start_chunk_samples_size += ngx_mp4_get_32value(pos);
- }
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
- "chunk samples sizes:%uL",
- trak->start_chunk_samples_size);
-
- if (mp4->length) {
- if (trak->end_sample - trak->start_sample > entries) {
- ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
- "end time is out mp4 stsz samples in \"%s\"",
- mp4->file.name.data);
- return NGX_ERROR;
- }
-
- entries = trak->end_sample - trak->start_sample;
- data->last = data->pos + entries * sizeof(uint32_t);
- end = (uint32_t *) data->last;
-
- for (pos = end - trak->end_chunk_samples; pos < end; pos++) {
- trak->end_chunk_samples_size += ngx_mp4_get_32value(pos);
- }
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
- "mp4 stsz end_chunk_samples_size:%uL",
- trak->end_chunk_samples_size);
- }
-
- atom_size = sizeof(ngx_mp4_stsz_atom_t) + (data->last - data->pos);
- trak->size += atom_size;
-
- atom = trak->out[NGX_HTTP_MP4_STSZ_ATOM].buf;
- stsz_atom = (ngx_mp4_stsz_atom_t *) atom->pos;
-
- ngx_mp4_set_32value(stsz_atom->size, atom_size);
- ngx_mp4_set_32value(stsz_atom->entries, entries);
- }
-
- return NGX_OK;
-}
-
-
-typedef struct {
- u_char size[4];
- u_char name[4];
- u_char version[1];
- u_char flags[3];
- u_char entries[4];
-} ngx_mp4_stco_atom_t;
-
-
-static ngx_int_t
-ngx_http_mp4_read_stco_atom(ngx_http_mp4_file_t *mp4, uint64_t atom_data_size)
-{
- u_char *atom_header, *atom_table, *atom_end;
- uint32_t entries;
- ngx_buf_t *atom, *data;
- ngx_mp4_stco_atom_t *stco_atom;
- ngx_http_mp4_trak_t *trak;
-
- /* chunk offsets atom */
-
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, "mp4 stco atom");
-
- atom_header = ngx_mp4_atom_header(mp4);
- stco_atom = (ngx_mp4_stco_atom_t *) atom_header;
- ngx_mp4_set_atom_name(stco_atom, 's', 't', 'c', 'o');
-
- if (ngx_mp4_atom_data_size(ngx_mp4_stco_atom_t) > atom_data_size) {
- ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
- "\"%s\" mp4 stco atom too small", mp4->file.name.data);
- return NGX_ERROR;
- }
-
- entries = ngx_mp4_get_32value(stco_atom->entries);
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, "chunks:%uD", entries);
-
- if (ngx_mp4_atom_data_size(ngx_mp4_stco_atom_t)
- + entries * sizeof(uint32_t) > atom_data_size)
- {
- ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
- "\"%s\" mp4 stco atom too small", mp4->file.name.data);
- return NGX_ERROR;
- }
-
- atom_table = atom_header + sizeof(ngx_mp4_stco_atom_t);
- atom_end = atom_table + entries * sizeof(uint32_t);
-
- trak = ngx_mp4_last_trak(mp4);
- trak->chunks = entries;
-
- atom = &trak->stco_atom_buf;
- atom->temporary = 1;
- atom->pos = atom_header;
- atom->last = atom_table;
-
- data = &trak->stco_data_buf;
- data->temporary = 1;
- data->pos = atom_table;
- data->last = atom_end;
-
- trak->out[NGX_HTTP_MP4_STCO_ATOM].buf = atom;
- trak->out[NGX_HTTP_MP4_STCO_DATA].buf = data;
-
- ngx_mp4_atom_next(mp4, atom_data_size);
-
- return NGX_OK;
-}
-
-
-static ngx_int_t
-ngx_http_mp4_update_stco_atom(ngx_http_mp4_file_t *mp4,
- ngx_http_mp4_trak_t *trak)
-{
- size_t atom_size;
- uint32_t entries;
- ngx_buf_t *atom, *data;
- ngx_mp4_stco_atom_t *stco_atom;
-
- /*
- * mdia.minf.stbl.stco updating requires trak->start_chunk
- * from mdia.minf.stbl.stsc which depends on value from mdia.mdhd
- * atom which may reside after mdia.minf
- */
-
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
- "mp4 stco atom update");
-
- data = trak->out[NGX_HTTP_MP4_STCO_DATA].buf;
-
- if (data == NULL) {
- ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
- "no mp4 stco atoms were found in \"%s\"",
- mp4->file.name.data);
- return NGX_ERROR;
- }
-
- if (trak->start_chunk > trak->chunks) {
- ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
- "start time is out mp4 stco chunks in \"%s\"",
- mp4->file.name.data);
- return NGX_ERROR;
- }
-
- data->pos += trak->start_chunk * sizeof(uint32_t);
-
- trak->start_offset = ngx_mp4_get_32value(data->pos);
- trak->start_offset += trak->start_chunk_samples_size;
- ngx_mp4_set_32value(data->pos, trak->start_offset);
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
- "start chunk offset:%O", trak->start_offset);
-
- if (mp4->length) {
-
- if (trak->end_chunk > trak->chunks) {
- ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
- "end time is out mp4 stco chunks in \"%s\"",
- mp4->file.name.data);
- return NGX_ERROR;
- }
-
- entries = trak->end_chunk - trak->start_chunk;
- data->last = data->pos + entries * sizeof(uint32_t);
-
- if (entries) {
- trak->end_offset =
- ngx_mp4_get_32value(data->last - sizeof(uint32_t));
- trak->end_offset += trak->end_chunk_samples_size;
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
- "end chunk offset:%O", trak->end_offset);
- }
-
- } else {
- entries = trak->chunks - trak->start_chunk;
- trak->end_offset = mp4->mdat_data.buf->file_last;
- }
-
- if (entries == 0) {
- trak->start_offset = mp4->end;
- trak->end_offset = 0;
- }
-
- atom_size = sizeof(ngx_mp4_stco_atom_t) + (data->last - data->pos);
- trak->size += atom_size;
-
- atom = trak->out[NGX_HTTP_MP4_STCO_ATOM].buf;
- stco_atom = (ngx_mp4_stco_atom_t *) atom->pos;
-
- ngx_mp4_set_32value(stco_atom->size, atom_size);
- ngx_mp4_set_32value(stco_atom->entries, entries);
-
- return NGX_OK;
-}
-
-
-static void
-ngx_http_mp4_adjust_stco_atom(ngx_http_mp4_file_t *mp4,
- ngx_http_mp4_trak_t *trak, int32_t adjustment)
-{
- uint32_t offset, *entry, *end;
- ngx_buf_t *data;
-
- /*
- * moov.trak.mdia.minf.stbl.stco adjustment requires
- * minimal start offset of all traks and new moov atom size
- */
-
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
- "mp4 stco atom adjustment");
-
- data = trak->out[NGX_HTTP_MP4_STCO_DATA].buf;
- entry = (uint32_t *) data->pos;
- end = (uint32_t *) data->last;
-
- while (entry < end) {
- offset = ngx_mp4_get_32value(entry);
- offset += adjustment;
- ngx_mp4_set_32value(entry, offset);
- entry++;
- }
-}
-
-
-typedef struct {
- u_char size[4];
- u_char name[4];
- u_char version[1];
- u_char flags[3];
- u_char entries[4];
-} ngx_mp4_co64_atom_t;
-
-
-static ngx_int_t
-ngx_http_mp4_read_co64_atom(ngx_http_mp4_file_t *mp4, uint64_t atom_data_size)
-{
- u_char *atom_header, *atom_table, *atom_end;
- uint32_t entries;
- ngx_buf_t *atom, *data;
- ngx_mp4_co64_atom_t *co64_atom;
- ngx_http_mp4_trak_t *trak;
-
- /* chunk offsets atom */
-
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, "mp4 co64 atom");
-
- atom_header = ngx_mp4_atom_header(mp4);
- co64_atom = (ngx_mp4_co64_atom_t *) atom_header;
- ngx_mp4_set_atom_name(co64_atom, 'c', 'o', '6', '4');
-
- if (ngx_mp4_atom_data_size(ngx_mp4_co64_atom_t) > atom_data_size) {
- ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
- "\"%s\" mp4 co64 atom too small", mp4->file.name.data);
- return NGX_ERROR;
- }
-
- entries = ngx_mp4_get_32value(co64_atom->entries);
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0, "chunks:%uD", entries);
-
- if (ngx_mp4_atom_data_size(ngx_mp4_co64_atom_t)
- + entries * sizeof(uint64_t) > atom_data_size)
- {
- ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
- "\"%s\" mp4 co64 atom too small", mp4->file.name.data);
- return NGX_ERROR;
- }
-
- atom_table = atom_header + sizeof(ngx_mp4_co64_atom_t);
- atom_end = atom_table + entries * sizeof(uint64_t);
-
- trak = ngx_mp4_last_trak(mp4);
- trak->chunks = entries;
-
- atom = &trak->co64_atom_buf;
- atom->temporary = 1;
- atom->pos = atom_header;
- atom->last = atom_table;
-
- data = &trak->co64_data_buf;
- data->temporary = 1;
- data->pos = atom_table;
- data->last = atom_end;
-
- trak->out[NGX_HTTP_MP4_CO64_ATOM].buf = atom;
- trak->out[NGX_HTTP_MP4_CO64_DATA].buf = data;
-
- ngx_mp4_atom_next(mp4, atom_data_size);
-
- return NGX_OK;
-}
-
-
-static ngx_int_t
-ngx_http_mp4_update_co64_atom(ngx_http_mp4_file_t *mp4,
- ngx_http_mp4_trak_t *trak)
-{
- size_t atom_size;
- uint64_t entries;
- ngx_buf_t *atom, *data;
- ngx_mp4_co64_atom_t *co64_atom;
-
- /*
- * mdia.minf.stbl.co64 updating requires trak->start_chunk
- * from mdia.minf.stbl.stsc which depends on value from mdia.mdhd
- * atom which may reside after mdia.minf
- */
-
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
- "mp4 co64 atom update");
-
- data = trak->out[NGX_HTTP_MP4_CO64_DATA].buf;
-
- if (data == NULL) {
- ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
- "no mp4 co64 atoms were found in \"%s\"",
- mp4->file.name.data);
- return NGX_ERROR;
- }
-
- if (trak->start_chunk > trak->chunks) {
- ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
- "start time is out mp4 co64 chunks in \"%s\"",
- mp4->file.name.data);
- return NGX_ERROR;
- }
-
- data->pos += trak->start_chunk * sizeof(uint64_t);
-
- trak->start_offset = ngx_mp4_get_64value(data->pos);
- trak->start_offset += trak->start_chunk_samples_size;
- ngx_mp4_set_64value(data->pos, trak->start_offset);
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
- "start chunk offset:%O", trak->start_offset);
-
- if (mp4->length) {
-
- if (trak->end_chunk > trak->chunks) {
- ngx_log_error(NGX_LOG_ERR, mp4->file.log, 0,
- "end time is out mp4 co64 chunks in \"%s\"",
- mp4->file.name.data);
- return NGX_ERROR;
- }
-
- entries = trak->end_chunk - trak->start_chunk;
- data->last = data->pos + entries * sizeof(uint64_t);
-
- if (entries) {
- trak->end_offset =
- ngx_mp4_get_64value(data->last - sizeof(uint64_t));
- trak->end_offset += trak->end_chunk_samples_size;
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
- "end chunk offset:%O", trak->end_offset);
- }
-
- } else {
- entries = trak->chunks - trak->start_chunk;
- trak->end_offset = mp4->mdat_data.buf->file_last;
- }
-
- if (entries == 0) {
- trak->start_offset = mp4->end;
- trak->end_offset = 0;
- }
-
- atom_size = sizeof(ngx_mp4_co64_atom_t) + (data->last - data->pos);
- trak->size += atom_size;
-
- atom = trak->out[NGX_HTTP_MP4_CO64_ATOM].buf;
- co64_atom = (ngx_mp4_co64_atom_t *) atom->pos;
-
- ngx_mp4_set_32value(co64_atom->size, atom_size);
- ngx_mp4_set_32value(co64_atom->entries, entries);
-
- return NGX_OK;
-}
-
-
-static void
-ngx_http_mp4_adjust_co64_atom(ngx_http_mp4_file_t *mp4,
- ngx_http_mp4_trak_t *trak, off_t adjustment)
-{
- uint64_t offset, *entry, *end;
- ngx_buf_t *data;
-
- /*
- * moov.trak.mdia.minf.stbl.co64 adjustment requires
- * minimal start offset of all traks and new moov atom size
- */
-
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
- "mp4 co64 atom adjustment");
-
- data = trak->out[NGX_HTTP_MP4_CO64_DATA].buf;
- entry = (uint64_t *) data->pos;
- end = (uint64_t *) data->last;
-
- while (entry < end) {
- offset = ngx_mp4_get_64value(entry);
- offset += adjustment;
- ngx_mp4_set_64value(entry, offset);
- entry++;
- }
-}
-
-
-static char *
-ngx_http_mp4(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
-{
- ngx_http_core_loc_conf_t *clcf;
-
- clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);
- clcf->handler = ngx_http_mp4_handler;
-
- return NGX_CONF_OK;
-}
-
-
-static void *
-ngx_http_mp4_create_conf(ngx_conf_t *cf)
-{
- ngx_http_mp4_conf_t *conf;
-
- conf = ngx_palloc(cf->pool, sizeof(ngx_http_mp4_conf_t));
- if (conf == NULL) {
- return NULL;
- }
-
- conf->buffer_size = NGX_CONF_UNSET_SIZE;
- conf->max_buffer_size = NGX_CONF_UNSET_SIZE;
-
- return conf;
-}
-
-
-static char *
-ngx_http_mp4_merge_conf(ngx_conf_t *cf, void *parent, void *child)
-{
- ngx_http_mp4_conf_t *prev = parent;
- ngx_http_mp4_conf_t *conf = child;
-
- ngx_conf_merge_size_value(conf->buffer_size, prev->buffer_size, 512 * 1024);
- ngx_conf_merge_size_value(conf->max_buffer_size, prev->max_buffer_size,
- 10 * 1024 * 1024);
-
- return NGX_CONF_OK;
-}
diff --git a/nginx/src/http/modules/ngx_http_not_modified_filter_module.c b/nginx/src/http/modules/ngx_http_not_modified_filter_module.c
deleted file mode 100644
index 032ba96..0000000
--- a/nginx/src/http/modules/ngx_http_not_modified_filter_module.c
+++ /dev/null
@@ -1,266 +0,0 @@
-
-/*
- * Copyright (C) Igor Sysoev
- * Copyright (C) Nginx, Inc.
- */
-
-
-#include <ngx_config.h>
-#include <ngx_core.h>
-#include <ngx_http.h>
-
-
-static ngx_uint_t ngx_http_test_if_unmodified(ngx_http_request_t *r);
-static ngx_uint_t ngx_http_test_if_modified(ngx_http_request_t *r);
-static ngx_uint_t ngx_http_test_if_match(ngx_http_request_t *r,
- ngx_table_elt_t *header, ngx_uint_t weak);
-static ngx_int_t ngx_http_not_modified_filter_init(ngx_conf_t *cf);
-
-
-static ngx_http_module_t ngx_http_not_modified_filter_module_ctx = {
- NULL, /* preconfiguration */
- ngx_http_not_modified_filter_init, /* postconfiguration */
-
- NULL, /* create main configuration */
- NULL, /* init main configuration */
-
- NULL, /* create server configuration */
- NULL, /* merge server configuration */
-
- NULL, /* create location configuration */
- NULL /* merge location configuration */
-};
-
-
-ngx_module_t ngx_http_not_modified_filter_module = {
- NGX_MODULE_V1,
- &ngx_http_not_modified_filter_module_ctx, /* module context */
- NULL, /* module directives */
- NGX_HTTP_MODULE, /* module type */
- NULL, /* init master */
- NULL, /* init module */
- NULL, /* init process */
- NULL, /* init thread */
- NULL, /* exit thread */
- NULL, /* exit process */
- NULL, /* exit master */
- NGX_MODULE_V1_PADDING
-};
-
-
-static ngx_http_output_header_filter_pt ngx_http_next_header_filter;
-
-
-static ngx_int_t
-ngx_http_not_modified_header_filter(ngx_http_request_t *r)
-{
- if (r->headers_out.status != NGX_HTTP_OK
- || r != r->main
- || r->disable_not_modified)
- {
- return ngx_http_next_header_filter(r);
- }
-
- if (r->headers_in.if_unmodified_since
- && !ngx_http_test_if_unmodified(r))
- {
- return ngx_http_filter_finalize_request(r, NULL,
- NGX_HTTP_PRECONDITION_FAILED);
- }
-
- if (r->headers_in.if_match
- && !ngx_http_test_if_match(r, r->headers_in.if_match, 0))
- {
- return ngx_http_filter_finalize_request(r, NULL,
- NGX_HTTP_PRECONDITION_FAILED);
- }
-
- if (r->headers_in.if_modified_since || r->headers_in.if_none_match) {
-
- if (r->headers_in.if_modified_since
- && ngx_http_test_if_modified(r))
- {
- return ngx_http_next_header_filter(r);
- }
-
- if (r->headers_in.if_none_match
- && !ngx_http_test_if_match(r, r->headers_in.if_none_match, 1))
- {
- return ngx_http_next_header_filter(r);
- }
-
- /* not modified */
-
- r->headers_out.status = NGX_HTTP_NOT_MODIFIED;
- r->headers_out.status_line.len = 0;
- r->headers_out.content_type.len = 0;
- ngx_http_clear_content_length(r);
- ngx_http_clear_accept_ranges(r);
-
- if (r->headers_out.content_encoding) {
- r->headers_out.content_encoding->hash = 0;
- r->headers_out.content_encoding = NULL;
- }
-
- return ngx_http_next_header_filter(r);
- }
-
- return ngx_http_next_header_filter(r);
-}
-
-
-static ngx_uint_t
-ngx_http_test_if_unmodified(ngx_http_request_t *r)
-{
- time_t iums;
-
- if (r->headers_out.last_modified_time == (time_t) -1) {
- return 0;
- }
-
- iums = ngx_parse_http_time(r->headers_in.if_unmodified_since->value.data,
- r->headers_in.if_unmodified_since->value.len);
-
- ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "http iums:%T lm:%T", iums, r->headers_out.last_modified_time);
-
- if (iums >= r->headers_out.last_modified_time) {
- return 1;
- }
-
- return 0;
-}
-
-
-static ngx_uint_t
-ngx_http_test_if_modified(ngx_http_request_t *r)
-{
- time_t ims;
- ngx_http_core_loc_conf_t *clcf;
-
- if (r->headers_out.last_modified_time == (time_t) -1) {
- return 1;
- }
-
- clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
-
- if (clcf->if_modified_since == NGX_HTTP_IMS_OFF) {
- return 1;
- }
-
- ims = ngx_parse_http_time(r->headers_in.if_modified_since->value.data,
- r->headers_in.if_modified_since->value.len);
-
- ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "http ims:%T lm:%T", ims, r->headers_out.last_modified_time);
-
- if (ims == r->headers_out.last_modified_time) {
- return 0;
- }
-
- if (clcf->if_modified_since == NGX_HTTP_IMS_EXACT
- || ims < r->headers_out.last_modified_time)
- {
- return 1;
- }
-
- return 0;
-}
-
-
-static ngx_uint_t
-ngx_http_test_if_match(ngx_http_request_t *r, ngx_table_elt_t *header,
- ngx_uint_t weak)
-{
- u_char *start, *end, ch;
- ngx_str_t etag, *list;
-
- list = &header->value;
-
- if (list->len == 1 && list->data[0] == '*') {
- return 1;
- }
-
- if (r->headers_out.etag == NULL) {
- return 0;
- }
-
- etag = r->headers_out.etag->value;
-
- ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "http im:\"%V\" etag:%V", list, &etag);
-
- if (weak
- && etag.len > 2
- && etag.data[0] == 'W'
- && etag.data[1] == '/')
- {
- etag.len -= 2;
- etag.data += 2;
- }
-
- start = list->data;
- end = list->data + list->len;
-
- while (start < end) {
-
- if (weak
- && end - start > 2
- && start[0] == 'W'
- && start[1] == '/')
- {
- start += 2;
- }
-
- if (etag.len > (size_t) (end - start)) {
- return 0;
- }
-
- if (ngx_strncmp(start, etag.data, etag.len) != 0) {
- goto skip;
- }
-
- start += etag.len;
-
- while (start < end) {
- ch = *start;
-
- if (ch == ' ' || ch == '\t') {
- start++;
- continue;
- }
-
- break;
- }
-
- if (start == end || *start == ',') {
- return 1;
- }
-
- skip:
-
- while (start < end && *start != ',') { start++; }
- while (start < end) {
- ch = *start;
-
- if (ch == ' ' || ch == '\t' || ch == ',') {
- start++;
- continue;
- }
-
- break;
- }
- }
-
- return 0;
-}
-
-
-static ngx_int_t
-ngx_http_not_modified_filter_init(ngx_conf_t *cf)
-{
- ngx_http_next_header_filter = ngx_http_top_header_filter;
- ngx_http_top_header_filter = ngx_http_not_modified_header_filter;
-
- return NGX_OK;
-}
diff --git a/nginx/src/http/modules/ngx_http_proxy_module.c b/nginx/src/http/modules/ngx_http_proxy_module.c
deleted file mode 100644
index e7f829d..0000000
--- a/nginx/src/http/modules/ngx_http_proxy_module.c
+++ /dev/null
@@ -1,4348 +0,0 @@
-
-/*
- * Copyright (C) Igor Sysoev
- * Copyright (C) Nginx, Inc.
- */
-
-
-#include <ngx_config.h>
-#include <ngx_core.h>
-#include <ngx_http.h>
-
-
-typedef struct {
- ngx_array_t caches; /* ngx_http_file_cache_t * */
-} ngx_http_proxy_main_conf_t;
-
-
-typedef struct ngx_http_proxy_rewrite_s ngx_http_proxy_rewrite_t;
-
-typedef ngx_int_t (*ngx_http_proxy_rewrite_pt)(ngx_http_request_t *r,
- ngx_table_elt_t *h, size_t prefix, size_t len,
- ngx_http_proxy_rewrite_t *pr);
-
-struct ngx_http_proxy_rewrite_s {
- ngx_http_proxy_rewrite_pt handler;
-
- union {
- ngx_http_complex_value_t complex;
-#if (NGX_PCRE)
- ngx_http_regex_t *regex;
-#endif
- } pattern;
-
- ngx_http_complex_value_t replacement;
-};
-
-
-typedef struct {
- ngx_str_t key_start;
- ngx_str_t schema;
- ngx_str_t host_header;
- ngx_str_t port;
- ngx_str_t uri;
-} ngx_http_proxy_vars_t;
-
-
-typedef struct {
- ngx_array_t *flushes;
- ngx_array_t *lengths;
- ngx_array_t *values;
- ngx_hash_t hash;
-} ngx_http_proxy_headers_t;
-
-
-typedef struct {
- ngx_http_upstream_conf_t upstream;
-
- ngx_array_t *body_flushes;
- ngx_array_t *body_lengths;
- ngx_array_t *body_values;
- ngx_str_t body_source;
-
- ngx_http_proxy_headers_t headers;
-#if (NGX_HTTP_CACHE)
- ngx_http_proxy_headers_t headers_cache;
-#endif
- ngx_array_t *headers_source;
-
- ngx_array_t *proxy_lengths;
- ngx_array_t *proxy_values;
-
- ngx_array_t *redirects;
- ngx_array_t *cookie_domains;
- ngx_array_t *cookie_paths;
-
- ngx_http_complex_value_t *method;
- ngx_str_t location;
- ngx_str_t url;
-
-#if (NGX_HTTP_CACHE)
- ngx_http_complex_value_t cache_key;
-#endif
-
- ngx_http_proxy_vars_t vars;
-
- ngx_flag_t redirect;
-
- ngx_uint_t http_version;
-
- ngx_uint_t headers_hash_max_size;
- ngx_uint_t headers_hash_bucket_size;
-
-#if (NGX_HTTP_SSL)
- ngx_uint_t ssl;
- ngx_uint_t ssl_protocols;
- ngx_str_t ssl_ciphers;
- ngx_uint_t ssl_verify_depth;
- ngx_str_t ssl_trusted_certificate;
- ngx_str_t ssl_crl;
- ngx_str_t ssl_certificate;
- ngx_str_t ssl_certificate_key;
- ngx_array_t *ssl_passwords;
-#endif
-} ngx_http_proxy_loc_conf_t;
-
-
-typedef struct {
- ngx_http_status_t status;
- ngx_http_chunked_t chunked;
- ngx_http_proxy_vars_t vars;
- off_t internal_body_length;
-
- ngx_chain_t *free;
- ngx_chain_t *busy;
-
- unsigned head:1;
- unsigned internal_chunked:1;
- unsigned header_sent:1;
-} ngx_http_proxy_ctx_t;
-
-
-static ngx_int_t ngx_http_proxy_eval(ngx_http_request_t *r,
- ngx_http_proxy_ctx_t *ctx, ngx_http_proxy_loc_conf_t *plcf);
-#if (NGX_HTTP_CACHE)
-static ngx_int_t ngx_http_proxy_create_key(ngx_http_request_t *r);
-#endif
-static ngx_int_t ngx_http_proxy_create_request(ngx_http_request_t *r);
-static ngx_int_t ngx_http_proxy_reinit_request(ngx_http_request_t *r);
-static ngx_int_t ngx_http_proxy_body_output_filter(void *data, ngx_chain_t *in);
-static ngx_int_t ngx_http_proxy_process_status_line(ngx_http_request_t *r);
-static ngx_int_t ngx_http_proxy_process_header(ngx_http_request_t *r);
-static ngx_int_t ngx_http_proxy_input_filter_init(void *data);
-static ngx_int_t ngx_http_proxy_copy_filter(ngx_event_pipe_t *p,
- ngx_buf_t *buf);
-static ngx_int_t ngx_http_proxy_chunked_filter(ngx_event_pipe_t *p,
- ngx_buf_t *buf);
-static ngx_int_t ngx_http_proxy_non_buffered_copy_filter(void *data,
- ssize_t bytes);
-static ngx_int_t ngx_http_proxy_non_buffered_chunked_filter(void *data,
- ssize_t bytes);
-static void ngx_http_proxy_abort_request(ngx_http_request_t *r);
-static void ngx_http_proxy_finalize_request(ngx_http_request_t *r,
- ngx_int_t rc);
-
-static ngx_int_t ngx_http_proxy_host_variable(ngx_http_request_t *r,
- ngx_http_variable_value_t *v, uintptr_t data);
-static ngx_int_t ngx_http_proxy_port_variable(ngx_http_request_t *r,
- ngx_http_variable_value_t *v, uintptr_t data);
-static ngx_int_t
- ngx_http_proxy_add_x_forwarded_for_variable(ngx_http_request_t *r,
- ngx_http_variable_value_t *v, uintptr_t data);
-static ngx_int_t
- ngx_http_proxy_internal_body_length_variable(ngx_http_request_t *r,
- ngx_http_variable_value_t *v, uintptr_t data);
-static ngx_int_t ngx_http_proxy_internal_chunked_variable(ngx_http_request_t *r,
- ngx_http_variable_value_t *v, uintptr_t data);
-static ngx_int_t ngx_http_proxy_rewrite_redirect(ngx_http_request_t *r,
- ngx_table_elt_t *h, size_t prefix);
-static ngx_int_t ngx_http_proxy_rewrite_cookie(ngx_http_request_t *r,
- ngx_table_elt_t *h);
-static ngx_int_t ngx_http_proxy_rewrite_cookie_value(ngx_http_request_t *r,
- ngx_table_elt_t *h, u_char *value, ngx_array_t *rewrites);
-static ngx_int_t ngx_http_proxy_rewrite(ngx_http_request_t *r,
- ngx_table_elt_t *h, size_t prefix, size_t len, ngx_str_t *replacement);
-
-static ngx_int_t ngx_http_proxy_add_variables(ngx_conf_t *cf);
-static void *ngx_http_proxy_create_main_conf(ngx_conf_t *cf);
-static void *ngx_http_proxy_create_loc_conf(ngx_conf_t *cf);
-static char *ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf,
- void *parent, void *child);
-static ngx_int_t ngx_http_proxy_init_headers(ngx_conf_t *cf,
- ngx_http_proxy_loc_conf_t *conf, ngx_http_proxy_headers_t *headers,
- ngx_keyval_t *default_headers);
-
-static char *ngx_http_proxy_pass(ngx_conf_t *cf, ngx_command_t *cmd,
- void *conf);
-static char *ngx_http_proxy_redirect(ngx_conf_t *cf, ngx_command_t *cmd,
- void *conf);
-static char *ngx_http_proxy_cookie_domain(ngx_conf_t *cf, ngx_command_t *cmd,
- void *conf);
-static char *ngx_http_proxy_cookie_path(ngx_conf_t *cf, ngx_command_t *cmd,
- void *conf);
-static char *ngx_http_proxy_store(ngx_conf_t *cf, ngx_command_t *cmd,
- void *conf);
-#if (NGX_HTTP_CACHE)
-static char *ngx_http_proxy_cache(ngx_conf_t *cf, ngx_command_t *cmd,
- void *conf);
-static char *ngx_http_proxy_cache_key(ngx_conf_t *cf, ngx_command_t *cmd,
- void *conf);
-#endif
-#if (NGX_HTTP_SSL)
-static char *ngx_http_proxy_ssl_password_file(ngx_conf_t *cf,
- ngx_command_t *cmd, void *conf);
-#endif
-
-static char *ngx_http_proxy_lowat_check(ngx_conf_t *cf, void *post, void *data);
-
-static ngx_int_t ngx_http_proxy_rewrite_regex(ngx_conf_t *cf,
- ngx_http_proxy_rewrite_t *pr, ngx_str_t *regex, ngx_uint_t caseless);
-
-#if (NGX_HTTP_SSL)
-static ngx_int_t ngx_http_proxy_set_ssl(ngx_conf_t *cf,
- ngx_http_proxy_loc_conf_t *plcf);
-#endif
-static void ngx_http_proxy_set_vars(ngx_url_t *u, ngx_http_proxy_vars_t *v);
-
-
-static ngx_conf_post_t ngx_http_proxy_lowat_post =
- { ngx_http_proxy_lowat_check };
-
-
-static ngx_conf_bitmask_t ngx_http_proxy_next_upstream_masks[] = {
- { ngx_string("error"), NGX_HTTP_UPSTREAM_FT_ERROR },
- { ngx_string("timeout"), NGX_HTTP_UPSTREAM_FT_TIMEOUT },
- { ngx_string("invalid_header"), NGX_HTTP_UPSTREAM_FT_INVALID_HEADER },
- { ngx_string("non_idempotent"), NGX_HTTP_UPSTREAM_FT_NON_IDEMPOTENT },
- { ngx_string("http_500"), NGX_HTTP_UPSTREAM_FT_HTTP_500 },
- { ngx_string("http_502"), NGX_HTTP_UPSTREAM_FT_HTTP_502 },
- { ngx_string("http_503"), NGX_HTTP_UPSTREAM_FT_HTTP_503 },
- { ngx_string("http_504"), NGX_HTTP_UPSTREAM_FT_HTTP_504 },
- { ngx_string("http_403"), NGX_HTTP_UPSTREAM_FT_HTTP_403 },
- { ngx_string("http_404"), NGX_HTTP_UPSTREAM_FT_HTTP_404 },
- { ngx_string("http_429"), NGX_HTTP_UPSTREAM_FT_HTTP_429 },
- { ngx_string("updating"), NGX_HTTP_UPSTREAM_FT_UPDATING },
- { ngx_string("off"), NGX_HTTP_UPSTREAM_FT_OFF },
- { ngx_null_string, 0 }
-};
-
-
-#if (NGX_HTTP_SSL)
-
-static ngx_conf_bitmask_t ngx_http_proxy_ssl_protocols[] = {
- { ngx_string("SSLv2"), NGX_SSL_SSLv2 },
- { ngx_string("SSLv3"), NGX_SSL_SSLv3 },
- { ngx_string("TLSv1"), NGX_SSL_TLSv1 },
- { ngx_string("TLSv1.1"), NGX_SSL_TLSv1_1 },
- { ngx_string("TLSv1.2"), NGX_SSL_TLSv1_2 },
- { ngx_string("TLSv1.3"), NGX_SSL_TLSv1_3 },
- { ngx_null_string, 0 }
-};
-
-#endif
-
-
-static ngx_conf_enum_t ngx_http_proxy_http_version[] = {
- { ngx_string("1.0"), NGX_HTTP_VERSION_10 },
- { ngx_string("1.1"), NGX_HTTP_VERSION_11 },
- { ngx_null_string, 0 }
-};
-
-
-ngx_module_t ngx_http_proxy_module;
-
-
-static ngx_command_t ngx_http_proxy_commands[] = {
-
- { ngx_string("proxy_pass"),
- NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_HTTP_LMT_CONF|NGX_CONF_TAKE1,
- ngx_http_proxy_pass,
- NGX_HTTP_LOC_CONF_OFFSET,
- 0,
- NULL },
-
- { ngx_string("proxy_redirect"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE12,
- ngx_http_proxy_redirect,
- NGX_HTTP_LOC_CONF_OFFSET,
- 0,
- NULL },
-
- { ngx_string("proxy_cookie_domain"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE12,
- ngx_http_proxy_cookie_domain,
- NGX_HTTP_LOC_CONF_OFFSET,
- 0,
- NULL },
-
- { ngx_string("proxy_cookie_path"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE12,
- ngx_http_proxy_cookie_path,
- NGX_HTTP_LOC_CONF_OFFSET,
- 0,
- NULL },
-
- { ngx_string("proxy_store"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_http_proxy_store,
- NGX_HTTP_LOC_CONF_OFFSET,
- 0,
- NULL },
-
- { ngx_string("proxy_store_access"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE123,
- ngx_conf_set_access_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_proxy_loc_conf_t, upstream.store_access),
- NULL },
-
- { ngx_string("proxy_buffering"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
- ngx_conf_set_flag_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_proxy_loc_conf_t, upstream.buffering),
- NULL },
-
- { ngx_string("proxy_request_buffering"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
- ngx_conf_set_flag_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_proxy_loc_conf_t, upstream.request_buffering),
- NULL },
-
- { ngx_string("proxy_ignore_client_abort"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
- ngx_conf_set_flag_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_proxy_loc_conf_t, upstream.ignore_client_abort),
- NULL },
-
- { ngx_string("proxy_bind"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE12,
- ngx_http_upstream_bind_set_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_proxy_loc_conf_t, upstream.local),
- NULL },
-
- { ngx_string("proxy_connect_timeout"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_msec_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_proxy_loc_conf_t, upstream.connect_timeout),
- NULL },
-
- { ngx_string("proxy_send_timeout"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_msec_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_proxy_loc_conf_t, upstream.send_timeout),
- NULL },
-
- { ngx_string("proxy_send_lowat"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_size_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_proxy_loc_conf_t, upstream.send_lowat),
- &ngx_http_proxy_lowat_post },
-
- { ngx_string("proxy_intercept_errors"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
- ngx_conf_set_flag_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_proxy_loc_conf_t, upstream.intercept_errors),
- NULL },
-
- { ngx_string("proxy_set_header"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE2,
- ngx_conf_set_keyval_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_proxy_loc_conf_t, headers_source),
- NULL },
-
- { ngx_string("proxy_headers_hash_max_size"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_num_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_proxy_loc_conf_t, headers_hash_max_size),
- NULL },
-
- { ngx_string("proxy_headers_hash_bucket_size"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_num_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_proxy_loc_conf_t, headers_hash_bucket_size),
- NULL },
-
- { ngx_string("proxy_set_body"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_str_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_proxy_loc_conf_t, body_source),
- NULL },
-
- { ngx_string("proxy_method"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_http_set_complex_value_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_proxy_loc_conf_t, method),
- NULL },
-
- { ngx_string("proxy_pass_request_headers"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
- ngx_conf_set_flag_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_proxy_loc_conf_t, upstream.pass_request_headers),
- NULL },
-
- { ngx_string("proxy_pass_request_body"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
- ngx_conf_set_flag_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_proxy_loc_conf_t, upstream.pass_request_body),
- NULL },
-
- { ngx_string("proxy_buffer_size"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_size_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_proxy_loc_conf_t, upstream.buffer_size),
- NULL },
-
- { ngx_string("proxy_read_timeout"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_msec_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_proxy_loc_conf_t, upstream.read_timeout),
- NULL },
-
- { ngx_string("proxy_buffers"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE2,
- ngx_conf_set_bufs_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_proxy_loc_conf_t, upstream.bufs),
- NULL },
-
- { ngx_string("proxy_busy_buffers_size"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_size_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_proxy_loc_conf_t, upstream.busy_buffers_size_conf),
- NULL },
-
- { ngx_string("proxy_force_ranges"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
- ngx_conf_set_flag_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_proxy_loc_conf_t, upstream.force_ranges),
- NULL },
-
- { ngx_string("proxy_limit_rate"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_size_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_proxy_loc_conf_t, upstream.limit_rate),
- NULL },
-
-#if (NGX_HTTP_CACHE)
-
- { ngx_string("proxy_cache"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_http_proxy_cache,
- NGX_HTTP_LOC_CONF_OFFSET,
- 0,
- NULL },
-
- { ngx_string("proxy_cache_key"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_http_proxy_cache_key,
- NGX_HTTP_LOC_CONF_OFFSET,
- 0,
- NULL },
-
- { ngx_string("proxy_cache_path"),
- NGX_HTTP_MAIN_CONF|NGX_CONF_2MORE,
- ngx_http_file_cache_set_slot,
- NGX_HTTP_MAIN_CONF_OFFSET,
- offsetof(ngx_http_proxy_main_conf_t, caches),
- &ngx_http_proxy_module },
-
- { ngx_string("proxy_cache_bypass"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
- ngx_http_set_predicate_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_proxy_loc_conf_t, upstream.cache_bypass),
- NULL },
-
- { ngx_string("proxy_no_cache"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
- ngx_http_set_predicate_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_proxy_loc_conf_t, upstream.no_cache),
- NULL },
-
- { ngx_string("proxy_cache_valid"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
- ngx_http_file_cache_valid_set_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_proxy_loc_conf_t, upstream.cache_valid),
- NULL },
-
- { ngx_string("proxy_cache_min_uses"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_num_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_proxy_loc_conf_t, upstream.cache_min_uses),
- NULL },
-
- { ngx_string("proxy_cache_max_range_offset"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_off_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_proxy_loc_conf_t, upstream.cache_max_range_offset),
- NULL },
-
- { ngx_string("proxy_cache_use_stale"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
- ngx_conf_set_bitmask_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_proxy_loc_conf_t, upstream.cache_use_stale),
- &ngx_http_proxy_next_upstream_masks },
-
- { ngx_string("proxy_cache_methods"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
- ngx_conf_set_bitmask_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_proxy_loc_conf_t, upstream.cache_methods),
- &ngx_http_upstream_cache_method_mask },
-
- { ngx_string("proxy_cache_lock"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
- ngx_conf_set_flag_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_proxy_loc_conf_t, upstream.cache_lock),
- NULL },
-
- { ngx_string("proxy_cache_lock_timeout"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_msec_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_proxy_loc_conf_t, upstream.cache_lock_timeout),
- NULL },
-
- { ngx_string("proxy_cache_lock_age"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_msec_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_proxy_loc_conf_t, upstream.cache_lock_age),
- NULL },
-
- { ngx_string("proxy_cache_revalidate"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
- ngx_conf_set_flag_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_proxy_loc_conf_t, upstream.cache_revalidate),
- NULL },
-
- { ngx_string("proxy_cache_convert_head"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
- ngx_conf_set_flag_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_proxy_loc_conf_t, upstream.cache_convert_head),
- NULL },
-
- { ngx_string("proxy_cache_background_update"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
- ngx_conf_set_flag_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_proxy_loc_conf_t, upstream.cache_background_update),
- NULL },
-
-#endif
-
- { ngx_string("proxy_temp_path"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1234,
- ngx_conf_set_path_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_proxy_loc_conf_t, upstream.temp_path),
- NULL },
-
- { ngx_string("proxy_max_temp_file_size"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_size_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_proxy_loc_conf_t, upstream.max_temp_file_size_conf),
- NULL },
-
- { ngx_string("proxy_temp_file_write_size"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_size_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_proxy_loc_conf_t, upstream.temp_file_write_size_conf),
- NULL },
-
- { ngx_string("proxy_next_upstream"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
- ngx_conf_set_bitmask_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_proxy_loc_conf_t, upstream.next_upstream),
- &ngx_http_proxy_next_upstream_masks },
-
- { ngx_string("proxy_next_upstream_tries"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_num_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_proxy_loc_conf_t, upstream.next_upstream_tries),
- NULL },
-
- { ngx_string("proxy_next_upstream_timeout"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_msec_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_proxy_loc_conf_t, upstream.next_upstream_timeout),
- NULL },
-
- { ngx_string("proxy_pass_header"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_str_array_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_proxy_loc_conf_t, upstream.pass_headers),
- NULL },
-
- { ngx_string("proxy_hide_header"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_str_array_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_proxy_loc_conf_t, upstream.hide_headers),
- NULL },
-
- { ngx_string("proxy_ignore_headers"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
- ngx_conf_set_bitmask_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_proxy_loc_conf_t, upstream.ignore_headers),
- &ngx_http_upstream_ignore_headers_masks },
-
- { ngx_string("proxy_http_version"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_enum_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_proxy_loc_conf_t, http_version),
- &ngx_http_proxy_http_version },
-
-#if (NGX_HTTP_SSL)
-
- { ngx_string("proxy_ssl_session_reuse"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
- ngx_conf_set_flag_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_proxy_loc_conf_t, upstream.ssl_session_reuse),
- NULL },
-
- { ngx_string("proxy_ssl_protocols"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
- ngx_conf_set_bitmask_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_proxy_loc_conf_t, ssl_protocols),
- &ngx_http_proxy_ssl_protocols },
-
- { ngx_string("proxy_ssl_ciphers"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_str_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_proxy_loc_conf_t, ssl_ciphers),
- NULL },
-
- { ngx_string("proxy_ssl_name"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_http_set_complex_value_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_proxy_loc_conf_t, upstream.ssl_name),
- NULL },
-
- { ngx_string("proxy_ssl_server_name"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
- ngx_conf_set_flag_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_proxy_loc_conf_t, upstream.ssl_server_name),
- NULL },
-
- { ngx_string("proxy_ssl_verify"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
- ngx_conf_set_flag_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_proxy_loc_conf_t, upstream.ssl_verify),
- NULL },
-
- { ngx_string("proxy_ssl_verify_depth"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_num_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_proxy_loc_conf_t, ssl_verify_depth),
- NULL },
-
- { ngx_string("proxy_ssl_trusted_certificate"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_str_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_proxy_loc_conf_t, ssl_trusted_certificate),
- NULL },
-
- { ngx_string("proxy_ssl_crl"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_str_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_proxy_loc_conf_t, ssl_crl),
- NULL },
-
- { ngx_string("proxy_ssl_certificate"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_str_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_proxy_loc_conf_t, ssl_certificate),
- NULL },
-
- { ngx_string("proxy_ssl_certificate_key"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_str_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_proxy_loc_conf_t, ssl_certificate_key),
- NULL },
-
- { ngx_string("proxy_ssl_password_file"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_http_proxy_ssl_password_file,
- NGX_HTTP_LOC_CONF_OFFSET,
- 0,
- NULL },
-
-#endif
-
- ngx_null_command
-};
-
-
-static ngx_http_module_t ngx_http_proxy_module_ctx = {
- ngx_http_proxy_add_variables, /* preconfiguration */
- NULL, /* postconfiguration */
-
- ngx_http_proxy_create_main_conf, /* create main configuration */
- NULL, /* init main configuration */
-
- NULL, /* create server configuration */
- NULL, /* merge server configuration */
-
- ngx_http_proxy_create_loc_conf, /* create location configuration */
- ngx_http_proxy_merge_loc_conf /* merge location configuration */
-};
-
-
-ngx_module_t ngx_http_proxy_module = {
- NGX_MODULE_V1,
- &ngx_http_proxy_module_ctx, /* module context */
- ngx_http_proxy_commands, /* module directives */
- NGX_HTTP_MODULE, /* module type */
- NULL, /* init master */
- NULL, /* init module */
- NULL, /* init process */
- NULL, /* init thread */
- NULL, /* exit thread */
- NULL, /* exit process */
- NULL, /* exit master */
- NGX_MODULE_V1_PADDING
-};
-
-
-static char ngx_http_proxy_version[] = " HTTP/1.0" CRLF;
-static char ngx_http_proxy_version_11[] = " HTTP/1.1" CRLF;
-
-
-static ngx_keyval_t ngx_http_proxy_headers[] = {
- { ngx_string("Host"), ngx_string("$proxy_host") },
- { ngx_string("Connection"), ngx_string("close") },
- { ngx_string("Content-Length"), ngx_string("$proxy_internal_body_length") },
- { ngx_string("Transfer-Encoding"), ngx_string("$proxy_internal_chunked") },
- { ngx_string("TE"), ngx_string("") },
- { ngx_string("Keep-Alive"), ngx_string("") },
- { ngx_string("Expect"), ngx_string("") },
- { ngx_string("Upgrade"), ngx_string("") },
- { ngx_null_string, ngx_null_string }
-};
-
-
-static ngx_str_t ngx_http_proxy_hide_headers[] = {
- ngx_string("Date"),
- ngx_string("Server"),
- ngx_string("X-Pad"),
- ngx_string("X-Accel-Expires"),
- ngx_string("X-Accel-Redirect"),
- ngx_string("X-Accel-Limit-Rate"),
- ngx_string("X-Accel-Buffering"),
- ngx_string("X-Accel-Charset"),
- ngx_null_string
-};
-
-
-#if (NGX_HTTP_CACHE)
-
-static ngx_keyval_t ngx_http_proxy_cache_headers[] = {
- { ngx_string("Host"), ngx_string("$proxy_host") },
- { ngx_string("Connection"), ngx_string("close") },
- { ngx_string("Content-Length"), ngx_string("$proxy_internal_body_length") },
- { ngx_string("Transfer-Encoding"), ngx_string("$proxy_internal_chunked") },
- { ngx_string("TE"), ngx_string("") },
- { ngx_string("Keep-Alive"), ngx_string("") },
- { ngx_string("Expect"), ngx_string("") },
- { ngx_string("Upgrade"), ngx_string("") },
- { ngx_string("If-Modified-Since"),
- ngx_string("$upstream_cache_last_modified") },
- { ngx_string("If-Unmodified-Since"), ngx_string("") },
- { ngx_string("If-None-Match"), ngx_string("$upstream_cache_etag") },
- { ngx_string("If-Match"), ngx_string("") },
- { ngx_string("Range"), ngx_string("") },
- { ngx_string("If-Range"), ngx_string("") },
- { ngx_null_string, ngx_null_string }
-};
-
-#endif
-
-
-static ngx_http_variable_t ngx_http_proxy_vars[] = {
-
- { ngx_string("proxy_host"), NULL, ngx_http_proxy_host_variable, 0,
- NGX_HTTP_VAR_CHANGEABLE|NGX_HTTP_VAR_NOCACHEABLE|NGX_HTTP_VAR_NOHASH, 0 },
-
- { ngx_string("proxy_port"), NULL, ngx_http_proxy_port_variable, 0,
- NGX_HTTP_VAR_CHANGEABLE|NGX_HTTP_VAR_NOCACHEABLE|NGX_HTTP_VAR_NOHASH, 0 },
-
- { ngx_string("proxy_add_x_forwarded_for"), NULL,
- ngx_http_proxy_add_x_forwarded_for_variable, 0, NGX_HTTP_VAR_NOHASH, 0 },
-
-#if 0
- { ngx_string("proxy_add_via"), NULL, NULL, 0, NGX_HTTP_VAR_NOHASH, 0 },
-#endif
-
- { ngx_string("proxy_internal_body_length"), NULL,
- ngx_http_proxy_internal_body_length_variable, 0,
- NGX_HTTP_VAR_NOCACHEABLE|NGX_HTTP_VAR_NOHASH, 0 },
-
- { ngx_string("proxy_internal_chunked"), NULL,
- ngx_http_proxy_internal_chunked_variable, 0,
- NGX_HTTP_VAR_NOCACHEABLE|NGX_HTTP_VAR_NOHASH, 0 },
-
- ngx_http_null_variable
-};
-
-
-static ngx_path_init_t ngx_http_proxy_temp_path = {
- ngx_string(NGX_HTTP_PROXY_TEMP_PATH), { 1, 2, 0 }
-};
-
-
-static ngx_int_t
-ngx_http_proxy_handler(ngx_http_request_t *r)
-{
- ngx_int_t rc;
- ngx_http_upstream_t *u;
- ngx_http_proxy_ctx_t *ctx;
- ngx_http_proxy_loc_conf_t *plcf;
-#if (NGX_HTTP_CACHE)
- ngx_http_proxy_main_conf_t *pmcf;
-#endif
-
- if (ngx_http_upstream_create(r) != NGX_OK) {
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
-
- ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_proxy_ctx_t));
- if (ctx == NULL) {
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
-
- ngx_http_set_ctx(r, ctx, ngx_http_proxy_module);
-
- plcf = ngx_http_get_module_loc_conf(r, ngx_http_proxy_module);
-
- u = r->upstream;
-
- if (plcf->proxy_lengths == NULL) {
- ctx->vars = plcf->vars;
- u->schema = plcf->vars.schema;
-#if (NGX_HTTP_SSL)
- u->ssl = (plcf->upstream.ssl != NULL);
-#endif
-
- } else {
- if (ngx_http_proxy_eval(r, ctx, plcf) != NGX_OK) {
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
- }
-
- u->output.tag = (ngx_buf_tag_t) &ngx_http_proxy_module;
-
- u->conf = &plcf->upstream;
-
-#if (NGX_HTTP_CACHE)
- pmcf = ngx_http_get_module_main_conf(r, ngx_http_proxy_module);
-
- u->caches = &pmcf->caches;
- u->create_key = ngx_http_proxy_create_key;
-#endif
-
- u->create_request = ngx_http_proxy_create_request;
- u->reinit_request = ngx_http_proxy_reinit_request;
- u->process_header = ngx_http_proxy_process_status_line;
- u->abort_request = ngx_http_proxy_abort_request;
- u->finalize_request = ngx_http_proxy_finalize_request;
- r->state = 0;
-
- if (plcf->redirects) {
- u->rewrite_redirect = ngx_http_proxy_rewrite_redirect;
- }
-
- if (plcf->cookie_domains || plcf->cookie_paths) {
- u->rewrite_cookie = ngx_http_proxy_rewrite_cookie;
- }
-
- u->buffering = plcf->upstream.buffering;
-
- u->pipe = ngx_pcalloc(r->pool, sizeof(ngx_event_pipe_t));
- if (u->pipe == NULL) {
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
-
- u->pipe->input_filter = ngx_http_proxy_copy_filter;
- u->pipe->input_ctx = r;
-
- u->input_filter_init = ngx_http_proxy_input_filter_init;
- u->input_filter = ngx_http_proxy_non_buffered_copy_filter;
- u->input_filter_ctx = r;
-
- u->accel = 1;
-
- if (!plcf->upstream.request_buffering
- && plcf->body_values == NULL && plcf->upstream.pass_request_body
- && (!r->headers_in.chunked
- || plcf->http_version == NGX_HTTP_VERSION_11))
- {
- r->request_body_no_buffering = 1;
- }
-
- rc = ngx_http_read_client_request_body(r, ngx_http_upstream_init);
-
- if (rc >= NGX_HTTP_SPECIAL_RESPONSE) {
- return rc;
- }
-
- return NGX_DONE;
-}
-
-
-static ngx_int_t
-ngx_http_proxy_eval(ngx_http_request_t *r, ngx_http_proxy_ctx_t *ctx,
- ngx_http_proxy_loc_conf_t *plcf)
-{
- u_char *p;
- size_t add;
- u_short port;
- ngx_str_t proxy;
- ngx_url_t url;
- ngx_http_upstream_t *u;
-
- if (ngx_http_script_run(r, &proxy, plcf->proxy_lengths->elts, 0,
- plcf->proxy_values->elts)
- == NULL)
- {
- return NGX_ERROR;
- }
-
- if (proxy.len > 7
- && ngx_strncasecmp(proxy.data, (u_char *) "http://", 7) == 0)
- {
- add = 7;
- port = 80;
-
-#if (NGX_HTTP_SSL)
-
- } else if (proxy.len > 8
- && ngx_strncasecmp(proxy.data, (u_char *) "https://", 8) == 0)
- {
- add = 8;
- port = 443;
- r->upstream->ssl = 1;
-
-#endif
-
- } else {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "invalid URL prefix in \"%V\"", &proxy);
- return NGX_ERROR;
- }
-
- u = r->upstream;
-
- u->schema.len = add;
- u->schema.data = proxy.data;
-
- ngx_memzero(&url, sizeof(ngx_url_t));
-
- url.url.len = proxy.len - add;
- url.url.data = proxy.data + add;
- url.default_port = port;
- url.uri_part = 1;
- url.no_resolve = 1;
-
- if (ngx_parse_url(r->pool, &url) != NGX_OK) {
- if (url.err) {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "%s in upstream \"%V\"", url.err, &url.url);
- }
-
- return NGX_ERROR;
- }
-
- if (url.uri.len) {
- if (url.uri.data[0] == '?') {
- p = ngx_pnalloc(r->pool, url.uri.len + 1);
- if (p == NULL) {
- return NGX_ERROR;
- }
-
- *p++ = '/';
- ngx_memcpy(p, url.uri.data, url.uri.len);
-
- url.uri.len++;
- url.uri.data = p - 1;
- }
- }
-
- ctx->vars.key_start = u->schema;
-
- ngx_http_proxy_set_vars(&url, &ctx->vars);
-
- u->resolved = ngx_pcalloc(r->pool, sizeof(ngx_http_upstream_resolved_t));
- if (u->resolved == NULL) {
- return NGX_ERROR;
- }
-
- if (url.addrs) {
- u->resolved->sockaddr = url.addrs[0].sockaddr;
- u->resolved->socklen = url.addrs[0].socklen;
- u->resolved->name = url.addrs[0].name;
- u->resolved->naddrs = 1;
- }
-
- u->resolved->host = url.host;
- u->resolved->port = (in_port_t) (url.no_port ? port : url.port);
- u->resolved->no_port = url.no_port;
-
- return NGX_OK;
-}
-
-
-#if (NGX_HTTP_CACHE)
-
-static ngx_int_t
-ngx_http_proxy_create_key(ngx_http_request_t *r)
-{
- size_t len, loc_len;
- u_char *p;
- uintptr_t escape;
- ngx_str_t *key;
- ngx_http_upstream_t *u;
- ngx_http_proxy_ctx_t *ctx;
- ngx_http_proxy_loc_conf_t *plcf;
-
- u = r->upstream;
-
- plcf = ngx_http_get_module_loc_conf(r, ngx_http_proxy_module);
-
- ctx = ngx_http_get_module_ctx(r, ngx_http_proxy_module);
-
- key = ngx_array_push(&r->cache->keys);
- if (key == NULL) {
- return NGX_ERROR;
- }
-
- if (plcf->cache_key.value.data) {
-
- if (ngx_http_complex_value(r, &plcf->cache_key, key) != NGX_OK) {
- return NGX_ERROR;
- }
-
- return NGX_OK;
- }
-
- *key = ctx->vars.key_start;
-
- key = ngx_array_push(&r->cache->keys);
- if (key == NULL) {
- return NGX_ERROR;
- }
-
- if (plcf->proxy_lengths && ctx->vars.uri.len) {
-
- *key = ctx->vars.uri;
- u->uri = ctx->vars.uri;
-
- return NGX_OK;
-
- } else if (ctx->vars.uri.len == 0 && r->valid_unparsed_uri) {
- *key = r->unparsed_uri;
- u->uri = r->unparsed_uri;
-
- return NGX_OK;
- }
-
- loc_len = (r->valid_location && ctx->vars.uri.len) ? plcf->location.len : 0;
-
- if (r->quoted_uri || r->space_in_uri || r->internal) {
- escape = 2 * ngx_escape_uri(NULL, r->uri.data + loc_len,
- r->uri.len - loc_len, NGX_ESCAPE_URI);
- } else {
- escape = 0;
- }
-
- len = ctx->vars.uri.len + r->uri.len - loc_len + escape
- + sizeof("?") - 1 + r->args.len;
-
- p = ngx_pnalloc(r->pool, len);
- if (p == NULL) {
- return NGX_ERROR;
- }
-
- key->data = p;
-
- if (r->valid_location) {
- p = ngx_copy(p, ctx->vars.uri.data, ctx->vars.uri.len);
- }
-
- if (escape) {
- ngx_escape_uri(p, r->uri.data + loc_len,
- r->uri.len - loc_len, NGX_ESCAPE_URI);
- p += r->uri.len - loc_len + escape;
-
- } else {
- p = ngx_copy(p, r->uri.data + loc_len, r->uri.len - loc_len);
- }
-
- if (r->args.len > 0) {
- *p++ = '?';
- p = ngx_copy(p, r->args.data, r->args.len);
- }
-
- key->len = p - key->data;
- u->uri = *key;
-
- return NGX_OK;
-}
-
-#endif
-
-
-static ngx_int_t
-ngx_http_proxy_create_request(ngx_http_request_t *r)
-{
- size_t len, uri_len, loc_len, body_len,
- key_len, val_len;
- uintptr_t escape;
- ngx_buf_t *b;
- ngx_str_t method;
- ngx_uint_t i, unparsed_uri;
- ngx_chain_t *cl, *body;
- ngx_list_part_t *part;
- ngx_table_elt_t *header;
- ngx_http_upstream_t *u;
- ngx_http_proxy_ctx_t *ctx;
- ngx_http_script_code_pt code;
- ngx_http_proxy_headers_t *headers;
- ngx_http_script_engine_t e, le;
- ngx_http_proxy_loc_conf_t *plcf;
- ngx_http_script_len_code_pt lcode;
-
- u = r->upstream;
-
- plcf = ngx_http_get_module_loc_conf(r, ngx_http_proxy_module);
-
-#if (NGX_HTTP_CACHE)
- headers = u->cacheable ? &plcf->headers_cache : &plcf->headers;
-#else
- headers = &plcf->headers;
-#endif
-
- if (u->method.len) {
- /* HEAD was changed to GET to cache response */
- method = u->method;
-
- } else if (plcf->method) {
- if (ngx_http_complex_value(r, plcf->method, &method) != NGX_OK) {
- return NGX_ERROR;
- }
-
- } else {
- method = r->method_name;
- }
-
- ctx = ngx_http_get_module_ctx(r, ngx_http_proxy_module);
-
- if (method.len == 4
- && ngx_strncasecmp(method.data, (u_char *) "HEAD", 4) == 0)
- {
- ctx->head = 1;
- }
-
- len = method.len + 1 + sizeof(ngx_http_proxy_version) - 1
- + sizeof(CRLF) - 1;
-
- escape = 0;
- loc_len = 0;
- unparsed_uri = 0;
-
- if (plcf->proxy_lengths && ctx->vars.uri.len) {
- uri_len = ctx->vars.uri.len;
-
- } else if (ctx->vars.uri.len == 0 && r->valid_unparsed_uri) {
- unparsed_uri = 1;
- uri_len = r->unparsed_uri.len;
-
- } else {
- loc_len = (r->valid_location && ctx->vars.uri.len) ?
- plcf->location.len : 0;
-
- if (r->quoted_uri || r->space_in_uri || r->internal) {
- escape = 2 * ngx_escape_uri(NULL, r->uri.data + loc_len,
- r->uri.len - loc_len, NGX_ESCAPE_URI);
- }
-
- uri_len = ctx->vars.uri.len + r->uri.len - loc_len + escape
- + sizeof("?") - 1 + r->args.len;
- }
-
- if (uri_len == 0) {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "zero length URI to proxy");
- return NGX_ERROR;
- }
-
- len += uri_len;
-
- ngx_memzero(&le, sizeof(ngx_http_script_engine_t));
-
- ngx_http_script_flush_no_cacheable_variables(r, plcf->body_flushes);
- ngx_http_script_flush_no_cacheable_variables(r, headers->flushes);
-
- if (plcf->body_lengths) {
- le.ip = plcf->body_lengths->elts;
- le.request = r;
- le.flushed = 1;
- body_len = 0;
-
- while (*(uintptr_t *) le.ip) {
- lcode = *(ngx_http_script_len_code_pt *) le.ip;
- body_len += lcode(&le);
- }
-
- ctx->internal_body_length = body_len;
- len += body_len;
-
- } else if (r->headers_in.chunked && r->reading_body) {
- ctx->internal_body_length = -1;
- ctx->internal_chunked = 1;
-
- } else {
- ctx->internal_body_length = r->headers_in.content_length_n;
- }
-
- le.ip = headers->lengths->elts;
- le.request = r;
- le.flushed = 1;
-
- while (*(uintptr_t *) le.ip) {
-
- lcode = *(ngx_http_script_len_code_pt *) le.ip;
- key_len = lcode(&le);
-
- for (val_len = 0; *(uintptr_t *) le.ip; val_len += lcode(&le)) {
- lcode = *(ngx_http_script_len_code_pt *) le.ip;
- }
- le.ip += sizeof(uintptr_t);
-
- if (val_len == 0) {
- continue;
- }
-
- len += key_len + sizeof(": ") - 1 + val_len + sizeof(CRLF) - 1;
- }
-
-
- if (plcf->upstream.pass_request_headers) {
- part = &r->headers_in.headers.part;
- header = part->elts;
-
- for (i = 0; /* void */; i++) {
-
- if (i >= part->nelts) {
- if (part->next == NULL) {
- break;
- }
-
- part = part->next;
- header = part->elts;
- i = 0;
- }
-
- if (ngx_hash_find(&headers->hash, header[i].hash,
- header[i].lowcase_key, header[i].key.len))
- {
- continue;
- }
-
- len += header[i].key.len + sizeof(": ") - 1
- + header[i].value.len + sizeof(CRLF) - 1;
- }
- }
-
-
- b = ngx_create_temp_buf(r->pool, len);
- if (b == NULL) {
- return NGX_ERROR;
- }
-
- cl = ngx_alloc_chain_link(r->pool);
- if (cl == NULL) {
- return NGX_ERROR;
- }
-
- cl->buf = b;
-
-
- /* the request line */
-
- b->last = ngx_copy(b->last, method.data, method.len);
- *b->last++ = ' ';
-
- u->uri.data = b->last;
-
- if (plcf->proxy_lengths && ctx->vars.uri.len) {
- b->last = ngx_copy(b->last, ctx->vars.uri.data, ctx->vars.uri.len);
-
- } else if (unparsed_uri) {
- b->last = ngx_copy(b->last, r->unparsed_uri.data, r->unparsed_uri.len);
-
- } else {
- if (r->valid_location) {
- b->last = ngx_copy(b->last, ctx->vars.uri.data, ctx->vars.uri.len);
- }
-
- if (escape) {
- ngx_escape_uri(b->last, r->uri.data + loc_len,
- r->uri.len - loc_len, NGX_ESCAPE_URI);
- b->last += r->uri.len - loc_len + escape;
-
- } else {
- b->last = ngx_copy(b->last, r->uri.data + loc_len,
- r->uri.len - loc_len);
- }
-
- if (r->args.len > 0) {
- *b->last++ = '?';
- b->last = ngx_copy(b->last, r->args.data, r->args.len);
- }
- }
-
- u->uri.len = b->last - u->uri.data;
-
- if (plcf->http_version == NGX_HTTP_VERSION_11) {
- b->last = ngx_cpymem(b->last, ngx_http_proxy_version_11,
- sizeof(ngx_http_proxy_version_11) - 1);
-
- } else {
- b->last = ngx_cpymem(b->last, ngx_http_proxy_version,
- sizeof(ngx_http_proxy_version) - 1);
- }
-
- ngx_memzero(&e, sizeof(ngx_http_script_engine_t));
-
- e.ip = headers->values->elts;
- e.pos = b->last;
- e.request = r;
- e.flushed = 1;
-
- le.ip = headers->lengths->elts;
-
- while (*(uintptr_t *) le.ip) {
-
- lcode = *(ngx_http_script_len_code_pt *) le.ip;
- (void) lcode(&le);
-
- for (val_len = 0; *(uintptr_t *) le.ip; val_len += lcode(&le)) {
- lcode = *(ngx_http_script_len_code_pt *) le.ip;
- }
- le.ip += sizeof(uintptr_t);
-
- if (val_len == 0) {
- e.skip = 1;
-
- while (*(uintptr_t *) e.ip) {
- code = *(ngx_http_script_code_pt *) e.ip;
- code((ngx_http_script_engine_t *) &e);
- }
- e.ip += sizeof(uintptr_t);
-
- e.skip = 0;
-
- continue;
- }
-
- code = *(ngx_http_script_code_pt *) e.ip;
- code((ngx_http_script_engine_t *) &e);
-
- *e.pos++ = ':'; *e.pos++ = ' ';
-
- while (*(uintptr_t *) e.ip) {
- code = *(ngx_http_script_code_pt *) e.ip;
- code((ngx_http_script_engine_t *) &e);
- }
- e.ip += sizeof(uintptr_t);
-
- *e.pos++ = CR; *e.pos++ = LF;
- }
-
- b->last = e.pos;
-
-
- if (plcf->upstream.pass_request_headers) {
- part = &r->headers_in.headers.part;
- header = part->elts;
-
- for (i = 0; /* void */; i++) {
-
- if (i >= part->nelts) {
- if (part->next == NULL) {
- break;
- }
-
- part = part->next;
- header = part->elts;
- i = 0;
- }
-
- if (ngx_hash_find(&headers->hash, header[i].hash,
- header[i].lowcase_key, header[i].key.len))
- {
- continue;
- }
-
- b->last = ngx_copy(b->last, header[i].key.data, header[i].key.len);
-
- *b->last++ = ':'; *b->last++ = ' ';
-
- b->last = ngx_copy(b->last, header[i].value.data,
- header[i].value.len);
-
- *b->last++ = CR; *b->last++ = LF;
-
- ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "http proxy header: \"%V: %V\"",
- &header[i].key, &header[i].value);
- }
- }
-
-
- /* add "\r\n" at the header end */
- *b->last++ = CR; *b->last++ = LF;
-
- if (plcf->body_values) {
- e.ip = plcf->body_values->elts;
- e.pos = b->last;
- e.skip = 0;
-
- while (*(uintptr_t *) e.ip) {
- code = *(ngx_http_script_code_pt *) e.ip;
- code((ngx_http_script_engine_t *) &e);
- }
-
- b->last = e.pos;
- }
-
- ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "http proxy header:%N\"%*s\"",
- (size_t) (b->last - b->pos), b->pos);
-
- if (r->request_body_no_buffering) {
-
- u->request_bufs = cl;
-
- if (ctx->internal_chunked) {
- u->output.output_filter = ngx_http_proxy_body_output_filter;
- u->output.filter_ctx = r;
- }
-
- } else if (plcf->body_values == NULL && plcf->upstream.pass_request_body) {
-
- body = u->request_bufs;
- u->request_bufs = cl;
-
- while (body) {
- b = ngx_alloc_buf(r->pool);
- if (b == NULL) {
- return NGX_ERROR;
- }
-
- ngx_memcpy(b, body->buf, sizeof(ngx_buf_t));
-
- cl->next = ngx_alloc_chain_link(r->pool);
- if (cl->next == NULL) {
- return NGX_ERROR;
- }
-
- cl = cl->next;
- cl->buf = b;
-
- body = body->next;
- }
-
- } else {
- u->request_bufs = cl;
- }
-
- b->flush = 1;
- cl->next = NULL;
-
- return NGX_OK;
-}
-
-
-static ngx_int_t
-ngx_http_proxy_reinit_request(ngx_http_request_t *r)
-{
- ngx_http_proxy_ctx_t *ctx;
-
- ctx = ngx_http_get_module_ctx(r, ngx_http_proxy_module);
-
- if (ctx == NULL) {
- return NGX_OK;
- }
-
- ctx->status.code = 0;
- ctx->status.count = 0;
- ctx->status.start = NULL;
- ctx->status.end = NULL;
- ctx->chunked.state = 0;
-
- r->upstream->process_header = ngx_http_proxy_process_status_line;
- r->upstream->pipe->input_filter = ngx_http_proxy_copy_filter;
- r->upstream->input_filter = ngx_http_proxy_non_buffered_copy_filter;
- r->state = 0;
-
- return NGX_OK;
-}
-
-
-static ngx_int_t
-ngx_http_proxy_body_output_filter(void *data, ngx_chain_t *in)
-{
- ngx_http_request_t *r = data;
-
- off_t size;
- u_char *chunk;
- ngx_int_t rc;
- ngx_buf_t *b;
- ngx_chain_t *out, *cl, *tl, **ll, **fl;
- ngx_http_proxy_ctx_t *ctx;
-
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "proxy output filter");
-
- ctx = ngx_http_get_module_ctx(r, ngx_http_proxy_module);
-
- if (in == NULL) {
- out = in;
- goto out;
- }
-
- out = NULL;
- ll = &out;
-
- if (!ctx->header_sent) {
- /* first buffer contains headers, pass it unmodified */
-
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "proxy output header");
-
- ctx->header_sent = 1;
-
- tl = ngx_alloc_chain_link(r->pool);
- if (tl == NULL) {
- return NGX_ERROR;
- }
-
- tl->buf = in->buf;
- *ll = tl;
- ll = &tl->next;
-
- in = in->next;
-
- if (in == NULL) {
- tl->next = NULL;
- goto out;
- }
- }
-
- size = 0;
- cl = in;
- fl = ll;
-
- for ( ;; ) {
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "proxy output chunk: %O", ngx_buf_size(cl->buf));
-
- size += ngx_buf_size(cl->buf);
-
- if (cl->buf->flush
- || cl->buf->sync
- || ngx_buf_in_memory(cl->buf)
- || cl->buf->in_file)
- {
- tl = ngx_alloc_chain_link(r->pool);
- if (tl == NULL) {
- return NGX_ERROR;
- }
-
- tl->buf = cl->buf;
- *ll = tl;
- ll = &tl->next;
- }
-
- if (cl->next == NULL) {
- break;
- }
-
- cl = cl->next;
- }
-
- if (size) {
- tl = ngx_chain_get_free_buf(r->pool, &ctx->free);
- if (tl == NULL) {
- return NGX_ERROR;
- }
-
- b = tl->buf;
- chunk = b->start;
-
- if (chunk == NULL) {
- /* the "0000000000000000" is 64-bit hexadecimal string */
-
- chunk = ngx_palloc(r->pool, sizeof("0000000000000000" CRLF) - 1);
- if (chunk == NULL) {
- return NGX_ERROR;
- }
-
- b->start = chunk;
- b->end = chunk + sizeof("0000000000000000" CRLF) - 1;
- }
-
- b->tag = (ngx_buf_tag_t) &ngx_http_proxy_body_output_filter;
- b->memory = 0;
- b->temporary = 1;
- b->pos = chunk;
- b->last = ngx_sprintf(chunk, "%xO" CRLF, size);
-
- tl->next = *fl;
- *fl = tl;
- }
-
- if (cl->buf->last_buf) {
- tl = ngx_chain_get_free_buf(r->pool, &ctx->free);
- if (tl == NULL) {
- return NGX_ERROR;
- }
-
- b = tl->buf;
-
- b->tag = (ngx_buf_tag_t) &ngx_http_proxy_body_output_filter;
- b->temporary = 0;
- b->memory = 1;
- b->last_buf = 1;
- b->pos = (u_char *) CRLF "0" CRLF CRLF;
- b->last = b->pos + 7;
-
- cl->buf->last_buf = 0;
-
- *ll = tl;
-
- if (size == 0) {
- b->pos += 2;
- }
-
- } else if (size > 0) {
- tl = ngx_chain_get_free_buf(r->pool, &ctx->free);
- if (tl == NULL) {
- return NGX_ERROR;
- }
-
- b = tl->buf;
-
- b->tag = (ngx_buf_tag_t) &ngx_http_proxy_body_output_filter;
- b->temporary = 0;
- b->memory = 1;
- b->pos = (u_char *) CRLF;
- b->last = b->pos + 2;
-
- *ll = tl;
-
- } else {
- *ll = NULL;
- }
-
-out:
-
- rc = ngx_chain_writer(&r->upstream->writer, out);
-
- ngx_chain_update_chains(r->pool, &ctx->free, &ctx->busy, &out,
- (ngx_buf_tag_t) &ngx_http_proxy_body_output_filter);
-
- return rc;
-}
-
-
-static ngx_int_t
-ngx_http_proxy_process_status_line(ngx_http_request_t *r)
-{
- size_t len;
- ngx_int_t rc;
- ngx_http_upstream_t *u;
- ngx_http_proxy_ctx_t *ctx;
-
- ctx = ngx_http_get_module_ctx(r, ngx_http_proxy_module);
-
- if (ctx == NULL) {
- return NGX_ERROR;
- }
-
- u = r->upstream;
-
- rc = ngx_http_parse_status_line(r, &u->buffer, &ctx->status);
-
- if (rc == NGX_AGAIN) {
- return rc;
- }
-
- if (rc == NGX_ERROR) {
-
-#if (NGX_HTTP_CACHE)
-
- if (r->cache) {
- r->http_version = NGX_HTTP_VERSION_9;
- return NGX_OK;
- }
-
-#endif
-
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "upstream sent no valid HTTP/1.0 header");
-
-#if 0
- if (u->accel) {
- return NGX_HTTP_UPSTREAM_INVALID_HEADER;
- }
-#endif
-
- r->http_version = NGX_HTTP_VERSION_9;
- u->state->status = NGX_HTTP_OK;
- u->headers_in.connection_close = 1;
-
- return NGX_OK;
- }
-
- if (u->state && u->state->status == 0) {
- u->state->status = ctx->status.code;
- }
-
- u->headers_in.status_n = ctx->status.code;
-
- len = ctx->status.end - ctx->status.start;
- u->headers_in.status_line.len = len;
-
- u->headers_in.status_line.data = ngx_pnalloc(r->pool, len);
- if (u->headers_in.status_line.data == NULL) {
- return NGX_ERROR;
- }
-
- ngx_memcpy(u->headers_in.status_line.data, ctx->status.start, len);
-
- ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "http proxy status %ui \"%V\"",
- u->headers_in.status_n, &u->headers_in.status_line);
-
- if (ctx->status.http_version < NGX_HTTP_VERSION_11) {
- u->headers_in.connection_close = 1;
- }
-
- u->process_header = ngx_http_proxy_process_header;
-
- return ngx_http_proxy_process_header(r);
-}
-
-
-static ngx_int_t
-ngx_http_proxy_process_header(ngx_http_request_t *r)
-{
- ngx_int_t rc;
- ngx_table_elt_t *h;
- ngx_http_upstream_t *u;
- ngx_http_proxy_ctx_t *ctx;
- ngx_http_upstream_header_t *hh;
- ngx_http_upstream_main_conf_t *umcf;
-
- umcf = ngx_http_get_module_main_conf(r, ngx_http_upstream_module);
-
- for ( ;; ) {
-
- rc = ngx_http_parse_header_line(r, &r->upstream->buffer, 1);
-
- if (rc == NGX_OK) {
-
- /* a header line has been parsed successfully */
-
- h = ngx_list_push(&r->upstream->headers_in.headers);
- if (h == NULL) {
- return NGX_ERROR;
- }
-
- h->hash = r->header_hash;
-
- h->key.len = r->header_name_end - r->header_name_start;
- h->value.len = r->header_end - r->header_start;
-
- h->key.data = ngx_pnalloc(r->pool,
- h->key.len + 1 + h->value.len + 1 + h->key.len);
- if (h->key.data == NULL) {
- h->hash = 0;
- return NGX_ERROR;
- }
-
- h->value.data = h->key.data + h->key.len + 1;
- h->lowcase_key = h->key.data + h->key.len + 1 + h->value.len + 1;
-
- ngx_memcpy(h->key.data, r->header_name_start, h->key.len);
- h->key.data[h->key.len] = '\0';
- ngx_memcpy(h->value.data, r->header_start, h->value.len);
- h->value.data[h->value.len] = '\0';
-
- if (h->key.len == r->lowcase_index) {
- ngx_memcpy(h->lowcase_key, r->lowcase_header, h->key.len);
-
- } else {
- ngx_strlow(h->lowcase_key, h->key.data, h->key.len);
- }
-
- hh = ngx_hash_find(&umcf->headers_in_hash, h->hash,
- h->lowcase_key, h->key.len);
-
- if (hh && hh->handler(r, h, hh->offset) != NGX_OK) {
- return NGX_ERROR;
- }
-
- ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "http proxy header: \"%V: %V\"",
- &h->key, &h->value);
-
- continue;
- }
-
- if (rc == NGX_HTTP_PARSE_HEADER_DONE) {
-
- /* a whole header has been parsed successfully */
-
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "http proxy header done");
-
- /*
- * if no "Server" and "Date" in header line,
- * then add the special empty headers
- */
-
- if (r->upstream->headers_in.server == NULL) {
- h = ngx_list_push(&r->upstream->headers_in.headers);
- if (h == NULL) {
- return NGX_ERROR;
- }
-
- h->hash = ngx_hash(ngx_hash(ngx_hash(ngx_hash(
- ngx_hash('s', 'e'), 'r'), 'v'), 'e'), 'r');
-
- ngx_str_set(&h->key, "Server");
- ngx_str_null(&h->value);
- h->lowcase_key = (u_char *) "server";
- }
-
- if (r->upstream->headers_in.date == NULL) {
- h = ngx_list_push(&r->upstream->headers_in.headers);
- if (h == NULL) {
- return NGX_ERROR;
- }
-
- h->hash = ngx_hash(ngx_hash(ngx_hash('d', 'a'), 't'), 'e');
-
- ngx_str_set(&h->key, "Date");
- ngx_str_null(&h->value);
- h->lowcase_key = (u_char *) "date";
- }
-
- /* clear content length if response is chunked */
-
- u = r->upstream;
-
- if (u->headers_in.chunked) {
- u->headers_in.content_length_n = -1;
- }
-
- /*
- * set u->keepalive if response has no body; this allows to keep
- * connections alive in case of r->header_only or X-Accel-Redirect
- */
-
- ctx = ngx_http_get_module_ctx(r, ngx_http_proxy_module);
-
- if (u->headers_in.status_n == NGX_HTTP_NO_CONTENT
- || u->headers_in.status_n == NGX_HTTP_NOT_MODIFIED
- || ctx->head
- || (!u->headers_in.chunked
- && u->headers_in.content_length_n == 0))
- {
- u->keepalive = !u->headers_in.connection_close;
- }
-
- if (u->headers_in.status_n == NGX_HTTP_SWITCHING_PROTOCOLS) {
- u->keepalive = 0;
-
- if (r->headers_in.upgrade) {
- u->upgrade = 1;
- }
- }
-
- return NGX_OK;
- }
-
- if (rc == NGX_AGAIN) {
- return NGX_AGAIN;
- }
-
- /* there was error while a header line parsing */
-
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "upstream sent invalid header");
-
- return NGX_HTTP_UPSTREAM_INVALID_HEADER;
- }
-}
-
-
-static ngx_int_t
-ngx_http_proxy_input_filter_init(void *data)
-{
- ngx_http_request_t *r = data;
- ngx_http_upstream_t *u;
- ngx_http_proxy_ctx_t *ctx;
-
- u = r->upstream;
- ctx = ngx_http_get_module_ctx(r, ngx_http_proxy_module);
-
- if (ctx == NULL) {
- return NGX_ERROR;
- }
-
- ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "http proxy filter init s:%ui h:%d c:%d l:%O",
- u->headers_in.status_n, ctx->head, u->headers_in.chunked,
- u->headers_in.content_length_n);
-
- /* as per RFC2616, 4.4 Message Length */
-
- if (u->headers_in.status_n == NGX_HTTP_NO_CONTENT
- || u->headers_in.status_n == NGX_HTTP_NOT_MODIFIED
- || ctx->head)
- {
- /* 1xx, 204, and 304 and replies to HEAD requests */
- /* no 1xx since we don't send Expect and Upgrade */
-
- u->pipe->length = 0;
- u->length = 0;
- u->keepalive = !u->headers_in.connection_close;
-
- } else if (u->headers_in.chunked) {
- /* chunked */
-
- u->pipe->input_filter = ngx_http_proxy_chunked_filter;
- u->pipe->length = 3; /* "0" LF LF */
-
- u->input_filter = ngx_http_proxy_non_buffered_chunked_filter;
- u->length = 1;
-
- } else if (u->headers_in.content_length_n == 0) {
- /* empty body: special case as filter won't be called */
-
- u->pipe->length = 0;
- u->length = 0;
- u->keepalive = !u->headers_in.connection_close;
-
- } else {
- /* content length or connection close */
-
- u->pipe->length = u->headers_in.content_length_n;
- u->length = u->headers_in.content_length_n;
- }
-
- return NGX_OK;
-}
-
-
-static ngx_int_t
-ngx_http_proxy_copy_filter(ngx_event_pipe_t *p, ngx_buf_t *buf)
-{
- ngx_buf_t *b;
- ngx_chain_t *cl;
- ngx_http_request_t *r;
-
- if (buf->pos == buf->last) {
- return NGX_OK;
- }
-
- cl = ngx_chain_get_free_buf(p->pool, &p->free);
- if (cl == NULL) {
- return NGX_ERROR;
- }
-
- b = cl->buf;
-
- ngx_memcpy(b, buf, sizeof(ngx_buf_t));
- b->shadow = buf;
- b->tag = p->tag;
- b->last_shadow = 1;
- b->recycled = 1;
- buf->shadow = b;
-
- ngx_log_debug1(NGX_LOG_DEBUG_EVENT, p->log, 0, "input buf #%d", b->num);
-
- if (p->in) {
- *p->last_in = cl;
- } else {
- p->in = cl;
- }
- p->last_in = &cl->next;
-
- if (p->length == -1) {
- return NGX_OK;
- }
-
- p->length -= b->last - b->pos;
-
- if (p->length == 0) {
- r = p->input_ctx;
- p->upstream_done = 1;
- r->upstream->keepalive = !r->upstream->headers_in.connection_close;
-
- } else if (p->length < 0) {
- r = p->input_ctx;
- p->upstream_done = 1;
-
- ngx_log_error(NGX_LOG_WARN, r->connection->log, 0,
- "upstream sent more data than specified in "
- "\"Content-Length\" header");
- }
-
- return NGX_OK;
-}
-
-
-static ngx_int_t
-ngx_http_proxy_chunked_filter(ngx_event_pipe_t *p, ngx_buf_t *buf)
-{
- ngx_int_t rc;
- ngx_buf_t *b, **prev;
- ngx_chain_t *cl;
- ngx_http_request_t *r;
- ngx_http_proxy_ctx_t *ctx;
-
- if (buf->pos == buf->last) {
- return NGX_OK;
- }
-
- r = p->input_ctx;
- ctx = ngx_http_get_module_ctx(r, ngx_http_proxy_module);
-
- if (ctx == NULL) {
- return NGX_ERROR;
- }
-
- b = NULL;
- prev = &buf->shadow;
-
- for ( ;; ) {
-
- rc = ngx_http_parse_chunked(r, buf, &ctx->chunked);
-
- if (rc == NGX_OK) {
-
- /* a chunk has been parsed successfully */
-
- cl = ngx_chain_get_free_buf(p->pool, &p->free);
- if (cl == NULL) {
- return NGX_ERROR;
- }
-
- b = cl->buf;
-
- ngx_memzero(b, sizeof(ngx_buf_t));
-
- b->pos = buf->pos;
- b->start = buf->start;
- b->end = buf->end;
- b->tag = p->tag;
- b->temporary = 1;
- b->recycled = 1;
-
- *prev = b;
- prev = &b->shadow;
-
- if (p->in) {
- *p->last_in = cl;
- } else {
- p->in = cl;
- }
- p->last_in = &cl->next;
-
- /* STUB */ b->num = buf->num;
-
- ngx_log_debug2(NGX_LOG_DEBUG_EVENT, p->log, 0,
- "input buf #%d %p", b->num, b->pos);
-
- if (buf->last - buf->pos >= ctx->chunked.size) {
-
- buf->pos += (size_t) ctx->chunked.size;
- b->last = buf->pos;
- ctx->chunked.size = 0;
-
- continue;
- }
-
- ctx->chunked.size -= buf->last - buf->pos;
- buf->pos = buf->last;
- b->last = buf->last;
-
- continue;
- }
-
- if (rc == NGX_DONE) {
-
- /* a whole response has been parsed successfully */
-
- p->upstream_done = 1;
- r->upstream->keepalive = !r->upstream->headers_in.connection_close;
-
- break;
- }
-
- if (rc == NGX_AGAIN) {
-
- /* set p->length, minimal amount of data we want to see */
-
- p->length = ctx->chunked.length;
-
- break;
- }
-
- /* invalid response */
-
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "upstream sent invalid chunked response");
-
- return NGX_ERROR;
- }
-
- ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "http proxy chunked state %ui, length %O",
- ctx->chunked.state, p->length);
-
- if (b) {
- b->shadow = buf;
- b->last_shadow = 1;
-
- ngx_log_debug2(NGX_LOG_DEBUG_EVENT, p->log, 0,
- "input buf %p %z", b->pos, b->last - b->pos);
-
- return NGX_OK;
- }
-
- /* there is no data record in the buf, add it to free chain */
-
- if (ngx_event_pipe_add_free_buf(p, buf) != NGX_OK) {
- return NGX_ERROR;
- }
-
- return NGX_OK;
-}
-
-
-static ngx_int_t
-ngx_http_proxy_non_buffered_copy_filter(void *data, ssize_t bytes)
-{
- ngx_http_request_t *r = data;
-
- ngx_buf_t *b;
- ngx_chain_t *cl, **ll;
- ngx_http_upstream_t *u;
-
- u = r->upstream;
-
- for (cl = u->out_bufs, ll = &u->out_bufs; cl; cl = cl->next) {
- ll = &cl->next;
- }
-
- cl = ngx_chain_get_free_buf(r->pool, &u->free_bufs);
- if (cl == NULL) {
- return NGX_ERROR;
- }
-
- *ll = cl;
-
- cl->buf->flush = 1;
- cl->buf->memory = 1;
-
- b = &u->buffer;
-
- cl->buf->pos = b->last;
- b->last += bytes;
- cl->buf->last = b->last;
- cl->buf->tag = u->output.tag;
-
- if (u->length == -1) {
- return NGX_OK;
- }
-
- u->length -= bytes;
-
- if (u->length == 0) {
- u->keepalive = !u->headers_in.connection_close;
- }
-
- return NGX_OK;
-}
-
-
-static ngx_int_t
-ngx_http_proxy_non_buffered_chunked_filter(void *data, ssize_t bytes)
-{
- ngx_http_request_t *r = data;
-
- ngx_int_t rc;
- ngx_buf_t *b, *buf;
- ngx_chain_t *cl, **ll;
- ngx_http_upstream_t *u;
- ngx_http_proxy_ctx_t *ctx;
-
- ctx = ngx_http_get_module_ctx(r, ngx_http_proxy_module);
-
- if (ctx == NULL) {
- return NGX_ERROR;
- }
-
- u = r->upstream;
- buf = &u->buffer;
-
- buf->pos = buf->last;
- buf->last += bytes;
-
- for (cl = u->out_bufs, ll = &u->out_bufs; cl; cl = cl->next) {
- ll = &cl->next;
- }
-
- for ( ;; ) {
-
- rc = ngx_http_parse_chunked(r, buf, &ctx->chunked);
-
- if (rc == NGX_OK) {
-
- /* a chunk has been parsed successfully */
-
- cl = ngx_chain_get_free_buf(r->pool, &u->free_bufs);
- if (cl == NULL) {
- return NGX_ERROR;
- }
-
- *ll = cl;
- ll = &cl->next;
-
- b = cl->buf;
-
- b->flush = 1;
- b->memory = 1;
-
- b->pos = buf->pos;
- b->tag = u->output.tag;
-
- if (buf->last - buf->pos >= ctx->chunked.size) {
- buf->pos += (size_t) ctx->chunked.size;
- b->last = buf->pos;
- ctx->chunked.size = 0;
-
- } else {
- ctx->chunked.size -= buf->last - buf->pos;
- buf->pos = buf->last;
- b->last = buf->last;
- }
-
- ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "http proxy out buf %p %z",
- b->pos, b->last - b->pos);
-
- continue;
- }
-
- if (rc == NGX_DONE) {
-
- /* a whole response has been parsed successfully */
-
- u->keepalive = !u->headers_in.connection_close;
- u->length = 0;
-
- break;
- }
-
- if (rc == NGX_AGAIN) {
- break;
- }
-
- /* invalid response */
-
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "upstream sent invalid chunked response");
-
- return NGX_ERROR;
- }
-
- return NGX_OK;
-}
-
-
-static void
-ngx_http_proxy_abort_request(ngx_http_request_t *r)
-{
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "abort http proxy request");
-
- return;
-}
-
-
-static void
-ngx_http_proxy_finalize_request(ngx_http_request_t *r, ngx_int_t rc)
-{
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "finalize http proxy request");
-
- return;
-}
-
-
-static ngx_int_t
-ngx_http_proxy_host_variable(ngx_http_request_t *r,
- ngx_http_variable_value_t *v, uintptr_t data)
-{
- ngx_http_proxy_ctx_t *ctx;
-
- ctx = ngx_http_get_module_ctx(r, ngx_http_proxy_module);
-
- if (ctx == NULL) {
- v->not_found = 1;
- return NGX_OK;
- }
-
- v->len = ctx->vars.host_header.len;
- v->valid = 1;
- v->no_cacheable = 0;
- v->not_found = 0;
- v->data = ctx->vars.host_header.data;
-
- return NGX_OK;
-}
-
-
-static ngx_int_t
-ngx_http_proxy_port_variable(ngx_http_request_t *r,
- ngx_http_variable_value_t *v, uintptr_t data)
-{
- ngx_http_proxy_ctx_t *ctx;
-
- ctx = ngx_http_get_module_ctx(r, ngx_http_proxy_module);
-
- if (ctx == NULL) {
- v->not_found = 1;
- return NGX_OK;
- }
-
- v->len = ctx->vars.port.len;
- v->valid = 1;
- v->no_cacheable = 0;
- v->not_found = 0;
- v->data = ctx->vars.port.data;
-
- return NGX_OK;
-}
-
-
-static ngx_int_t
-ngx_http_proxy_add_x_forwarded_for_variable(ngx_http_request_t *r,
- ngx_http_variable_value_t *v, uintptr_t data)
-{
- size_t len;
- u_char *p;
- ngx_uint_t i, n;
- ngx_table_elt_t **h;
-
- v->valid = 1;
- v->no_cacheable = 0;
- v->not_found = 0;
-
- n = r->headers_in.x_forwarded_for.nelts;
- h = r->headers_in.x_forwarded_for.elts;
-
- len = 0;
-
- for (i = 0; i < n; i++) {
- len += h[i]->value.len + sizeof(", ") - 1;
- }
-
- if (len == 0) {
- v->len = r->connection->addr_text.len;
- v->data = r->connection->addr_text.data;
- return NGX_OK;
- }
-
- len += r->connection->addr_text.len;
-
- p = ngx_pnalloc(r->pool, len);
- if (p == NULL) {
- return NGX_ERROR;
- }
-
- v->len = len;
- v->data = p;
-
- for (i = 0; i < n; i++) {
- p = ngx_copy(p, h[i]->value.data, h[i]->value.len);
- *p++ = ','; *p++ = ' ';
- }
-
- ngx_memcpy(p, r->connection->addr_text.data, r->connection->addr_text.len);
-
- return NGX_OK;
-}
-
-
-static ngx_int_t
-ngx_http_proxy_internal_body_length_variable(ngx_http_request_t *r,
- ngx_http_variable_value_t *v, uintptr_t data)
-{
- ngx_http_proxy_ctx_t *ctx;
-
- ctx = ngx_http_get_module_ctx(r, ngx_http_proxy_module);
-
- if (ctx == NULL || ctx->internal_body_length < 0) {
- v->not_found = 1;
- return NGX_OK;
- }
-
- v->valid = 1;
- v->no_cacheable = 0;
- v->not_found = 0;
-
- v->data = ngx_pnalloc(r->pool, NGX_OFF_T_LEN);
-
- if (v->data == NULL) {
- return NGX_ERROR;
- }
-
- v->len = ngx_sprintf(v->data, "%O", ctx->internal_body_length) - v->data;
-
- return NGX_OK;
-}
-
-
-static ngx_int_t
-ngx_http_proxy_internal_chunked_variable(ngx_http_request_t *r,
- ngx_http_variable_value_t *v, uintptr_t data)
-{
- ngx_http_proxy_ctx_t *ctx;
-
- ctx = ngx_http_get_module_ctx(r, ngx_http_proxy_module);
-
- if (ctx == NULL || !ctx->internal_chunked) {
- v->not_found = 1;
- return NGX_OK;
- }
-
- v->valid = 1;
- v->no_cacheable = 0;
- v->not_found = 0;
-
- v->data = (u_char *) "chunked";
- v->len = sizeof("chunked") - 1;
-
- return NGX_OK;
-}
-
-
-static ngx_int_t
-ngx_http_proxy_rewrite_redirect(ngx_http_request_t *r, ngx_table_elt_t *h,
- size_t prefix)
-{
- size_t len;
- ngx_int_t rc;
- ngx_uint_t i;
- ngx_http_proxy_rewrite_t *pr;
- ngx_http_proxy_loc_conf_t *plcf;
-
- plcf = ngx_http_get_module_loc_conf(r, ngx_http_proxy_module);
-
- pr = plcf->redirects->elts;
-
- if (pr == NULL) {
- return NGX_DECLINED;
- }
-
- len = h->value.len - prefix;
-
- for (i = 0; i < plcf->redirects->nelts; i++) {
- rc = pr[i].handler(r, h, prefix, len, &pr[i]);
-
- if (rc != NGX_DECLINED) {
- return rc;
- }
- }
-
- return NGX_DECLINED;
-}
-
-
-static ngx_int_t
-ngx_http_proxy_rewrite_cookie(ngx_http_request_t *r, ngx_table_elt_t *h)
-{
- size_t prefix;
- u_char *p;
- ngx_int_t rc, rv;
- ngx_http_proxy_loc_conf_t *plcf;
-
- p = (u_char *) ngx_strchr(h->value.data, ';');
- if (p == NULL) {
- return NGX_DECLINED;
- }
-
- prefix = p + 1 - h->value.data;
-
- rv = NGX_DECLINED;
-
- plcf = ngx_http_get_module_loc_conf(r, ngx_http_proxy_module);
-
- if (plcf->cookie_domains) {
- p = ngx_strcasestrn(h->value.data + prefix, "domain=", 7 - 1);
-
- if (p) {
- rc = ngx_http_proxy_rewrite_cookie_value(r, h, p + 7,
- plcf->cookie_domains);
- if (rc == NGX_ERROR) {
- return NGX_ERROR;
- }
-
- if (rc != NGX_DECLINED) {
- rv = rc;
- }
- }
- }
-
- if (plcf->cookie_paths) {
- p = ngx_strcasestrn(h->value.data + prefix, "path=", 5 - 1);
-
- if (p) {
- rc = ngx_http_proxy_rewrite_cookie_value(r, h, p + 5,
- plcf->cookie_paths);
- if (rc == NGX_ERROR) {
- return NGX_ERROR;
- }
-
- if (rc != NGX_DECLINED) {
- rv = rc;
- }
- }
- }
-
- return rv;
-}
-
-
-static ngx_int_t
-ngx_http_proxy_rewrite_cookie_value(ngx_http_request_t *r, ngx_table_elt_t *h,
- u_char *value, ngx_array_t *rewrites)
-{
- size_t len, prefix;
- u_char *p;
- ngx_int_t rc;
- ngx_uint_t i;
- ngx_http_proxy_rewrite_t *pr;
-
- prefix = value - h->value.data;
-
- p = (u_char *) ngx_strchr(value, ';');
-
- len = p ? (size_t) (p - value) : (h->value.len - prefix);
-
- pr = rewrites->elts;
-
- for (i = 0; i < rewrites->nelts; i++) {
- rc = pr[i].handler(r, h, prefix, len, &pr[i]);
-
- if (rc != NGX_DECLINED) {
- return rc;
- }
- }
-
- return NGX_DECLINED;
-}
-
-
-static ngx_int_t
-ngx_http_proxy_rewrite_complex_handler(ngx_http_request_t *r,
- ngx_table_elt_t *h, size_t prefix, size_t len, ngx_http_proxy_rewrite_t *pr)
-{
- ngx_str_t pattern, replacement;
-
- if (ngx_http_complex_value(r, &pr->pattern.complex, &pattern) != NGX_OK) {
- return NGX_ERROR;
- }
-
- if (pattern.len > len
- || ngx_rstrncmp(h->value.data + prefix, pattern.data,
- pattern.len) != 0)
- {
- return NGX_DECLINED;
- }
-
- if (ngx_http_complex_value(r, &pr->replacement, &replacement) != NGX_OK) {
- return NGX_ERROR;
- }
-
- return ngx_http_proxy_rewrite(r, h, prefix, pattern.len, &replacement);
-}
-
-
-#if (NGX_PCRE)
-
-static ngx_int_t
-ngx_http_proxy_rewrite_regex_handler(ngx_http_request_t *r, ngx_table_elt_t *h,
- size_t prefix, size_t len, ngx_http_proxy_rewrite_t *pr)
-{
- ngx_str_t pattern, replacement;
-
- pattern.len = len;
- pattern.data = h->value.data + prefix;
-
- if (ngx_http_regex_exec(r, pr->pattern.regex, &pattern) != NGX_OK) {
- return NGX_DECLINED;
- }
-
- if (ngx_http_complex_value(r, &pr->replacement, &replacement) != NGX_OK) {
- return NGX_ERROR;
- }
-
- if (prefix == 0 && h->value.len == len) {
- h->value = replacement;
- return NGX_OK;
- }
-
- return ngx_http_proxy_rewrite(r, h, prefix, len, &replacement);
-}
-
-#endif
-
-
-static ngx_int_t
-ngx_http_proxy_rewrite_domain_handler(ngx_http_request_t *r,
- ngx_table_elt_t *h, size_t prefix, size_t len, ngx_http_proxy_rewrite_t *pr)
-{
- u_char *p;
- ngx_str_t pattern, replacement;
-
- if (ngx_http_complex_value(r, &pr->pattern.complex, &pattern) != NGX_OK) {
- return NGX_ERROR;
- }
-
- p = h->value.data + prefix;
-
- if (p[0] == '.') {
- p++;
- prefix++;
- len--;
- }
-
- if (pattern.len != len || ngx_rstrncasecmp(pattern.data, p, len) != 0) {
- return NGX_DECLINED;
- }
-
- if (ngx_http_complex_value(r, &pr->replacement, &replacement) != NGX_OK) {
- return NGX_ERROR;
- }
-
- return ngx_http_proxy_rewrite(r, h, prefix, len, &replacement);
-}
-
-
-static ngx_int_t
-ngx_http_proxy_rewrite(ngx_http_request_t *r, ngx_table_elt_t *h, size_t prefix,
- size_t len, ngx_str_t *replacement)
-{
- u_char *p, *data;
- size_t new_len;
-
- new_len = replacement->len + h->value.len - len;
-
- if (replacement->len > len) {
-
- data = ngx_pnalloc(r->pool, new_len + 1);
- if (data == NULL) {
- return NGX_ERROR;
- }
-
- p = ngx_copy(data, h->value.data, prefix);
- p = ngx_copy(p, replacement->data, replacement->len);
-
- ngx_memcpy(p, h->value.data + prefix + len,
- h->value.len - len - prefix + 1);
-
- h->value.data = data;
-
- } else {
- p = ngx_copy(h->value.data + prefix, replacement->data,
- replacement->len);
-
- ngx_memmove(p, h->value.data + prefix + len,
- h->value.len - len - prefix + 1);
- }
-
- h->value.len = new_len;
-
- return NGX_OK;
-}
-
-
-static ngx_int_t
-ngx_http_proxy_add_variables(ngx_conf_t *cf)
-{
- ngx_http_variable_t *var, *v;
-
- for (v = ngx_http_proxy_vars; v->name.len; v++) {
- var = ngx_http_add_variable(cf, &v->name, v->flags);
- if (var == NULL) {
- return NGX_ERROR;
- }
-
- var->get_handler = v->get_handler;
- var->data = v->data;
- }
-
- return NGX_OK;
-}
-
-
-static void *
-ngx_http_proxy_create_main_conf(ngx_conf_t *cf)
-{
- ngx_http_proxy_main_conf_t *conf;
-
- conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_proxy_main_conf_t));
- if (conf == NULL) {
- return NULL;
- }
-
-#if (NGX_HTTP_CACHE)
- if (ngx_array_init(&conf->caches, cf->pool, 4,
- sizeof(ngx_http_file_cache_t *))
- != NGX_OK)
- {
- return NULL;
- }
-#endif
-
- return conf;
-}
-
-
-static void *
-ngx_http_proxy_create_loc_conf(ngx_conf_t *cf)
-{
- ngx_http_proxy_loc_conf_t *conf;
-
- conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_proxy_loc_conf_t));
- if (conf == NULL) {
- return NULL;
- }
-
- /*
- * set by ngx_pcalloc():
- *
- * conf->upstream.bufs.num = 0;
- * conf->upstream.ignore_headers = 0;
- * conf->upstream.next_upstream = 0;
- * conf->upstream.cache_zone = NULL;
- * conf->upstream.cache_use_stale = 0;
- * conf->upstream.cache_methods = 0;
- * conf->upstream.temp_path = NULL;
- * conf->upstream.hide_headers_hash = { NULL, 0 };
- * conf->upstream.store_lengths = NULL;
- * conf->upstream.store_values = NULL;
- * conf->upstream.ssl_name = NULL;
- *
- * conf->method = NULL;
- * conf->location = NULL;
- * conf->url = { 0, NULL };
- * conf->headers_source = NULL;
- * conf->headers.lengths = NULL;
- * conf->headers.values = NULL;
- * conf->headers.hash = { NULL, 0 };
- * conf->headers_cache.lengths = NULL;
- * conf->headers_cache.values = NULL;
- * conf->headers_cache.hash = { NULL, 0 };
- * conf->body_lengths = NULL;
- * conf->body_values = NULL;
- * conf->body_source = { 0, NULL };
- * conf->redirects = NULL;
- * conf->ssl = 0;
- * conf->ssl_protocols = 0;
- * conf->ssl_ciphers = { 0, NULL };
- * conf->ssl_trusted_certificate = { 0, NULL };
- * conf->ssl_crl = { 0, NULL };
- * conf->ssl_certificate = { 0, NULL };
- * conf->ssl_certificate_key = { 0, NULL };
- */
-
- conf->upstream.store = NGX_CONF_UNSET;
- conf->upstream.store_access = NGX_CONF_UNSET_UINT;
- conf->upstream.next_upstream_tries = NGX_CONF_UNSET_UINT;
- conf->upstream.buffering = NGX_CONF_UNSET;
- conf->upstream.request_buffering = NGX_CONF_UNSET;
- conf->upstream.ignore_client_abort = NGX_CONF_UNSET;
- conf->upstream.force_ranges = NGX_CONF_UNSET;
-
- conf->upstream.local = NGX_CONF_UNSET_PTR;
-
- conf->upstream.connect_timeout = NGX_CONF_UNSET_MSEC;
- conf->upstream.send_timeout = NGX_CONF_UNSET_MSEC;
- conf->upstream.read_timeout = NGX_CONF_UNSET_MSEC;
- conf->upstream.next_upstream_timeout = NGX_CONF_UNSET_MSEC;
-
- conf->upstream.send_lowat = NGX_CONF_UNSET_SIZE;
- conf->upstream.buffer_size = NGX_CONF_UNSET_SIZE;
- conf->upstream.limit_rate = NGX_CONF_UNSET_SIZE;
-
- conf->upstream.busy_buffers_size_conf = NGX_CONF_UNSET_SIZE;
- conf->upstream.max_temp_file_size_conf = NGX_CONF_UNSET_SIZE;
- conf->upstream.temp_file_write_size_conf = NGX_CONF_UNSET_SIZE;
-
- conf->upstream.pass_request_headers = NGX_CONF_UNSET;
- conf->upstream.pass_request_body = NGX_CONF_UNSET;
-
-#if (NGX_HTTP_CACHE)
- conf->upstream.cache = NGX_CONF_UNSET;
- conf->upstream.cache_min_uses = NGX_CONF_UNSET_UINT;
- conf->upstream.cache_max_range_offset = NGX_CONF_UNSET;
- conf->upstream.cache_bypass = NGX_CONF_UNSET_PTR;
- conf->upstream.no_cache = NGX_CONF_UNSET_PTR;
- conf->upstream.cache_valid = NGX_CONF_UNSET_PTR;
- conf->upstream.cache_lock = NGX_CONF_UNSET;
- conf->upstream.cache_lock_timeout = NGX_CONF_UNSET_MSEC;
- conf->upstream.cache_lock_age = NGX_CONF_UNSET_MSEC;
- conf->upstream.cache_revalidate = NGX_CONF_UNSET;
- conf->upstream.cache_convert_head = NGX_CONF_UNSET;
- conf->upstream.cache_background_update = NGX_CONF_UNSET;
-#endif
-
- conf->upstream.hide_headers = NGX_CONF_UNSET_PTR;
- conf->upstream.pass_headers = NGX_CONF_UNSET_PTR;
-
- conf->upstream.intercept_errors = NGX_CONF_UNSET;
-
-#if (NGX_HTTP_SSL)
- conf->upstream.ssl_session_reuse = NGX_CONF_UNSET;
- conf->upstream.ssl_server_name = NGX_CONF_UNSET;
- conf->upstream.ssl_verify = NGX_CONF_UNSET;
- conf->ssl_verify_depth = NGX_CONF_UNSET_UINT;
- conf->ssl_passwords = NGX_CONF_UNSET_PTR;
-#endif
-
- /* "proxy_cyclic_temp_file" is disabled */
- conf->upstream.cyclic_temp_file = 0;
-
- conf->redirect = NGX_CONF_UNSET;
- conf->upstream.change_buffering = 1;
-
- conf->cookie_domains = NGX_CONF_UNSET_PTR;
- conf->cookie_paths = NGX_CONF_UNSET_PTR;
-
- conf->http_version = NGX_CONF_UNSET_UINT;
-
- conf->headers_hash_max_size = NGX_CONF_UNSET_UINT;
- conf->headers_hash_bucket_size = NGX_CONF_UNSET_UINT;
-
- ngx_str_set(&conf->upstream.module, "proxy");
-
- return conf;
-}
-
-
-static char *
-ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
-{
- ngx_http_proxy_loc_conf_t *prev = parent;
- ngx_http_proxy_loc_conf_t *conf = child;
-
- u_char *p;
- size_t size;
- ngx_int_t rc;
- ngx_hash_init_t hash;
- ngx_http_core_loc_conf_t *clcf;
- ngx_http_proxy_rewrite_t *pr;
- ngx_http_script_compile_t sc;
-
-#if (NGX_HTTP_CACHE)
-
- if (conf->upstream.store > 0) {
- conf->upstream.cache = 0;
- }
-
- if (conf->upstream.cache > 0) {
- conf->upstream.store = 0;
- }
-
-#endif
-
- if (conf->upstream.store == NGX_CONF_UNSET) {
- ngx_conf_merge_value(conf->upstream.store,
- prev->upstream.store, 0);
-
- conf->upstream.store_lengths = prev->upstream.store_lengths;
- conf->upstream.store_values = prev->upstream.store_values;
- }
-
- ngx_conf_merge_uint_value(conf->upstream.store_access,
- prev->upstream.store_access, 0600);
-
- ngx_conf_merge_uint_value(conf->upstream.next_upstream_tries,
- prev->upstream.next_upstream_tries, 0);
-
- ngx_conf_merge_value(conf->upstream.buffering,
- prev->upstream.buffering, 1);
-
- ngx_conf_merge_value(conf->upstream.request_buffering,
- prev->upstream.request_buffering, 1);
-
- ngx_conf_merge_value(conf->upstream.ignore_client_abort,
- prev->upstream.ignore_client_abort, 0);
-
- ngx_conf_merge_value(conf->upstream.force_ranges,
- prev->upstream.force_ranges, 0);
-
- ngx_conf_merge_ptr_value(conf->upstream.local,
- prev->upstream.local, NULL);
-
- ngx_conf_merge_msec_value(conf->upstream.connect_timeout,
- prev->upstream.connect_timeout, 60000);
-
- ngx_conf_merge_msec_value(conf->upstream.send_timeout,
- prev->upstream.send_timeout, 60000);
-
- ngx_conf_merge_msec_value(conf->upstream.read_timeout,
- prev->upstream.read_timeout, 60000);
-
- ngx_conf_merge_msec_value(conf->upstream.next_upstream_timeout,
- prev->upstream.next_upstream_timeout, 0);
-
- ngx_conf_merge_size_value(conf->upstream.send_lowat,
- prev->upstream.send_lowat, 0);
-
- ngx_conf_merge_size_value(conf->upstream.buffer_size,
- prev->upstream.buffer_size,
- (size_t) ngx_pagesize);
-
- ngx_conf_merge_size_value(conf->upstream.limit_rate,
- prev->upstream.limit_rate, 0);
-
- ngx_conf_merge_bufs_value(conf->upstream.bufs, prev->upstream.bufs,
- 8, ngx_pagesize);
-
- if (conf->upstream.bufs.num < 2) {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "there must be at least 2 \"proxy_buffers\"");
- return NGX_CONF_ERROR;
- }
-
-
- size = conf->upstream.buffer_size;
- if (size < conf->upstream.bufs.size) {
- size = conf->upstream.bufs.size;
- }
-
-
- ngx_conf_merge_size_value(conf->upstream.busy_buffers_size_conf,
- prev->upstream.busy_buffers_size_conf,
- NGX_CONF_UNSET_SIZE);
-
- if (conf->upstream.busy_buffers_size_conf == NGX_CONF_UNSET_SIZE) {
- conf->upstream.busy_buffers_size = 2 * size;
- } else {
- conf->upstream.busy_buffers_size =
- conf->upstream.busy_buffers_size_conf;
- }
-
- if (conf->upstream.busy_buffers_size < size) {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "\"proxy_busy_buffers_size\" must be equal to or greater than "
- "the maximum of the value of \"proxy_buffer_size\" and "
- "one of the \"proxy_buffers\"");
-
- return NGX_CONF_ERROR;
- }
-
- if (conf->upstream.busy_buffers_size
- > (conf->upstream.bufs.num - 1) * conf->upstream.bufs.size)
- {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "\"proxy_busy_buffers_size\" must be less than "
- "the size of all \"proxy_buffers\" minus one buffer");
-
- return NGX_CONF_ERROR;
- }
-
-
- ngx_conf_merge_size_value(conf->upstream.temp_file_write_size_conf,
- prev->upstream.temp_file_write_size_conf,
- NGX_CONF_UNSET_SIZE);
-
- if (conf->upstream.temp_file_write_size_conf == NGX_CONF_UNSET_SIZE) {
- conf->upstream.temp_file_write_size = 2 * size;
- } else {
- conf->upstream.temp_file_write_size =
- conf->upstream.temp_file_write_size_conf;
- }
-
- if (conf->upstream.temp_file_write_size < size) {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "\"proxy_temp_file_write_size\" must be equal to or greater "
- "than the maximum of the value of \"proxy_buffer_size\" and "
- "one of the \"proxy_buffers\"");
-
- return NGX_CONF_ERROR;
- }
-
- ngx_conf_merge_size_value(conf->upstream.max_temp_file_size_conf,
- prev->upstream.max_temp_file_size_conf,
- NGX_CONF_UNSET_SIZE);
-
- if (conf->upstream.max_temp_file_size_conf == NGX_CONF_UNSET_SIZE) {
- conf->upstream.max_temp_file_size = 1024 * 1024 * 1024;
- } else {
- conf->upstream.max_temp_file_size =
- conf->upstream.max_temp_file_size_conf;
- }
-
- if (conf->upstream.max_temp_file_size != 0
- && conf->upstream.max_temp_file_size < size)
- {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "\"proxy_max_temp_file_size\" must be equal to zero to disable "
- "temporary files usage or must be equal to or greater than "
- "the maximum of the value of \"proxy_buffer_size\" and "
- "one of the \"proxy_buffers\"");
-
- return NGX_CONF_ERROR;
- }
-
-
- ngx_conf_merge_bitmask_value(conf->upstream.ignore_headers,
- prev->upstream.ignore_headers,
- NGX_CONF_BITMASK_SET);
-
-
- ngx_conf_merge_bitmask_value(conf->upstream.next_upstream,
- prev->upstream.next_upstream,
- (NGX_CONF_BITMASK_SET
- |NGX_HTTP_UPSTREAM_FT_ERROR
- |NGX_HTTP_UPSTREAM_FT_TIMEOUT));
-
- if (conf->upstream.next_upstream & NGX_HTTP_UPSTREAM_FT_OFF) {
- conf->upstream.next_upstream = NGX_CONF_BITMASK_SET
- |NGX_HTTP_UPSTREAM_FT_OFF;
- }
-
- if (ngx_conf_merge_path_value(cf, &conf->upstream.temp_path,
- prev->upstream.temp_path,
- &ngx_http_proxy_temp_path)
- != NGX_OK)
- {
- return NGX_CONF_ERROR;
- }
-
-
-#if (NGX_HTTP_CACHE)
-
- if (conf->upstream.cache == NGX_CONF_UNSET) {
- ngx_conf_merge_value(conf->upstream.cache,
- prev->upstream.cache, 0);
-
- conf->upstream.cache_zone = prev->upstream.cache_zone;
- conf->upstream.cache_value = prev->upstream.cache_value;
- }
-
- if (conf->upstream.cache_zone && conf->upstream.cache_zone->data == NULL) {
- ngx_shm_zone_t *shm_zone;
-
- shm_zone = conf->upstream.cache_zone;
-
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "\"proxy_cache\" zone \"%V\" is unknown",
- &shm_zone->shm.name);
-
- return NGX_CONF_ERROR;
- }
-
- ngx_conf_merge_uint_value(conf->upstream.cache_min_uses,
- prev->upstream.cache_min_uses, 1);
-
- ngx_conf_merge_off_value(conf->upstream.cache_max_range_offset,
- prev->upstream.cache_max_range_offset,
- NGX_MAX_OFF_T_VALUE);
-
- ngx_conf_merge_bitmask_value(conf->upstream.cache_use_stale,
- prev->upstream.cache_use_stale,
- (NGX_CONF_BITMASK_SET
- |NGX_HTTP_UPSTREAM_FT_OFF));
-
- if (conf->upstream.cache_use_stale & NGX_HTTP_UPSTREAM_FT_OFF) {
- conf->upstream.cache_use_stale = NGX_CONF_BITMASK_SET
- |NGX_HTTP_UPSTREAM_FT_OFF;
- }
-
- if (conf->upstream.cache_use_stale & NGX_HTTP_UPSTREAM_FT_ERROR) {
- conf->upstream.cache_use_stale |= NGX_HTTP_UPSTREAM_FT_NOLIVE;
- }
-
- if (conf->upstream.cache_methods == 0) {
- conf->upstream.cache_methods = prev->upstream.cache_methods;
- }
-
- conf->upstream.cache_methods |= NGX_HTTP_GET|NGX_HTTP_HEAD;
-
- ngx_conf_merge_ptr_value(conf->upstream.cache_bypass,
- prev->upstream.cache_bypass, NULL);
-
- ngx_conf_merge_ptr_value(conf->upstream.no_cache,
- prev->upstream.no_cache, NULL);
-
- ngx_conf_merge_ptr_value(conf->upstream.cache_valid,
- prev->upstream.cache_valid, NULL);
-
- if (conf->cache_key.value.data == NULL) {
- conf->cache_key = prev->cache_key;
- }
-
- ngx_conf_merge_value(conf->upstream.cache_lock,
- prev->upstream.cache_lock, 0);
-
- ngx_conf_merge_msec_value(conf->upstream.cache_lock_timeout,
- prev->upstream.cache_lock_timeout, 5000);
-
- ngx_conf_merge_msec_value(conf->upstream.cache_lock_age,
- prev->upstream.cache_lock_age, 5000);
-
- ngx_conf_merge_value(conf->upstream.cache_revalidate,
- prev->upstream.cache_revalidate, 0);
-
- ngx_conf_merge_value(conf->upstream.cache_convert_head,
- prev->upstream.cache_convert_head, 1);
-
- ngx_conf_merge_value(conf->upstream.cache_background_update,
- prev->upstream.cache_background_update, 0);
-
-#endif
-
- if (conf->method == NULL) {
- conf->method = prev->method;
- }
-
- ngx_conf_merge_value(conf->upstream.pass_request_headers,
- prev->upstream.pass_request_headers, 1);
- ngx_conf_merge_value(conf->upstream.pass_request_body,
- prev->upstream.pass_request_body, 1);
-
- ngx_conf_merge_value(conf->upstream.intercept_errors,
- prev->upstream.intercept_errors, 0);
-
-#if (NGX_HTTP_SSL)
-
- ngx_conf_merge_value(conf->upstream.ssl_session_reuse,
- prev->upstream.ssl_session_reuse, 1);
-
- ngx_conf_merge_bitmask_value(conf->ssl_protocols, prev->ssl_protocols,
- (NGX_CONF_BITMASK_SET|NGX_SSL_TLSv1
- |NGX_SSL_TLSv1_1|NGX_SSL_TLSv1_2));
-
- ngx_conf_merge_str_value(conf->ssl_ciphers, prev->ssl_ciphers,
- "DEFAULT");
-
- if (conf->upstream.ssl_name == NULL) {
- conf->upstream.ssl_name = prev->upstream.ssl_name;
- }
-
- ngx_conf_merge_value(conf->upstream.ssl_server_name,
- prev->upstream.ssl_server_name, 0);
- ngx_conf_merge_value(conf->upstream.ssl_verify,
- prev->upstream.ssl_verify, 0);
- ngx_conf_merge_uint_value(conf->ssl_verify_depth,
- prev->ssl_verify_depth, 1);
- ngx_conf_merge_str_value(conf->ssl_trusted_certificate,
- prev->ssl_trusted_certificate, "");
- ngx_conf_merge_str_value(conf->ssl_crl, prev->ssl_crl, "");
-
- ngx_conf_merge_str_value(conf->ssl_certificate,
- prev->ssl_certificate, "");
- ngx_conf_merge_str_value(conf->ssl_certificate_key,
- prev->ssl_certificate_key, "");
- ngx_conf_merge_ptr_value(conf->ssl_passwords, prev->ssl_passwords, NULL);
-
- if (conf->ssl && ngx_http_proxy_set_ssl(cf, conf) != NGX_OK) {
- return NGX_CONF_ERROR;
- }
-
-#endif
-
- ngx_conf_merge_value(conf->redirect, prev->redirect, 1);
-
- if (conf->redirect) {
-
- if (conf->redirects == NULL) {
- conf->redirects = prev->redirects;
- }
-
- if (conf->redirects == NULL && conf->url.data) {
-
- conf->redirects = ngx_array_create(cf->pool, 1,
- sizeof(ngx_http_proxy_rewrite_t));
- if (conf->redirects == NULL) {
- return NGX_CONF_ERROR;
- }
-
- pr = ngx_array_push(conf->redirects);
- if (pr == NULL) {
- return NGX_CONF_ERROR;
- }
-
- ngx_memzero(&pr->pattern.complex,
- sizeof(ngx_http_complex_value_t));
-
- ngx_memzero(&pr->replacement, sizeof(ngx_http_complex_value_t));
-
- pr->handler = ngx_http_proxy_rewrite_complex_handler;
-
- if (conf->vars.uri.len) {
- pr->pattern.complex.value = conf->url;
- pr->replacement.value = conf->location;
-
- } else {
- pr->pattern.complex.value.len = conf->url.len
- + sizeof("/") - 1;
-
- p = ngx_pnalloc(cf->pool, pr->pattern.complex.value.len);
- if (p == NULL) {
- return NGX_CONF_ERROR;
- }
-
- pr->pattern.complex.value.data = p;
-
- p = ngx_cpymem(p, conf->url.data, conf->url.len);
- *p = '/';
-
- ngx_str_set(&pr->replacement.value, "/");
- }
- }
- }
-
- ngx_conf_merge_ptr_value(conf->cookie_domains, prev->cookie_domains, NULL);
-
- ngx_conf_merge_ptr_value(conf->cookie_paths, prev->cookie_paths, NULL);
-
- ngx_conf_merge_uint_value(conf->http_version, prev->http_version,
- NGX_HTTP_VERSION_10);
-
- ngx_conf_merge_uint_value(conf->headers_hash_max_size,
- prev->headers_hash_max_size, 512);
-
- ngx_conf_merge_uint_value(conf->headers_hash_bucket_size,
- prev->headers_hash_bucket_size, 64);
-
- conf->headers_hash_bucket_size = ngx_align(conf->headers_hash_bucket_size,
- ngx_cacheline_size);
-
- hash.max_size = conf->headers_hash_max_size;
- hash.bucket_size = conf->headers_hash_bucket_size;
- hash.name = "proxy_headers_hash";
-
- if (ngx_http_upstream_hide_headers_hash(cf, &conf->upstream,
- &prev->upstream, ngx_http_proxy_hide_headers, &hash)
- != NGX_OK)
- {
- return NGX_CONF_ERROR;
- }
-
- clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);
-
- if (clcf->noname
- && conf->upstream.upstream == NULL && conf->proxy_lengths == NULL)
- {
- conf->upstream.upstream = prev->upstream.upstream;
- conf->location = prev->location;
- conf->vars = prev->vars;
-
- conf->proxy_lengths = prev->proxy_lengths;
- conf->proxy_values = prev->proxy_values;
-
-#if (NGX_HTTP_SSL)
- conf->upstream.ssl = prev->upstream.ssl;
-#endif
- }
-
- if (clcf->lmt_excpt && clcf->handler == NULL
- && (conf->upstream.upstream || conf->proxy_lengths))
- {
- clcf->handler = ngx_http_proxy_handler;
- }
-
- if (conf->body_source.data == NULL) {
- conf->body_flushes = prev->body_flushes;
- conf->body_source = prev->body_source;
- conf->body_lengths = prev->body_lengths;
- conf->body_values = prev->body_values;
- }
-
- if (conf->body_source.data && conf->body_lengths == NULL) {
-
- ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));
-
- sc.cf = cf;
- sc.source = &conf->body_source;
- sc.flushes = &conf->body_flushes;
- sc.lengths = &conf->body_lengths;
- sc.values = &conf->body_values;
- sc.complete_lengths = 1;
- sc.complete_values = 1;
-
- if (ngx_http_script_compile(&sc) != NGX_OK) {
- return NGX_CONF_ERROR;
- }
- }
-
- if (conf->headers_source == NULL) {
- conf->headers = prev->headers;
-#if (NGX_HTTP_CACHE)
- conf->headers_cache = prev->headers_cache;
-#endif
- conf->headers_source = prev->headers_source;
- }
-
- rc = ngx_http_proxy_init_headers(cf, conf, &conf->headers,
- ngx_http_proxy_headers);
- if (rc != NGX_OK) {
- return NGX_CONF_ERROR;
- }
-
-#if (NGX_HTTP_CACHE)
-
- if (conf->upstream.cache) {
- rc = ngx_http_proxy_init_headers(cf, conf, &conf->headers_cache,
- ngx_http_proxy_cache_headers);
- if (rc != NGX_OK) {
- return NGX_CONF_ERROR;
- }
- }
-
-#endif
-
- /*
- * special handling to preserve conf->headers in the "http" section
- * to inherit it to all servers
- */
-
- if (prev->headers.hash.buckets == NULL
- && conf->headers_source == prev->headers_source)
- {
- prev->headers = conf->headers;
-#if (NGX_HTTP_CACHE)
- prev->headers_cache = conf->headers_cache;
-#endif
- }
-
- return NGX_CONF_OK;
-}
-
-
-static ngx_int_t
-ngx_http_proxy_init_headers(ngx_conf_t *cf, ngx_http_proxy_loc_conf_t *conf,
- ngx_http_proxy_headers_t *headers, ngx_keyval_t *default_headers)
-{
- u_char *p;
- size_t size;
- uintptr_t *code;
- ngx_uint_t i;
- ngx_array_t headers_names, headers_merged;
- ngx_keyval_t *src, *s, *h;
- ngx_hash_key_t *hk;
- ngx_hash_init_t hash;
- ngx_http_script_compile_t sc;
- ngx_http_script_copy_code_t *copy;
-
- if (headers->hash.buckets) {
- return NGX_OK;
- }
-
- if (ngx_array_init(&headers_names, cf->temp_pool, 4, sizeof(ngx_hash_key_t))
- != NGX_OK)
- {
- return NGX_ERROR;
- }
-
- if (ngx_array_init(&headers_merged, cf->temp_pool, 4, sizeof(ngx_keyval_t))
- != NGX_OK)
- {
- return NGX_ERROR;
- }
-
- headers->lengths = ngx_array_create(cf->pool, 64, 1);
- if (headers->lengths == NULL) {
- return NGX_ERROR;
- }
-
- headers->values = ngx_array_create(cf->pool, 512, 1);
- if (headers->values == NULL) {
- return NGX_ERROR;
- }
-
- if (conf->headers_source) {
-
- src = conf->headers_source->elts;
- for (i = 0; i < conf->headers_source->nelts; i++) {
-
- s = ngx_array_push(&headers_merged);
- if (s == NULL) {
- return NGX_ERROR;
- }
-
- *s = src[i];
- }
- }
-
- h = default_headers;
-
- while (h->key.len) {
-
- src = headers_merged.elts;
- for (i = 0; i < headers_merged.nelts; i++) {
- if (ngx_strcasecmp(h->key.data, src[i].key.data) == 0) {
- goto next;
- }
- }
-
- s = ngx_array_push(&headers_merged);
- if (s == NULL) {
- return NGX_ERROR;
- }
-
- *s = *h;
-
- next:
-
- h++;
- }
-
-
- src = headers_merged.elts;
- for (i = 0; i < headers_merged.nelts; i++) {
-
- hk = ngx_array_push(&headers_names);
- if (hk == NULL) {
- return NGX_ERROR;
- }
-
- hk->key = src[i].key;
- hk->key_hash = ngx_hash_key_lc(src[i].key.data, src[i].key.len);
- hk->value = (void *) 1;
-
- if (src[i].value.len == 0) {
- continue;
- }
-
- copy = ngx_array_push_n(headers->lengths,
- sizeof(ngx_http_script_copy_code_t));
- if (copy == NULL) {
- return NGX_ERROR;
- }
-
- copy->code = (ngx_http_script_code_pt) (void *)
- ngx_http_script_copy_len_code;
- copy->len = src[i].key.len;
-
- size = (sizeof(ngx_http_script_copy_code_t)
- + src[i].key.len + sizeof(uintptr_t) - 1)
- & ~(sizeof(uintptr_t) - 1);
-
- copy = ngx_array_push_n(headers->values, size);
- if (copy == NULL) {
- return NGX_ERROR;
- }
-
- copy->code = ngx_http_script_copy_code;
- copy->len = src[i].key.len;
-
- p = (u_char *) copy + sizeof(ngx_http_script_copy_code_t);
- ngx_memcpy(p, src[i].key.data, src[i].key.len);
-
- ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));
-
- sc.cf = cf;
- sc.source = &src[i].value;
- sc.flushes = &headers->flushes;
- sc.lengths = &headers->lengths;
- sc.values = &headers->values;
-
- if (ngx_http_script_compile(&sc) != NGX_OK) {
- return NGX_ERROR;
- }
-
- code = ngx_array_push_n(headers->lengths, sizeof(uintptr_t));
- if (code == NULL) {
- return NGX_ERROR;
- }
-
- *code = (uintptr_t) NULL;
-
- code = ngx_array_push_n(headers->values, sizeof(uintptr_t));
- if (code == NULL) {
- return NGX_ERROR;
- }
-
- *code = (uintptr_t) NULL;
- }
-
- code = ngx_array_push_n(headers->lengths, sizeof(uintptr_t));
- if (code == NULL) {
- return NGX_ERROR;
- }
-
- *code = (uintptr_t) NULL;
-
-
- hash.hash = &headers->hash;
- hash.key = ngx_hash_key_lc;
- hash.max_size = conf->headers_hash_max_size;
- hash.bucket_size = conf->headers_hash_bucket_size;
- hash.name = "proxy_headers_hash";
- hash.pool = cf->pool;
- hash.temp_pool = NULL;
-
- return ngx_hash_init(&hash, headers_names.elts, headers_names.nelts);
-}
-
-
-static char *
-ngx_http_proxy_pass(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
-{
- ngx_http_proxy_loc_conf_t *plcf = conf;
-
- size_t add;
- u_short port;
- ngx_str_t *value, *url;
- ngx_url_t u;
- ngx_uint_t n;
- ngx_http_core_loc_conf_t *clcf;
- ngx_http_script_compile_t sc;
-
- if (plcf->upstream.upstream || plcf->proxy_lengths) {
- return "is duplicate";
- }
-
- clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);
-
- clcf->handler = ngx_http_proxy_handler;
-
- if (clcf->name.data[clcf->name.len - 1] == '/') {
- clcf->auto_redirect = 1;
- }
-
- value = cf->args->elts;
-
- url = &value[1];
-
- n = ngx_http_script_variables_count(url);
-
- if (n) {
-
- ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));
-
- sc.cf = cf;
- sc.source = url;
- sc.lengths = &plcf->proxy_lengths;
- sc.values = &plcf->proxy_values;
- sc.variables = n;
- sc.complete_lengths = 1;
- sc.complete_values = 1;
-
- if (ngx_http_script_compile(&sc) != NGX_OK) {
- return NGX_CONF_ERROR;
- }
-
-#if (NGX_HTTP_SSL)
- plcf->ssl = 1;
-#endif
-
- return NGX_CONF_OK;
- }
-
- if (ngx_strncasecmp(url->data, (u_char *) "http://", 7) == 0) {
- add = 7;
- port = 80;
-
- } else if (ngx_strncasecmp(url->data, (u_char *) "https://", 8) == 0) {
-
-#if (NGX_HTTP_SSL)
- plcf->ssl = 1;
-
- add = 8;
- port = 443;
-#else
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "https protocol requires SSL support");
- return NGX_CONF_ERROR;
-#endif
-
- } else {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid URL prefix");
- return NGX_CONF_ERROR;
- }
-
- ngx_memzero(&u, sizeof(ngx_url_t));
-
- u.url.len = url->len - add;
- u.url.data = url->data + add;
- u.default_port = port;
- u.uri_part = 1;
- u.no_resolve = 1;
-
- plcf->upstream.upstream = ngx_http_upstream_add(cf, &u, 0);
- if (plcf->upstream.upstream == NULL) {
- return NGX_CONF_ERROR;
- }
-
- plcf->vars.schema.len = add;
- plcf->vars.schema.data = url->data;
- plcf->vars.key_start = plcf->vars.schema;
-
- ngx_http_proxy_set_vars(&u, &plcf->vars);
-
- plcf->location = clcf->name;
-
- if (clcf->named
-#if (NGX_PCRE)
- || clcf->regex
-#endif
- || clcf->noname)
- {
- if (plcf->vars.uri.len) {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "\"proxy_pass\" cannot have URI part in "
- "location given by regular expression, "
- "or inside named location, "
- "or inside \"if\" statement, "
- "or inside \"limit_except\" block");
- return NGX_CONF_ERROR;
- }
-
- plcf->location.len = 0;
- }
-
- plcf->url = *url;
-
- return NGX_CONF_OK;
-}
-
-
-static char *
-ngx_http_proxy_redirect(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
-{
- ngx_http_proxy_loc_conf_t *plcf = conf;
-
- u_char *p;
- ngx_str_t *value;
- ngx_http_proxy_rewrite_t *pr;
- ngx_http_compile_complex_value_t ccv;
-
- if (plcf->redirect == 0) {
- return NGX_CONF_OK;
- }
-
- plcf->redirect = 1;
-
- value = cf->args->elts;
-
- if (cf->args->nelts == 2) {
- if (ngx_strcmp(value[1].data, "off") == 0) {
- plcf->redirect = 0;
- plcf->redirects = NULL;
- return NGX_CONF_OK;
- }
-
- if (ngx_strcmp(value[1].data, "false") == 0) {
- ngx_conf_log_error(NGX_LOG_ERR, cf, 0,
- "invalid parameter \"false\", use \"off\" instead");
- plcf->redirect = 0;
- plcf->redirects = NULL;
- return NGX_CONF_OK;
- }
-
- if (ngx_strcmp(value[1].data, "default") != 0) {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "invalid parameter \"%V\"", &value[1]);
- return NGX_CONF_ERROR;
- }
- }
-
- if (plcf->redirects == NULL) {
- plcf->redirects = ngx_array_create(cf->pool, 1,
- sizeof(ngx_http_proxy_rewrite_t));
- if (plcf->redirects == NULL) {
- return NGX_CONF_ERROR;
- }
- }
-
- pr = ngx_array_push(plcf->redirects);
- if (pr == NULL) {
- return NGX_CONF_ERROR;
- }
-
- if (ngx_strcmp(value[1].data, "default") == 0) {
- if (plcf->proxy_lengths) {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "\"proxy_redirect default\" cannot be used "
- "with \"proxy_pass\" directive with variables");
- return NGX_CONF_ERROR;
- }
-
- if (plcf->url.data == NULL) {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "\"proxy_redirect default\" should be placed "
- "after the \"proxy_pass\" directive");
- return NGX_CONF_ERROR;
- }
-
- pr->handler = ngx_http_proxy_rewrite_complex_handler;
-
- ngx_memzero(&pr->pattern.complex, sizeof(ngx_http_complex_value_t));
-
- ngx_memzero(&pr->replacement, sizeof(ngx_http_complex_value_t));
-
- if (plcf->vars.uri.len) {
- pr->pattern.complex.value = plcf->url;
- pr->replacement.value = plcf->location;
-
- } else {
- pr->pattern.complex.value.len = plcf->url.len + sizeof("/") - 1;
-
- p = ngx_pnalloc(cf->pool, pr->pattern.complex.value.len);
- if (p == NULL) {
- return NGX_CONF_ERROR;
- }
-
- pr->pattern.complex.value.data = p;
-
- p = ngx_cpymem(p, plcf->url.data, plcf->url.len);
- *p = '/';
-
- ngx_str_set(&pr->replacement.value, "/");
- }
-
- return NGX_CONF_OK;
- }
-
-
- if (value[1].data[0] == '~') {
- value[1].len--;
- value[1].data++;
-
- if (value[1].data[0] == '*') {
- value[1].len--;
- value[1].data++;
-
- if (ngx_http_proxy_rewrite_regex(cf, pr, &value[1], 1) != NGX_OK) {
- return NGX_CONF_ERROR;
- }
-
- } else {
- if (ngx_http_proxy_rewrite_regex(cf, pr, &value[1], 0) != NGX_OK) {
- return NGX_CONF_ERROR;
- }
- }
-
- } else {
-
- ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));
-
- ccv.cf = cf;
- ccv.value = &value[1];
- ccv.complex_value = &pr->pattern.complex;
-
- if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
- return NGX_CONF_ERROR;
- }
-
- pr->handler = ngx_http_proxy_rewrite_complex_handler;
- }
-
-
- ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));
-
- ccv.cf = cf;
- ccv.value = &value[2];
- ccv.complex_value = &pr->replacement;
-
- if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
- return NGX_CONF_ERROR;
- }
-
- return NGX_CONF_OK;
-}
-
-
-static char *
-ngx_http_proxy_cookie_domain(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
-{
- ngx_http_proxy_loc_conf_t *plcf = conf;
-
- ngx_str_t *value;
- ngx_http_proxy_rewrite_t *pr;
- ngx_http_compile_complex_value_t ccv;
-
- if (plcf->cookie_domains == NULL) {
- return NGX_CONF_OK;
- }
-
- value = cf->args->elts;
-
- if (cf->args->nelts == 2) {
-
- if (ngx_strcmp(value[1].data, "off") == 0) {
- plcf->cookie_domains = NULL;
- return NGX_CONF_OK;
- }
-
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "invalid parameter \"%V\"", &value[1]);
- return NGX_CONF_ERROR;
- }
-
- if (plcf->cookie_domains == NGX_CONF_UNSET_PTR) {
- plcf->cookie_domains = ngx_array_create(cf->pool, 1,
- sizeof(ngx_http_proxy_rewrite_t));
- if (plcf->cookie_domains == NULL) {
- return NGX_CONF_ERROR;
- }
- }
-
- pr = ngx_array_push(plcf->cookie_domains);
- if (pr == NULL) {
- return NGX_CONF_ERROR;
- }
-
- if (value[1].data[0] == '~') {
- value[1].len--;
- value[1].data++;
-
- if (ngx_http_proxy_rewrite_regex(cf, pr, &value[1], 1) != NGX_OK) {
- return NGX_CONF_ERROR;
- }
-
- } else {
-
- if (value[1].data[0] == '.') {
- value[1].len--;
- value[1].data++;
- }
-
- ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));
-
- ccv.cf = cf;
- ccv.value = &value[1];
- ccv.complex_value = &pr->pattern.complex;
-
- if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
- return NGX_CONF_ERROR;
- }
-
- pr->handler = ngx_http_proxy_rewrite_domain_handler;
-
- if (value[2].data[0] == '.') {
- value[2].len--;
- value[2].data++;
- }
- }
-
- ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));
-
- ccv.cf = cf;
- ccv.value = &value[2];
- ccv.complex_value = &pr->replacement;
-
- if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
- return NGX_CONF_ERROR;
- }
-
- return NGX_CONF_OK;
-}
-
-
-static char *
-ngx_http_proxy_cookie_path(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
-{
- ngx_http_proxy_loc_conf_t *plcf = conf;
-
- ngx_str_t *value;
- ngx_http_proxy_rewrite_t *pr;
- ngx_http_compile_complex_value_t ccv;
-
- if (plcf->cookie_paths == NULL) {
- return NGX_CONF_OK;
- }
-
- value = cf->args->elts;
-
- if (cf->args->nelts == 2) {
-
- if (ngx_strcmp(value[1].data, "off") == 0) {
- plcf->cookie_paths = NULL;
- return NGX_CONF_OK;
- }
-
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "invalid parameter \"%V\"", &value[1]);
- return NGX_CONF_ERROR;
- }
-
- if (plcf->cookie_paths == NGX_CONF_UNSET_PTR) {
- plcf->cookie_paths = ngx_array_create(cf->pool, 1,
- sizeof(ngx_http_proxy_rewrite_t));
- if (plcf->cookie_paths == NULL) {
- return NGX_CONF_ERROR;
- }
- }
-
- pr = ngx_array_push(plcf->cookie_paths);
- if (pr == NULL) {
- return NGX_CONF_ERROR;
- }
-
- if (value[1].data[0] == '~') {
- value[1].len--;
- value[1].data++;
-
- if (value[1].data[0] == '*') {
- value[1].len--;
- value[1].data++;
-
- if (ngx_http_proxy_rewrite_regex(cf, pr, &value[1], 1) != NGX_OK) {
- return NGX_CONF_ERROR;
- }
-
- } else {
- if (ngx_http_proxy_rewrite_regex(cf, pr, &value[1], 0) != NGX_OK) {
- return NGX_CONF_ERROR;
- }
- }
-
- } else {
-
- ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));
-
- ccv.cf = cf;
- ccv.value = &value[1];
- ccv.complex_value = &pr->pattern.complex;
-
- if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
- return NGX_CONF_ERROR;
- }
-
- pr->handler = ngx_http_proxy_rewrite_complex_handler;
- }
-
- ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));
-
- ccv.cf = cf;
- ccv.value = &value[2];
- ccv.complex_value = &pr->replacement;
-
- if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
- return NGX_CONF_ERROR;
- }
-
- return NGX_CONF_OK;
-}
-
-
-static ngx_int_t
-ngx_http_proxy_rewrite_regex(ngx_conf_t *cf, ngx_http_proxy_rewrite_t *pr,
- ngx_str_t *regex, ngx_uint_t caseless)
-{
-#if (NGX_PCRE)
- u_char errstr[NGX_MAX_CONF_ERRSTR];
- ngx_regex_compile_t rc;
-
- ngx_memzero(&rc, sizeof(ngx_regex_compile_t));
-
- rc.pattern = *regex;
- rc.err.len = NGX_MAX_CONF_ERRSTR;
- rc.err.data = errstr;
-
- if (caseless) {
- rc.options = NGX_REGEX_CASELESS;
- }
-
- pr->pattern.regex = ngx_http_regex_compile(cf, &rc);
- if (pr->pattern.regex == NULL) {
- return NGX_ERROR;
- }
-
- pr->handler = ngx_http_proxy_rewrite_regex_handler;
-
- return NGX_OK;
-
-#else
-
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "using regex \"%V\" requires PCRE library", regex);
- return NGX_ERROR;
-
-#endif
-}
-
-
-static char *
-ngx_http_proxy_store(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
-{
- ngx_http_proxy_loc_conf_t *plcf = conf;
-
- ngx_str_t *value;
- ngx_http_script_compile_t sc;
-
- if (plcf->upstream.store != NGX_CONF_UNSET) {
- return "is duplicate";
- }
-
- value = cf->args->elts;
-
- if (ngx_strcmp(value[1].data, "off") == 0) {
- plcf->upstream.store = 0;
- return NGX_CONF_OK;
- }
-
-#if (NGX_HTTP_CACHE)
- if (plcf->upstream.cache > 0) {
- return "is incompatible with \"proxy_cache\"";
- }
-#endif
-
- plcf->upstream.store = 1;
-
- if (ngx_strcmp(value[1].data, "on") == 0) {
- return NGX_CONF_OK;
- }
-
- /* include the terminating '\0' into script */
- value[1].len++;
-
- ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));
-
- sc.cf = cf;
- sc.source = &value[1];
- sc.lengths = &plcf->upstream.store_lengths;
- sc.values = &plcf->upstream.store_values;
- sc.variables = ngx_http_script_variables_count(&value[1]);
- sc.complete_lengths = 1;
- sc.complete_values = 1;
-
- if (ngx_http_script_compile(&sc) != NGX_OK) {
- return NGX_CONF_ERROR;
- }
-
- return NGX_CONF_OK;
-}
-
-
-#if (NGX_HTTP_CACHE)
-
-static char *
-ngx_http_proxy_cache(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
-{
- ngx_http_proxy_loc_conf_t *plcf = conf;
-
- ngx_str_t *value;
- ngx_http_complex_value_t cv;
- ngx_http_compile_complex_value_t ccv;
-
- value = cf->args->elts;
-
- if (plcf->upstream.cache != NGX_CONF_UNSET) {
- return "is duplicate";
- }
-
- if (ngx_strcmp(value[1].data, "off") == 0) {
- plcf->upstream.cache = 0;
- return NGX_CONF_OK;
- }
-
- if (plcf->upstream.store > 0) {
- return "is incompatible with \"proxy_store\"";
- }
-
- plcf->upstream.cache = 1;
-
- 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) {
-
- plcf->upstream.cache_value = ngx_palloc(cf->pool,
- sizeof(ngx_http_complex_value_t));
- if (plcf->upstream.cache_value == NULL) {
- return NGX_CONF_ERROR;
- }
-
- *plcf->upstream.cache_value = cv;
-
- return NGX_CONF_OK;
- }
-
- plcf->upstream.cache_zone = ngx_shared_memory_add(cf, &value[1], 0,
- &ngx_http_proxy_module);
- if (plcf->upstream.cache_zone == NULL) {
- return NGX_CONF_ERROR;
- }
-
- return NGX_CONF_OK;
-}
-
-
-static char *
-ngx_http_proxy_cache_key(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
-{
- ngx_http_proxy_loc_conf_t *plcf = conf;
-
- ngx_str_t *value;
- ngx_http_compile_complex_value_t ccv;
-
- value = cf->args->elts;
-
- if (plcf->cache_key.value.data) {
- return "is duplicate";
- }
-
- ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));
-
- ccv.cf = cf;
- ccv.value = &value[1];
- ccv.complex_value = &plcf->cache_key;
-
- if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
- return NGX_CONF_ERROR;
- }
-
- return NGX_CONF_OK;
-}
-
-#endif
-
-
-#if (NGX_HTTP_SSL)
-
-static char *
-ngx_http_proxy_ssl_password_file(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
-{
- ngx_http_proxy_loc_conf_t *plcf = conf;
-
- ngx_str_t *value;
-
- if (plcf->ssl_passwords != NGX_CONF_UNSET_PTR) {
- return "is duplicate";
- }
-
- value = cf->args->elts;
-
- plcf->ssl_passwords = ngx_ssl_read_password_file(cf, &value[1]);
-
- if (plcf->ssl_passwords == NULL) {
- return NGX_CONF_ERROR;
- }
-
- return NGX_CONF_OK;
-}
-
-#endif
-
-
-static char *
-ngx_http_proxy_lowat_check(ngx_conf_t *cf, void *post, void *data)
-{
-#if (NGX_FREEBSD)
- ssize_t *np = data;
-
- if ((u_long) *np >= ngx_freebsd_net_inet_tcp_sendspace) {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "\"proxy_send_lowat\" must be less than %d "
- "(sysctl net.inet.tcp.sendspace)",
- ngx_freebsd_net_inet_tcp_sendspace);
-
- return NGX_CONF_ERROR;
- }
-
-#elif !(NGX_HAVE_SO_SNDLOWAT)
- ssize_t *np = data;
-
- ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
- "\"proxy_send_lowat\" is not supported, ignored");
-
- *np = 0;
-
-#endif
-
- return NGX_CONF_OK;
-}
-
-
-#if (NGX_HTTP_SSL)
-
-static ngx_int_t
-ngx_http_proxy_set_ssl(ngx_conf_t *cf, ngx_http_proxy_loc_conf_t *plcf)
-{
- ngx_pool_cleanup_t *cln;
-
- plcf->upstream.ssl = ngx_pcalloc(cf->pool, sizeof(ngx_ssl_t));
- if (plcf->upstream.ssl == NULL) {
- return NGX_ERROR;
- }
-
- plcf->upstream.ssl->log = cf->log;
-
- if (ngx_ssl_create(plcf->upstream.ssl, plcf->ssl_protocols, NULL)
- != NGX_OK)
- {
- return NGX_ERROR;
- }
-
- cln = ngx_pool_cleanup_add(cf->pool, 0);
- if (cln == NULL) {
- return NGX_ERROR;
- }
-
- cln->handler = ngx_ssl_cleanup_ctx;
- cln->data = plcf->upstream.ssl;
-
- if (plcf->ssl_certificate.len) {
-
- if (plcf->ssl_certificate_key.len == 0) {
- ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
- "no \"proxy_ssl_certificate_key\" is defined "
- "for certificate \"%V\"", &plcf->ssl_certificate);
- return NGX_ERROR;
- }
-
- if (ngx_ssl_certificate(cf, plcf->upstream.ssl, &plcf->ssl_certificate,
- &plcf->ssl_certificate_key, plcf->ssl_passwords)
- != NGX_OK)
- {
- return NGX_ERROR;
- }
- }
-
- if (ngx_ssl_ciphers(cf, plcf->upstream.ssl, &plcf->ssl_ciphers, 0)
- != NGX_OK)
- {
- return NGX_ERROR;
- }
-
- if (plcf->upstream.ssl_verify) {
- if (plcf->ssl_trusted_certificate.len == 0) {
- ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
- "no proxy_ssl_trusted_certificate for proxy_ssl_verify");
- return NGX_ERROR;
- }
-
- if (ngx_ssl_trusted_certificate(cf, plcf->upstream.ssl,
- &plcf->ssl_trusted_certificate,
- plcf->ssl_verify_depth)
- != NGX_OK)
- {
- return NGX_ERROR;
- }
-
- if (ngx_ssl_crl(cf, plcf->upstream.ssl, &plcf->ssl_crl) != NGX_OK) {
- return NGX_ERROR;
- }
- }
-
- return NGX_OK;
-}
-
-#endif
-
-
-static void
-ngx_http_proxy_set_vars(ngx_url_t *u, ngx_http_proxy_vars_t *v)
-{
- if (u->family != AF_UNIX) {
-
- if (u->no_port || u->port == u->default_port) {
-
- v->host_header = u->host;
-
- if (u->default_port == 80) {
- ngx_str_set(&v->port, "80");
-
- } else {
- ngx_str_set(&v->port, "443");
- }
-
- } else {
- v->host_header.len = u->host.len + 1 + u->port_text.len;
- v->host_header.data = u->host.data;
- v->port = u->port_text;
- }
-
- v->key_start.len += v->host_header.len;
-
- } else {
- ngx_str_set(&v->host_header, "localhost");
- ngx_str_null(&v->port);
- v->key_start.len += sizeof("unix:") - 1 + u->host.len + 1;
- }
-
- v->uri = u->uri;
-}
diff --git a/nginx/src/http/modules/ngx_http_random_index_module.c b/nginx/src/http/modules/ngx_http_random_index_module.c
deleted file mode 100644
index b47ee4f..0000000
--- a/nginx/src/http/modules/ngx_http_random_index_module.c
+++ /dev/null
@@ -1,317 +0,0 @@
-
-/*
- * Copyright (C) Igor Sysoev
- * Copyright (C) Nginx, Inc.
- */
-
-
-#include <ngx_config.h>
-#include <ngx_core.h>
-#include <ngx_http.h>
-
-
-typedef struct {
- ngx_flag_t enable;
-} ngx_http_random_index_loc_conf_t;
-
-
-#define NGX_HTTP_RANDOM_INDEX_PREALLOCATE 50
-
-
-static ngx_int_t ngx_http_random_index_error(ngx_http_request_t *r,
- ngx_dir_t *dir, ngx_str_t *name);
-static ngx_int_t ngx_http_random_index_init(ngx_conf_t *cf);
-static void *ngx_http_random_index_create_loc_conf(ngx_conf_t *cf);
-static char *ngx_http_random_index_merge_loc_conf(ngx_conf_t *cf,
- void *parent, void *child);
-
-
-static ngx_command_t ngx_http_random_index_commands[] = {
-
- { ngx_string("random_index"),
- NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
- ngx_conf_set_flag_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_random_index_loc_conf_t, enable),
- NULL },
-
- ngx_null_command
-};
-
-
-static ngx_http_module_t ngx_http_random_index_module_ctx = {
- NULL, /* preconfiguration */
- ngx_http_random_index_init, /* postconfiguration */
-
- NULL, /* create main configuration */
- NULL, /* init main configuration */
-
- NULL, /* create server configuration */
- NULL, /* merge server configuration */
-
- ngx_http_random_index_create_loc_conf, /* create location configuration */
- ngx_http_random_index_merge_loc_conf /* merge location configuration */
-};
-
-
-ngx_module_t ngx_http_random_index_module = {
- NGX_MODULE_V1,
- &ngx_http_random_index_module_ctx, /* module context */
- ngx_http_random_index_commands, /* module directives */
- NGX_HTTP_MODULE, /* module type */
- NULL, /* init master */
- NULL, /* init module */
- NULL, /* init process */
- NULL, /* init thread */
- NULL, /* exit thread */
- NULL, /* exit process */
- NULL, /* exit master */
- NGX_MODULE_V1_PADDING
-};
-
-
-static ngx_int_t
-ngx_http_random_index_handler(ngx_http_request_t *r)
-{
- u_char *last, *filename;
- size_t len, allocated, root;
- ngx_err_t err;
- ngx_int_t rc;
- ngx_str_t path, uri, *name;
- ngx_dir_t dir;
- ngx_uint_t n, level;
- ngx_array_t names;
- ngx_http_random_index_loc_conf_t *rlcf;
-
- if (r->uri.data[r->uri.len - 1] != '/') {
- return NGX_DECLINED;
- }
-
- if (!(r->method & (NGX_HTTP_GET|NGX_HTTP_HEAD|NGX_HTTP_POST))) {
- return NGX_DECLINED;
- }
-
- rlcf = ngx_http_get_module_loc_conf(r, ngx_http_random_index_module);
-
- if (!rlcf->enable) {
- return NGX_DECLINED;
- }
-
-#if (NGX_HAVE_D_TYPE)
- len = NGX_DIR_MASK_LEN;
-#else
- len = NGX_HTTP_RANDOM_INDEX_PREALLOCATE;
-#endif
-
- last = ngx_http_map_uri_to_path(r, &path, &root, len);
- if (last == NULL) {
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
-
- allocated = path.len;
-
- path.len = last - path.data - 1;
- path.data[path.len] = '\0';
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "http random index: \"%s\"", path.data);
-
- if (ngx_open_dir(&path, &dir) == NGX_ERROR) {
- err = ngx_errno;
-
- if (err == NGX_ENOENT
- || err == NGX_ENOTDIR
- || err == NGX_ENAMETOOLONG)
- {
- level = NGX_LOG_ERR;
- rc = NGX_HTTP_NOT_FOUND;
-
- } else if (err == NGX_EACCES) {
- level = NGX_LOG_ERR;
- rc = NGX_HTTP_FORBIDDEN;
-
- } else {
- level = NGX_LOG_CRIT;
- rc = NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
-
- ngx_log_error(level, r->connection->log, err,
- ngx_open_dir_n " \"%s\" failed", path.data);
-
- return rc;
- }
-
- if (ngx_array_init(&names, r->pool, 32, sizeof(ngx_str_t)) != NGX_OK) {
- return ngx_http_random_index_error(r, &dir, &path);
- }
-
- filename = path.data;
- filename[path.len] = '/';
-
- for ( ;; ) {
- ngx_set_errno(0);
-
- if (ngx_read_dir(&dir) == NGX_ERROR) {
- err = ngx_errno;
-
- if (err != NGX_ENOMOREFILES) {
- ngx_log_error(NGX_LOG_CRIT, r->connection->log, err,
- ngx_read_dir_n " \"%V\" failed", &path);
- return ngx_http_random_index_error(r, &dir, &path);
- }
-
- break;
- }
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "http random index file: \"%s\"", ngx_de_name(&dir));
-
- if (ngx_de_name(&dir)[0] == '.') {
- continue;
- }
-
- len = ngx_de_namelen(&dir);
-
- if (dir.type == 0 || ngx_de_is_link(&dir)) {
-
- /* 1 byte for '/' and 1 byte for terminating '\0' */
-
- if (path.len + 1 + len + 1 > allocated) {
- allocated = path.len + 1 + len + 1
- + NGX_HTTP_RANDOM_INDEX_PREALLOCATE;
-
- filename = ngx_pnalloc(r->pool, allocated);
- if (filename == NULL) {
- return ngx_http_random_index_error(r, &dir, &path);
- }
-
- last = ngx_cpystrn(filename, path.data, path.len + 1);
- *last++ = '/';
- }
-
- ngx_cpystrn(last, ngx_de_name(&dir), len + 1);
-
- if (ngx_de_info(filename, &dir) == NGX_FILE_ERROR) {
- err = ngx_errno;
-
- if (err != NGX_ENOENT) {
- ngx_log_error(NGX_LOG_CRIT, r->connection->log, err,
- ngx_de_info_n " \"%s\" failed", filename);
- return ngx_http_random_index_error(r, &dir, &path);
- }
-
- if (ngx_de_link_info(filename, &dir) == NGX_FILE_ERROR) {
- ngx_log_error(NGX_LOG_CRIT, r->connection->log, ngx_errno,
- ngx_de_link_info_n " \"%s\" failed",
- filename);
- return ngx_http_random_index_error(r, &dir, &path);
- }
- }
- }
-
- if (!ngx_de_is_file(&dir)) {
- continue;
- }
-
- name = ngx_array_push(&names);
- if (name == NULL) {
- return ngx_http_random_index_error(r, &dir, &path);
- }
-
- name->len = len;
-
- name->data = ngx_pnalloc(r->pool, len);
- if (name->data == NULL) {
- return ngx_http_random_index_error(r, &dir, &path);
- }
-
- ngx_memcpy(name->data, ngx_de_name(&dir), len);
- }
-
- if (ngx_close_dir(&dir) == NGX_ERROR) {
- ngx_log_error(NGX_LOG_ALERT, r->connection->log, ngx_errno,
- ngx_close_dir_n " \"%V\" failed", &path);
- }
-
- n = names.nelts;
-
- if (n == 0) {
- return NGX_DECLINED;
- }
-
- name = names.elts;
-
- n = (ngx_uint_t) (((uint64_t) ngx_random() * n) / 0x80000000);
-
- uri.len = r->uri.len + name[n].len;
-
- uri.data = ngx_pnalloc(r->pool, uri.len);
- if (uri.data == NULL) {
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
-
- last = ngx_copy(uri.data, r->uri.data, r->uri.len);
- ngx_memcpy(last, name[n].data, name[n].len);
-
- return ngx_http_internal_redirect(r, &uri, &r->args);
-}
-
-
-static ngx_int_t
-ngx_http_random_index_error(ngx_http_request_t *r, ngx_dir_t *dir,
- ngx_str_t *name)
-{
- if (ngx_close_dir(dir) == NGX_ERROR) {
- ngx_log_error(NGX_LOG_ALERT, r->connection->log, ngx_errno,
- ngx_close_dir_n " \"%V\" failed", name);
- }
-
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
-}
-
-
-static void *
-ngx_http_random_index_create_loc_conf(ngx_conf_t *cf)
-{
- ngx_http_random_index_loc_conf_t *conf;
-
- conf = ngx_palloc(cf->pool, sizeof(ngx_http_random_index_loc_conf_t));
- if (conf == NULL) {
- return NULL;
- }
-
- conf->enable = NGX_CONF_UNSET;
-
- return conf;
-}
-
-
-static char *
-ngx_http_random_index_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
-{
- ngx_http_random_index_loc_conf_t *prev = parent;
- ngx_http_random_index_loc_conf_t *conf = child;
-
- ngx_conf_merge_value(conf->enable, prev->enable, 0);
-
- return NGX_CONF_OK;
-}
-
-
-static ngx_int_t
-ngx_http_random_index_init(ngx_conf_t *cf)
-{
- ngx_http_handler_pt *h;
- ngx_http_core_main_conf_t *cmcf;
-
- cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);
-
- h = ngx_array_push(&cmcf->phases[NGX_HTTP_CONTENT_PHASE].handlers);
- if (h == NULL) {
- return NGX_ERROR;
- }
-
- *h = ngx_http_random_index_handler;
-
- return NGX_OK;
-}
diff --git a/nginx/src/http/modules/ngx_http_range_filter_module.c b/nginx/src/http/modules/ngx_http_range_filter_module.c
deleted file mode 100644
index 819c5c9..0000000
--- a/nginx/src/http/modules/ngx_http_range_filter_module.c
+++ /dev/null
@@ -1,932 +0,0 @@
-
-/*
- * Copyright (C) Igor Sysoev
- * Copyright (C) Nginx, Inc.
- */
-
-
-#include <ngx_config.h>
-#include <ngx_core.h>
-#include <ngx_http.h>
-
-
-/*
- * the single part format:
- *
- * "HTTP/1.0 206 Partial Content" CRLF
- * ... header ...
- * "Content-Type: image/jpeg" CRLF
- * "Content-Length: SIZE" CRLF
- * "Content-Range: bytes START-END/SIZE" CRLF
- * CRLF
- * ... data ...
- *
- *
- * the multipart format:
- *
- * "HTTP/1.0 206 Partial Content" CRLF
- * ... header ...
- * "Content-Type: multipart/byteranges; boundary=0123456789" CRLF
- * CRLF
- * CRLF
- * "--0123456789" CRLF
- * "Content-Type: image/jpeg" CRLF
- * "Content-Range: bytes START0-END0/SIZE" CRLF
- * CRLF
- * ... data ...
- * CRLF
- * "--0123456789" CRLF
- * "Content-Type: image/jpeg" CRLF
- * "Content-Range: bytes START1-END1/SIZE" CRLF
- * CRLF
- * ... data ...
- * CRLF
- * "--0123456789--" CRLF
- */
-
-
-typedef struct {
- off_t start;
- off_t end;
- ngx_str_t content_range;
-} ngx_http_range_t;
-
-
-typedef struct {
- off_t offset;
- ngx_str_t boundary_header;
- ngx_array_t ranges;
-} ngx_http_range_filter_ctx_t;
-
-
-static ngx_int_t ngx_http_range_parse(ngx_http_request_t *r,
- ngx_http_range_filter_ctx_t *ctx, ngx_uint_t ranges);
-static ngx_int_t ngx_http_range_singlepart_header(ngx_http_request_t *r,
- ngx_http_range_filter_ctx_t *ctx);
-static ngx_int_t ngx_http_range_multipart_header(ngx_http_request_t *r,
- ngx_http_range_filter_ctx_t *ctx);
-static ngx_int_t ngx_http_range_not_satisfiable(ngx_http_request_t *r);
-static ngx_int_t ngx_http_range_test_overlapped(ngx_http_request_t *r,
- ngx_http_range_filter_ctx_t *ctx, ngx_chain_t *in);
-static ngx_int_t ngx_http_range_singlepart_body(ngx_http_request_t *r,
- ngx_http_range_filter_ctx_t *ctx, ngx_chain_t *in);
-static ngx_int_t ngx_http_range_multipart_body(ngx_http_request_t *r,
- ngx_http_range_filter_ctx_t *ctx, ngx_chain_t *in);
-
-static ngx_int_t ngx_http_range_header_filter_init(ngx_conf_t *cf);
-static ngx_int_t ngx_http_range_body_filter_init(ngx_conf_t *cf);
-
-
-static ngx_http_module_t ngx_http_range_header_filter_module_ctx = {
- NULL, /* preconfiguration */
- ngx_http_range_header_filter_init, /* postconfiguration */
-
- NULL, /* create main configuration */
- NULL, /* init main configuration */
-
- NULL, /* create server configuration */
- NULL, /* merge server configuration */
-
- NULL, /* create location configuration */
- NULL, /* merge location configuration */
-};
-
-
-ngx_module_t ngx_http_range_header_filter_module = {
- NGX_MODULE_V1,
- &ngx_http_range_header_filter_module_ctx, /* module context */
- NULL, /* module directives */
- NGX_HTTP_MODULE, /* module type */
- NULL, /* init master */
- NULL, /* init module */
- NULL, /* init process */
- NULL, /* init thread */
- NULL, /* exit thread */
- NULL, /* exit process */
- NULL, /* exit master */
- NGX_MODULE_V1_PADDING
-};
-
-
-static ngx_http_module_t ngx_http_range_body_filter_module_ctx = {
- NULL, /* preconfiguration */
- ngx_http_range_body_filter_init, /* postconfiguration */
-
- NULL, /* create main configuration */
- NULL, /* init main configuration */
-
- NULL, /* create server configuration */
- NULL, /* merge server configuration */
-
- NULL, /* create location configuration */
- NULL, /* merge location configuration */
-};
-
-
-ngx_module_t ngx_http_range_body_filter_module = {
- NGX_MODULE_V1,
- &ngx_http_range_body_filter_module_ctx, /* module context */
- NULL, /* module directives */
- NGX_HTTP_MODULE, /* module type */
- NULL, /* init master */
- NULL, /* init module */
- NULL, /* init process */
- NULL, /* init thread */
- NULL, /* exit thread */
- NULL, /* exit process */
- NULL, /* exit master */
- NGX_MODULE_V1_PADDING
-};
-
-
-static ngx_http_output_header_filter_pt ngx_http_next_header_filter;
-static ngx_http_output_body_filter_pt ngx_http_next_body_filter;
-
-
-static ngx_int_t
-ngx_http_range_header_filter(ngx_http_request_t *r)
-{
- time_t if_range_time;
- ngx_str_t *if_range, *etag;
- ngx_uint_t ranges;
- ngx_http_core_loc_conf_t *clcf;
- ngx_http_range_filter_ctx_t *ctx;
-
- if (r->http_version < NGX_HTTP_VERSION_10
- || r->headers_out.status != NGX_HTTP_OK
- || (r != r->main && !r->subrequest_ranges)
- || r->headers_out.content_length_n == -1
- || !r->allow_ranges)
- {
- return ngx_http_next_header_filter(r);
- }
-
- clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
-
- if (clcf->max_ranges == 0) {
- return ngx_http_next_header_filter(r);
- }
-
- if (r->headers_in.range == NULL
- || r->headers_in.range->value.len < 7
- || ngx_strncasecmp(r->headers_in.range->value.data,
- (u_char *) "bytes=", 6)
- != 0)
- {
- goto next_filter;
- }
-
- if (r->headers_in.if_range) {
-
- if_range = &r->headers_in.if_range->value;
-
- if (if_range->len >= 2 && if_range->data[if_range->len - 1] == '"') {
-
- if (r->headers_out.etag == NULL) {
- goto next_filter;
- }
-
- etag = &r->headers_out.etag->value;
-
- ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "http ir:%V etag:%V", if_range, etag);
-
- if (if_range->len != etag->len
- || ngx_strncmp(if_range->data, etag->data, etag->len) != 0)
- {
- goto next_filter;
- }
-
- goto parse;
- }
-
- if (r->headers_out.last_modified_time == (time_t) -1) {
- goto next_filter;
- }
-
- if_range_time = ngx_parse_http_time(if_range->data, if_range->len);
-
- ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "http ir:%T lm:%T",
- if_range_time, r->headers_out.last_modified_time);
-
- if (if_range_time != r->headers_out.last_modified_time) {
- goto next_filter;
- }
- }
-
-parse:
-
- ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_range_filter_ctx_t));
- if (ctx == NULL) {
- return NGX_ERROR;
- }
-
- ctx->offset = r->headers_out.content_offset;
-
- ranges = r->single_range ? 1 : clcf->max_ranges;
-
- switch (ngx_http_range_parse(r, ctx, ranges)) {
-
- case NGX_OK:
- ngx_http_set_ctx(r, ctx, ngx_http_range_body_filter_module);
-
- r->headers_out.status = NGX_HTTP_PARTIAL_CONTENT;
- r->headers_out.status_line.len = 0;
-
- if (ctx->ranges.nelts == 1) {
- return ngx_http_range_singlepart_header(r, ctx);
- }
-
- return ngx_http_range_multipart_header(r, ctx);
-
- case NGX_HTTP_RANGE_NOT_SATISFIABLE:
- return ngx_http_range_not_satisfiable(r);
-
- case NGX_ERROR:
- return NGX_ERROR;
-
- default: /* NGX_DECLINED */
- break;
- }
-
-next_filter:
-
- r->headers_out.accept_ranges = ngx_list_push(&r->headers_out.headers);
- if (r->headers_out.accept_ranges == NULL) {
- return NGX_ERROR;
- }
-
- r->headers_out.accept_ranges->hash = 1;
- ngx_str_set(&r->headers_out.accept_ranges->key, "Accept-Ranges");
- ngx_str_set(&r->headers_out.accept_ranges->value, "bytes");
-
- return ngx_http_next_header_filter(r);
-}
-
-
-static ngx_int_t
-ngx_http_range_parse(ngx_http_request_t *r, ngx_http_range_filter_ctx_t *ctx,
- ngx_uint_t ranges)
-{
- u_char *p;
- off_t start, end, size, content_length, cutoff,
- cutlim;
- ngx_uint_t suffix;
- ngx_http_range_t *range;
- ngx_http_range_filter_ctx_t *mctx;
-
- if (r != r->main) {
- mctx = ngx_http_get_module_ctx(r->main,
- ngx_http_range_body_filter_module);
- if (mctx) {
- ctx->ranges = mctx->ranges;
- return NGX_OK;
- }
- }
-
- if (ngx_array_init(&ctx->ranges, r->pool, 1, sizeof(ngx_http_range_t))
- != NGX_OK)
- {
- return NGX_ERROR;
- }
-
- p = r->headers_in.range->value.data + 6;
- size = 0;
- content_length = r->headers_out.content_length_n;
-
- cutoff = NGX_MAX_OFF_T_VALUE / 10;
- cutlim = NGX_MAX_OFF_T_VALUE % 10;
-
- for ( ;; ) {
- start = 0;
- end = 0;
- suffix = 0;
-
- while (*p == ' ') { p++; }
-
- if (*p != '-') {
- if (*p < '0' || *p > '9') {
- return NGX_HTTP_RANGE_NOT_SATISFIABLE;
- }
-
- while (*p >= '0' && *p <= '9') {
- if (start >= cutoff && (start > cutoff || *p - '0' > cutlim)) {
- return NGX_HTTP_RANGE_NOT_SATISFIABLE;
- }
-
- start = start * 10 + (*p++ - '0');
- }
-
- while (*p == ' ') { p++; }
-
- if (*p++ != '-') {
- return NGX_HTTP_RANGE_NOT_SATISFIABLE;
- }
-
- while (*p == ' ') { p++; }
-
- if (*p == ',' || *p == '\0') {
- end = content_length;
- goto found;
- }
-
- } else {
- suffix = 1;
- p++;
- }
-
- if (*p < '0' || *p > '9') {
- return NGX_HTTP_RANGE_NOT_SATISFIABLE;
- }
-
- while (*p >= '0' && *p <= '9') {
- if (end >= cutoff && (end > cutoff || *p - '0' > cutlim)) {
- return NGX_HTTP_RANGE_NOT_SATISFIABLE;
- }
-
- end = end * 10 + (*p++ - '0');
- }
-
- while (*p == ' ') { p++; }
-
- if (*p != ',' && *p != '\0') {
- return NGX_HTTP_RANGE_NOT_SATISFIABLE;
- }
-
- if (suffix) {
- start = (end < content_length) ? content_length - end : 0;
- end = content_length - 1;
- }
-
- if (end >= content_length) {
- end = content_length;
-
- } else {
- end++;
- }
-
- found:
-
- if (start < end) {
- range = ngx_array_push(&ctx->ranges);
- if (range == NULL) {
- return NGX_ERROR;
- }
-
- range->start = start;
- range->end = end;
-
- if (size > NGX_MAX_OFF_T_VALUE - (end - start)) {
- return NGX_HTTP_RANGE_NOT_SATISFIABLE;
- }
-
- size += end - start;
-
- if (ranges-- == 0) {
- return NGX_DECLINED;
- }
-
- } else if (start == 0) {
- return NGX_DECLINED;
- }
-
- if (*p++ != ',') {
- break;
- }
- }
-
- if (ctx->ranges.nelts == 0) {
- return NGX_HTTP_RANGE_NOT_SATISFIABLE;
- }
-
- if (size > content_length) {
- return NGX_DECLINED;
- }
-
- return NGX_OK;
-}
-
-
-static ngx_int_t
-ngx_http_range_singlepart_header(ngx_http_request_t *r,
- ngx_http_range_filter_ctx_t *ctx)
-{
- ngx_table_elt_t *content_range;
- ngx_http_range_t *range;
-
- if (r != r->main) {
- return ngx_http_next_header_filter(r);
- }
-
- content_range = ngx_list_push(&r->headers_out.headers);
- if (content_range == NULL) {
- return NGX_ERROR;
- }
-
- r->headers_out.content_range = content_range;
-
- content_range->hash = 1;
- ngx_str_set(&content_range->key, "Content-Range");
-
- content_range->value.data = ngx_pnalloc(r->pool,
- sizeof("bytes -/") - 1 + 3 * NGX_OFF_T_LEN);
- if (content_range->value.data == NULL) {
- content_range->hash = 0;
- r->headers_out.content_range = NULL;
- return NGX_ERROR;
- }
-
- /* "Content-Range: bytes SSSS-EEEE/TTTT" header */
-
- range = ctx->ranges.elts;
-
- content_range->value.len = ngx_sprintf(content_range->value.data,
- "bytes %O-%O/%O",
- range->start, range->end - 1,
- r->headers_out.content_length_n)
- - content_range->value.data;
-
- r->headers_out.content_length_n = range->end - range->start;
- r->headers_out.content_offset = range->start;
-
- if (r->headers_out.content_length) {
- r->headers_out.content_length->hash = 0;
- r->headers_out.content_length = NULL;
- }
-
- return ngx_http_next_header_filter(r);
-}
-
-
-static ngx_int_t
-ngx_http_range_multipart_header(ngx_http_request_t *r,
- ngx_http_range_filter_ctx_t *ctx)
-{
- off_t len;
- size_t size;
- ngx_uint_t i;
- ngx_http_range_t *range;
- ngx_atomic_uint_t boundary;
-
- size = sizeof(CRLF "--") - 1 + NGX_ATOMIC_T_LEN
- + sizeof(CRLF "Content-Type: ") - 1
- + r->headers_out.content_type.len
- + sizeof(CRLF "Content-Range: bytes ") - 1;
-
- if (r->headers_out.content_type_len == r->headers_out.content_type.len
- && r->headers_out.charset.len)
- {
- size += sizeof("; charset=") - 1 + r->headers_out.charset.len;
- }
-
- ctx->boundary_header.data = ngx_pnalloc(r->pool, size);
- if (ctx->boundary_header.data == NULL) {
- return NGX_ERROR;
- }
-
- boundary = ngx_next_temp_number(0);
-
- /*
- * The boundary header of the range:
- * CRLF
- * "--0123456789" CRLF
- * "Content-Type: image/jpeg" CRLF
- * "Content-Range: bytes "
- */
-
- if (r->headers_out.content_type_len == r->headers_out.content_type.len
- && r->headers_out.charset.len)
- {
- ctx->boundary_header.len = ngx_sprintf(ctx->boundary_header.data,
- CRLF "--%0muA" CRLF
- "Content-Type: %V; charset=%V" CRLF
- "Content-Range: bytes ",
- boundary,
- &r->headers_out.content_type,
- &r->headers_out.charset)
- - ctx->boundary_header.data;
-
- } else if (r->headers_out.content_type.len) {
- ctx->boundary_header.len = ngx_sprintf(ctx->boundary_header.data,
- CRLF "--%0muA" CRLF
- "Content-Type: %V" CRLF
- "Content-Range: bytes ",
- boundary,
- &r->headers_out.content_type)
- - ctx->boundary_header.data;
-
- } else {
- ctx->boundary_header.len = ngx_sprintf(ctx->boundary_header.data,
- CRLF "--%0muA" CRLF
- "Content-Range: bytes ",
- boundary)
- - ctx->boundary_header.data;
- }
-
- r->headers_out.content_type.data =
- ngx_pnalloc(r->pool,
- sizeof("Content-Type: multipart/byteranges; boundary=") - 1
- + NGX_ATOMIC_T_LEN);
-
- if (r->headers_out.content_type.data == NULL) {
- return NGX_ERROR;
- }
-
- r->headers_out.content_type_lowcase = NULL;
-
- /* "Content-Type: multipart/byteranges; boundary=0123456789" */
-
- r->headers_out.content_type.len =
- ngx_sprintf(r->headers_out.content_type.data,
- "multipart/byteranges; boundary=%0muA",
- boundary)
- - r->headers_out.content_type.data;
-
- r->headers_out.content_type_len = r->headers_out.content_type.len;
-
- r->headers_out.charset.len = 0;
-
- /* the size of the last boundary CRLF "--0123456789--" CRLF */
-
- len = sizeof(CRLF "--") - 1 + NGX_ATOMIC_T_LEN + sizeof("--" CRLF) - 1;
-
- range = ctx->ranges.elts;
- for (i = 0; i < ctx->ranges.nelts; i++) {
-
- /* the size of the range: "SSSS-EEEE/TTTT" CRLF CRLF */
-
- range[i].content_range.data =
- ngx_pnalloc(r->pool, 3 * NGX_OFF_T_LEN + 2 + 4);
-
- if (range[i].content_range.data == NULL) {
- return NGX_ERROR;
- }
-
- range[i].content_range.len = ngx_sprintf(range[i].content_range.data,
- "%O-%O/%O" CRLF CRLF,
- range[i].start, range[i].end - 1,
- r->headers_out.content_length_n)
- - range[i].content_range.data;
-
- len += ctx->boundary_header.len + range[i].content_range.len
- + (range[i].end - range[i].start);
- }
-
- r->headers_out.content_length_n = len;
-
- if (r->headers_out.content_length) {
- r->headers_out.content_length->hash = 0;
- r->headers_out.content_length = NULL;
- }
-
- return ngx_http_next_header_filter(r);
-}
-
-
-static ngx_int_t
-ngx_http_range_not_satisfiable(ngx_http_request_t *r)
-{
- ngx_table_elt_t *content_range;
-
- r->headers_out.status = NGX_HTTP_RANGE_NOT_SATISFIABLE;
-
- content_range = ngx_list_push(&r->headers_out.headers);
- if (content_range == NULL) {
- return NGX_ERROR;
- }
-
- r->headers_out.content_range = content_range;
-
- content_range->hash = 1;
- ngx_str_set(&content_range->key, "Content-Range");
-
- content_range->value.data = ngx_pnalloc(r->pool,
- sizeof("bytes */") - 1 + NGX_OFF_T_LEN);
- if (content_range->value.data == NULL) {
- content_range->hash = 0;
- r->headers_out.content_range = NULL;
- return NGX_ERROR;
- }
-
- content_range->value.len = ngx_sprintf(content_range->value.data,
- "bytes */%O",
- r->headers_out.content_length_n)
- - content_range->value.data;
-
- ngx_http_clear_content_length(r);
-
- return NGX_HTTP_RANGE_NOT_SATISFIABLE;
-}
-
-
-static ngx_int_t
-ngx_http_range_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
-{
- ngx_http_range_filter_ctx_t *ctx;
-
- if (in == NULL) {
- return ngx_http_next_body_filter(r, in);
- }
-
- ctx = ngx_http_get_module_ctx(r, ngx_http_range_body_filter_module);
-
- if (ctx == NULL) {
- return ngx_http_next_body_filter(r, in);
- }
-
- if (ctx->ranges.nelts == 1) {
- return ngx_http_range_singlepart_body(r, ctx, in);
- }
-
- /*
- * multipart ranges are supported only if whole body is in a single buffer
- */
-
- if (ngx_buf_special(in->buf)) {
- return ngx_http_next_body_filter(r, in);
- }
-
- if (ngx_http_range_test_overlapped(r, ctx, in) != NGX_OK) {
- return NGX_ERROR;
- }
-
- return ngx_http_range_multipart_body(r, ctx, in);
-}
-
-
-static ngx_int_t
-ngx_http_range_test_overlapped(ngx_http_request_t *r,
- ngx_http_range_filter_ctx_t *ctx, ngx_chain_t *in)
-{
- off_t start, last;
- ngx_buf_t *buf;
- ngx_uint_t i;
- ngx_http_range_t *range;
-
- if (ctx->offset) {
- goto overlapped;
- }
-
- buf = in->buf;
-
- if (!buf->last_buf) {
- start = ctx->offset;
- last = ctx->offset + ngx_buf_size(buf);
-
- range = ctx->ranges.elts;
- for (i = 0; i < ctx->ranges.nelts; i++) {
- if (start > range[i].start || last < range[i].end) {
- goto overlapped;
- }
- }
- }
-
- ctx->offset = ngx_buf_size(buf);
-
- return NGX_OK;
-
-overlapped:
-
- ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
- "range in overlapped buffers");
-
- return NGX_ERROR;
-}
-
-
-static ngx_int_t
-ngx_http_range_singlepart_body(ngx_http_request_t *r,
- ngx_http_range_filter_ctx_t *ctx, ngx_chain_t *in)
-{
- off_t start, last;
- ngx_buf_t *buf;
- ngx_chain_t *out, *cl, **ll;
- ngx_http_range_t *range;
-
- out = NULL;
- ll = &out;
- range = ctx->ranges.elts;
-
- for (cl = in; cl; cl = cl->next) {
-
- buf = cl->buf;
-
- start = ctx->offset;
- last = ctx->offset + ngx_buf_size(buf);
-
- ctx->offset = last;
-
- ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "http range body buf: %O-%O", start, last);
-
- if (ngx_buf_special(buf)) {
- *ll = cl;
- ll = &cl->next;
- continue;
- }
-
- if (range->end <= start || range->start >= last) {
-
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "http range body skip");
-
- if (buf->in_file) {
- buf->file_pos = buf->file_last;
- }
-
- buf->pos = buf->last;
- buf->sync = 1;
-
- continue;
- }
-
- if (range->start > start) {
-
- if (buf->in_file) {
- buf->file_pos += range->start - start;
- }
-
- if (ngx_buf_in_memory(buf)) {
- buf->pos += (size_t) (range->start - start);
- }
- }
-
- if (range->end <= last) {
-
- if (buf->in_file) {
- buf->file_last -= last - range->end;
- }
-
- if (ngx_buf_in_memory(buf)) {
- buf->last -= (size_t) (last - range->end);
- }
-
- buf->last_buf = (r == r->main) ? 1 : 0;
- buf->last_in_chain = 1;
- *ll = cl;
- cl->next = NULL;
-
- break;
- }
-
- *ll = cl;
- ll = &cl->next;
- }
-
- if (out == NULL) {
- return NGX_OK;
- }
-
- return ngx_http_next_body_filter(r, out);
-}
-
-
-static ngx_int_t
-ngx_http_range_multipart_body(ngx_http_request_t *r,
- ngx_http_range_filter_ctx_t *ctx, ngx_chain_t *in)
-{
- ngx_buf_t *b, *buf;
- ngx_uint_t i;
- ngx_chain_t *out, *hcl, *rcl, *dcl, **ll;
- ngx_http_range_t *range;
-
- ll = &out;
- buf = in->buf;
- range = ctx->ranges.elts;
-
- for (i = 0; i < ctx->ranges.nelts; i++) {
-
- /*
- * The boundary header of the range:
- * CRLF
- * "--0123456789" CRLF
- * "Content-Type: image/jpeg" CRLF
- * "Content-Range: bytes "
- */
-
- b = ngx_calloc_buf(r->pool);
- if (b == NULL) {
- return NGX_ERROR;
- }
-
- b->memory = 1;
- b->pos = ctx->boundary_header.data;
- b->last = ctx->boundary_header.data + ctx->boundary_header.len;
-
- hcl = ngx_alloc_chain_link(r->pool);
- if (hcl == NULL) {
- return NGX_ERROR;
- }
-
- hcl->buf = b;
-
-
- /* "SSSS-EEEE/TTTT" CRLF CRLF */
-
- b = ngx_calloc_buf(r->pool);
- if (b == NULL) {
- return NGX_ERROR;
- }
-
- b->temporary = 1;
- b->pos = range[i].content_range.data;
- b->last = range[i].content_range.data + range[i].content_range.len;
-
- rcl = ngx_alloc_chain_link(r->pool);
- if (rcl == NULL) {
- return NGX_ERROR;
- }
-
- rcl->buf = b;
-
-
- /* the range data */
-
- b = ngx_calloc_buf(r->pool);
- if (b == NULL) {
- return NGX_ERROR;
- }
-
- b->in_file = buf->in_file;
- b->temporary = buf->temporary;
- b->memory = buf->memory;
- b->mmap = buf->mmap;
- b->file = buf->file;
-
- if (buf->in_file) {
- b->file_pos = buf->file_pos + range[i].start;
- b->file_last = buf->file_pos + range[i].end;
- }
-
- if (ngx_buf_in_memory(buf)) {
- b->pos = buf->pos + (size_t) range[i].start;
- b->last = buf->pos + (size_t) range[i].end;
- }
-
- dcl = ngx_alloc_chain_link(r->pool);
- if (dcl == NULL) {
- return NGX_ERROR;
- }
-
- dcl->buf = b;
-
- *ll = hcl;
- hcl->next = rcl;
- rcl->next = dcl;
- ll = &dcl->next;
- }
-
- /* the last boundary CRLF "--0123456789--" CRLF */
-
- b = ngx_calloc_buf(r->pool);
- if (b == NULL) {
- return NGX_ERROR;
- }
-
- b->temporary = 1;
- b->last_buf = 1;
-
- b->pos = ngx_pnalloc(r->pool, sizeof(CRLF "--") - 1 + NGX_ATOMIC_T_LEN
- + sizeof("--" CRLF) - 1);
- if (b->pos == NULL) {
- return NGX_ERROR;
- }
-
- b->last = ngx_cpymem(b->pos, ctx->boundary_header.data,
- sizeof(CRLF "--") - 1 + NGX_ATOMIC_T_LEN);
- *b->last++ = '-'; *b->last++ = '-';
- *b->last++ = CR; *b->last++ = LF;
-
- hcl = ngx_alloc_chain_link(r->pool);
- if (hcl == NULL) {
- return NGX_ERROR;
- }
-
- hcl->buf = b;
- hcl->next = NULL;
-
- *ll = hcl;
-
- return ngx_http_next_body_filter(r, out);
-}
-
-
-static ngx_int_t
-ngx_http_range_header_filter_init(ngx_conf_t *cf)
-{
- ngx_http_next_header_filter = ngx_http_top_header_filter;
- ngx_http_top_header_filter = ngx_http_range_header_filter;
-
- return NGX_OK;
-}
-
-
-static ngx_int_t
-ngx_http_range_body_filter_init(ngx_conf_t *cf)
-{
- ngx_http_next_body_filter = ngx_http_top_body_filter;
- ngx_http_top_body_filter = ngx_http_range_body_filter;
-
- return NGX_OK;
-}
diff --git a/nginx/src/http/modules/ngx_http_realip_module.c b/nginx/src/http/modules/ngx_http_realip_module.c
deleted file mode 100644
index 7d3f2a9..0000000
--- a/nginx/src/http/modules/ngx_http_realip_module.c
+++ /dev/null
@@ -1,623 +0,0 @@
-
-/*
- * Copyright (C) Igor Sysoev
- * Copyright (C) Nginx, Inc.
- */
-
-
-#include <ngx_config.h>
-#include <ngx_core.h>
-#include <ngx_http.h>
-
-
-#define NGX_HTTP_REALIP_XREALIP 0
-#define NGX_HTTP_REALIP_XFWD 1
-#define NGX_HTTP_REALIP_HEADER 2
-#define NGX_HTTP_REALIP_PROXY 3
-
-
-typedef struct {
- ngx_array_t *from; /* array of ngx_cidr_t */
- ngx_uint_t type;
- ngx_uint_t hash;
- ngx_str_t header;
- ngx_flag_t recursive;
-} ngx_http_realip_loc_conf_t;
-
-
-typedef struct {
- ngx_connection_t *connection;
- struct sockaddr *sockaddr;
- socklen_t socklen;
- ngx_str_t addr_text;
-} ngx_http_realip_ctx_t;
-
-
-static ngx_int_t ngx_http_realip_handler(ngx_http_request_t *r);
-static ngx_int_t ngx_http_realip_set_addr(ngx_http_request_t *r,
- ngx_addr_t *addr);
-static void ngx_http_realip_cleanup(void *data);
-static char *ngx_http_realip_from(ngx_conf_t *cf, ngx_command_t *cmd,
- void *conf);
-static char *ngx_http_realip(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
-static void *ngx_http_realip_create_loc_conf(ngx_conf_t *cf);
-static char *ngx_http_realip_merge_loc_conf(ngx_conf_t *cf,
- void *parent, void *child);
-static ngx_int_t ngx_http_realip_add_variables(ngx_conf_t *cf);
-static ngx_int_t ngx_http_realip_init(ngx_conf_t *cf);
-static ngx_http_realip_ctx_t *ngx_http_realip_get_module_ctx(
- ngx_http_request_t *r);
-
-
-static ngx_int_t ngx_http_realip_remote_addr_variable(ngx_http_request_t *r,
- ngx_http_variable_value_t *v, uintptr_t data);
-static ngx_int_t ngx_http_realip_remote_port_variable(ngx_http_request_t *r,
- ngx_http_variable_value_t *v, uintptr_t data);
-
-
-static ngx_command_t ngx_http_realip_commands[] = {
-
- { ngx_string("set_real_ip_from"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_http_realip_from,
- NGX_HTTP_LOC_CONF_OFFSET,
- 0,
- NULL },
-
- { ngx_string("real_ip_header"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_http_realip,
- NGX_HTTP_LOC_CONF_OFFSET,
- 0,
- NULL },
-
- { ngx_string("real_ip_recursive"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
- ngx_conf_set_flag_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_realip_loc_conf_t, recursive),
- NULL },
-
- ngx_null_command
-};
-
-
-
-static ngx_http_module_t ngx_http_realip_module_ctx = {
- ngx_http_realip_add_variables, /* preconfiguration */
- ngx_http_realip_init, /* postconfiguration */
-
- NULL, /* create main configuration */
- NULL, /* init main configuration */
-
- NULL, /* create server configuration */
- NULL, /* merge server configuration */
-
- ngx_http_realip_create_loc_conf, /* create location configuration */
- ngx_http_realip_merge_loc_conf /* merge location configuration */
-};
-
-
-ngx_module_t ngx_http_realip_module = {
- NGX_MODULE_V1,
- &ngx_http_realip_module_ctx, /* module context */
- ngx_http_realip_commands, /* module directives */
- NGX_HTTP_MODULE, /* module type */
- NULL, /* init master */
- NULL, /* init module */
- NULL, /* init process */
- NULL, /* init thread */
- NULL, /* exit thread */
- NULL, /* exit process */
- NULL, /* exit master */
- NGX_MODULE_V1_PADDING
-};
-
-
-static ngx_http_variable_t ngx_http_realip_vars[] = {
-
- { ngx_string("realip_remote_addr"), NULL,
- ngx_http_realip_remote_addr_variable, 0, 0, 0 },
-
- { ngx_string("realip_remote_port"), NULL,
- ngx_http_realip_remote_port_variable, 0, 0, 0 },
-
- ngx_http_null_variable
-};
-
-
-static ngx_int_t
-ngx_http_realip_handler(ngx_http_request_t *r)
-{
- u_char *p;
- size_t len;
- ngx_str_t *value;
- ngx_uint_t i, hash;
- ngx_addr_t addr;
- ngx_array_t *xfwd;
- ngx_list_part_t *part;
- ngx_table_elt_t *header;
- ngx_connection_t *c;
- ngx_http_realip_ctx_t *ctx;
- ngx_http_realip_loc_conf_t *rlcf;
-
- rlcf = ngx_http_get_module_loc_conf(r, ngx_http_realip_module);
-
- if (rlcf->from == NULL) {
- return NGX_DECLINED;
- }
-
- ctx = ngx_http_realip_get_module_ctx(r);
-
- if (ctx) {
- return NGX_DECLINED;
- }
-
- switch (rlcf->type) {
-
- case NGX_HTTP_REALIP_XREALIP:
-
- if (r->headers_in.x_real_ip == NULL) {
- return NGX_DECLINED;
- }
-
- value = &r->headers_in.x_real_ip->value;
- xfwd = NULL;
-
- break;
-
- case NGX_HTTP_REALIP_XFWD:
-
- xfwd = &r->headers_in.x_forwarded_for;
-
- if (xfwd->elts == NULL) {
- return NGX_DECLINED;
- }
-
- value = NULL;
-
- break;
-
- case NGX_HTTP_REALIP_PROXY:
-
- value = &r->connection->proxy_protocol_addr;
-
- if (value->len == 0) {
- return NGX_DECLINED;
- }
-
- xfwd = NULL;
-
- break;
-
- default: /* NGX_HTTP_REALIP_HEADER */
-
- part = &r->headers_in.headers.part;
- header = part->elts;
-
- hash = rlcf->hash;
- len = rlcf->header.len;
- p = rlcf->header.data;
-
- for (i = 0; /* void */ ; i++) {
-
- if (i >= part->nelts) {
- if (part->next == NULL) {
- break;
- }
-
- part = part->next;
- header = part->elts;
- i = 0;
- }
-
- if (hash == header[i].hash
- && len == header[i].key.len
- && ngx_strncmp(p, header[i].lowcase_key, len) == 0)
- {
- value = &header[i].value;
- xfwd = NULL;
-
- goto found;
- }
- }
-
- return NGX_DECLINED;
- }
-
-found:
-
- c = r->connection;
-
- addr.sockaddr = c->sockaddr;
- addr.socklen = c->socklen;
- /* addr.name = c->addr_text; */
-
- if (ngx_http_get_forwarded_addr(r, &addr, xfwd, value, rlcf->from,
- rlcf->recursive)
- != NGX_DECLINED)
- {
- if (rlcf->type == NGX_HTTP_REALIP_PROXY) {
- ngx_inet_set_port(addr.sockaddr, c->proxy_protocol_port);
- }
-
- return ngx_http_realip_set_addr(r, &addr);
- }
-
- return NGX_DECLINED;
-}
-
-
-static ngx_int_t
-ngx_http_realip_set_addr(ngx_http_request_t *r, ngx_addr_t *addr)
-{
- size_t len;
- u_char *p;
- u_char text[NGX_SOCKADDR_STRLEN];
- ngx_connection_t *c;
- ngx_pool_cleanup_t *cln;
- ngx_http_realip_ctx_t *ctx;
-
- cln = ngx_pool_cleanup_add(r->pool, sizeof(ngx_http_realip_ctx_t));
- if (cln == NULL) {
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
-
- ctx = cln->data;
-
- c = r->connection;
-
- len = ngx_sock_ntop(addr->sockaddr, addr->socklen, text,
- NGX_SOCKADDR_STRLEN, 0);
- if (len == 0) {
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
-
- p = ngx_pnalloc(c->pool, len);
- if (p == NULL) {
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
-
- ngx_memcpy(p, text, len);
-
- cln->handler = ngx_http_realip_cleanup;
- ngx_http_set_ctx(r, ctx, ngx_http_realip_module);
-
- ctx->connection = c;
- ctx->sockaddr = c->sockaddr;
- ctx->socklen = c->socklen;
- ctx->addr_text = c->addr_text;
-
- c->sockaddr = addr->sockaddr;
- c->socklen = addr->socklen;
- c->addr_text.len = len;
- c->addr_text.data = p;
-
- return NGX_DECLINED;
-}
-
-
-static void
-ngx_http_realip_cleanup(void *data)
-{
- ngx_http_realip_ctx_t *ctx = data;
-
- ngx_connection_t *c;
-
- c = ctx->connection;
-
- c->sockaddr = ctx->sockaddr;
- c->socklen = ctx->socklen;
- c->addr_text = ctx->addr_text;
-}
-
-
-static char *
-ngx_http_realip_from(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
-{
- ngx_http_realip_loc_conf_t *rlcf = conf;
-
- ngx_int_t rc;
- ngx_str_t *value;
- ngx_url_t u;
- ngx_cidr_t c, *cidr;
- ngx_uint_t i;
- struct sockaddr_in *sin;
-#if (NGX_HAVE_INET6)
- struct sockaddr_in6 *sin6;
-#endif
-
- value = cf->args->elts;
-
- if (rlcf->from == NULL) {
- rlcf->from = ngx_array_create(cf->pool, 2,
- sizeof(ngx_cidr_t));
- if (rlcf->from == NULL) {
- return NGX_CONF_ERROR;
- }
- }
-
-#if (NGX_HAVE_UNIX_DOMAIN)
-
- if (ngx_strcmp(value[1].data, "unix:") == 0) {
- cidr = ngx_array_push(rlcf->from);
- if (cidr == NULL) {
- return NGX_CONF_ERROR;
- }
-
- cidr->family = AF_UNIX;
- return NGX_CONF_OK;
- }
-
-#endif
-
- rc = ngx_ptocidr(&value[1], &c);
-
- if (rc != NGX_ERROR) {
- if (rc == NGX_DONE) {
- ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
- "low address bits of %V are meaningless",
- &value[1]);
- }
-
- cidr = ngx_array_push(rlcf->from);
- if (cidr == NULL) {
- return NGX_CONF_ERROR;
- }
-
- *cidr = c;
-
- return NGX_CONF_OK;
- }
-
- ngx_memzero(&u, sizeof(ngx_url_t));
- u.host = value[1];
-
- if (ngx_inet_resolve_host(cf->pool, &u) != NGX_OK) {
- if (u.err) {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "%s in set_real_ip_from \"%V\"",
- u.err, &u.host);
- }
-
- return NGX_CONF_ERROR;
- }
-
- cidr = ngx_array_push_n(rlcf->from, u.naddrs);
- if (cidr == NULL) {
- return NGX_CONF_ERROR;
- }
-
- ngx_memzero(cidr, u.naddrs * sizeof(ngx_cidr_t));
-
- for (i = 0; i < u.naddrs; i++) {
- cidr[i].family = u.addrs[i].sockaddr->sa_family;
-
- switch (cidr[i].family) {
-
-#if (NGX_HAVE_INET6)
- case AF_INET6:
- sin6 = (struct sockaddr_in6 *) u.addrs[i].sockaddr;
- cidr[i].u.in6.addr = sin6->sin6_addr;
- ngx_memset(cidr[i].u.in6.mask.s6_addr, 0xff, 16);
- break;
-#endif
-
- default: /* AF_INET */
- sin = (struct sockaddr_in *) u.addrs[i].sockaddr;
- cidr[i].u.in.addr = sin->sin_addr.s_addr;
- cidr[i].u.in.mask = 0xffffffff;
- break;
- }
- }
-
- return NGX_CONF_OK;
-}
-
-
-static char *
-ngx_http_realip(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
-{
- ngx_http_realip_loc_conf_t *rlcf = conf;
-
- ngx_str_t *value;
-
- if (rlcf->type != NGX_CONF_UNSET_UINT) {
- return "is duplicate";
- }
-
- value = cf->args->elts;
-
- if (ngx_strcmp(value[1].data, "X-Real-IP") == 0) {
- rlcf->type = NGX_HTTP_REALIP_XREALIP;
- return NGX_CONF_OK;
- }
-
- if (ngx_strcmp(value[1].data, "X-Forwarded-For") == 0) {
- rlcf->type = NGX_HTTP_REALIP_XFWD;
- return NGX_CONF_OK;
- }
-
- if (ngx_strcmp(value[1].data, "proxy_protocol") == 0) {
- rlcf->type = NGX_HTTP_REALIP_PROXY;
- return NGX_CONF_OK;
- }
-
- rlcf->type = NGX_HTTP_REALIP_HEADER;
- rlcf->hash = ngx_hash_strlow(value[1].data, value[1].data, value[1].len);
- rlcf->header = value[1];
-
- return NGX_CONF_OK;
-}
-
-
-static void *
-ngx_http_realip_create_loc_conf(ngx_conf_t *cf)
-{
- ngx_http_realip_loc_conf_t *conf;
-
- conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_realip_loc_conf_t));
- if (conf == NULL) {
- return NULL;
- }
-
- /*
- * set by ngx_pcalloc():
- *
- * conf->from = NULL;
- * conf->hash = 0;
- * conf->header = { 0, NULL };
- */
-
- conf->type = NGX_CONF_UNSET_UINT;
- conf->recursive = NGX_CONF_UNSET;
-
- return conf;
-}
-
-
-static char *
-ngx_http_realip_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
-{
- ngx_http_realip_loc_conf_t *prev = parent;
- ngx_http_realip_loc_conf_t *conf = child;
-
- if (conf->from == NULL) {
- conf->from = prev->from;
- }
-
- ngx_conf_merge_uint_value(conf->type, prev->type, NGX_HTTP_REALIP_XREALIP);
- ngx_conf_merge_value(conf->recursive, prev->recursive, 0);
-
- if (conf->header.len == 0) {
- conf->hash = prev->hash;
- conf->header = prev->header;
- }
-
- return NGX_CONF_OK;
-}
-
-
-static ngx_int_t
-ngx_http_realip_add_variables(ngx_conf_t *cf)
-{
- ngx_http_variable_t *var, *v;
-
- for (v = ngx_http_realip_vars; v->name.len; v++) {
- var = ngx_http_add_variable(cf, &v->name, v->flags);
- if (var == NULL) {
- return NGX_ERROR;
- }
-
- var->get_handler = v->get_handler;
- var->data = v->data;
- }
-
- return NGX_OK;
-}
-
-
-static ngx_int_t
-ngx_http_realip_init(ngx_conf_t *cf)
-{
- ngx_http_handler_pt *h;
- ngx_http_core_main_conf_t *cmcf;
-
- cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);
-
- h = ngx_array_push(&cmcf->phases[NGX_HTTP_POST_READ_PHASE].handlers);
- if (h == NULL) {
- return NGX_ERROR;
- }
-
- *h = ngx_http_realip_handler;
-
- h = ngx_array_push(&cmcf->phases[NGX_HTTP_PREACCESS_PHASE].handlers);
- if (h == NULL) {
- return NGX_ERROR;
- }
-
- *h = ngx_http_realip_handler;
-
- return NGX_OK;
-}
-
-
-static ngx_http_realip_ctx_t *
-ngx_http_realip_get_module_ctx(ngx_http_request_t *r)
-{
- ngx_pool_cleanup_t *cln;
- ngx_http_realip_ctx_t *ctx;
-
- ctx = ngx_http_get_module_ctx(r, ngx_http_realip_module);
-
- if (ctx == NULL && (r->internal || r->filter_finalize)) {
-
- /*
- * if module context was reset, the original address
- * can still be found in the cleanup handler
- */
-
- for (cln = r->pool->cleanup; cln; cln = cln->next) {
- if (cln->handler == ngx_http_realip_cleanup) {
- ctx = cln->data;
- break;
- }
- }
- }
-
- return ctx;
-}
-
-
-static ngx_int_t
-ngx_http_realip_remote_addr_variable(ngx_http_request_t *r,
- ngx_http_variable_value_t *v, uintptr_t data)
-{
- ngx_str_t *addr_text;
- ngx_http_realip_ctx_t *ctx;
-
- ctx = ngx_http_realip_get_module_ctx(r);
-
- addr_text = ctx ? &ctx->addr_text : &r->connection->addr_text;
-
- v->len = addr_text->len;
- v->valid = 1;
- v->no_cacheable = 0;
- v->not_found = 0;
- v->data = addr_text->data;
-
- return NGX_OK;
-}
-
-
-static ngx_int_t
-ngx_http_realip_remote_port_variable(ngx_http_request_t *r,
- ngx_http_variable_value_t *v, uintptr_t data)
-{
- ngx_uint_t port;
- struct sockaddr *sa;
- ngx_http_realip_ctx_t *ctx;
-
- ctx = ngx_http_realip_get_module_ctx(r);
-
- sa = ctx ? ctx->sockaddr : r->connection->sockaddr;
-
- v->len = 0;
- v->valid = 1;
- v->no_cacheable = 0;
- v->not_found = 0;
-
- v->data = ngx_pnalloc(r->pool, sizeof("65535") - 1);
- if (v->data == NULL) {
- return NGX_ERROR;
- }
-
- port = ngx_inet_get_port(sa);
-
- if (port > 0 && port < 65536) {
- v->len = ngx_sprintf(v->data, "%ui", port) - v->data;
- }
-
- return NGX_OK;
-}
diff --git a/nginx/src/http/modules/ngx_http_referer_module.c b/nginx/src/http/modules/ngx_http_referer_module.c
deleted file mode 100644
index 599dd3a..0000000
--- a/nginx/src/http/modules/ngx_http_referer_module.c
+++ /dev/null
@@ -1,682 +0,0 @@
-
-/*
- * Copyright (C) Igor Sysoev
- * Copyright (C) Nginx, Inc.
- */
-
-
-#include <ngx_config.h>
-#include <ngx_core.h>
-#include <ngx_http.h>
-
-
-#define NGX_HTTP_REFERER_NO_URI_PART ((void *) 4)
-
-
-typedef struct {
- ngx_hash_combined_t hash;
-
-#if (NGX_PCRE)
- ngx_array_t *regex;
- ngx_array_t *server_name_regex;
-#endif
-
- ngx_flag_t no_referer;
- ngx_flag_t blocked_referer;
- ngx_flag_t server_names;
-
- ngx_hash_keys_arrays_t *keys;
-
- ngx_uint_t referer_hash_max_size;
- ngx_uint_t referer_hash_bucket_size;
-} ngx_http_referer_conf_t;
-
-
-static ngx_int_t ngx_http_referer_add_variables(ngx_conf_t *cf);
-static void * ngx_http_referer_create_conf(ngx_conf_t *cf);
-static char * ngx_http_referer_merge_conf(ngx_conf_t *cf, void *parent,
- void *child);
-static char *ngx_http_valid_referers(ngx_conf_t *cf, ngx_command_t *cmd,
- void *conf);
-static ngx_int_t ngx_http_add_referer(ngx_conf_t *cf,
- ngx_hash_keys_arrays_t *keys, ngx_str_t *value, ngx_str_t *uri);
-static ngx_int_t ngx_http_add_regex_referer(ngx_conf_t *cf,
- ngx_http_referer_conf_t *rlcf, ngx_str_t *name);
-#if (NGX_PCRE)
-static ngx_int_t ngx_http_add_regex_server_name(ngx_conf_t *cf,
- ngx_http_referer_conf_t *rlcf, ngx_http_regex_t *regex);
-#endif
-static int ngx_libc_cdecl ngx_http_cmp_referer_wildcards(const void *one,
- const void *two);
-
-
-static ngx_command_t ngx_http_referer_commands[] = {
-
- { ngx_string("valid_referers"),
- NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
- ngx_http_valid_referers,
- NGX_HTTP_LOC_CONF_OFFSET,
- 0,
- NULL },
-
- { ngx_string("referer_hash_max_size"),
- NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_num_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_referer_conf_t, referer_hash_max_size),
- NULL },
-
- { ngx_string("referer_hash_bucket_size"),
- NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_num_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_referer_conf_t, referer_hash_bucket_size),
- NULL },
-
- ngx_null_command
-};
-
-
-static ngx_http_module_t ngx_http_referer_module_ctx = {
- ngx_http_referer_add_variables, /* preconfiguration */
- NULL, /* postconfiguration */
-
- NULL, /* create main configuration */
- NULL, /* init main configuration */
-
- NULL, /* create server configuration */
- NULL, /* merge server configuration */
-
- ngx_http_referer_create_conf, /* create location configuration */
- ngx_http_referer_merge_conf /* merge location configuration */
-};
-
-
-ngx_module_t ngx_http_referer_module = {
- NGX_MODULE_V1,
- &ngx_http_referer_module_ctx, /* module context */
- ngx_http_referer_commands, /* module directives */
- NGX_HTTP_MODULE, /* module type */
- NULL, /* init master */
- NULL, /* init module */
- NULL, /* init process */
- NULL, /* init thread */
- NULL, /* exit thread */
- NULL, /* exit process */
- NULL, /* exit master */
- NGX_MODULE_V1_PADDING
-};
-
-
-static ngx_str_t ngx_http_invalid_referer_name = ngx_string("invalid_referer");
-
-
-static ngx_int_t
-ngx_http_referer_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v,
- uintptr_t data)
-{
- u_char *p, *ref, *last;
- size_t len;
- ngx_str_t *uri;
- ngx_uint_t i, key;
- ngx_http_referer_conf_t *rlcf;
- u_char buf[256];
-#if (NGX_PCRE)
- ngx_int_t rc;
- ngx_str_t referer;
-#endif
-
- rlcf = ngx_http_get_module_loc_conf(r, ngx_http_referer_module);
-
- if (rlcf->hash.hash.buckets == NULL
- && rlcf->hash.wc_head == NULL
- && rlcf->hash.wc_tail == NULL
-#if (NGX_PCRE)
- && rlcf->regex == NULL
- && rlcf->server_name_regex == NULL
-#endif
- )
- {
- goto valid;
- }
-
- if (r->headers_in.referer == NULL) {
- if (rlcf->no_referer) {
- goto valid;
- }
-
- goto invalid;
- }
-
- len = r->headers_in.referer->value.len;
- ref = r->headers_in.referer->value.data;
-
- if (len >= sizeof("http://i.ru") - 1) {
- last = ref + len;
-
- if (ngx_strncasecmp(ref, (u_char *) "http://", 7) == 0) {
- ref += 7;
- len -= 7;
- goto valid_scheme;
-
- } else if (ngx_strncasecmp(ref, (u_char *) "https://", 8) == 0) {
- ref += 8;
- len -= 8;
- goto valid_scheme;
- }
- }
-
- if (rlcf->blocked_referer) {
- goto valid;
- }
-
- goto invalid;
-
-valid_scheme:
-
- i = 0;
- key = 0;
-
- for (p = ref; p < last; p++) {
- if (*p == '/' || *p == ':') {
- break;
- }
-
- if (i == 256) {
- goto invalid;
- }
-
- buf[i] = ngx_tolower(*p);
- key = ngx_hash(key, buf[i++]);
- }
-
- uri = ngx_hash_find_combined(&rlcf->hash, key, buf, p - ref);
-
- if (uri) {
- goto uri;
- }
-
-#if (NGX_PCRE)
-
- if (rlcf->server_name_regex) {
- referer.len = p - ref;
- referer.data = buf;
-
- rc = ngx_regex_exec_array(rlcf->server_name_regex, &referer,
- r->connection->log);
-
- if (rc == NGX_OK) {
- goto valid;
- }
-
- if (rc == NGX_ERROR) {
- return rc;
- }
-
- /* NGX_DECLINED */
- }
-
- if (rlcf->regex) {
- referer.len = len;
- referer.data = ref;
-
- rc = ngx_regex_exec_array(rlcf->regex, &referer, r->connection->log);
-
- if (rc == NGX_OK) {
- goto valid;
- }
-
- if (rc == NGX_ERROR) {
- return rc;
- }
-
- /* NGX_DECLINED */
- }
-
-#endif
-
-invalid:
-
- *v = ngx_http_variable_true_value;
-
- return NGX_OK;
-
-uri:
-
- for ( /* void */ ; p < last; p++) {
- if (*p == '/') {
- break;
- }
- }
-
- len = last - p;
-
- if (uri == NGX_HTTP_REFERER_NO_URI_PART) {
- goto valid;
- }
-
- if (len < uri->len || ngx_strncmp(uri->data, p, uri->len) != 0) {
- goto invalid;
- }
-
-valid:
-
- *v = ngx_http_variable_null_value;
-
- return NGX_OK;
-}
-
-
-static ngx_int_t
-ngx_http_referer_add_variables(ngx_conf_t *cf)
-{
- ngx_http_variable_t *var;
-
- var = ngx_http_add_variable(cf, &ngx_http_invalid_referer_name,
- NGX_HTTP_VAR_CHANGEABLE);
- if (var == NULL) {
- return NGX_ERROR;
- }
-
- var->get_handler = ngx_http_referer_variable;
-
- return NGX_OK;
-}
-
-
-static void *
-ngx_http_referer_create_conf(ngx_conf_t *cf)
-{
- ngx_http_referer_conf_t *conf;
-
- conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_referer_conf_t));
- if (conf == NULL) {
- return NULL;
- }
-
- /*
- * set by ngx_pcalloc():
- *
- * conf->hash = { NULL };
- * conf->server_names = 0;
- * conf->keys = NULL;
- */
-
-#if (NGX_PCRE)
- conf->regex = NGX_CONF_UNSET_PTR;
- conf->server_name_regex = NGX_CONF_UNSET_PTR;
-#endif
-
- conf->no_referer = NGX_CONF_UNSET;
- conf->blocked_referer = NGX_CONF_UNSET;
- conf->referer_hash_max_size = NGX_CONF_UNSET_UINT;
- conf->referer_hash_bucket_size = NGX_CONF_UNSET_UINT;
-
- return conf;
-}
-
-
-static char *
-ngx_http_referer_merge_conf(ngx_conf_t *cf, void *parent, void *child)
-{
- ngx_http_referer_conf_t *prev = parent;
- ngx_http_referer_conf_t *conf = child;
-
- ngx_uint_t n;
- ngx_hash_init_t hash;
- ngx_http_server_name_t *sn;
- ngx_http_core_srv_conf_t *cscf;
-
- if (conf->keys == NULL) {
- conf->hash = prev->hash;
-
-#if (NGX_PCRE)
- ngx_conf_merge_ptr_value(conf->regex, prev->regex, NULL);
- ngx_conf_merge_ptr_value(conf->server_name_regex,
- prev->server_name_regex, NULL);
-#endif
- ngx_conf_merge_value(conf->no_referer, prev->no_referer, 0);
- ngx_conf_merge_value(conf->blocked_referer, prev->blocked_referer, 0);
- ngx_conf_merge_uint_value(conf->referer_hash_max_size,
- prev->referer_hash_max_size, 2048);
- ngx_conf_merge_uint_value(conf->referer_hash_bucket_size,
- prev->referer_hash_bucket_size, 64);
-
- return NGX_CONF_OK;
- }
-
- if (conf->server_names == 1) {
- cscf = ngx_http_conf_get_module_srv_conf(cf, ngx_http_core_module);
-
- sn = cscf->server_names.elts;
- for (n = 0; n < cscf->server_names.nelts; n++) {
-
-#if (NGX_PCRE)
- if (sn[n].regex) {
-
- if (ngx_http_add_regex_server_name(cf, conf, sn[n].regex)
- != NGX_OK)
- {
- return NGX_CONF_ERROR;
- }
-
- continue;
- }
-#endif
-
- if (ngx_http_add_referer(cf, conf->keys, &sn[n].name, NULL)
- != NGX_OK)
- {
- return NGX_CONF_ERROR;
- }
- }
- }
-
- if ((conf->no_referer == 1 || conf->blocked_referer == 1)
- && conf->keys->keys.nelts == 0
- && conf->keys->dns_wc_head.nelts == 0
- && conf->keys->dns_wc_tail.nelts == 0)
- {
- ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
- "the \"none\" or \"blocked\" referers are specified "
- "in the \"valid_referers\" directive "
- "without any valid referer");
- return NGX_CONF_ERROR;
- }
-
- ngx_conf_merge_uint_value(conf->referer_hash_max_size,
- prev->referer_hash_max_size, 2048);
- ngx_conf_merge_uint_value(conf->referer_hash_bucket_size,
- prev->referer_hash_bucket_size, 64);
- conf->referer_hash_bucket_size = ngx_align(conf->referer_hash_bucket_size,
- ngx_cacheline_size);
-
- hash.key = ngx_hash_key_lc;
- hash.max_size = conf->referer_hash_max_size;
- hash.bucket_size = conf->referer_hash_bucket_size;
- hash.name = "referer_hash";
- hash.pool = cf->pool;
-
- if (conf->keys->keys.nelts) {
- hash.hash = &conf->hash.hash;
- hash.temp_pool = NULL;
-
- if (ngx_hash_init(&hash, conf->keys->keys.elts, conf->keys->keys.nelts)
- != NGX_OK)
- {
- return NGX_CONF_ERROR;
- }
- }
-
- if (conf->keys->dns_wc_head.nelts) {
-
- ngx_qsort(conf->keys->dns_wc_head.elts,
- (size_t) conf->keys->dns_wc_head.nelts,
- sizeof(ngx_hash_key_t),
- ngx_http_cmp_referer_wildcards);
-
- hash.hash = NULL;
- hash.temp_pool = cf->temp_pool;
-
- if (ngx_hash_wildcard_init(&hash, conf->keys->dns_wc_head.elts,
- conf->keys->dns_wc_head.nelts)
- != NGX_OK)
- {
- return NGX_CONF_ERROR;
- }
-
- conf->hash.wc_head = (ngx_hash_wildcard_t *) hash.hash;
- }
-
- if (conf->keys->dns_wc_tail.nelts) {
-
- ngx_qsort(conf->keys->dns_wc_tail.elts,
- (size_t) conf->keys->dns_wc_tail.nelts,
- sizeof(ngx_hash_key_t),
- ngx_http_cmp_referer_wildcards);
-
- hash.hash = NULL;
- hash.temp_pool = cf->temp_pool;
-
- if (ngx_hash_wildcard_init(&hash, conf->keys->dns_wc_tail.elts,
- conf->keys->dns_wc_tail.nelts)
- != NGX_OK)
- {
- return NGX_CONF_ERROR;
- }
-
- conf->hash.wc_tail = (ngx_hash_wildcard_t *) hash.hash;
- }
-
-#if (NGX_PCRE)
- ngx_conf_merge_ptr_value(conf->regex, prev->regex, NULL);
- ngx_conf_merge_ptr_value(conf->server_name_regex, prev->server_name_regex,
- NULL);
-#endif
-
- if (conf->no_referer == NGX_CONF_UNSET) {
- conf->no_referer = 0;
- }
-
- if (conf->blocked_referer == NGX_CONF_UNSET) {
- conf->blocked_referer = 0;
- }
-
- conf->keys = NULL;
-
- return NGX_CONF_OK;
-}
-
-
-static char *
-ngx_http_valid_referers(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
-{
- ngx_http_referer_conf_t *rlcf = conf;
-
- u_char *p;
- ngx_str_t *value, uri;
- ngx_uint_t i;
-
- if (rlcf->keys == NULL) {
- rlcf->keys = ngx_pcalloc(cf->temp_pool, sizeof(ngx_hash_keys_arrays_t));
- if (rlcf->keys == NULL) {
- return NGX_CONF_ERROR;
- }
-
- rlcf->keys->pool = cf->pool;
- rlcf->keys->temp_pool = cf->pool;
-
- if (ngx_hash_keys_array_init(rlcf->keys, NGX_HASH_SMALL) != NGX_OK) {
- return NGX_CONF_ERROR;
- }
- }
-
- value = cf->args->elts;
-
- for (i = 1; i < cf->args->nelts; i++) {
- if (value[i].len == 0) {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "invalid referer \"%V\"", &value[i]);
- return NGX_CONF_ERROR;
- }
-
- if (ngx_strcmp(value[i].data, "none") == 0) {
- rlcf->no_referer = 1;
- continue;
- }
-
- if (ngx_strcmp(value[i].data, "blocked") == 0) {
- rlcf->blocked_referer = 1;
- continue;
- }
-
- if (ngx_strcmp(value[i].data, "server_names") == 0) {
- rlcf->server_names = 1;
- continue;
- }
-
- if (value[i].data[0] == '~') {
- if (ngx_http_add_regex_referer(cf, rlcf, &value[i]) != NGX_OK) {
- return NGX_CONF_ERROR;
- }
-
- continue;
- }
-
- ngx_str_null(&uri);
-
- p = (u_char *) ngx_strchr(value[i].data, '/');
-
- if (p) {
- uri.len = (value[i].data + value[i].len) - p;
- uri.data = p;
- value[i].len = p - value[i].data;
- }
-
- if (ngx_http_add_referer(cf, rlcf->keys, &value[i], &uri) != NGX_OK) {
- return NGX_CONF_ERROR;
- }
- }
-
- return NGX_CONF_OK;
-}
-
-
-static ngx_int_t
-ngx_http_add_referer(ngx_conf_t *cf, ngx_hash_keys_arrays_t *keys,
- ngx_str_t *value, ngx_str_t *uri)
-{
- ngx_int_t rc;
- ngx_str_t *u;
-
- if (uri == NULL || uri->len == 0) {
- u = NGX_HTTP_REFERER_NO_URI_PART;
-
- } else {
- u = ngx_palloc(cf->pool, sizeof(ngx_str_t));
- if (u == NULL) {
- return NGX_ERROR;
- }
-
- *u = *uri;
- }
-
- rc = ngx_hash_add_key(keys, value, u, NGX_HASH_WILDCARD_KEY);
-
- if (rc == NGX_OK) {
- return NGX_OK;
- }
-
- if (rc == NGX_DECLINED) {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "invalid hostname or wildcard \"%V\"", value);
- }
-
- if (rc == NGX_BUSY) {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "conflicting parameter \"%V\"", value);
- }
-
- return NGX_ERROR;
-}
-
-
-static ngx_int_t
-ngx_http_add_regex_referer(ngx_conf_t *cf, ngx_http_referer_conf_t *rlcf,
- ngx_str_t *name)
-{
-#if (NGX_PCRE)
- ngx_regex_elt_t *re;
- ngx_regex_compile_t rc;
- u_char errstr[NGX_MAX_CONF_ERRSTR];
-
- if (name->len == 1) {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "empty regex in \"%V\"", name);
- return NGX_ERROR;
- }
-
- if (rlcf->regex == NGX_CONF_UNSET_PTR) {
- rlcf->regex = ngx_array_create(cf->pool, 2, sizeof(ngx_regex_elt_t));
- if (rlcf->regex == NULL) {
- return NGX_ERROR;
- }
- }
-
- re = ngx_array_push(rlcf->regex);
- if (re == NULL) {
- return NGX_ERROR;
- }
-
- name->len--;
- name->data++;
-
- ngx_memzero(&rc, sizeof(ngx_regex_compile_t));
-
- rc.pattern = *name;
- rc.pool = cf->pool;
- rc.options = NGX_REGEX_CASELESS;
- rc.err.len = NGX_MAX_CONF_ERRSTR;
- rc.err.data = errstr;
-
- if (ngx_regex_compile(&rc) != NGX_OK) {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%V", &rc.err);
- return NGX_ERROR;
- }
-
- re->regex = rc.regex;
- re->name = name->data;
-
- return NGX_OK;
-
-#else
-
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "the using of the regex \"%V\" requires PCRE library",
- name);
-
- return NGX_ERROR;
-
-#endif
-}
-
-
-#if (NGX_PCRE)
-
-static ngx_int_t
-ngx_http_add_regex_server_name(ngx_conf_t *cf, ngx_http_referer_conf_t *rlcf,
- ngx_http_regex_t *regex)
-{
- ngx_regex_elt_t *re;
-
- if (rlcf->server_name_regex == NGX_CONF_UNSET_PTR) {
- rlcf->server_name_regex = ngx_array_create(cf->pool, 2,
- sizeof(ngx_regex_elt_t));
- if (rlcf->server_name_regex == NULL) {
- return NGX_ERROR;
- }
- }
-
- re = ngx_array_push(rlcf->server_name_regex);
- if (re == NULL) {
- return NGX_ERROR;
- }
-
- re->regex = regex->regex;
- re->name = regex->name.data;
-
- return NGX_OK;
-}
-
-#endif
-
-
-static int ngx_libc_cdecl
-ngx_http_cmp_referer_wildcards(const void *one, const void *two)
-{
- ngx_hash_key_t *first, *second;
-
- first = (ngx_hash_key_t *) one;
- second = (ngx_hash_key_t *) two;
-
- return ngx_dns_strcmp(first->key.data, second->key.data);
-}
diff --git a/nginx/src/http/modules/ngx_http_rewrite_module.c b/nginx/src/http/modules/ngx_http_rewrite_module.c
deleted file mode 100644
index a6f1fc8..0000000
--- a/nginx/src/http/modules/ngx_http_rewrite_module.c
+++ /dev/null
@@ -1,1022 +0,0 @@
-
-/*
- * Copyright (C) Igor Sysoev
- * Copyright (C) Nginx, Inc.
- */
-
-
-#include <ngx_config.h>
-#include <ngx_core.h>
-#include <ngx_http.h>
-
-
-typedef struct {
- ngx_array_t *codes; /* uintptr_t */
-
- ngx_uint_t stack_size;
-
- ngx_flag_t log;
- ngx_flag_t uninitialized_variable_warn;
-} ngx_http_rewrite_loc_conf_t;
-
-
-static void *ngx_http_rewrite_create_loc_conf(ngx_conf_t *cf);
-static char *ngx_http_rewrite_merge_loc_conf(ngx_conf_t *cf,
- void *parent, void *child);
-static ngx_int_t ngx_http_rewrite_init(ngx_conf_t *cf);
-static char *ngx_http_rewrite(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
-static char *ngx_http_rewrite_return(ngx_conf_t *cf, ngx_command_t *cmd,
- void *conf);
-static char *ngx_http_rewrite_break(ngx_conf_t *cf, ngx_command_t *cmd,
- void *conf);
-static char *ngx_http_rewrite_if(ngx_conf_t *cf, ngx_command_t *cmd,
- void *conf);
-static char * ngx_http_rewrite_if_condition(ngx_conf_t *cf,
- ngx_http_rewrite_loc_conf_t *lcf);
-static char *ngx_http_rewrite_variable(ngx_conf_t *cf,
- ngx_http_rewrite_loc_conf_t *lcf, ngx_str_t *value);
-static char *ngx_http_rewrite_set(ngx_conf_t *cf, ngx_command_t *cmd,
- void *conf);
-static char * ngx_http_rewrite_value(ngx_conf_t *cf,
- ngx_http_rewrite_loc_conf_t *lcf, ngx_str_t *value);
-
-
-static ngx_command_t ngx_http_rewrite_commands[] = {
-
- { ngx_string("rewrite"),
- NGX_HTTP_SRV_CONF|NGX_HTTP_SIF_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF
- |NGX_CONF_TAKE23,
- ngx_http_rewrite,
- NGX_HTTP_LOC_CONF_OFFSET,
- 0,
- NULL },
-
- { ngx_string("return"),
- NGX_HTTP_SRV_CONF|NGX_HTTP_SIF_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF
- |NGX_CONF_TAKE12,
- ngx_http_rewrite_return,
- NGX_HTTP_LOC_CONF_OFFSET,
- 0,
- NULL },
-
- { ngx_string("break"),
- NGX_HTTP_SRV_CONF|NGX_HTTP_SIF_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF
- |NGX_CONF_NOARGS,
- ngx_http_rewrite_break,
- NGX_HTTP_LOC_CONF_OFFSET,
- 0,
- NULL },
-
- { ngx_string("if"),
- NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_BLOCK|NGX_CONF_1MORE,
- ngx_http_rewrite_if,
- NGX_HTTP_LOC_CONF_OFFSET,
- 0,
- NULL },
-
- { ngx_string("set"),
- NGX_HTTP_SRV_CONF|NGX_HTTP_SIF_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF
- |NGX_CONF_TAKE2,
- ngx_http_rewrite_set,
- NGX_HTTP_LOC_CONF_OFFSET,
- 0,
- NULL },
-
- { ngx_string("rewrite_log"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_SIF_CONF|NGX_HTTP_LOC_CONF
- |NGX_HTTP_LIF_CONF|NGX_CONF_FLAG,
- ngx_conf_set_flag_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_rewrite_loc_conf_t, log),
- NULL },
-
- { ngx_string("uninitialized_variable_warn"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_SIF_CONF|NGX_HTTP_LOC_CONF
- |NGX_HTTP_LIF_CONF|NGX_CONF_FLAG,
- ngx_conf_set_flag_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_rewrite_loc_conf_t, uninitialized_variable_warn),
- NULL },
-
- ngx_null_command
-};
-
-
-static ngx_http_module_t ngx_http_rewrite_module_ctx = {
- NULL, /* preconfiguration */
- ngx_http_rewrite_init, /* postconfiguration */
-
- NULL, /* create main configuration */
- NULL, /* init main configuration */
-
- NULL, /* create server configuration */
- NULL, /* merge server configuration */
-
- ngx_http_rewrite_create_loc_conf, /* create location configuration */
- ngx_http_rewrite_merge_loc_conf /* merge location configuration */
-};
-
-
-ngx_module_t ngx_http_rewrite_module = {
- NGX_MODULE_V1,
- &ngx_http_rewrite_module_ctx, /* module context */
- ngx_http_rewrite_commands, /* module directives */
- NGX_HTTP_MODULE, /* module type */
- NULL, /* init master */
- NULL, /* init module */
- NULL, /* init process */
- NULL, /* init thread */
- NULL, /* exit thread */
- NULL, /* exit process */
- NULL, /* exit master */
- NGX_MODULE_V1_PADDING
-};
-
-
-static ngx_int_t
-ngx_http_rewrite_handler(ngx_http_request_t *r)
-{
- ngx_int_t index;
- ngx_http_script_code_pt code;
- ngx_http_script_engine_t *e;
- ngx_http_core_srv_conf_t *cscf;
- ngx_http_core_main_conf_t *cmcf;
- ngx_http_rewrite_loc_conf_t *rlcf;
-
- cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
- cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
- index = cmcf->phase_engine.location_rewrite_index;
-
- if (r->phase_handler == index && r->loc_conf == cscf->ctx->loc_conf) {
- /* skipping location rewrite phase for server null location */
- return NGX_DECLINED;
- }
-
- rlcf = ngx_http_get_module_loc_conf(r, ngx_http_rewrite_module);
-
- if (rlcf->codes == NULL) {
- return NGX_DECLINED;
- }
-
- e = ngx_pcalloc(r->pool, sizeof(ngx_http_script_engine_t));
- if (e == NULL) {
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
-
- e->sp = ngx_pcalloc(r->pool,
- rlcf->stack_size * sizeof(ngx_http_variable_value_t));
- if (e->sp == NULL) {
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
-
- e->ip = rlcf->codes->elts;
- e->request = r;
- e->quote = 1;
- e->log = rlcf->log;
- e->status = NGX_DECLINED;
-
- while (*(uintptr_t *) e->ip) {
- code = *(ngx_http_script_code_pt *) e->ip;
- code(e);
- }
-
- if (e->status < NGX_HTTP_BAD_REQUEST) {
- return e->status;
- }
-
- if (r->err_status == 0) {
- return e->status;
- }
-
- return r->err_status;
-}
-
-
-static ngx_int_t
-ngx_http_rewrite_var(ngx_http_request_t *r, ngx_http_variable_value_t *v,
- uintptr_t data)
-{
- ngx_http_variable_t *var;
- ngx_http_core_main_conf_t *cmcf;
- ngx_http_rewrite_loc_conf_t *rlcf;
-
- rlcf = ngx_http_get_module_loc_conf(r, ngx_http_rewrite_module);
-
- if (rlcf->uninitialized_variable_warn == 0) {
- *v = ngx_http_variable_null_value;
- return NGX_OK;
- }
-
- cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
-
- var = cmcf->variables.elts;
-
- /*
- * the ngx_http_rewrite_module sets variables directly in r->variables,
- * and they should be handled by ngx_http_get_indexed_variable(),
- * so the handler is called only if the variable is not initialized
- */
-
- ngx_log_error(NGX_LOG_WARN, r->connection->log, 0,
- "using uninitialized \"%V\" variable", &var[data].name);
-
- *v = ngx_http_variable_null_value;
-
- return NGX_OK;
-}
-
-
-static void *
-ngx_http_rewrite_create_loc_conf(ngx_conf_t *cf)
-{
- ngx_http_rewrite_loc_conf_t *conf;
-
- conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_rewrite_loc_conf_t));
- if (conf == NULL) {
- return NULL;
- }
-
- conf->stack_size = NGX_CONF_UNSET_UINT;
- conf->log = NGX_CONF_UNSET;
- conf->uninitialized_variable_warn = NGX_CONF_UNSET;
-
- return conf;
-}
-
-
-static char *
-ngx_http_rewrite_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
-{
- ngx_http_rewrite_loc_conf_t *prev = parent;
- ngx_http_rewrite_loc_conf_t *conf = child;
-
- uintptr_t *code;
-
- ngx_conf_merge_value(conf->log, prev->log, 0);
- ngx_conf_merge_value(conf->uninitialized_variable_warn,
- prev->uninitialized_variable_warn, 1);
- ngx_conf_merge_uint_value(conf->stack_size, prev->stack_size, 10);
-
- if (conf->codes == NULL) {
- return NGX_CONF_OK;
- }
-
- if (conf->codes == prev->codes) {
- return NGX_CONF_OK;
- }
-
- code = ngx_array_push_n(conf->codes, sizeof(uintptr_t));
- if (code == NULL) {
- return NGX_CONF_ERROR;
- }
-
- *code = (uintptr_t) NULL;
-
- return NGX_CONF_OK;
-}
-
-
-static ngx_int_t
-ngx_http_rewrite_init(ngx_conf_t *cf)
-{
- ngx_http_handler_pt *h;
- ngx_http_core_main_conf_t *cmcf;
-
- cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);
-
- h = ngx_array_push(&cmcf->phases[NGX_HTTP_SERVER_REWRITE_PHASE].handlers);
- if (h == NULL) {
- return NGX_ERROR;
- }
-
- *h = ngx_http_rewrite_handler;
-
- h = ngx_array_push(&cmcf->phases[NGX_HTTP_REWRITE_PHASE].handlers);
- if (h == NULL) {
- return NGX_ERROR;
- }
-
- *h = ngx_http_rewrite_handler;
-
- return NGX_OK;
-}
-
-
-static char *
-ngx_http_rewrite(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
-{
- ngx_http_rewrite_loc_conf_t *lcf = conf;
-
- ngx_str_t *value;
- ngx_uint_t last;
- ngx_regex_compile_t rc;
- ngx_http_script_code_pt *code;
- ngx_http_script_compile_t sc;
- ngx_http_script_regex_code_t *regex;
- ngx_http_script_regex_end_code_t *regex_end;
- u_char errstr[NGX_MAX_CONF_ERRSTR];
-
- regex = ngx_http_script_start_code(cf->pool, &lcf->codes,
- sizeof(ngx_http_script_regex_code_t));
- if (regex == NULL) {
- return NGX_CONF_ERROR;
- }
-
- ngx_memzero(regex, sizeof(ngx_http_script_regex_code_t));
-
- value = cf->args->elts;
-
- ngx_memzero(&rc, sizeof(ngx_regex_compile_t));
-
- rc.pattern = value[1];
- rc.err.len = NGX_MAX_CONF_ERRSTR;
- rc.err.data = errstr;
-
- /* TODO: NGX_REGEX_CASELESS */
-
- regex->regex = ngx_http_regex_compile(cf, &rc);
- if (regex->regex == NULL) {
- return NGX_CONF_ERROR;
- }
-
- regex->code = ngx_http_script_regex_start_code;
- regex->uri = 1;
- regex->name = value[1];
-
- if (value[2].data[value[2].len - 1] == '?') {
-
- /* the last "?" drops the original arguments */
- value[2].len--;
-
- } else {
- regex->add_args = 1;
- }
-
- last = 0;
-
- if (ngx_strncmp(value[2].data, "http://", sizeof("http://") - 1) == 0
- || ngx_strncmp(value[2].data, "https://", sizeof("https://") - 1) == 0
- || ngx_strncmp(value[2].data, "$scheme", sizeof("$scheme") - 1) == 0)
- {
- regex->status = NGX_HTTP_MOVED_TEMPORARILY;
- regex->redirect = 1;
- last = 1;
- }
-
- if (cf->args->nelts == 4) {
- if (ngx_strcmp(value[3].data, "last") == 0) {
- last = 1;
-
- } else if (ngx_strcmp(value[3].data, "break") == 0) {
- regex->break_cycle = 1;
- last = 1;
-
- } else if (ngx_strcmp(value[3].data, "redirect") == 0) {
- regex->status = NGX_HTTP_MOVED_TEMPORARILY;
- regex->redirect = 1;
- last = 1;
-
- } else if (ngx_strcmp(value[3].data, "permanent") == 0) {
- regex->status = NGX_HTTP_MOVED_PERMANENTLY;
- regex->redirect = 1;
- last = 1;
-
- } else {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "invalid parameter \"%V\"", &value[3]);
- return NGX_CONF_ERROR;
- }
- }
-
- ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));
-
- sc.cf = cf;
- sc.source = &value[2];
- sc.lengths = &regex->lengths;
- sc.values = &lcf->codes;
- sc.variables = ngx_http_script_variables_count(&value[2]);
- sc.main = regex;
- sc.complete_lengths = 1;
- sc.compile_args = !regex->redirect;
-
- if (ngx_http_script_compile(&sc) != NGX_OK) {
- return NGX_CONF_ERROR;
- }
-
- regex = sc.main;
-
- regex->size = sc.size;
- regex->args = sc.args;
-
- if (sc.variables == 0 && !sc.dup_capture) {
- regex->lengths = NULL;
- }
-
- regex_end = ngx_http_script_add_code(lcf->codes,
- sizeof(ngx_http_script_regex_end_code_t),
- &regex);
- if (regex_end == NULL) {
- return NGX_CONF_ERROR;
- }
-
- regex_end->code = ngx_http_script_regex_end_code;
- regex_end->uri = regex->uri;
- regex_end->args = regex->args;
- regex_end->add_args = regex->add_args;
- regex_end->redirect = regex->redirect;
-
- if (last) {
- code = ngx_http_script_add_code(lcf->codes, sizeof(uintptr_t), &regex);
- if (code == NULL) {
- return NGX_CONF_ERROR;
- }
-
- *code = NULL;
- }
-
- regex->next = (u_char *) lcf->codes->elts + lcf->codes->nelts
- - (u_char *) regex;
-
- return NGX_CONF_OK;
-}
-
-
-static char *
-ngx_http_rewrite_return(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
-{
- ngx_http_rewrite_loc_conf_t *lcf = conf;
-
- u_char *p;
- ngx_str_t *value, *v;
- ngx_http_script_return_code_t *ret;
- ngx_http_compile_complex_value_t ccv;
-
- ret = ngx_http_script_start_code(cf->pool, &lcf->codes,
- sizeof(ngx_http_script_return_code_t));
- if (ret == NULL) {
- return NGX_CONF_ERROR;
- }
-
- value = cf->args->elts;
-
- ngx_memzero(ret, sizeof(ngx_http_script_return_code_t));
-
- ret->code = ngx_http_script_return_code;
-
- p = value[1].data;
-
- ret->status = ngx_atoi(p, value[1].len);
-
- if (ret->status == (uintptr_t) NGX_ERROR) {
-
- if (cf->args->nelts == 2
- && (ngx_strncmp(p, "http://", sizeof("http://") - 1) == 0
- || ngx_strncmp(p, "https://", sizeof("https://") - 1) == 0
- || ngx_strncmp(p, "$scheme", sizeof("$scheme") - 1) == 0))
- {
- ret->status = NGX_HTTP_MOVED_TEMPORARILY;
- v = &value[1];
-
- } else {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "invalid return code \"%V\"", &value[1]);
- return NGX_CONF_ERROR;
- }
-
- } else {
-
- if (ret->status > 999) {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "invalid return code \"%V\"", &value[1]);
- return NGX_CONF_ERROR;
- }
-
- if (cf->args->nelts == 2) {
- return NGX_CONF_OK;
- }
-
- v = &value[2];
- }
-
- ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));
-
- ccv.cf = cf;
- ccv.value = v;
- ccv.complex_value = &ret->text;
-
- if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
- return NGX_CONF_ERROR;
- }
-
- return NGX_CONF_OK;
-}
-
-
-static char *
-ngx_http_rewrite_break(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
-{
- ngx_http_rewrite_loc_conf_t *lcf = conf;
-
- ngx_http_script_code_pt *code;
-
- code = ngx_http_script_start_code(cf->pool, &lcf->codes, sizeof(uintptr_t));
- if (code == NULL) {
- return NGX_CONF_ERROR;
- }
-
- *code = ngx_http_script_break_code;
-
- return NGX_CONF_OK;
-}
-
-
-static char *
-ngx_http_rewrite_if(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
-{
- ngx_http_rewrite_loc_conf_t *lcf = conf;
-
- void *mconf;
- char *rv;
- u_char *elts;
- ngx_uint_t i;
- ngx_conf_t save;
- ngx_http_module_t *module;
- ngx_http_conf_ctx_t *ctx, *pctx;
- ngx_http_core_loc_conf_t *clcf, *pclcf;
- ngx_http_script_if_code_t *if_code;
- ngx_http_rewrite_loc_conf_t *nlcf;
-
- ctx = ngx_pcalloc(cf->pool, sizeof(ngx_http_conf_ctx_t));
- if (ctx == NULL) {
- return NGX_CONF_ERROR;
- }
-
- pctx = cf->ctx;
- ctx->main_conf = pctx->main_conf;
- ctx->srv_conf = pctx->srv_conf;
-
- ctx->loc_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module);
- if (ctx->loc_conf == NULL) {
- return NGX_CONF_ERROR;
- }
-
- for (i = 0; cf->cycle->modules[i]; i++) {
- if (cf->cycle->modules[i]->type != NGX_HTTP_MODULE) {
- continue;
- }
-
- module = cf->cycle->modules[i]->ctx;
-
- if (module->create_loc_conf) {
-
- mconf = module->create_loc_conf(cf);
- if (mconf == NULL) {
- return NGX_CONF_ERROR;
- }
-
- ctx->loc_conf[cf->cycle->modules[i]->ctx_index] = mconf;
- }
- }
-
- pclcf = pctx->loc_conf[ngx_http_core_module.ctx_index];
-
- clcf = ctx->loc_conf[ngx_http_core_module.ctx_index];
- clcf->loc_conf = ctx->loc_conf;
- clcf->name = pclcf->name;
- clcf->noname = 1;
-
- if (ngx_http_add_location(cf, &pclcf->locations, clcf) != NGX_OK) {
- return NGX_CONF_ERROR;
- }
-
- if (ngx_http_rewrite_if_condition(cf, lcf) != NGX_CONF_OK) {
- return NGX_CONF_ERROR;
- }
-
- if_code = ngx_array_push_n(lcf->codes, sizeof(ngx_http_script_if_code_t));
- if (if_code == NULL) {
- return NGX_CONF_ERROR;
- }
-
- if_code->code = ngx_http_script_if_code;
-
- elts = lcf->codes->elts;
-
-
- /* the inner directives must be compiled to the same code array */
-
- nlcf = ctx->loc_conf[ngx_http_rewrite_module.ctx_index];
- nlcf->codes = lcf->codes;
-
-
- save = *cf;
- cf->ctx = ctx;
-
- if (cf->cmd_type == NGX_HTTP_SRV_CONF) {
- if_code->loc_conf = NULL;
- cf->cmd_type = NGX_HTTP_SIF_CONF;
-
- } else {
- if_code->loc_conf = ctx->loc_conf;
- cf->cmd_type = NGX_HTTP_LIF_CONF;
- }
-
- rv = ngx_conf_parse(cf, NULL);
-
- *cf = save;
-
- if (rv != NGX_CONF_OK) {
- return rv;
- }
-
-
- if (elts != lcf->codes->elts) {
- if_code = (ngx_http_script_if_code_t *)
- ((u_char *) if_code + ((u_char *) lcf->codes->elts - elts));
- }
-
- if_code->next = (u_char *) lcf->codes->elts + lcf->codes->nelts
- - (u_char *) if_code;
-
- /* the code array belong to parent block */
-
- nlcf->codes = NULL;
-
- return NGX_CONF_OK;
-}
-
-
-static char *
-ngx_http_rewrite_if_condition(ngx_conf_t *cf, ngx_http_rewrite_loc_conf_t *lcf)
-{
- u_char *p;
- size_t len;
- ngx_str_t *value;
- ngx_uint_t cur, last;
- ngx_regex_compile_t rc;
- ngx_http_script_code_pt *code;
- ngx_http_script_file_code_t *fop;
- ngx_http_script_regex_code_t *regex;
- u_char errstr[NGX_MAX_CONF_ERRSTR];
-
- value = cf->args->elts;
- last = cf->args->nelts - 1;
-
- if (value[1].len < 1 || value[1].data[0] != '(') {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "invalid condition \"%V\"", &value[1]);
- return NGX_CONF_ERROR;
- }
-
- if (value[1].len == 1) {
- cur = 2;
-
- } else {
- cur = 1;
- value[1].len--;
- value[1].data++;
- }
-
- if (value[last].len < 1 || value[last].data[value[last].len - 1] != ')') {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "invalid condition \"%V\"", &value[last]);
- return NGX_CONF_ERROR;
- }
-
- if (value[last].len == 1) {
- last--;
-
- } else {
- value[last].len--;
- value[last].data[value[last].len] = '\0';
- }
-
- len = value[cur].len;
- p = value[cur].data;
-
- if (len > 1 && p[0] == '$') {
-
- if (cur != last && cur + 2 != last) {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "invalid condition \"%V\"", &value[cur]);
- return NGX_CONF_ERROR;
- }
-
- if (ngx_http_rewrite_variable(cf, lcf, &value[cur]) != NGX_CONF_OK) {
- return NGX_CONF_ERROR;
- }
-
- if (cur == last) {
- return NGX_CONF_OK;
- }
-
- cur++;
-
- len = value[cur].len;
- p = value[cur].data;
-
- if (len == 1 && p[0] == '=') {
-
- if (ngx_http_rewrite_value(cf, lcf, &value[last]) != NGX_CONF_OK) {
- return NGX_CONF_ERROR;
- }
-
- code = ngx_http_script_start_code(cf->pool, &lcf->codes,
- sizeof(uintptr_t));
- if (code == NULL) {
- return NGX_CONF_ERROR;
- }
-
- *code = ngx_http_script_equal_code;
-
- return NGX_CONF_OK;
- }
-
- if (len == 2 && p[0] == '!' && p[1] == '=') {
-
- if (ngx_http_rewrite_value(cf, lcf, &value[last]) != NGX_CONF_OK) {
- return NGX_CONF_ERROR;
- }
-
- code = ngx_http_script_start_code(cf->pool, &lcf->codes,
- sizeof(uintptr_t));
- if (code == NULL) {
- return NGX_CONF_ERROR;
- }
-
- *code = ngx_http_script_not_equal_code;
- return NGX_CONF_OK;
- }
-
- if ((len == 1 && p[0] == '~')
- || (len == 2 && p[0] == '~' && p[1] == '*')
- || (len == 2 && p[0] == '!' && p[1] == '~')
- || (len == 3 && p[0] == '!' && p[1] == '~' && p[2] == '*'))
- {
- regex = ngx_http_script_start_code(cf->pool, &lcf->codes,
- sizeof(ngx_http_script_regex_code_t));
- if (regex == NULL) {
- return NGX_CONF_ERROR;
- }
-
- ngx_memzero(regex, sizeof(ngx_http_script_regex_code_t));
-
- ngx_memzero(&rc, sizeof(ngx_regex_compile_t));
-
- rc.pattern = value[last];
- rc.options = (p[len - 1] == '*') ? NGX_REGEX_CASELESS : 0;
- rc.err.len = NGX_MAX_CONF_ERRSTR;
- rc.err.data = errstr;
-
- regex->regex = ngx_http_regex_compile(cf, &rc);
- if (regex->regex == NULL) {
- return NGX_CONF_ERROR;
- }
-
- regex->code = ngx_http_script_regex_start_code;
- regex->next = sizeof(ngx_http_script_regex_code_t);
- regex->test = 1;
- if (p[0] == '!') {
- regex->negative_test = 1;
- }
- regex->name = value[last];
-
- return NGX_CONF_OK;
- }
-
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "unexpected \"%V\" in condition", &value[cur]);
- return NGX_CONF_ERROR;
-
- } else if ((len == 2 && p[0] == '-')
- || (len == 3 && p[0] == '!' && p[1] == '-'))
- {
- if (cur + 1 != last) {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "invalid condition \"%V\"", &value[cur]);
- return NGX_CONF_ERROR;
- }
-
- value[last].data[value[last].len] = '\0';
- value[last].len++;
-
- if (ngx_http_rewrite_value(cf, lcf, &value[last]) != NGX_CONF_OK) {
- return NGX_CONF_ERROR;
- }
-
- fop = ngx_http_script_start_code(cf->pool, &lcf->codes,
- sizeof(ngx_http_script_file_code_t));
- if (fop == NULL) {
- return NGX_CONF_ERROR;
- }
-
- fop->code = ngx_http_script_file_code;
-
- if (p[1] == 'f') {
- fop->op = ngx_http_script_file_plain;
- return NGX_CONF_OK;
- }
-
- if (p[1] == 'd') {
- fop->op = ngx_http_script_file_dir;
- return NGX_CONF_OK;
- }
-
- if (p[1] == 'e') {
- fop->op = ngx_http_script_file_exists;
- return NGX_CONF_OK;
- }
-
- if (p[1] == 'x') {
- fop->op = ngx_http_script_file_exec;
- return NGX_CONF_OK;
- }
-
- if (p[0] == '!') {
- if (p[2] == 'f') {
- fop->op = ngx_http_script_file_not_plain;
- return NGX_CONF_OK;
- }
-
- if (p[2] == 'd') {
- fop->op = ngx_http_script_file_not_dir;
- return NGX_CONF_OK;
- }
-
- if (p[2] == 'e') {
- fop->op = ngx_http_script_file_not_exists;
- return NGX_CONF_OK;
- }
-
- if (p[2] == 'x') {
- fop->op = ngx_http_script_file_not_exec;
- return NGX_CONF_OK;
- }
- }
-
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "invalid condition \"%V\"", &value[cur]);
- return NGX_CONF_ERROR;
- }
-
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "invalid condition \"%V\"", &value[cur]);
-
- return NGX_CONF_ERROR;
-}
-
-
-static char *
-ngx_http_rewrite_variable(ngx_conf_t *cf, ngx_http_rewrite_loc_conf_t *lcf,
- ngx_str_t *value)
-{
- ngx_int_t index;
- ngx_http_script_var_code_t *var_code;
-
- value->len--;
- value->data++;
-
- index = ngx_http_get_variable_index(cf, value);
-
- if (index == NGX_ERROR) {
- return NGX_CONF_ERROR;
- }
-
- var_code = ngx_http_script_start_code(cf->pool, &lcf->codes,
- sizeof(ngx_http_script_var_code_t));
- if (var_code == NULL) {
- return NGX_CONF_ERROR;
- }
-
- var_code->code = ngx_http_script_var_code;
- var_code->index = index;
-
- return NGX_CONF_OK;
-}
-
-
-static char *
-ngx_http_rewrite_set(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
-{
- ngx_http_rewrite_loc_conf_t *lcf = conf;
-
- ngx_int_t index;
- ngx_str_t *value;
- ngx_http_variable_t *v;
- ngx_http_script_var_code_t *vcode;
- ngx_http_script_var_handler_code_t *vhcode;
-
- value = cf->args->elts;
-
- if (value[1].data[0] != '$') {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "invalid variable name \"%V\"", &value[1]);
- return NGX_CONF_ERROR;
- }
-
- value[1].len--;
- value[1].data++;
-
- v = ngx_http_add_variable(cf, &value[1],
- NGX_HTTP_VAR_CHANGEABLE|NGX_HTTP_VAR_WEAK);
- if (v == NULL) {
- return NGX_CONF_ERROR;
- }
-
- index = ngx_http_get_variable_index(cf, &value[1]);
- if (index == NGX_ERROR) {
- return NGX_CONF_ERROR;
- }
-
- if (v->get_handler == NULL) {
- v->get_handler = ngx_http_rewrite_var;
- v->data = index;
- }
-
- if (ngx_http_rewrite_value(cf, lcf, &value[2]) != NGX_CONF_OK) {
- return NGX_CONF_ERROR;
- }
-
- if (v->set_handler) {
- vhcode = ngx_http_script_start_code(cf->pool, &lcf->codes,
- sizeof(ngx_http_script_var_handler_code_t));
- if (vhcode == NULL) {
- return NGX_CONF_ERROR;
- }
-
- vhcode->code = ngx_http_script_var_set_handler_code;
- vhcode->handler = v->set_handler;
- vhcode->data = v->data;
-
- return NGX_CONF_OK;
- }
-
- vcode = ngx_http_script_start_code(cf->pool, &lcf->codes,
- sizeof(ngx_http_script_var_code_t));
- if (vcode == NULL) {
- return NGX_CONF_ERROR;
- }
-
- vcode->code = ngx_http_script_set_var_code;
- vcode->index = (uintptr_t) index;
-
- return NGX_CONF_OK;
-}
-
-
-static char *
-ngx_http_rewrite_value(ngx_conf_t *cf, ngx_http_rewrite_loc_conf_t *lcf,
- ngx_str_t *value)
-{
- ngx_int_t n;
- ngx_http_script_compile_t sc;
- ngx_http_script_value_code_t *val;
- ngx_http_script_complex_value_code_t *complex;
-
- n = ngx_http_script_variables_count(value);
-
- if (n == 0) {
- val = ngx_http_script_start_code(cf->pool, &lcf->codes,
- sizeof(ngx_http_script_value_code_t));
- if (val == NULL) {
- return NGX_CONF_ERROR;
- }
-
- n = ngx_atoi(value->data, value->len);
-
- if (n == NGX_ERROR) {
- n = 0;
- }
-
- val->code = ngx_http_script_value_code;
- val->value = (uintptr_t) n;
- val->text_len = (uintptr_t) value->len;
- val->text_data = (uintptr_t) value->data;
-
- return NGX_CONF_OK;
- }
-
- complex = ngx_http_script_start_code(cf->pool, &lcf->codes,
- sizeof(ngx_http_script_complex_value_code_t));
- if (complex == NULL) {
- return NGX_CONF_ERROR;
- }
-
- complex->code = ngx_http_script_complex_value_code;
- complex->lengths = NULL;
-
- ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));
-
- sc.cf = cf;
- sc.source = value;
- sc.lengths = &complex->lengths;
- sc.values = &lcf->codes;
- sc.variables = n;
- sc.complete_lengths = 1;
-
- if (ngx_http_script_compile(&sc) != NGX_OK) {
- return NGX_CONF_ERROR;
- }
-
- return NGX_CONF_OK;
-}
diff --git a/nginx/src/http/modules/ngx_http_scgi_module.c b/nginx/src/http/modules/ngx_http_scgi_module.c
deleted file mode 100644
index 9bd45bd..0000000
--- a/nginx/src/http/modules/ngx_http_scgi_module.c
+++ /dev/null
@@ -1,2008 +0,0 @@
-
-/*
- * Copyright (C) Igor Sysoev
- * Copyright (C) Nginx, Inc.
- * Copyright (C) Manlio Perillo (manlio.perillo@gmail.com)
- */
-
-
-#include <ngx_config.h>
-#include <ngx_core.h>
-#include <ngx_http.h>
-
-
-typedef struct {
- ngx_array_t caches; /* ngx_http_file_cache_t * */
-} ngx_http_scgi_main_conf_t;
-
-
-typedef struct {
- ngx_array_t *flushes;
- ngx_array_t *lengths;
- ngx_array_t *values;
- ngx_uint_t number;
- ngx_hash_t hash;
-} ngx_http_scgi_params_t;
-
-
-typedef struct {
- ngx_http_upstream_conf_t upstream;
-
- ngx_http_scgi_params_t params;
-#if (NGX_HTTP_CACHE)
- ngx_http_scgi_params_t params_cache;
-#endif
- ngx_array_t *params_source;
-
- ngx_array_t *scgi_lengths;
- ngx_array_t *scgi_values;
-
-#if (NGX_HTTP_CACHE)
- ngx_http_complex_value_t cache_key;
-#endif
-} ngx_http_scgi_loc_conf_t;
-
-
-static ngx_int_t ngx_http_scgi_eval(ngx_http_request_t *r,
- ngx_http_scgi_loc_conf_t *scf);
-static ngx_int_t ngx_http_scgi_create_request(ngx_http_request_t *r);
-static ngx_int_t ngx_http_scgi_reinit_request(ngx_http_request_t *r);
-static ngx_int_t ngx_http_scgi_process_status_line(ngx_http_request_t *r);
-static ngx_int_t ngx_http_scgi_process_header(ngx_http_request_t *r);
-static void ngx_http_scgi_abort_request(ngx_http_request_t *r);
-static void ngx_http_scgi_finalize_request(ngx_http_request_t *r, ngx_int_t rc);
-
-static void *ngx_http_scgi_create_main_conf(ngx_conf_t *cf);
-static void *ngx_http_scgi_create_loc_conf(ngx_conf_t *cf);
-static char *ngx_http_scgi_merge_loc_conf(ngx_conf_t *cf, void *parent,
- void *child);
-static ngx_int_t ngx_http_scgi_init_params(ngx_conf_t *cf,
- ngx_http_scgi_loc_conf_t *conf, ngx_http_scgi_params_t *params,
- ngx_keyval_t *default_params);
-
-static char *ngx_http_scgi_pass(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
-static char *ngx_http_scgi_store(ngx_conf_t *cf, ngx_command_t *cmd,
- void *conf);
-
-#if (NGX_HTTP_CACHE)
-static ngx_int_t ngx_http_scgi_create_key(ngx_http_request_t *r);
-static char *ngx_http_scgi_cache(ngx_conf_t *cf, ngx_command_t *cmd,
- void *conf);
-static char *ngx_http_scgi_cache_key(ngx_conf_t *cf, ngx_command_t *cmd,
- void *conf);
-#endif
-
-
-static ngx_conf_bitmask_t ngx_http_scgi_next_upstream_masks[] = {
- { ngx_string("error"), NGX_HTTP_UPSTREAM_FT_ERROR },
- { ngx_string("timeout"), NGX_HTTP_UPSTREAM_FT_TIMEOUT },
- { ngx_string("invalid_header"), NGX_HTTP_UPSTREAM_FT_INVALID_HEADER },
- { ngx_string("non_idempotent"), NGX_HTTP_UPSTREAM_FT_NON_IDEMPOTENT },
- { ngx_string("http_500"), NGX_HTTP_UPSTREAM_FT_HTTP_500 },
- { ngx_string("http_503"), NGX_HTTP_UPSTREAM_FT_HTTP_503 },
- { ngx_string("http_403"), NGX_HTTP_UPSTREAM_FT_HTTP_403 },
- { ngx_string("http_404"), NGX_HTTP_UPSTREAM_FT_HTTP_404 },
- { ngx_string("http_429"), NGX_HTTP_UPSTREAM_FT_HTTP_429 },
- { ngx_string("updating"), NGX_HTTP_UPSTREAM_FT_UPDATING },
- { ngx_string("off"), NGX_HTTP_UPSTREAM_FT_OFF },
- { ngx_null_string, 0 }
-};
-
-
-ngx_module_t ngx_http_scgi_module;
-
-
-static ngx_command_t ngx_http_scgi_commands[] = {
-
- { ngx_string("scgi_pass"),
- NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_TAKE1,
- ngx_http_scgi_pass,
- NGX_HTTP_LOC_CONF_OFFSET,
- 0,
- NULL },
-
- { ngx_string("scgi_store"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_http_scgi_store,
- NGX_HTTP_LOC_CONF_OFFSET,
- 0,
- NULL },
-
- { ngx_string("scgi_store_access"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE123,
- ngx_conf_set_access_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_scgi_loc_conf_t, upstream.store_access),
- NULL },
-
- { ngx_string("scgi_buffering"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
- ngx_conf_set_flag_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_scgi_loc_conf_t, upstream.buffering),
- NULL },
-
- { ngx_string("scgi_request_buffering"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
- ngx_conf_set_flag_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_scgi_loc_conf_t, upstream.request_buffering),
- NULL },
-
- { ngx_string("scgi_ignore_client_abort"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
- ngx_conf_set_flag_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_scgi_loc_conf_t, upstream.ignore_client_abort),
- NULL },
-
- { ngx_string("scgi_bind"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE12,
- ngx_http_upstream_bind_set_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_scgi_loc_conf_t, upstream.local),
- NULL },
-
- { ngx_string("scgi_connect_timeout"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_msec_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_scgi_loc_conf_t, upstream.connect_timeout),
- NULL },
-
- { ngx_string("scgi_send_timeout"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_msec_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_scgi_loc_conf_t, upstream.send_timeout),
- NULL },
-
- { ngx_string("scgi_buffer_size"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_size_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_scgi_loc_conf_t, upstream.buffer_size),
- NULL },
-
- { ngx_string("scgi_pass_request_headers"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
- ngx_conf_set_flag_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_scgi_loc_conf_t, upstream.pass_request_headers),
- NULL },
-
- { ngx_string("scgi_pass_request_body"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
- ngx_conf_set_flag_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_scgi_loc_conf_t, upstream.pass_request_body),
- NULL },
-
- { ngx_string("scgi_intercept_errors"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
- ngx_conf_set_flag_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_scgi_loc_conf_t, upstream.intercept_errors),
- NULL },
-
- { ngx_string("scgi_read_timeout"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_msec_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_scgi_loc_conf_t, upstream.read_timeout),
- NULL },
-
- { ngx_string("scgi_buffers"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE2,
- ngx_conf_set_bufs_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_scgi_loc_conf_t, upstream.bufs),
- NULL },
-
- { ngx_string("scgi_busy_buffers_size"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_size_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_scgi_loc_conf_t, upstream.busy_buffers_size_conf),
- NULL },
-
- { ngx_string("scgi_force_ranges"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
- ngx_conf_set_flag_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_scgi_loc_conf_t, upstream.force_ranges),
- NULL },
-
- { ngx_string("scgi_limit_rate"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_size_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_scgi_loc_conf_t, upstream.limit_rate),
- NULL },
-
-#if (NGX_HTTP_CACHE)
-
- { ngx_string("scgi_cache"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_http_scgi_cache,
- NGX_HTTP_LOC_CONF_OFFSET,
- 0,
- NULL },
-
- { ngx_string("scgi_cache_key"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_http_scgi_cache_key,
- NGX_HTTP_LOC_CONF_OFFSET,
- 0,
- NULL },
-
- { ngx_string("scgi_cache_path"),
- NGX_HTTP_MAIN_CONF|NGX_CONF_2MORE,
- ngx_http_file_cache_set_slot,
- NGX_HTTP_MAIN_CONF_OFFSET,
- offsetof(ngx_http_scgi_main_conf_t, caches),
- &ngx_http_scgi_module },
-
- { ngx_string("scgi_cache_bypass"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
- ngx_http_set_predicate_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_scgi_loc_conf_t, upstream.cache_bypass),
- NULL },
-
- { ngx_string("scgi_no_cache"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
- ngx_http_set_predicate_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_scgi_loc_conf_t, upstream.no_cache),
- NULL },
-
- { ngx_string("scgi_cache_valid"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
- ngx_http_file_cache_valid_set_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_scgi_loc_conf_t, upstream.cache_valid),
- NULL },
-
- { ngx_string("scgi_cache_min_uses"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_num_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_scgi_loc_conf_t, upstream.cache_min_uses),
- NULL },
-
- { ngx_string("scgi_cache_max_range_offset"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_off_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_scgi_loc_conf_t, upstream.cache_max_range_offset),
- NULL },
-
- { ngx_string("scgi_cache_use_stale"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
- ngx_conf_set_bitmask_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_scgi_loc_conf_t, upstream.cache_use_stale),
- &ngx_http_scgi_next_upstream_masks },
-
- { ngx_string("scgi_cache_methods"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
- ngx_conf_set_bitmask_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_scgi_loc_conf_t, upstream.cache_methods),
- &ngx_http_upstream_cache_method_mask },
-
- { ngx_string("scgi_cache_lock"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
- ngx_conf_set_flag_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_scgi_loc_conf_t, upstream.cache_lock),
- NULL },
-
- { ngx_string("scgi_cache_lock_timeout"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_msec_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_scgi_loc_conf_t, upstream.cache_lock_timeout),
- NULL },
-
- { ngx_string("scgi_cache_lock_age"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_msec_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_scgi_loc_conf_t, upstream.cache_lock_age),
- NULL },
-
- { ngx_string("scgi_cache_revalidate"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
- ngx_conf_set_flag_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_scgi_loc_conf_t, upstream.cache_revalidate),
- NULL },
-
- { ngx_string("scgi_cache_background_update"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
- ngx_conf_set_flag_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_scgi_loc_conf_t, upstream.cache_background_update),
- NULL },
-
-#endif
-
- { ngx_string("scgi_temp_path"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1234,
- ngx_conf_set_path_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_scgi_loc_conf_t, upstream.temp_path),
- NULL },
-
- { ngx_string("scgi_max_temp_file_size"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_size_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_scgi_loc_conf_t, upstream.max_temp_file_size_conf),
- NULL },
-
- { ngx_string("scgi_temp_file_write_size"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_size_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_scgi_loc_conf_t, upstream.temp_file_write_size_conf),
- NULL },
-
- { ngx_string("scgi_next_upstream"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
- ngx_conf_set_bitmask_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_scgi_loc_conf_t, upstream.next_upstream),
- &ngx_http_scgi_next_upstream_masks },
-
- { ngx_string("scgi_next_upstream_tries"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_num_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_scgi_loc_conf_t, upstream.next_upstream_tries),
- NULL },
-
- { ngx_string("scgi_next_upstream_timeout"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_msec_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_scgi_loc_conf_t, upstream.next_upstream_timeout),
- NULL },
-
- { ngx_string("scgi_param"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE23,
- ngx_http_upstream_param_set_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_scgi_loc_conf_t, params_source),
- NULL },
-
- { ngx_string("scgi_pass_header"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_str_array_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_scgi_loc_conf_t, upstream.pass_headers),
- NULL },
-
- { ngx_string("scgi_hide_header"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_str_array_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_scgi_loc_conf_t, upstream.hide_headers),
- NULL },
-
- { ngx_string("scgi_ignore_headers"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
- ngx_conf_set_bitmask_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_scgi_loc_conf_t, upstream.ignore_headers),
- &ngx_http_upstream_ignore_headers_masks },
-
- ngx_null_command
-};
-
-
-static ngx_http_module_t ngx_http_scgi_module_ctx = {
- NULL, /* preconfiguration */
- NULL, /* postconfiguration */
-
- ngx_http_scgi_create_main_conf, /* create main configuration */
- NULL, /* init main configuration */
-
- NULL, /* create server configuration */
- NULL, /* merge server configuration */
-
- ngx_http_scgi_create_loc_conf, /* create location configuration */
- ngx_http_scgi_merge_loc_conf /* merge location configuration */
-};
-
-
-ngx_module_t ngx_http_scgi_module = {
- NGX_MODULE_V1,
- &ngx_http_scgi_module_ctx, /* module context */
- ngx_http_scgi_commands, /* module directives */
- NGX_HTTP_MODULE, /* module type */
- NULL, /* init master */
- NULL, /* init module */
- NULL, /* init process */
- NULL, /* init thread */
- NULL, /* exit thread */
- NULL, /* exit process */
- NULL, /* exit master */
- NGX_MODULE_V1_PADDING
-};
-
-
-static ngx_str_t ngx_http_scgi_hide_headers[] = {
- ngx_string("Status"),
- ngx_string("X-Accel-Expires"),
- ngx_string("X-Accel-Redirect"),
- ngx_string("X-Accel-Limit-Rate"),
- ngx_string("X-Accel-Buffering"),
- ngx_string("X-Accel-Charset"),
- ngx_null_string
-};
-
-
-#if (NGX_HTTP_CACHE)
-
-static ngx_keyval_t ngx_http_scgi_cache_headers[] = {
- { ngx_string("HTTP_IF_MODIFIED_SINCE"),
- ngx_string("$upstream_cache_last_modified") },
- { ngx_string("HTTP_IF_UNMODIFIED_SINCE"), ngx_string("") },
- { ngx_string("HTTP_IF_NONE_MATCH"), ngx_string("$upstream_cache_etag") },
- { ngx_string("HTTP_IF_MATCH"), ngx_string("") },
- { ngx_string("HTTP_RANGE"), ngx_string("") },
- { ngx_string("HTTP_IF_RANGE"), ngx_string("") },
- { ngx_null_string, ngx_null_string }
-};
-
-#endif
-
-
-static ngx_path_init_t ngx_http_scgi_temp_path = {
- ngx_string(NGX_HTTP_SCGI_TEMP_PATH), { 1, 2, 0 }
-};
-
-
-static ngx_int_t
-ngx_http_scgi_handler(ngx_http_request_t *r)
-{
- ngx_int_t rc;
- ngx_http_status_t *status;
- ngx_http_upstream_t *u;
- ngx_http_scgi_loc_conf_t *scf;
-#if (NGX_HTTP_CACHE)
- ngx_http_scgi_main_conf_t *smcf;
-#endif
-
- if (ngx_http_upstream_create(r) != NGX_OK) {
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
-
- status = ngx_pcalloc(r->pool, sizeof(ngx_http_status_t));
- if (status == NULL) {
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
-
- ngx_http_set_ctx(r, status, ngx_http_scgi_module);
-
- scf = ngx_http_get_module_loc_conf(r, ngx_http_scgi_module);
-
- if (scf->scgi_lengths) {
- if (ngx_http_scgi_eval(r, scf) != NGX_OK) {
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
- }
-
- u = r->upstream;
-
- ngx_str_set(&u->schema, "scgi://");
- u->output.tag = (ngx_buf_tag_t) &ngx_http_scgi_module;
-
- u->conf = &scf->upstream;
-
-#if (NGX_HTTP_CACHE)
- smcf = ngx_http_get_module_main_conf(r, ngx_http_scgi_module);
-
- u->caches = &smcf->caches;
- u->create_key = ngx_http_scgi_create_key;
-#endif
-
- u->create_request = ngx_http_scgi_create_request;
- u->reinit_request = ngx_http_scgi_reinit_request;
- u->process_header = ngx_http_scgi_process_status_line;
- u->abort_request = ngx_http_scgi_abort_request;
- u->finalize_request = ngx_http_scgi_finalize_request;
- r->state = 0;
-
- u->buffering = scf->upstream.buffering;
-
- u->pipe = ngx_pcalloc(r->pool, sizeof(ngx_event_pipe_t));
- if (u->pipe == NULL) {
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
-
- u->pipe->input_filter = ngx_event_pipe_copy_input_filter;
- u->pipe->input_ctx = r;
-
- if (!scf->upstream.request_buffering
- && scf->upstream.pass_request_body
- && !r->headers_in.chunked)
- {
- r->request_body_no_buffering = 1;
- }
-
- rc = ngx_http_read_client_request_body(r, ngx_http_upstream_init);
-
- if (rc >= NGX_HTTP_SPECIAL_RESPONSE) {
- return rc;
- }
-
- return NGX_DONE;
-}
-
-
-static ngx_int_t
-ngx_http_scgi_eval(ngx_http_request_t *r, ngx_http_scgi_loc_conf_t * scf)
-{
- ngx_url_t url;
- ngx_http_upstream_t *u;
-
- ngx_memzero(&url, sizeof(ngx_url_t));
-
- if (ngx_http_script_run(r, &url.url, scf->scgi_lengths->elts, 0,
- scf->scgi_values->elts)
- == NULL)
- {
- return NGX_ERROR;
- }
-
- url.no_resolve = 1;
-
- if (ngx_parse_url(r->pool, &url) != NGX_OK) {
- if (url.err) {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "%s in upstream \"%V\"", url.err, &url.url);
- }
-
- return NGX_ERROR;
- }
-
- u = r->upstream;
-
- u->resolved = ngx_pcalloc(r->pool, sizeof(ngx_http_upstream_resolved_t));
- if (u->resolved == NULL) {
- return NGX_ERROR;
- }
-
- if (url.addrs) {
- u->resolved->sockaddr = url.addrs[0].sockaddr;
- u->resolved->socklen = url.addrs[0].socklen;
- u->resolved->name = url.addrs[0].name;
- u->resolved->naddrs = 1;
- }
-
- u->resolved->host = url.host;
- u->resolved->port = url.port;
- u->resolved->no_port = url.no_port;
-
- return NGX_OK;
-}
-
-
-#if (NGX_HTTP_CACHE)
-
-static ngx_int_t
-ngx_http_scgi_create_key(ngx_http_request_t *r)
-{
- ngx_str_t *key;
- ngx_http_scgi_loc_conf_t *scf;
-
- key = ngx_array_push(&r->cache->keys);
- if (key == NULL) {
- return NGX_ERROR;
- }
-
- scf = ngx_http_get_module_loc_conf(r, ngx_http_scgi_module);
-
- if (ngx_http_complex_value(r, &scf->cache_key, key) != NGX_OK) {
- return NGX_ERROR;
- }
-
- return NGX_OK;
-}
-
-#endif
-
-
-static ngx_int_t
-ngx_http_scgi_create_request(ngx_http_request_t *r)
-{
- off_t content_length_n;
- u_char ch, *key, *val, *lowcase_key;
- size_t len, key_len, val_len, allocated;
- ngx_buf_t *b;
- ngx_str_t content_length;
- ngx_uint_t i, n, hash, skip_empty, header_params;
- ngx_chain_t *cl, *body;
- ngx_list_part_t *part;
- ngx_table_elt_t *header, **ignored;
- ngx_http_scgi_params_t *params;
- ngx_http_script_code_pt code;
- ngx_http_script_engine_t e, le;
- ngx_http_scgi_loc_conf_t *scf;
- ngx_http_script_len_code_pt lcode;
- u_char buffer[NGX_OFF_T_LEN];
-
- content_length_n = 0;
- body = r->upstream->request_bufs;
-
- while (body) {
- content_length_n += ngx_buf_size(body->buf);
- body = body->next;
- }
-
- content_length.data = buffer;
- content_length.len = ngx_sprintf(buffer, "%O", content_length_n) - buffer;
-
- len = sizeof("CONTENT_LENGTH") + content_length.len + 1;
-
- header_params = 0;
- ignored = NULL;
-
- scf = ngx_http_get_module_loc_conf(r, ngx_http_scgi_module);
-
-#if (NGX_HTTP_CACHE)
- params = r->upstream->cacheable ? &scf->params_cache : &scf->params;
-#else
- params = &scf->params;
-#endif
-
- if (params->lengths) {
- ngx_memzero(&le, sizeof(ngx_http_script_engine_t));
-
- ngx_http_script_flush_no_cacheable_variables(r, params->flushes);
- le.flushed = 1;
-
- le.ip = params->lengths->elts;
- le.request = r;
-
- while (*(uintptr_t *) le.ip) {
-
- lcode = *(ngx_http_script_len_code_pt *) le.ip;
- key_len = lcode(&le);
-
- lcode = *(ngx_http_script_len_code_pt *) le.ip;
- skip_empty = lcode(&le);
-
- for (val_len = 0; *(uintptr_t *) le.ip; val_len += lcode(&le)) {
- lcode = *(ngx_http_script_len_code_pt *) le.ip;
- }
- le.ip += sizeof(uintptr_t);
-
- if (skip_empty && val_len == 0) {
- continue;
- }
-
- len += key_len + val_len + 1;
- }
- }
-
- if (scf->upstream.pass_request_headers) {
-
- allocated = 0;
- lowcase_key = NULL;
-
- if (params->number) {
- n = 0;
- part = &r->headers_in.headers.part;
-
- while (part) {
- n += part->nelts;
- part = part->next;
- }
-
- ignored = ngx_palloc(r->pool, n * sizeof(void *));
- if (ignored == NULL) {
- return NGX_ERROR;
- }
- }
-
- part = &r->headers_in.headers.part;
- header = part->elts;
-
- for (i = 0; /* void */; i++) {
-
- if (i >= part->nelts) {
- if (part->next == NULL) {
- break;
- }
-
- part = part->next;
- header = part->elts;
- i = 0;
- }
-
- if (params->number) {
- if (allocated < header[i].key.len) {
- allocated = header[i].key.len + 16;
- lowcase_key = ngx_pnalloc(r->pool, allocated);
- if (lowcase_key == NULL) {
- return NGX_ERROR;
- }
- }
-
- hash = 0;
-
- for (n = 0; n < header[i].key.len; n++) {
- ch = header[i].key.data[n];
-
- if (ch >= 'A' && ch <= 'Z') {
- ch |= 0x20;
-
- } else if (ch == '-') {
- ch = '_';
- }
-
- hash = ngx_hash(hash, ch);
- lowcase_key[n] = ch;
- }
-
- if (ngx_hash_find(&params->hash, hash, lowcase_key, n)) {
- ignored[header_params++] = &header[i];
- continue;
- }
- }
-
- len += sizeof("HTTP_") - 1 + header[i].key.len + 1
- + header[i].value.len + 1;
- }
- }
-
- /* netstring: "length:" + packet + "," */
-
- b = ngx_create_temp_buf(r->pool, NGX_SIZE_T_LEN + 1 + len + 1);
- if (b == NULL) {
- return NGX_ERROR;
- }
-
- cl = ngx_alloc_chain_link(r->pool);
- if (cl == NULL) {
- return NGX_ERROR;
- }
-
- cl->buf = b;
-
- b->last = ngx_sprintf(b->last, "%ui:CONTENT_LENGTH%Z%V%Z",
- len, &content_length);
-
- if (params->lengths) {
- ngx_memzero(&e, sizeof(ngx_http_script_engine_t));
-
- e.ip = params->values->elts;
- e.pos = b->last;
- e.request = r;
- e.flushed = 1;
-
- le.ip = params->lengths->elts;
-
- while (*(uintptr_t *) le.ip) {
-
- lcode = *(ngx_http_script_len_code_pt *) le.ip;
- lcode(&le); /* key length */
-
- lcode = *(ngx_http_script_len_code_pt *) le.ip;
- skip_empty = lcode(&le);
-
- for (val_len = 0; *(uintptr_t *) le.ip; val_len += lcode(&le)) {
- lcode = *(ngx_http_script_len_code_pt *) le.ip;
- }
- le.ip += sizeof(uintptr_t);
-
- if (skip_empty && val_len == 0) {
- e.skip = 1;
-
- while (*(uintptr_t *) e.ip) {
- code = *(ngx_http_script_code_pt *) e.ip;
- code((ngx_http_script_engine_t *) &e);
- }
- e.ip += sizeof(uintptr_t);
-
- e.skip = 0;
-
- continue;
- }
-
-#if (NGX_DEBUG)
- key = e.pos;
-#endif
- code = *(ngx_http_script_code_pt *) e.ip;
- code((ngx_http_script_engine_t *) &e);
-
-#if (NGX_DEBUG)
- val = e.pos;
-#endif
- while (*(uintptr_t *) e.ip) {
- code = *(ngx_http_script_code_pt *) e.ip;
- code((ngx_http_script_engine_t *) &e);
- }
- *e.pos++ = '\0';
- e.ip += sizeof(uintptr_t);
-
- ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "scgi param: \"%s: %s\"", key, val);
- }
-
- b->last = e.pos;
- }
-
- if (scf->upstream.pass_request_headers) {
-
- part = &r->headers_in.headers.part;
- header = part->elts;
-
- for (i = 0; /* void */; i++) {
-
- if (i >= part->nelts) {
- if (part->next == NULL) {
- break;
- }
-
- part = part->next;
- header = part->elts;
- i = 0;
- }
-
- for (n = 0; n < header_params; n++) {
- if (&header[i] == ignored[n]) {
- goto next;
- }
- }
-
- key = b->last;
- b->last = ngx_cpymem(key, "HTTP_", sizeof("HTTP_") - 1);
-
- for (n = 0; n < header[i].key.len; n++) {
- ch = header[i].key.data[n];
-
- if (ch >= 'a' && ch <= 'z') {
- ch &= ~0x20;
-
- } else if (ch == '-') {
- ch = '_';
- }
-
- *b->last++ = ch;
- }
-
- *b->last++ = (u_char) 0;
-
- val = b->last;
- b->last = ngx_copy(val, header[i].value.data, header[i].value.len);
- *b->last++ = (u_char) 0;
-
- ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "scgi param: \"%s: %s\"", key, val);
-
- next:
-
- continue;
- }
- }
-
- *b->last++ = (u_char) ',';
-
- if (r->request_body_no_buffering) {
- r->upstream->request_bufs = cl;
-
- } else if (scf->upstream.pass_request_body) {
- body = r->upstream->request_bufs;
- r->upstream->request_bufs = cl;
-
- while (body) {
- b = ngx_alloc_buf(r->pool);
- if (b == NULL) {
- return NGX_ERROR;
- }
-
- ngx_memcpy(b, body->buf, sizeof(ngx_buf_t));
-
- cl->next = ngx_alloc_chain_link(r->pool);
- if (cl->next == NULL) {
- return NGX_ERROR;
- }
-
- cl = cl->next;
- cl->buf = b;
-
- body = body->next;
- }
-
- } else {
- r->upstream->request_bufs = cl;
- }
-
- cl->next = NULL;
-
- return NGX_OK;
-}
-
-
-static ngx_int_t
-ngx_http_scgi_reinit_request(ngx_http_request_t *r)
-{
- ngx_http_status_t *status;
-
- status = ngx_http_get_module_ctx(r, ngx_http_scgi_module);
-
- if (status == NULL) {
- return NGX_OK;
- }
-
- status->code = 0;
- status->count = 0;
- status->start = NULL;
- status->end = NULL;
-
- r->upstream->process_header = ngx_http_scgi_process_status_line;
- r->state = 0;
-
- return NGX_OK;
-}
-
-
-static ngx_int_t
-ngx_http_scgi_process_status_line(ngx_http_request_t *r)
-{
- size_t len;
- ngx_int_t rc;
- ngx_http_status_t *status;
- ngx_http_upstream_t *u;
-
- status = ngx_http_get_module_ctx(r, ngx_http_scgi_module);
-
- if (status == NULL) {
- return NGX_ERROR;
- }
-
- u = r->upstream;
-
- rc = ngx_http_parse_status_line(r, &u->buffer, status);
-
- if (rc == NGX_AGAIN) {
- return rc;
- }
-
- if (rc == NGX_ERROR) {
- u->process_header = ngx_http_scgi_process_header;
- return ngx_http_scgi_process_header(r);
- }
-
- if (u->state && u->state->status == 0) {
- u->state->status = status->code;
- }
-
- u->headers_in.status_n = status->code;
-
- len = status->end - status->start;
- u->headers_in.status_line.len = len;
-
- u->headers_in.status_line.data = ngx_pnalloc(r->pool, len);
- if (u->headers_in.status_line.data == NULL) {
- return NGX_ERROR;
- }
-
- ngx_memcpy(u->headers_in.status_line.data, status->start, len);
-
- ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "http scgi status %ui \"%V\"",
- u->headers_in.status_n, &u->headers_in.status_line);
-
- u->process_header = ngx_http_scgi_process_header;
-
- return ngx_http_scgi_process_header(r);
-}
-
-
-static ngx_int_t
-ngx_http_scgi_process_header(ngx_http_request_t *r)
-{
- ngx_str_t *status_line;
- ngx_int_t rc, status;
- ngx_table_elt_t *h;
- ngx_http_upstream_t *u;
- ngx_http_upstream_header_t *hh;
- ngx_http_upstream_main_conf_t *umcf;
-
- umcf = ngx_http_get_module_main_conf(r, ngx_http_upstream_module);
-
- for ( ;; ) {
-
- rc = ngx_http_parse_header_line(r, &r->upstream->buffer, 1);
-
- if (rc == NGX_OK) {
-
- /* a header line has been parsed successfully */
-
- h = ngx_list_push(&r->upstream->headers_in.headers);
- if (h == NULL) {
- return NGX_ERROR;
- }
-
- h->hash = r->header_hash;
-
- h->key.len = r->header_name_end - r->header_name_start;
- h->value.len = r->header_end - r->header_start;
-
- h->key.data = ngx_pnalloc(r->pool,
- h->key.len + 1 + h->value.len + 1
- + h->key.len);
- if (h->key.data == NULL) {
- h->hash = 0;
- return NGX_ERROR;
- }
-
- h->value.data = h->key.data + h->key.len + 1;
- h->lowcase_key = h->key.data + h->key.len + 1 + h->value.len + 1;
-
- ngx_memcpy(h->key.data, r->header_name_start, h->key.len);
- h->key.data[h->key.len] = '\0';
- ngx_memcpy(h->value.data, r->header_start, h->value.len);
- h->value.data[h->value.len] = '\0';
-
- if (h->key.len == r->lowcase_index) {
- ngx_memcpy(h->lowcase_key, r->lowcase_header, h->key.len);
-
- } else {
- ngx_strlow(h->lowcase_key, h->key.data, h->key.len);
- }
-
- hh = ngx_hash_find(&umcf->headers_in_hash, h->hash,
- h->lowcase_key, h->key.len);
-
- if (hh && hh->handler(r, h, hh->offset) != NGX_OK) {
- return NGX_ERROR;
- }
-
- ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "http scgi header: \"%V: %V\"", &h->key, &h->value);
-
- continue;
- }
-
- if (rc == NGX_HTTP_PARSE_HEADER_DONE) {
-
- /* a whole header has been parsed successfully */
-
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "http scgi header done");
-
- u = r->upstream;
-
- if (u->headers_in.status_n) {
- goto done;
- }
-
- if (u->headers_in.status) {
- status_line = &u->headers_in.status->value;
-
- status = ngx_atoi(status_line->data, 3);
- if (status == NGX_ERROR) {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "upstream sent invalid status \"%V\"",
- status_line);
- return NGX_HTTP_UPSTREAM_INVALID_HEADER;
- }
-
- u->headers_in.status_n = status;
- u->headers_in.status_line = *status_line;
-
- } else if (u->headers_in.location) {
- u->headers_in.status_n = 302;
- ngx_str_set(&u->headers_in.status_line,
- "302 Moved Temporarily");
-
- } else {
- u->headers_in.status_n = 200;
- ngx_str_set(&u->headers_in.status_line, "200 OK");
- }
-
- if (u->state && u->state->status == 0) {
- u->state->status = u->headers_in.status_n;
- }
-
- done:
-
- if (u->headers_in.status_n == NGX_HTTP_SWITCHING_PROTOCOLS
- && r->headers_in.upgrade)
- {
- u->upgrade = 1;
- }
-
- return NGX_OK;
- }
-
- if (rc == NGX_AGAIN) {
- return NGX_AGAIN;
- }
-
- /* there was error while a header line parsing */
-
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "upstream sent invalid header");
-
- return NGX_HTTP_UPSTREAM_INVALID_HEADER;
- }
-}
-
-
-static void
-ngx_http_scgi_abort_request(ngx_http_request_t *r)
-{
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "abort http scgi request");
-
- return;
-}
-
-
-static void
-ngx_http_scgi_finalize_request(ngx_http_request_t *r, ngx_int_t rc)
-{
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "finalize http scgi request");
-
- return;
-}
-
-
-static void *
-ngx_http_scgi_create_main_conf(ngx_conf_t *cf)
-{
- ngx_http_scgi_main_conf_t *conf;
-
- conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_scgi_main_conf_t));
- if (conf == NULL) {
- return NULL;
- }
-
-#if (NGX_HTTP_CACHE)
- if (ngx_array_init(&conf->caches, cf->pool, 4,
- sizeof(ngx_http_file_cache_t *))
- != NGX_OK)
- {
- return NULL;
- }
-#endif
-
- return conf;
-}
-
-
-static void *
-ngx_http_scgi_create_loc_conf(ngx_conf_t *cf)
-{
- ngx_http_scgi_loc_conf_t *conf;
-
- conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_scgi_loc_conf_t));
- if (conf == NULL) {
- return NULL;
- }
-
- conf->upstream.store = NGX_CONF_UNSET;
- conf->upstream.store_access = NGX_CONF_UNSET_UINT;
- conf->upstream.next_upstream_tries = NGX_CONF_UNSET_UINT;
- conf->upstream.buffering = NGX_CONF_UNSET;
- conf->upstream.request_buffering = NGX_CONF_UNSET;
- conf->upstream.ignore_client_abort = NGX_CONF_UNSET;
- conf->upstream.force_ranges = NGX_CONF_UNSET;
-
- conf->upstream.local = NGX_CONF_UNSET_PTR;
-
- conf->upstream.connect_timeout = NGX_CONF_UNSET_MSEC;
- conf->upstream.send_timeout = NGX_CONF_UNSET_MSEC;
- conf->upstream.read_timeout = NGX_CONF_UNSET_MSEC;
- conf->upstream.next_upstream_timeout = NGX_CONF_UNSET_MSEC;
-
- conf->upstream.send_lowat = NGX_CONF_UNSET_SIZE;
- conf->upstream.buffer_size = NGX_CONF_UNSET_SIZE;
- conf->upstream.limit_rate = NGX_CONF_UNSET_SIZE;
-
- conf->upstream.busy_buffers_size_conf = NGX_CONF_UNSET_SIZE;
- conf->upstream.max_temp_file_size_conf = NGX_CONF_UNSET_SIZE;
- conf->upstream.temp_file_write_size_conf = NGX_CONF_UNSET_SIZE;
-
- conf->upstream.pass_request_headers = NGX_CONF_UNSET;
- conf->upstream.pass_request_body = NGX_CONF_UNSET;
-
-#if (NGX_HTTP_CACHE)
- conf->upstream.cache = NGX_CONF_UNSET;
- conf->upstream.cache_min_uses = NGX_CONF_UNSET_UINT;
- conf->upstream.cache_max_range_offset = NGX_CONF_UNSET;
- conf->upstream.cache_bypass = NGX_CONF_UNSET_PTR;
- conf->upstream.no_cache = NGX_CONF_UNSET_PTR;
- conf->upstream.cache_valid = NGX_CONF_UNSET_PTR;
- conf->upstream.cache_lock = NGX_CONF_UNSET;
- conf->upstream.cache_lock_timeout = NGX_CONF_UNSET_MSEC;
- conf->upstream.cache_lock_age = NGX_CONF_UNSET_MSEC;
- conf->upstream.cache_revalidate = NGX_CONF_UNSET;
- conf->upstream.cache_background_update = NGX_CONF_UNSET;
-#endif
-
- conf->upstream.hide_headers = NGX_CONF_UNSET_PTR;
- conf->upstream.pass_headers = NGX_CONF_UNSET_PTR;
-
- conf->upstream.intercept_errors = NGX_CONF_UNSET;
-
- /* "scgi_cyclic_temp_file" is disabled */
- conf->upstream.cyclic_temp_file = 0;
-
- conf->upstream.change_buffering = 1;
-
- ngx_str_set(&conf->upstream.module, "scgi");
-
- return conf;
-}
-
-
-static char *
-ngx_http_scgi_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
-{
- ngx_http_scgi_loc_conf_t *prev = parent;
- ngx_http_scgi_loc_conf_t *conf = child;
-
- size_t size;
- ngx_int_t rc;
- ngx_hash_init_t hash;
- ngx_http_core_loc_conf_t *clcf;
-
-#if (NGX_HTTP_CACHE)
-
- if (conf->upstream.store > 0) {
- conf->upstream.cache = 0;
- }
-
- if (conf->upstream.cache > 0) {
- conf->upstream.store = 0;
- }
-
-#endif
-
- if (conf->upstream.store == NGX_CONF_UNSET) {
- ngx_conf_merge_value(conf->upstream.store, prev->upstream.store, 0);
-
- conf->upstream.store_lengths = prev->upstream.store_lengths;
- conf->upstream.store_values = prev->upstream.store_values;
- }
-
- ngx_conf_merge_uint_value(conf->upstream.store_access,
- prev->upstream.store_access, 0600);
-
- ngx_conf_merge_uint_value(conf->upstream.next_upstream_tries,
- prev->upstream.next_upstream_tries, 0);
-
- ngx_conf_merge_value(conf->upstream.buffering,
- prev->upstream.buffering, 1);
-
- ngx_conf_merge_value(conf->upstream.request_buffering,
- prev->upstream.request_buffering, 1);
-
- ngx_conf_merge_value(conf->upstream.ignore_client_abort,
- prev->upstream.ignore_client_abort, 0);
-
- ngx_conf_merge_value(conf->upstream.force_ranges,
- prev->upstream.force_ranges, 0);
-
- ngx_conf_merge_ptr_value(conf->upstream.local,
- prev->upstream.local, NULL);
-
- ngx_conf_merge_msec_value(conf->upstream.connect_timeout,
- prev->upstream.connect_timeout, 60000);
-
- ngx_conf_merge_msec_value(conf->upstream.send_timeout,
- prev->upstream.send_timeout, 60000);
-
- ngx_conf_merge_msec_value(conf->upstream.read_timeout,
- prev->upstream.read_timeout, 60000);
-
- ngx_conf_merge_msec_value(conf->upstream.next_upstream_timeout,
- prev->upstream.next_upstream_timeout, 0);
-
- ngx_conf_merge_size_value(conf->upstream.send_lowat,
- prev->upstream.send_lowat, 0);
-
- ngx_conf_merge_size_value(conf->upstream.buffer_size,
- prev->upstream.buffer_size,
- (size_t) ngx_pagesize);
-
- ngx_conf_merge_size_value(conf->upstream.limit_rate,
- prev->upstream.limit_rate, 0);
-
-
- ngx_conf_merge_bufs_value(conf->upstream.bufs, prev->upstream.bufs,
- 8, ngx_pagesize);
-
- if (conf->upstream.bufs.num < 2) {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "there must be at least 2 \"scgi_buffers\"");
- return NGX_CONF_ERROR;
- }
-
-
- size = conf->upstream.buffer_size;
- if (size < conf->upstream.bufs.size) {
- size = conf->upstream.bufs.size;
- }
-
-
- ngx_conf_merge_size_value(conf->upstream.busy_buffers_size_conf,
- prev->upstream.busy_buffers_size_conf,
- NGX_CONF_UNSET_SIZE);
-
- if (conf->upstream.busy_buffers_size_conf == NGX_CONF_UNSET_SIZE) {
- conf->upstream.busy_buffers_size = 2 * size;
- } else {
- conf->upstream.busy_buffers_size =
- conf->upstream.busy_buffers_size_conf;
- }
-
- if (conf->upstream.busy_buffers_size < size) {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "\"scgi_busy_buffers_size\" must be equal to or greater "
- "than the maximum of the value of \"scgi_buffer_size\" and "
- "one of the \"scgi_buffers\"");
-
- return NGX_CONF_ERROR;
- }
-
- if (conf->upstream.busy_buffers_size
- > (conf->upstream.bufs.num - 1) * conf->upstream.bufs.size)
- {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "\"scgi_busy_buffers_size\" must be less than "
- "the size of all \"scgi_buffers\" minus one buffer");
-
- return NGX_CONF_ERROR;
- }
-
-
- ngx_conf_merge_size_value(conf->upstream.temp_file_write_size_conf,
- prev->upstream.temp_file_write_size_conf,
- NGX_CONF_UNSET_SIZE);
-
- if (conf->upstream.temp_file_write_size_conf == NGX_CONF_UNSET_SIZE) {
- conf->upstream.temp_file_write_size = 2 * size;
- } else {
- conf->upstream.temp_file_write_size =
- conf->upstream.temp_file_write_size_conf;
- }
-
- if (conf->upstream.temp_file_write_size < size) {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "\"scgi_temp_file_write_size\" must be equal to or greater than "
- "the maximum of the value of \"scgi_buffer_size\" and "
- "one of the \"scgi_buffers\"");
-
- return NGX_CONF_ERROR;
- }
-
-
- ngx_conf_merge_size_value(conf->upstream.max_temp_file_size_conf,
- prev->upstream.max_temp_file_size_conf,
- NGX_CONF_UNSET_SIZE);
-
- if (conf->upstream.max_temp_file_size_conf == NGX_CONF_UNSET_SIZE) {
- conf->upstream.max_temp_file_size = 1024 * 1024 * 1024;
- } else {
- conf->upstream.max_temp_file_size =
- conf->upstream.max_temp_file_size_conf;
- }
-
- if (conf->upstream.max_temp_file_size != 0
- && conf->upstream.max_temp_file_size < size)
- {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "\"scgi_max_temp_file_size\" must be equal to zero to disable "
- "temporary files usage or must be equal to or greater than "
- "the maximum of the value of \"scgi_buffer_size\" and "
- "one of the \"scgi_buffers\"");
-
- return NGX_CONF_ERROR;
- }
-
-
- ngx_conf_merge_bitmask_value(conf->upstream.ignore_headers,
- prev->upstream.ignore_headers,
- NGX_CONF_BITMASK_SET);
-
-
- ngx_conf_merge_bitmask_value(conf->upstream.next_upstream,
- prev->upstream.next_upstream,
- (NGX_CONF_BITMASK_SET
- |NGX_HTTP_UPSTREAM_FT_ERROR
- |NGX_HTTP_UPSTREAM_FT_TIMEOUT));
-
- if (conf->upstream.next_upstream & NGX_HTTP_UPSTREAM_FT_OFF) {
- conf->upstream.next_upstream = NGX_CONF_BITMASK_SET
- |NGX_HTTP_UPSTREAM_FT_OFF;
- }
-
- if (ngx_conf_merge_path_value(cf, &conf->upstream.temp_path,
- prev->upstream.temp_path,
- &ngx_http_scgi_temp_path)
- != NGX_OK)
- {
- return NGX_CONF_ERROR;
- }
-
-#if (NGX_HTTP_CACHE)
-
- if (conf->upstream.cache == NGX_CONF_UNSET) {
- ngx_conf_merge_value(conf->upstream.cache,
- prev->upstream.cache, 0);
-
- conf->upstream.cache_zone = prev->upstream.cache_zone;
- conf->upstream.cache_value = prev->upstream.cache_value;
- }
-
- if (conf->upstream.cache_zone && conf->upstream.cache_zone->data == NULL) {
- ngx_shm_zone_t *shm_zone;
-
- shm_zone = conf->upstream.cache_zone;
-
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "\"scgi_cache\" zone \"%V\" is unknown",
- &shm_zone->shm.name);
-
- return NGX_CONF_ERROR;
- }
-
- ngx_conf_merge_uint_value(conf->upstream.cache_min_uses,
- prev->upstream.cache_min_uses, 1);
-
- ngx_conf_merge_off_value(conf->upstream.cache_max_range_offset,
- prev->upstream.cache_max_range_offset,
- NGX_MAX_OFF_T_VALUE);
-
- ngx_conf_merge_bitmask_value(conf->upstream.cache_use_stale,
- prev->upstream.cache_use_stale,
- (NGX_CONF_BITMASK_SET
- |NGX_HTTP_UPSTREAM_FT_OFF));
-
- if (conf->upstream.cache_use_stale & NGX_HTTP_UPSTREAM_FT_OFF) {
- conf->upstream.cache_use_stale = NGX_CONF_BITMASK_SET
- |NGX_HTTP_UPSTREAM_FT_OFF;
- }
-
- if (conf->upstream.cache_use_stale & NGX_HTTP_UPSTREAM_FT_ERROR) {
- conf->upstream.cache_use_stale |= NGX_HTTP_UPSTREAM_FT_NOLIVE;
- }
-
- if (conf->upstream.cache_methods == 0) {
- conf->upstream.cache_methods = prev->upstream.cache_methods;
- }
-
- conf->upstream.cache_methods |= NGX_HTTP_GET|NGX_HTTP_HEAD;
-
- ngx_conf_merge_ptr_value(conf->upstream.cache_bypass,
- prev->upstream.cache_bypass, NULL);
-
- ngx_conf_merge_ptr_value(conf->upstream.no_cache,
- prev->upstream.no_cache, NULL);
-
- ngx_conf_merge_ptr_value(conf->upstream.cache_valid,
- prev->upstream.cache_valid, NULL);
-
- if (conf->cache_key.value.data == NULL) {
- conf->cache_key = prev->cache_key;
- }
-
- if (conf->upstream.cache && conf->cache_key.value.data == NULL) {
- ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
- "no \"scgi_cache_key\" for \"scgi_cache\"");
- }
-
- ngx_conf_merge_value(conf->upstream.cache_lock,
- prev->upstream.cache_lock, 0);
-
- ngx_conf_merge_msec_value(conf->upstream.cache_lock_timeout,
- prev->upstream.cache_lock_timeout, 5000);
-
- ngx_conf_merge_msec_value(conf->upstream.cache_lock_age,
- prev->upstream.cache_lock_age, 5000);
-
- ngx_conf_merge_value(conf->upstream.cache_revalidate,
- prev->upstream.cache_revalidate, 0);
-
- ngx_conf_merge_value(conf->upstream.cache_background_update,
- prev->upstream.cache_background_update, 0);
-
-#endif
-
- ngx_conf_merge_value(conf->upstream.pass_request_headers,
- prev->upstream.pass_request_headers, 1);
- ngx_conf_merge_value(conf->upstream.pass_request_body,
- prev->upstream.pass_request_body, 1);
-
- ngx_conf_merge_value(conf->upstream.intercept_errors,
- prev->upstream.intercept_errors, 0);
-
- hash.max_size = 512;
- hash.bucket_size = ngx_align(64, ngx_cacheline_size);
- hash.name = "scgi_hide_headers_hash";
-
- if (ngx_http_upstream_hide_headers_hash(cf, &conf->upstream,
- &prev->upstream, ngx_http_scgi_hide_headers, &hash)
- != NGX_OK)
- {
- return NGX_CONF_ERROR;
- }
-
- clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);
-
- if (clcf->noname
- && conf->upstream.upstream == NULL && conf->scgi_lengths == NULL)
- {
- conf->upstream.upstream = prev->upstream.upstream;
- conf->scgi_lengths = prev->scgi_lengths;
- conf->scgi_values = prev->scgi_values;
- }
-
- if (clcf->lmt_excpt && clcf->handler == NULL
- && (conf->upstream.upstream || conf->scgi_lengths))
- {
- clcf->handler = ngx_http_scgi_handler;
- }
-
- if (conf->params_source == NULL) {
- conf->params = prev->params;
-#if (NGX_HTTP_CACHE)
- conf->params_cache = prev->params_cache;
-#endif
- conf->params_source = prev->params_source;
- }
-
- rc = ngx_http_scgi_init_params(cf, conf, &conf->params, NULL);
- if (rc != NGX_OK) {
- return NGX_CONF_ERROR;
- }
-
-#if (NGX_HTTP_CACHE)
-
- if (conf->upstream.cache) {
- rc = ngx_http_scgi_init_params(cf, conf, &conf->params_cache,
- ngx_http_scgi_cache_headers);
- if (rc != NGX_OK) {
- return NGX_CONF_ERROR;
- }
- }
-
-#endif
-
- /*
- * special handling to preserve conf->params in the "http" section
- * to inherit it to all servers
- */
-
- if (prev->params.hash.buckets == NULL
- && conf->params_source == prev->params_source)
- {
- prev->params = conf->params;
-#if (NGX_HTTP_CACHE)
- prev->params_cache = conf->params_cache;
-#endif
- }
-
- return NGX_CONF_OK;
-}
-
-
-static ngx_int_t
-ngx_http_scgi_init_params(ngx_conf_t *cf, ngx_http_scgi_loc_conf_t *conf,
- ngx_http_scgi_params_t *params, ngx_keyval_t *default_params)
-{
- u_char *p;
- size_t size;
- uintptr_t *code;
- ngx_uint_t i, nsrc;
- ngx_array_t headers_names, params_merged;
- ngx_keyval_t *h;
- ngx_hash_key_t *hk;
- ngx_hash_init_t hash;
- ngx_http_upstream_param_t *src, *s;
- ngx_http_script_compile_t sc;
- ngx_http_script_copy_code_t *copy;
-
- if (params->hash.buckets) {
- return NGX_OK;
- }
-
- if (conf->params_source == NULL && default_params == NULL) {
- params->hash.buckets = (void *) 1;
- return NGX_OK;
- }
-
- params->lengths = ngx_array_create(cf->pool, 64, 1);
- if (params->lengths == NULL) {
- return NGX_ERROR;
- }
-
- params->values = ngx_array_create(cf->pool, 512, 1);
- if (params->values == NULL) {
- return NGX_ERROR;
- }
-
- if (ngx_array_init(&headers_names, cf->temp_pool, 4, sizeof(ngx_hash_key_t))
- != NGX_OK)
- {
- return NGX_ERROR;
- }
-
- if (conf->params_source) {
- src = conf->params_source->elts;
- nsrc = conf->params_source->nelts;
-
- } else {
- src = NULL;
- nsrc = 0;
- }
-
- if (default_params) {
- if (ngx_array_init(&params_merged, cf->temp_pool, 4,
- sizeof(ngx_http_upstream_param_t))
- != NGX_OK)
- {
- return NGX_ERROR;
- }
-
- for (i = 0; i < nsrc; i++) {
-
- s = ngx_array_push(&params_merged);
- if (s == NULL) {
- return NGX_ERROR;
- }
-
- *s = src[i];
- }
-
- h = default_params;
-
- while (h->key.len) {
-
- src = params_merged.elts;
- nsrc = params_merged.nelts;
-
- for (i = 0; i < nsrc; i++) {
- if (ngx_strcasecmp(h->key.data, src[i].key.data) == 0) {
- goto next;
- }
- }
-
- s = ngx_array_push(&params_merged);
- if (s == NULL) {
- return NGX_ERROR;
- }
-
- s->key = h->key;
- s->value = h->value;
- s->skip_empty = 1;
-
- next:
-
- h++;
- }
-
- src = params_merged.elts;
- nsrc = params_merged.nelts;
- }
-
- for (i = 0; i < nsrc; i++) {
-
- if (src[i].key.len > sizeof("HTTP_") - 1
- && ngx_strncmp(src[i].key.data, "HTTP_", sizeof("HTTP_") - 1) == 0)
- {
- hk = ngx_array_push(&headers_names);
- if (hk == NULL) {
- return NGX_ERROR;
- }
-
- hk->key.len = src[i].key.len - 5;
- hk->key.data = src[i].key.data + 5;
- hk->key_hash = ngx_hash_key_lc(hk->key.data, hk->key.len);
- hk->value = (void *) 1;
-
- if (src[i].value.len == 0) {
- continue;
- }
- }
-
- copy = ngx_array_push_n(params->lengths,
- sizeof(ngx_http_script_copy_code_t));
- if (copy == NULL) {
- return NGX_ERROR;
- }
-
- copy->code = (ngx_http_script_code_pt) (void *)
- ngx_http_script_copy_len_code;
- copy->len = src[i].key.len + 1;
-
- copy = ngx_array_push_n(params->lengths,
- sizeof(ngx_http_script_copy_code_t));
- if (copy == NULL) {
- return NGX_ERROR;
- }
-
- copy->code = (ngx_http_script_code_pt) (void *)
- ngx_http_script_copy_len_code;
- copy->len = src[i].skip_empty;
-
-
- size = (sizeof(ngx_http_script_copy_code_t)
- + src[i].key.len + 1 + sizeof(uintptr_t) - 1)
- & ~(sizeof(uintptr_t) - 1);
-
- copy = ngx_array_push_n(params->values, size);
- if (copy == NULL) {
- return NGX_ERROR;
- }
-
- copy->code = ngx_http_script_copy_code;
- copy->len = src[i].key.len + 1;
-
- p = (u_char *) copy + sizeof(ngx_http_script_copy_code_t);
- (void) ngx_cpystrn(p, src[i].key.data, src[i].key.len + 1);
-
-
- ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));
-
- sc.cf = cf;
- sc.source = &src[i].value;
- sc.flushes = &params->flushes;
- sc.lengths = &params->lengths;
- sc.values = &params->values;
-
- if (ngx_http_script_compile(&sc) != NGX_OK) {
- return NGX_ERROR;
- }
-
- code = ngx_array_push_n(params->lengths, sizeof(uintptr_t));
- if (code == NULL) {
- return NGX_ERROR;
- }
-
- *code = (uintptr_t) NULL;
-
-
- code = ngx_array_push_n(params->values, sizeof(uintptr_t));
- if (code == NULL) {
- return NGX_ERROR;
- }
-
- *code = (uintptr_t) NULL;
- }
-
- code = ngx_array_push_n(params->lengths, sizeof(uintptr_t));
- if (code == NULL) {
- return NGX_ERROR;
- }
-
- *code = (uintptr_t) NULL;
-
- params->number = headers_names.nelts;
-
- hash.hash = &params->hash;
- hash.key = ngx_hash_key_lc;
- hash.max_size = 512;
- hash.bucket_size = 64;
- hash.name = "scgi_params_hash";
- hash.pool = cf->pool;
- hash.temp_pool = NULL;
-
- return ngx_hash_init(&hash, headers_names.elts, headers_names.nelts);
-}
-
-
-static char *
-ngx_http_scgi_pass(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
-{
- ngx_http_scgi_loc_conf_t *scf = conf;
-
- ngx_url_t u;
- ngx_str_t *value, *url;
- ngx_uint_t n;
- ngx_http_core_loc_conf_t *clcf;
- ngx_http_script_compile_t sc;
-
- if (scf->upstream.upstream || scf->scgi_lengths) {
- return "is duplicate";
- }
-
- clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);
- clcf->handler = ngx_http_scgi_handler;
-
- value = cf->args->elts;
-
- url = &value[1];
-
- n = ngx_http_script_variables_count(url);
-
- if (n) {
-
- ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));
-
- sc.cf = cf;
- sc.source = url;
- sc.lengths = &scf->scgi_lengths;
- sc.values = &scf->scgi_values;
- sc.variables = n;
- sc.complete_lengths = 1;
- sc.complete_values = 1;
-
- if (ngx_http_script_compile(&sc) != NGX_OK) {
- return NGX_CONF_ERROR;
- }
-
- return NGX_CONF_OK;
- }
-
- ngx_memzero(&u, sizeof(ngx_url_t));
-
- u.url = value[1];
- u.no_resolve = 1;
-
- scf->upstream.upstream = ngx_http_upstream_add(cf, &u, 0);
- if (scf->upstream.upstream == NULL) {
- return NGX_CONF_ERROR;
- }
-
- if (clcf->name.data[clcf->name.len - 1] == '/') {
- clcf->auto_redirect = 1;
- }
-
- return NGX_CONF_OK;
-}
-
-
-static char *
-ngx_http_scgi_store(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
-{
- ngx_http_scgi_loc_conf_t *scf = conf;
-
- ngx_str_t *value;
- ngx_http_script_compile_t sc;
-
- if (scf->upstream.store != NGX_CONF_UNSET) {
- return "is duplicate";
- }
-
- value = cf->args->elts;
-
- if (ngx_strcmp(value[1].data, "off") == 0) {
- scf->upstream.store = 0;
- return NGX_CONF_OK;
- }
-
-#if (NGX_HTTP_CACHE)
- if (scf->upstream.cache > 0) {
- return "is incompatible with \"scgi_cache\"";
- }
-#endif
-
- scf->upstream.store = 1;
-
- if (ngx_strcmp(value[1].data, "on") == 0) {
- return NGX_CONF_OK;
- }
-
- /* include the terminating '\0' into script */
- value[1].len++;
-
- ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));
-
- sc.cf = cf;
- sc.source = &value[1];
- sc.lengths = &scf->upstream.store_lengths;
- sc.values = &scf->upstream.store_values;
- sc.variables = ngx_http_script_variables_count(&value[1]);
- sc.complete_lengths = 1;
- sc.complete_values = 1;
-
- if (ngx_http_script_compile(&sc) != NGX_OK) {
- return NGX_CONF_ERROR;
- }
-
- return NGX_CONF_OK;
-}
-
-
-#if (NGX_HTTP_CACHE)
-
-static char *
-ngx_http_scgi_cache(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
-{
- ngx_http_scgi_loc_conf_t *scf = conf;
-
- ngx_str_t *value;
- ngx_http_complex_value_t cv;
- ngx_http_compile_complex_value_t ccv;
-
- value = cf->args->elts;
-
- if (scf->upstream.cache != NGX_CONF_UNSET) {
- return "is duplicate";
- }
-
- if (ngx_strcmp(value[1].data, "off") == 0) {
- scf->upstream.cache = 0;
- return NGX_CONF_OK;
- }
-
- if (scf->upstream.store > 0) {
- return "is incompatible with \"scgi_store\"";
- }
-
- scf->upstream.cache = 1;
-
- 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) {
-
- scf->upstream.cache_value = ngx_palloc(cf->pool,
- sizeof(ngx_http_complex_value_t));
- if (scf->upstream.cache_value == NULL) {
- return NGX_CONF_ERROR;
- }
-
- *scf->upstream.cache_value = cv;
-
- return NGX_CONF_OK;
- }
-
- scf->upstream.cache_zone = ngx_shared_memory_add(cf, &value[1], 0,
- &ngx_http_scgi_module);
- if (scf->upstream.cache_zone == NULL) {
- return NGX_CONF_ERROR;
- }
-
- return NGX_CONF_OK;
-}
-
-
-static char *
-ngx_http_scgi_cache_key(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
-{
- ngx_http_scgi_loc_conf_t *scf = conf;
-
- ngx_str_t *value;
- ngx_http_compile_complex_value_t ccv;
-
- value = cf->args->elts;
-
- if (scf->cache_key.value.data) {
- return "is duplicate";
- }
-
- ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));
-
- ccv.cf = cf;
- ccv.value = &value[1];
- ccv.complex_value = &scf->cache_key;
-
- if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
- return NGX_CONF_ERROR;
- }
-
- return NGX_CONF_OK;
-}
-
-#endif
diff --git a/nginx/src/http/modules/ngx_http_secure_link_module.c b/nginx/src/http/modules/ngx_http_secure_link_module.c
deleted file mode 100644
index 536e09a..0000000
--- a/nginx/src/http/modules/ngx_http_secure_link_module.c
+++ /dev/null
@@ -1,367 +0,0 @@
-
-/*
- * Copyright (C) Igor Sysoev
- * Copyright (C) Nginx, Inc.
- */
-
-
-#include <ngx_config.h>
-#include <ngx_core.h>
-#include <ngx_http.h>
-#include <ngx_md5.h>
-
-
-typedef struct {
- ngx_http_complex_value_t *variable;
- ngx_http_complex_value_t *md5;
- ngx_str_t secret;
-} ngx_http_secure_link_conf_t;
-
-
-typedef struct {
- ngx_str_t expires;
-} ngx_http_secure_link_ctx_t;
-
-
-static ngx_int_t ngx_http_secure_link_old_variable(ngx_http_request_t *r,
- ngx_http_secure_link_conf_t *conf, ngx_http_variable_value_t *v,
- uintptr_t data);
-static ngx_int_t ngx_http_secure_link_expires_variable(ngx_http_request_t *r,
- ngx_http_variable_value_t *v, uintptr_t data);
-static void *ngx_http_secure_link_create_conf(ngx_conf_t *cf);
-static char *ngx_http_secure_link_merge_conf(ngx_conf_t *cf, void *parent,
- void *child);
-static ngx_int_t ngx_http_secure_link_add_variables(ngx_conf_t *cf);
-
-
-static ngx_command_t ngx_http_secure_link_commands[] = {
-
- { ngx_string("secure_link"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_http_set_complex_value_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_secure_link_conf_t, variable),
- NULL },
-
- { ngx_string("secure_link_md5"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_http_set_complex_value_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_secure_link_conf_t, md5),
- NULL },
-
- { ngx_string("secure_link_secret"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_str_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_secure_link_conf_t, secret),
- NULL },
-
- ngx_null_command
-};
-
-
-static ngx_http_module_t ngx_http_secure_link_module_ctx = {
- ngx_http_secure_link_add_variables, /* preconfiguration */
- NULL, /* postconfiguration */
-
- NULL, /* create main configuration */
- NULL, /* init main configuration */
-
- NULL, /* create server configuration */
- NULL, /* merge server configuration */
-
- ngx_http_secure_link_create_conf, /* create location configuration */
- ngx_http_secure_link_merge_conf /* merge location configuration */
-};
-
-
-ngx_module_t ngx_http_secure_link_module = {
- NGX_MODULE_V1,
- &ngx_http_secure_link_module_ctx, /* module context */
- ngx_http_secure_link_commands, /* module directives */
- NGX_HTTP_MODULE, /* module type */
- NULL, /* init master */
- NULL, /* init module */
- NULL, /* init process */
- NULL, /* init thread */
- NULL, /* exit thread */
- NULL, /* exit process */
- NULL, /* exit master */
- NGX_MODULE_V1_PADDING
-};
-
-
-static ngx_str_t ngx_http_secure_link_name = ngx_string("secure_link");
-static ngx_str_t ngx_http_secure_link_expires_name =
- ngx_string("secure_link_expires");
-
-
-static ngx_int_t
-ngx_http_secure_link_variable(ngx_http_request_t *r,
- ngx_http_variable_value_t *v, uintptr_t data)
-{
- u_char *p, *last;
- ngx_str_t val, hash;
- time_t expires;
- ngx_md5_t md5;
- ngx_http_secure_link_ctx_t *ctx;
- ngx_http_secure_link_conf_t *conf;
- u_char hash_buf[18], md5_buf[16];
-
- conf = ngx_http_get_module_loc_conf(r, ngx_http_secure_link_module);
-
- if (conf->secret.data) {
- return ngx_http_secure_link_old_variable(r, conf, v, data);
- }
-
- if (conf->variable == NULL || conf->md5 == NULL) {
- goto not_found;
- }
-
- if (ngx_http_complex_value(r, conf->variable, &val) != NGX_OK) {
- return NGX_ERROR;
- }
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "secure link: \"%V\"", &val);
-
- last = val.data + val.len;
-
- p = ngx_strlchr(val.data, last, ',');
- expires = 0;
-
- if (p) {
- val.len = p++ - val.data;
-
- expires = ngx_atotm(p, last - p);
- if (expires <= 0) {
- goto not_found;
- }
-
- ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_secure_link_ctx_t));
- if (ctx == NULL) {
- return NGX_ERROR;
- }
-
- ngx_http_set_ctx(r, ctx, ngx_http_secure_link_module);
-
- ctx->expires.len = last - p;
- ctx->expires.data = p;
- }
-
- if (val.len > 24) {
- goto not_found;
- }
-
- hash.data = hash_buf;
-
- if (ngx_decode_base64url(&hash, &val) != NGX_OK) {
- goto not_found;
- }
-
- if (hash.len != 16) {
- goto not_found;
- }
-
- if (ngx_http_complex_value(r, conf->md5, &val) != NGX_OK) {
- return NGX_ERROR;
- }
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "secure link md5: \"%V\"", &val);
-
- ngx_md5_init(&md5);
- ngx_md5_update(&md5, val.data, val.len);
- ngx_md5_final(md5_buf, &md5);
-
- if (ngx_memcmp(hash_buf, md5_buf, 16) != 0) {
- goto not_found;
- }
-
- v->data = (u_char *) ((expires && expires < ngx_time()) ? "0" : "1");
- v->len = 1;
- v->valid = 1;
- v->no_cacheable = 0;
- v->not_found = 0;
-
- return NGX_OK;
-
-not_found:
-
- v->not_found = 1;
-
- return NGX_OK;
-}
-
-
-static ngx_int_t
-ngx_http_secure_link_old_variable(ngx_http_request_t *r,
- ngx_http_secure_link_conf_t *conf, ngx_http_variable_value_t *v,
- uintptr_t data)
-{
- u_char *p, *start, *end, *last;
- size_t len;
- ngx_int_t n;
- ngx_uint_t i;
- ngx_md5_t md5;
- u_char hash[16];
-
- p = &r->unparsed_uri.data[1];
- last = r->unparsed_uri.data + r->unparsed_uri.len;
-
- while (p < last) {
- if (*p++ == '/') {
- start = p;
- goto md5_start;
- }
- }
-
- goto not_found;
-
-md5_start:
-
- while (p < last) {
- if (*p++ == '/') {
- end = p - 1;
- goto url_start;
- }
- }
-
- goto not_found;
-
-url_start:
-
- len = last - p;
-
- if (end - start != 32 || len == 0) {
- goto not_found;
- }
-
- ngx_md5_init(&md5);
- ngx_md5_update(&md5, p, len);
- ngx_md5_update(&md5, conf->secret.data, conf->secret.len);
- ngx_md5_final(hash, &md5);
-
- for (i = 0; i < 16; i++) {
- n = ngx_hextoi(&start[2 * i], 2);
- if (n == NGX_ERROR || n != hash[i]) {
- goto not_found;
- }
- }
-
- v->len = len;
- v->valid = 1;
- v->no_cacheable = 0;
- v->not_found = 0;
- v->data = p;
-
- return NGX_OK;
-
-not_found:
-
- v->not_found = 1;
-
- return NGX_OK;
-}
-
-
-static ngx_int_t
-ngx_http_secure_link_expires_variable(ngx_http_request_t *r,
- ngx_http_variable_value_t *v, uintptr_t data)
-{
- ngx_http_secure_link_ctx_t *ctx;
-
- ctx = ngx_http_get_module_ctx(r, ngx_http_secure_link_module);
-
- if (ctx) {
- v->len = ctx->expires.len;
- v->valid = 1;
- v->no_cacheable = 0;
- v->not_found = 0;
- v->data = ctx->expires.data;
-
- } else {
- v->not_found = 1;
- }
-
- return NGX_OK;
-}
-
-
-static void *
-ngx_http_secure_link_create_conf(ngx_conf_t *cf)
-{
- ngx_http_secure_link_conf_t *conf;
-
- conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_secure_link_conf_t));
- if (conf == NULL) {
- return NULL;
- }
-
- /*
- * set by ngx_pcalloc():
- *
- * conf->variable = NULL;
- * conf->md5 = NULL;
- * conf->secret = { 0, NULL };
- */
-
- return conf;
-}
-
-
-static char *
-ngx_http_secure_link_merge_conf(ngx_conf_t *cf, void *parent, void *child)
-{
- ngx_http_secure_link_conf_t *prev = parent;
- ngx_http_secure_link_conf_t *conf = child;
-
- if (conf->secret.data) {
- if (conf->variable || conf->md5) {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "\"secure_link_secret\" cannot be mixed with "
- "\"secure_link\" and \"secure_link_md5\"");
- return NGX_CONF_ERROR;
- }
-
- return NGX_CONF_OK;
- }
-
- if (conf->variable == NULL) {
- conf->variable = prev->variable;
- }
-
- if (conf->md5 == NULL) {
- conf->md5 = prev->md5;
- }
-
- if (conf->variable == NULL && conf->md5 == NULL) {
- conf->secret = prev->secret;
- }
-
- return NGX_CONF_OK;
-}
-
-
-static ngx_int_t
-ngx_http_secure_link_add_variables(ngx_conf_t *cf)
-{
- ngx_http_variable_t *var;
-
- var = ngx_http_add_variable(cf, &ngx_http_secure_link_name, 0);
- if (var == NULL) {
- return NGX_ERROR;
- }
-
- var->get_handler = ngx_http_secure_link_variable;
-
- var = ngx_http_add_variable(cf, &ngx_http_secure_link_expires_name, 0);
- if (var == NULL) {
- return NGX_ERROR;
- }
-
- var->get_handler = ngx_http_secure_link_expires_variable;
-
- return NGX_OK;
-}
diff --git a/nginx/src/http/modules/ngx_http_slice_filter_module.c b/nginx/src/http/modules/ngx_http_slice_filter_module.c
deleted file mode 100644
index c1edbca..0000000
--- a/nginx/src/http/modules/ngx_http_slice_filter_module.c
+++ /dev/null
@@ -1,545 +0,0 @@
-
-/*
- * Copyright (C) Roman Arutyunyan
- * Copyright (C) Nginx, Inc.
- */
-
-
-#include <ngx_config.h>
-#include <ngx_core.h>
-#include <ngx_http.h>
-
-
-typedef struct {
- size_t size;
-} ngx_http_slice_loc_conf_t;
-
-
-typedef struct {
- off_t start;
- off_t end;
- ngx_str_t range;
- ngx_str_t etag;
- unsigned last:1;
- unsigned active:1;
- ngx_http_request_t *sr;
-} ngx_http_slice_ctx_t;
-
-
-typedef struct {
- off_t start;
- off_t end;
- off_t complete_length;
-} ngx_http_slice_content_range_t;
-
-
-static ngx_int_t ngx_http_slice_header_filter(ngx_http_request_t *r);
-static ngx_int_t ngx_http_slice_body_filter(ngx_http_request_t *r,
- ngx_chain_t *in);
-static ngx_int_t ngx_http_slice_parse_content_range(ngx_http_request_t *r,
- ngx_http_slice_content_range_t *cr);
-static ngx_int_t ngx_http_slice_range_variable(ngx_http_request_t *r,
- ngx_http_variable_value_t *v, uintptr_t data);
-static off_t ngx_http_slice_get_start(ngx_http_request_t *r);
-static void *ngx_http_slice_create_loc_conf(ngx_conf_t *cf);
-static char *ngx_http_slice_merge_loc_conf(ngx_conf_t *cf, void *parent,
- void *child);
-static ngx_int_t ngx_http_slice_add_variables(ngx_conf_t *cf);
-static ngx_int_t ngx_http_slice_init(ngx_conf_t *cf);
-
-
-static ngx_command_t ngx_http_slice_filter_commands[] = {
-
- { ngx_string("slice"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_size_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_slice_loc_conf_t, size),
- NULL },
-
- ngx_null_command
-};
-
-
-static ngx_http_module_t ngx_http_slice_filter_module_ctx = {
- ngx_http_slice_add_variables, /* preconfiguration */
- ngx_http_slice_init, /* postconfiguration */
-
- NULL, /* create main configuration */
- NULL, /* init main configuration */
-
- NULL, /* create server configuration */
- NULL, /* merge server configuration */
-
- ngx_http_slice_create_loc_conf, /* create location configuration */
- ngx_http_slice_merge_loc_conf /* merge location configuration */
-};
-
-
-ngx_module_t ngx_http_slice_filter_module = {
- NGX_MODULE_V1,
- &ngx_http_slice_filter_module_ctx, /* module context */
- ngx_http_slice_filter_commands, /* module directives */
- NGX_HTTP_MODULE, /* module type */
- NULL, /* init master */
- NULL, /* init module */
- NULL, /* init process */
- NULL, /* init thread */
- NULL, /* exit thread */
- NULL, /* exit process */
- NULL, /* exit master */
- NGX_MODULE_V1_PADDING
-};
-
-
-static ngx_str_t ngx_http_slice_range_name = ngx_string("slice_range");
-
-static ngx_http_output_header_filter_pt ngx_http_next_header_filter;
-static ngx_http_output_body_filter_pt ngx_http_next_body_filter;
-
-
-static ngx_int_t
-ngx_http_slice_header_filter(ngx_http_request_t *r)
-{
- off_t end;
- ngx_int_t rc;
- ngx_table_elt_t *h;
- ngx_http_slice_ctx_t *ctx;
- ngx_http_slice_loc_conf_t *slcf;
- ngx_http_slice_content_range_t cr;
-
- ctx = ngx_http_get_module_ctx(r, ngx_http_slice_filter_module);
- if (ctx == NULL) {
- return ngx_http_next_header_filter(r);
- }
-
- if (r->headers_out.status != NGX_HTTP_PARTIAL_CONTENT) {
- if (r == r->main) {
- ngx_http_set_ctx(r, NULL, ngx_http_slice_filter_module);
- return ngx_http_next_header_filter(r);
- }
-
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "unexpected status code %ui in slice response",
- r->headers_out.status);
- return NGX_ERROR;
- }
-
- h = r->headers_out.etag;
-
- if (ctx->etag.len) {
- if (h == NULL
- || h->value.len != ctx->etag.len
- || ngx_strncmp(h->value.data, ctx->etag.data, ctx->etag.len)
- != 0)
- {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "etag mismatch in slice response");
- return NGX_ERROR;
- }
- }
-
- if (h) {
- ctx->etag = h->value;
- }
-
- if (ngx_http_slice_parse_content_range(r, &cr) != NGX_OK) {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "invalid range in slice response");
- return NGX_ERROR;
- }
-
- if (cr.complete_length == -1) {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "no complete length in slice response");
- return NGX_ERROR;
- }
-
- ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "http slice response range: %O-%O/%O",
- cr.start, cr.end, cr.complete_length);
-
- slcf = ngx_http_get_module_loc_conf(r, ngx_http_slice_filter_module);
-
- end = ngx_min(cr.start + (off_t) slcf->size, cr.complete_length);
-
- if (cr.start != ctx->start || cr.end != end) {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "unexpected range in slice response: %O-%O",
- cr.start, cr.end);
- return NGX_ERROR;
- }
-
- ctx->start = end;
- ctx->active = 1;
-
- r->headers_out.status = NGX_HTTP_OK;
- r->headers_out.status_line.len = 0;
- r->headers_out.content_length_n = cr.complete_length;
- r->headers_out.content_offset = cr.start;
- r->headers_out.content_range->hash = 0;
- r->headers_out.content_range = NULL;
-
- r->allow_ranges = 1;
- r->subrequest_ranges = 1;
- r->single_range = 1;
-
- rc = ngx_http_next_header_filter(r);
-
- if (r != r->main) {
- return rc;
- }
-
- r->preserve_body = 1;
-
- if (r->headers_out.status == NGX_HTTP_PARTIAL_CONTENT) {
- if (ctx->start + (off_t) slcf->size <= r->headers_out.content_offset) {
- ctx->start = slcf->size
- * (r->headers_out.content_offset / slcf->size);
- }
-
- ctx->end = r->headers_out.content_offset
- + r->headers_out.content_length_n;
-
- } else {
- ctx->end = cr.complete_length;
- }
-
- return rc;
-}
-
-
-static ngx_int_t
-ngx_http_slice_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
-{
- ngx_int_t rc;
- ngx_chain_t *cl;
- ngx_http_slice_ctx_t *ctx;
- ngx_http_slice_loc_conf_t *slcf;
-
- ctx = ngx_http_get_module_ctx(r, ngx_http_slice_filter_module);
-
- if (ctx == NULL || r != r->main) {
- return ngx_http_next_body_filter(r, in);
- }
-
- for (cl = in; cl; cl = cl->next) {
- if (cl->buf->last_buf) {
- cl->buf->last_buf = 0;
- cl->buf->last_in_chain = 1;
- cl->buf->sync = 1;
- ctx->last = 1;
- }
- }
-
- rc = ngx_http_next_body_filter(r, in);
-
- if (rc == NGX_ERROR || !ctx->last) {
- return rc;
- }
-
- if (ctx->sr && !ctx->sr->done) {
- return rc;
- }
-
- if (!ctx->active) {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "missing slice response");
- return NGX_ERROR;
- }
-
- if (ctx->start >= ctx->end) {
- ngx_http_set_ctx(r, NULL, ngx_http_slice_filter_module);
- ngx_http_send_special(r, NGX_HTTP_LAST);
- return rc;
- }
-
- if (r->buffered) {
- return rc;
- }
-
- if (ngx_http_subrequest(r, &r->uri, &r->args, &ctx->sr, NULL,
- NGX_HTTP_SUBREQUEST_CLONE)
- != NGX_OK)
- {
- return NGX_ERROR;
- }
-
- ngx_http_set_ctx(ctx->sr, ctx, ngx_http_slice_filter_module);
-
- slcf = ngx_http_get_module_loc_conf(r, ngx_http_slice_filter_module);
-
- ctx->range.len = ngx_sprintf(ctx->range.data, "bytes=%O-%O", ctx->start,
- ctx->start + (off_t) slcf->size - 1)
- - ctx->range.data;
-
- ctx->active = 0;
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "http slice subrequest: \"%V\"", &ctx->range);
-
- return rc;
-}
-
-
-static ngx_int_t
-ngx_http_slice_parse_content_range(ngx_http_request_t *r,
- ngx_http_slice_content_range_t *cr)
-{
- off_t start, end, complete_length, cutoff, cutlim;
- u_char *p;
- ngx_table_elt_t *h;
-
- h = r->headers_out.content_range;
-
- if (h == NULL
- || h->value.len < 7
- || ngx_strncmp(h->value.data, "bytes ", 6) != 0)
- {
- return NGX_ERROR;
- }
-
- p = h->value.data + 6;
-
- cutoff = NGX_MAX_OFF_T_VALUE / 10;
- cutlim = NGX_MAX_OFF_T_VALUE % 10;
-
- start = 0;
- end = 0;
- complete_length = 0;
-
- while (*p == ' ') { p++; }
-
- if (*p < '0' || *p > '9') {
- return NGX_ERROR;
- }
-
- while (*p >= '0' && *p <= '9') {
- if (start >= cutoff && (start > cutoff || *p - '0' > cutlim)) {
- return NGX_ERROR;
- }
-
- start = start * 10 + (*p++ - '0');
- }
-
- while (*p == ' ') { p++; }
-
- if (*p++ != '-') {
- return NGX_ERROR;
- }
-
- while (*p == ' ') { p++; }
-
- if (*p < '0' || *p > '9') {
- return NGX_ERROR;
- }
-
- while (*p >= '0' && *p <= '9') {
- if (end >= cutoff && (end > cutoff || *p - '0' > cutlim)) {
- return NGX_ERROR;
- }
-
- end = end * 10 + (*p++ - '0');
- }
-
- end++;
-
- while (*p == ' ') { p++; }
-
- if (*p++ != '/') {
- return NGX_ERROR;
- }
-
- while (*p == ' ') { p++; }
-
- if (*p != '*') {
- if (*p < '0' || *p > '9') {
- return NGX_ERROR;
- }
-
- while (*p >= '0' && *p <= '9') {
- if (complete_length >= cutoff
- && (complete_length > cutoff || *p - '0' > cutlim))
- {
- return NGX_ERROR;
- }
-
- complete_length = complete_length * 10 + (*p++ - '0');
- }
-
- } else {
- complete_length = -1;
- p++;
- }
-
- while (*p == ' ') { p++; }
-
- if (*p != '\0') {
- return NGX_ERROR;
- }
-
- cr->start = start;
- cr->end = end;
- cr->complete_length = complete_length;
-
- return NGX_OK;
-}
-
-
-static ngx_int_t
-ngx_http_slice_range_variable(ngx_http_request_t *r,
- ngx_http_variable_value_t *v, uintptr_t data)
-{
- u_char *p;
- ngx_http_slice_ctx_t *ctx;
- ngx_http_slice_loc_conf_t *slcf;
-
- ctx = ngx_http_get_module_ctx(r, ngx_http_slice_filter_module);
-
- if (ctx == NULL) {
- if (r != r->main || r->headers_out.status) {
- v->not_found = 1;
- return NGX_OK;
- }
-
- slcf = ngx_http_get_module_loc_conf(r, ngx_http_slice_filter_module);
-
- if (slcf->size == 0) {
- v->not_found = 1;
- return NGX_OK;
- }
-
- ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_slice_ctx_t));
- if (ctx == NULL) {
- return NGX_ERROR;
- }
-
- ngx_http_set_ctx(r, ctx, ngx_http_slice_filter_module);
-
- p = ngx_pnalloc(r->pool, sizeof("bytes=-") - 1 + 2 * NGX_OFF_T_LEN);
- if (p == NULL) {
- return NGX_ERROR;
- }
-
- ctx->start = slcf->size * (ngx_http_slice_get_start(r) / slcf->size);
-
- ctx->range.data = p;
- ctx->range.len = ngx_sprintf(p, "bytes=%O-%O", ctx->start,
- ctx->start + (off_t) slcf->size - 1)
- - p;
- }
-
- v->data = ctx->range.data;
- v->valid = 1;
- v->not_found = 0;
- v->no_cacheable = 1;
- v->len = ctx->range.len;
-
- return NGX_OK;
-}
-
-
-static off_t
-ngx_http_slice_get_start(ngx_http_request_t *r)
-{
- off_t start, cutoff, cutlim;
- u_char *p;
- ngx_table_elt_t *h;
-
- if (r->headers_in.if_range) {
- return 0;
- }
-
- h = r->headers_in.range;
-
- if (h == NULL
- || h->value.len < 7
- || ngx_strncasecmp(h->value.data, (u_char *) "bytes=", 6) != 0)
- {
- return 0;
- }
-
- p = h->value.data + 6;
-
- if (ngx_strchr(p, ',')) {
- return 0;
- }
-
- while (*p == ' ') { p++; }
-
- if (*p == '-') {
- return 0;
- }
-
- cutoff = NGX_MAX_OFF_T_VALUE / 10;
- cutlim = NGX_MAX_OFF_T_VALUE % 10;
-
- start = 0;
-
- while (*p >= '0' && *p <= '9') {
- if (start >= cutoff && (start > cutoff || *p - '0' > cutlim)) {
- return 0;
- }
-
- start = start * 10 + (*p++ - '0');
- }
-
- return start;
-}
-
-
-static void *
-ngx_http_slice_create_loc_conf(ngx_conf_t *cf)
-{
- ngx_http_slice_loc_conf_t *slcf;
-
- slcf = ngx_palloc(cf->pool, sizeof(ngx_http_slice_loc_conf_t));
- if (slcf == NULL) {
- return NULL;
- }
-
- slcf->size = NGX_CONF_UNSET_SIZE;
-
- return slcf;
-}
-
-
-static char *
-ngx_http_slice_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
-{
- ngx_http_slice_loc_conf_t *prev = parent;
- ngx_http_slice_loc_conf_t *conf = child;
-
- ngx_conf_merge_size_value(conf->size, prev->size, 0);
-
- return NGX_CONF_OK;
-}
-
-
-static ngx_int_t
-ngx_http_slice_add_variables(ngx_conf_t *cf)
-{
- ngx_http_variable_t *var;
-
- var = ngx_http_add_variable(cf, &ngx_http_slice_range_name, 0);
- if (var == NULL) {
- return NGX_ERROR;
- }
-
- var->get_handler = ngx_http_slice_range_variable;
-
- return NGX_OK;
-}
-
-
-static ngx_int_t
-ngx_http_slice_init(ngx_conf_t *cf)
-{
- ngx_http_next_header_filter = ngx_http_top_header_filter;
- ngx_http_top_header_filter = ngx_http_slice_header_filter;
-
- ngx_http_next_body_filter = ngx_http_top_body_filter;
- ngx_http_top_body_filter = ngx_http_slice_body_filter;
-
- return NGX_OK;
-}
diff --git a/nginx/src/http/modules/ngx_http_split_clients_module.c b/nginx/src/http/modules/ngx_http_split_clients_module.c
deleted file mode 100644
index 2f92c9e..0000000
--- a/nginx/src/http/modules/ngx_http_split_clients_module.c
+++ /dev/null
@@ -1,246 +0,0 @@
-
-/*
- * Copyright (C) Igor Sysoev
- * Copyright (C) Nginx, Inc.
- */
-
-
-#include <ngx_config.h>
-#include <ngx_core.h>
-#include <ngx_http.h>
-
-
-typedef struct {
- uint32_t percent;
- ngx_http_variable_value_t value;
-} ngx_http_split_clients_part_t;
-
-
-typedef struct {
- ngx_http_complex_value_t value;
- ngx_array_t parts;
-} ngx_http_split_clients_ctx_t;
-
-
-static char *ngx_conf_split_clients_block(ngx_conf_t *cf, ngx_command_t *cmd,
- void *conf);
-static char *ngx_http_split_clients(ngx_conf_t *cf, ngx_command_t *dummy,
- void *conf);
-
-static ngx_command_t ngx_http_split_clients_commands[] = {
-
- { ngx_string("split_clients"),
- NGX_HTTP_MAIN_CONF|NGX_CONF_BLOCK|NGX_CONF_TAKE2,
- ngx_conf_split_clients_block,
- NGX_HTTP_MAIN_CONF_OFFSET,
- 0,
- NULL },
-
- ngx_null_command
-};
-
-
-static ngx_http_module_t ngx_http_split_clients_module_ctx = {
- NULL, /* preconfiguration */
- NULL, /* postconfiguration */
-
- NULL, /* create main configuration */
- NULL, /* init main configuration */
-
- NULL, /* create server configuration */
- NULL, /* merge server configuration */
-
- NULL, /* create location configuration */
- NULL /* merge location configuration */
-};
-
-
-ngx_module_t ngx_http_split_clients_module = {
- NGX_MODULE_V1,
- &ngx_http_split_clients_module_ctx, /* module context */
- ngx_http_split_clients_commands, /* module directives */
- NGX_HTTP_MODULE, /* module type */
- NULL, /* init master */
- NULL, /* init module */
- NULL, /* init process */
- NULL, /* init thread */
- NULL, /* exit thread */
- NULL, /* exit process */
- NULL, /* exit master */
- NGX_MODULE_V1_PADDING
-};
-
-
-static ngx_int_t
-ngx_http_split_clients_variable(ngx_http_request_t *r,
- ngx_http_variable_value_t *v, uintptr_t data)
-{
- ngx_http_split_clients_ctx_t *ctx = (ngx_http_split_clients_ctx_t *) data;
-
- uint32_t hash;
- ngx_str_t val;
- ngx_uint_t i;
- ngx_http_split_clients_part_t *part;
-
- *v = ngx_http_variable_null_value;
-
- if (ngx_http_complex_value(r, &ctx->value, &val) != NGX_OK) {
- return NGX_OK;
- }
-
- hash = ngx_murmur_hash2(val.data, val.len);
-
- part = ctx->parts.elts;
-
- for (i = 0; i < ctx->parts.nelts; i++) {
-
- ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "http split: %uD %uD", hash, part[i].percent);
-
- if (hash < part[i].percent || part[i].percent == 0) {
- *v = part[i].value;
- return NGX_OK;
- }
- }
-
- return NGX_OK;
-}
-
-
-static char *
-ngx_conf_split_clients_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
-{
- char *rv;
- uint32_t sum, last;
- ngx_str_t *value, name;
- ngx_uint_t i;
- ngx_conf_t save;
- ngx_http_variable_t *var;
- ngx_http_split_clients_ctx_t *ctx;
- ngx_http_split_clients_part_t *part;
- ngx_http_compile_complex_value_t ccv;
-
- ctx = ngx_pcalloc(cf->pool, sizeof(ngx_http_split_clients_ctx_t));
- if (ctx == NULL) {
- return NGX_CONF_ERROR;
- }
-
- value = cf->args->elts;
-
- ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));
-
- ccv.cf = cf;
- ccv.value = &value[1];
- ccv.complex_value = &ctx->value;
-
- if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
- return NGX_CONF_ERROR;
- }
-
- name = value[2];
-
- if (name.data[0] != '$') {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "invalid variable name \"%V\"", &name);
- return NGX_CONF_ERROR;
- }
-
- name.len--;
- name.data++;
-
- var = ngx_http_add_variable(cf, &name, NGX_HTTP_VAR_CHANGEABLE);
- if (var == NULL) {
- return NGX_CONF_ERROR;
- }
-
- var->get_handler = ngx_http_split_clients_variable;
- var->data = (uintptr_t) ctx;
-
- if (ngx_array_init(&ctx->parts, cf->pool, 2,
- sizeof(ngx_http_split_clients_part_t))
- != NGX_OK)
- {
- return NGX_CONF_ERROR;
- }
-
- save = *cf;
- cf->ctx = ctx;
- cf->handler = ngx_http_split_clients;
- cf->handler_conf = conf;
-
- rv = ngx_conf_parse(cf, NULL);
-
- *cf = save;
-
- if (rv != NGX_CONF_OK) {
- return rv;
- }
-
- sum = 0;
- last = 0;
- part = ctx->parts.elts;
-
- for (i = 0; i < ctx->parts.nelts; i++) {
- sum = part[i].percent ? sum + part[i].percent : 10000;
- if (sum > 10000) {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "percent total is greater than 100%%");
- return NGX_CONF_ERROR;
- }
-
- if (part[i].percent) {
- last += part[i].percent * (uint64_t) 0xffffffff / 10000;
- part[i].percent = last;
- }
- }
-
- return rv;
-}
-
-
-static char *
-ngx_http_split_clients(ngx_conf_t *cf, ngx_command_t *dummy, void *conf)
-{
- ngx_int_t n;
- ngx_str_t *value;
- ngx_http_split_clients_ctx_t *ctx;
- ngx_http_split_clients_part_t *part;
-
- ctx = cf->ctx;
- value = cf->args->elts;
-
- part = ngx_array_push(&ctx->parts);
- if (part == NULL) {
- return NGX_CONF_ERROR;
- }
-
- if (value[0].len == 1 && value[0].data[0] == '*') {
- part->percent = 0;
-
- } else {
- if (value[0].len == 0 || value[0].data[value[0].len - 1] != '%') {
- goto invalid;
- }
-
- n = ngx_atofp(value[0].data, value[0].len - 1, 2);
- if (n == NGX_ERROR || n == 0) {
- goto invalid;
- }
-
- part->percent = (uint32_t) n;
- }
-
- part->value.len = value[1].len;
- part->value.valid = 1;
- part->value.no_cacheable = 0;
- part->value.not_found = 0;
- part->value.data = value[1].data;
-
- return NGX_CONF_OK;
-
-invalid:
-
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "invalid percent value \"%V\"", &value[0]);
- return NGX_CONF_ERROR;
-}
diff --git a/nginx/src/http/modules/ngx_http_ssi_filter_module.c b/nginx/src/http/modules/ngx_http_ssi_filter_module.c
deleted file mode 100644
index d608df9..0000000
--- a/nginx/src/http/modules/ngx_http_ssi_filter_module.c
+++ /dev/null
@@ -1,2933 +0,0 @@
-
-/*
- * Copyright (C) Igor Sysoev
- * Copyright (C) Nginx, Inc.
- */
-
-
-#include <ngx_config.h>
-#include <ngx_core.h>
-#include <ngx_http.h>
-
-#define NGX_HTTP_SSI_ERROR 1
-
-#define NGX_HTTP_SSI_DATE_LEN 2048
-
-#define NGX_HTTP_SSI_ADD_PREFIX 1
-#define NGX_HTTP_SSI_ADD_ZERO 2
-
-
-typedef struct {
- ngx_flag_t enable;
- ngx_flag_t silent_errors;
- ngx_flag_t ignore_recycled_buffers;
- ngx_flag_t last_modified;
-
- ngx_hash_t types;
-
- size_t min_file_chunk;
- size_t value_len;
-
- ngx_array_t *types_keys;
-} ngx_http_ssi_loc_conf_t;
-
-
-typedef struct {
- ngx_str_t name;
- ngx_uint_t key;
- ngx_str_t value;
-} ngx_http_ssi_var_t;
-
-
-typedef struct {
- ngx_str_t name;
- ngx_chain_t *bufs;
- ngx_uint_t count;
-} ngx_http_ssi_block_t;
-
-
-typedef enum {
- ssi_start_state = 0,
- ssi_tag_state,
- ssi_comment0_state,
- ssi_comment1_state,
- ssi_sharp_state,
- ssi_precommand_state,
- ssi_command_state,
- ssi_preparam_state,
- ssi_param_state,
- ssi_preequal_state,
- ssi_prevalue_state,
- ssi_double_quoted_value_state,
- ssi_quoted_value_state,
- ssi_quoted_symbol_state,
- ssi_postparam_state,
- ssi_comment_end0_state,
- ssi_comment_end1_state,
- ssi_error_state,
- ssi_error_end0_state,
- ssi_error_end1_state
-} ngx_http_ssi_state_e;
-
-
-static ngx_int_t ngx_http_ssi_output(ngx_http_request_t *r,
- ngx_http_ssi_ctx_t *ctx);
-static void ngx_http_ssi_buffered(ngx_http_request_t *r,
- ngx_http_ssi_ctx_t *ctx);
-static ngx_int_t ngx_http_ssi_parse(ngx_http_request_t *r,
- ngx_http_ssi_ctx_t *ctx);
-static ngx_str_t *ngx_http_ssi_get_variable(ngx_http_request_t *r,
- ngx_str_t *name, ngx_uint_t key);
-static ngx_int_t ngx_http_ssi_evaluate_string(ngx_http_request_t *r,
- ngx_http_ssi_ctx_t *ctx, ngx_str_t *text, ngx_uint_t flags);
-static ngx_int_t ngx_http_ssi_regex_match(ngx_http_request_t *r,
- ngx_str_t *pattern, ngx_str_t *str);
-
-static ngx_int_t ngx_http_ssi_include(ngx_http_request_t *r,
- ngx_http_ssi_ctx_t *ctx, ngx_str_t **params);
-static ngx_int_t ngx_http_ssi_stub_output(ngx_http_request_t *r, void *data,
- ngx_int_t rc);
-static ngx_int_t ngx_http_ssi_set_variable(ngx_http_request_t *r, void *data,
- ngx_int_t rc);
-static ngx_int_t ngx_http_ssi_echo(ngx_http_request_t *r,
- ngx_http_ssi_ctx_t *ctx, ngx_str_t **params);
-static ngx_int_t ngx_http_ssi_config(ngx_http_request_t *r,
- ngx_http_ssi_ctx_t *ctx, ngx_str_t **params);
-static ngx_int_t ngx_http_ssi_set(ngx_http_request_t *r,
- ngx_http_ssi_ctx_t *ctx, ngx_str_t **params);
-static ngx_int_t ngx_http_ssi_if(ngx_http_request_t *r,
- ngx_http_ssi_ctx_t *ctx, ngx_str_t **params);
-static ngx_int_t ngx_http_ssi_else(ngx_http_request_t *r,
- ngx_http_ssi_ctx_t *ctx, ngx_str_t **params);
-static ngx_int_t ngx_http_ssi_endif(ngx_http_request_t *r,
- ngx_http_ssi_ctx_t *ctx, ngx_str_t **params);
-static ngx_int_t ngx_http_ssi_block(ngx_http_request_t *r,
- ngx_http_ssi_ctx_t *ctx, ngx_str_t **params);
-static ngx_int_t ngx_http_ssi_endblock(ngx_http_request_t *r,
- ngx_http_ssi_ctx_t *ctx, ngx_str_t **params);
-
-static ngx_int_t ngx_http_ssi_date_gmt_local_variable(ngx_http_request_t *r,
- ngx_http_variable_value_t *v, uintptr_t gmt);
-
-static ngx_int_t ngx_http_ssi_preconfiguration(ngx_conf_t *cf);
-static void *ngx_http_ssi_create_main_conf(ngx_conf_t *cf);
-static char *ngx_http_ssi_init_main_conf(ngx_conf_t *cf, void *conf);
-static void *ngx_http_ssi_create_loc_conf(ngx_conf_t *cf);
-static char *ngx_http_ssi_merge_loc_conf(ngx_conf_t *cf,
- void *parent, void *child);
-static ngx_int_t ngx_http_ssi_filter_init(ngx_conf_t *cf);
-
-
-static ngx_command_t ngx_http_ssi_filter_commands[] = {
-
- { ngx_string("ssi"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF
- |NGX_CONF_FLAG,
- ngx_conf_set_flag_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_ssi_loc_conf_t, enable),
- NULL },
-
- { ngx_string("ssi_silent_errors"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
- ngx_conf_set_flag_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_ssi_loc_conf_t, silent_errors),
- NULL },
-
- { ngx_string("ssi_ignore_recycled_buffers"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
- ngx_conf_set_flag_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_ssi_loc_conf_t, ignore_recycled_buffers),
- NULL },
-
- { ngx_string("ssi_min_file_chunk"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_size_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_ssi_loc_conf_t, min_file_chunk),
- NULL },
-
- { ngx_string("ssi_value_length"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_size_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_ssi_loc_conf_t, value_len),
- NULL },
-
- { ngx_string("ssi_types"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
- ngx_http_types_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_ssi_loc_conf_t, types_keys),
- &ngx_http_html_default_types[0] },
-
- { ngx_string("ssi_last_modified"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
- ngx_conf_set_flag_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_ssi_loc_conf_t, last_modified),
- NULL },
-
- ngx_null_command
-};
-
-
-
-static ngx_http_module_t ngx_http_ssi_filter_module_ctx = {
- ngx_http_ssi_preconfiguration, /* preconfiguration */
- ngx_http_ssi_filter_init, /* postconfiguration */
-
- ngx_http_ssi_create_main_conf, /* create main configuration */
- ngx_http_ssi_init_main_conf, /* init main configuration */
-
- NULL, /* create server configuration */
- NULL, /* merge server configuration */
-
- ngx_http_ssi_create_loc_conf, /* create location configuration */
- ngx_http_ssi_merge_loc_conf /* merge location configuration */
-};
-
-
-ngx_module_t ngx_http_ssi_filter_module = {
- NGX_MODULE_V1,
- &ngx_http_ssi_filter_module_ctx, /* module context */
- ngx_http_ssi_filter_commands, /* module directives */
- NGX_HTTP_MODULE, /* module type */
- NULL, /* init master */
- NULL, /* init module */
- NULL, /* init process */
- NULL, /* init thread */
- NULL, /* exit thread */
- NULL, /* exit process */
- NULL, /* exit master */
- NGX_MODULE_V1_PADDING
-};
-
-
-static ngx_http_output_header_filter_pt ngx_http_next_header_filter;
-static ngx_http_output_body_filter_pt ngx_http_next_body_filter;
-
-
-static u_char ngx_http_ssi_string[] = "<!--";
-
-static ngx_str_t ngx_http_ssi_none = ngx_string("(none)");
-static ngx_str_t ngx_http_ssi_timefmt = ngx_string("%A, %d-%b-%Y %H:%M:%S %Z");
-static ngx_str_t ngx_http_ssi_null_string = ngx_null_string;
-
-
-#define NGX_HTTP_SSI_INCLUDE_VIRTUAL 0
-#define NGX_HTTP_SSI_INCLUDE_FILE 1
-#define NGX_HTTP_SSI_INCLUDE_WAIT 2
-#define NGX_HTTP_SSI_INCLUDE_SET 3
-#define NGX_HTTP_SSI_INCLUDE_STUB 4
-
-#define NGX_HTTP_SSI_ECHO_VAR 0
-#define NGX_HTTP_SSI_ECHO_DEFAULT 1
-#define NGX_HTTP_SSI_ECHO_ENCODING 2
-
-#define NGX_HTTP_SSI_CONFIG_ERRMSG 0
-#define NGX_HTTP_SSI_CONFIG_TIMEFMT 1
-
-#define NGX_HTTP_SSI_SET_VAR 0
-#define NGX_HTTP_SSI_SET_VALUE 1
-
-#define NGX_HTTP_SSI_IF_EXPR 0
-
-#define NGX_HTTP_SSI_BLOCK_NAME 0
-
-
-static ngx_http_ssi_param_t ngx_http_ssi_include_params[] = {
- { ngx_string("virtual"), NGX_HTTP_SSI_INCLUDE_VIRTUAL, 0, 0 },
- { ngx_string("file"), NGX_HTTP_SSI_INCLUDE_FILE, 0, 0 },
- { ngx_string("wait"), NGX_HTTP_SSI_INCLUDE_WAIT, 0, 0 },
- { ngx_string("set"), NGX_HTTP_SSI_INCLUDE_SET, 0, 0 },
- { ngx_string("stub"), NGX_HTTP_SSI_INCLUDE_STUB, 0, 0 },
- { ngx_null_string, 0, 0, 0 }
-};
-
-
-static ngx_http_ssi_param_t ngx_http_ssi_echo_params[] = {
- { ngx_string("var"), NGX_HTTP_SSI_ECHO_VAR, 1, 0 },
- { ngx_string("default"), NGX_HTTP_SSI_ECHO_DEFAULT, 0, 0 },
- { ngx_string("encoding"), NGX_HTTP_SSI_ECHO_ENCODING, 0, 0 },
- { ngx_null_string, 0, 0, 0 }
-};
-
-
-static ngx_http_ssi_param_t ngx_http_ssi_config_params[] = {
- { ngx_string("errmsg"), NGX_HTTP_SSI_CONFIG_ERRMSG, 0, 0 },
- { ngx_string("timefmt"), NGX_HTTP_SSI_CONFIG_TIMEFMT, 0, 0 },
- { ngx_null_string, 0, 0, 0 }
-};
-
-
-static ngx_http_ssi_param_t ngx_http_ssi_set_params[] = {
- { ngx_string("var"), NGX_HTTP_SSI_SET_VAR, 1, 0 },
- { ngx_string("value"), NGX_HTTP_SSI_SET_VALUE, 1, 0 },
- { ngx_null_string, 0, 0, 0 }
-};
-
-
-static ngx_http_ssi_param_t ngx_http_ssi_if_params[] = {
- { ngx_string("expr"), NGX_HTTP_SSI_IF_EXPR, 1, 0 },
- { ngx_null_string, 0, 0, 0 }
-};
-
-
-static ngx_http_ssi_param_t ngx_http_ssi_block_params[] = {
- { ngx_string("name"), NGX_HTTP_SSI_BLOCK_NAME, 1, 0 },
- { ngx_null_string, 0, 0, 0 }
-};
-
-
-static ngx_http_ssi_param_t ngx_http_ssi_no_params[] = {
- { ngx_null_string, 0, 0, 0 }
-};
-
-
-static ngx_http_ssi_command_t ngx_http_ssi_commands[] = {
- { ngx_string("include"), ngx_http_ssi_include,
- ngx_http_ssi_include_params, 0, 0, 1 },
- { ngx_string("echo"), ngx_http_ssi_echo,
- ngx_http_ssi_echo_params, 0, 0, 0 },
- { ngx_string("config"), ngx_http_ssi_config,
- ngx_http_ssi_config_params, 0, 0, 0 },
- { ngx_string("set"), ngx_http_ssi_set, ngx_http_ssi_set_params, 0, 0, 0 },
-
- { ngx_string("if"), ngx_http_ssi_if, ngx_http_ssi_if_params, 0, 0, 0 },
- { ngx_string("elif"), ngx_http_ssi_if, ngx_http_ssi_if_params,
- NGX_HTTP_SSI_COND_IF, 0, 0 },
- { ngx_string("else"), ngx_http_ssi_else, ngx_http_ssi_no_params,
- NGX_HTTP_SSI_COND_IF, 0, 0 },
- { ngx_string("endif"), ngx_http_ssi_endif, ngx_http_ssi_no_params,
- NGX_HTTP_SSI_COND_ELSE, 0, 0 },
-
- { ngx_string("block"), ngx_http_ssi_block,
- ngx_http_ssi_block_params, 0, 0, 0 },
- { ngx_string("endblock"), ngx_http_ssi_endblock,
- ngx_http_ssi_no_params, 0, 1, 0 },
-
- { ngx_null_string, NULL, NULL, 0, 0, 0 }
-};
-
-
-static ngx_http_variable_t ngx_http_ssi_vars[] = {
-
- { ngx_string("date_local"), NULL, ngx_http_ssi_date_gmt_local_variable, 0,
- NGX_HTTP_VAR_NOCACHEABLE, 0 },
-
- { ngx_string("date_gmt"), NULL, ngx_http_ssi_date_gmt_local_variable, 1,
- NGX_HTTP_VAR_NOCACHEABLE, 0 },
-
- ngx_http_null_variable
-};
-
-
-
-static ngx_int_t
-ngx_http_ssi_header_filter(ngx_http_request_t *r)
-{
- ngx_http_ssi_ctx_t *ctx;
- ngx_http_ssi_loc_conf_t *slcf;
-
- slcf = ngx_http_get_module_loc_conf(r, ngx_http_ssi_filter_module);
-
- if (!slcf->enable
- || r->headers_out.content_length_n == 0
- || ngx_http_test_content_type(r, &slcf->types) == NULL)
- {
- return ngx_http_next_header_filter(r);
- }
-
- ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_ssi_ctx_t));
- if (ctx == NULL) {
- return NGX_ERROR;
- }
-
- ngx_http_set_ctx(r, ctx, ngx_http_ssi_filter_module);
-
-
- ctx->value_len = slcf->value_len;
- ctx->last_out = &ctx->out;
-
- ctx->encoding = NGX_HTTP_SSI_ENTITY_ENCODING;
- ctx->output = 1;
-
- ctx->params.elts = ctx->params_array;
- ctx->params.size = sizeof(ngx_table_elt_t);
- ctx->params.nalloc = NGX_HTTP_SSI_PARAMS_N;
- ctx->params.pool = r->pool;
-
- ctx->timefmt = ngx_http_ssi_timefmt;
- ngx_str_set(&ctx->errmsg,
- "[an error occurred while processing the directive]");
-
- r->filter_need_in_memory = 1;
-
- if (r == r->main) {
- ngx_http_clear_content_length(r);
- ngx_http_clear_accept_ranges(r);
-
- r->preserve_body = 1;
-
- if (!slcf->last_modified) {
- ngx_http_clear_last_modified(r);
- ngx_http_clear_etag(r);
-
- } else {
- ngx_http_weak_etag(r);
- }
- }
-
- return ngx_http_next_header_filter(r);
-}
-
-
-static ngx_int_t
-ngx_http_ssi_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
-{
- size_t len;
- ngx_int_t rc;
- ngx_buf_t *b;
- ngx_uint_t i, index;
- ngx_chain_t *cl, **ll;
- ngx_table_elt_t *param;
- ngx_http_ssi_ctx_t *ctx, *mctx;
- ngx_http_ssi_block_t *bl;
- ngx_http_ssi_param_t *prm;
- ngx_http_ssi_command_t *cmd;
- ngx_http_ssi_loc_conf_t *slcf;
- ngx_http_ssi_main_conf_t *smcf;
- ngx_str_t *params[NGX_HTTP_SSI_MAX_PARAMS + 1];
-
- ctx = ngx_http_get_module_ctx(r, ngx_http_ssi_filter_module);
-
- if (ctx == NULL
- || (in == NULL
- && ctx->buf == NULL
- && ctx->in == NULL
- && ctx->busy == NULL))
- {
- return ngx_http_next_body_filter(r, in);
- }
-
- /* add the incoming chain to the chain ctx->in */
-
- if (in) {
- if (ngx_chain_add_copy(r->pool, &ctx->in, in) != NGX_OK) {
- return NGX_ERROR;
- }
- }
-
- ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "http ssi filter \"%V?%V\"", &r->uri, &r->args);
-
- if (ctx->wait) {
-
- if (r != r->connection->data) {
- ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "http ssi filter wait \"%V?%V\" non-active",
- &ctx->wait->uri, &ctx->wait->args);
-
- return NGX_AGAIN;
- }
-
- if (ctx->wait->done) {
- ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "http ssi filter wait \"%V?%V\" done",
- &ctx->wait->uri, &ctx->wait->args);
-
- ctx->wait = NULL;
-
- } else {
- ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "http ssi filter wait \"%V?%V\"",
- &ctx->wait->uri, &ctx->wait->args);
-
- return ngx_http_next_body_filter(r, NULL);
- }
- }
-
- slcf = ngx_http_get_module_loc_conf(r, ngx_http_ssi_filter_module);
-
- while (ctx->in || ctx->buf) {
-
- if (ctx->buf == NULL) {
- ctx->buf = ctx->in->buf;
- ctx->in = ctx->in->next;
- ctx->pos = ctx->buf->pos;
- }
-
- if (ctx->state == ssi_start_state) {
- ctx->copy_start = ctx->pos;
- ctx->copy_end = ctx->pos;
- }
-
- b = NULL;
-
- while (ctx->pos < ctx->buf->last) {
-
- ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "saved: %uz state: %ui", ctx->saved, ctx->state);
-
- rc = ngx_http_ssi_parse(r, ctx);
-
- ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "parse: %i, looked: %uz %p-%p",
- rc, ctx->looked, ctx->copy_start, ctx->copy_end);
-
- if (rc == NGX_ERROR) {
- return rc;
- }
-
- if (ctx->copy_start != ctx->copy_end) {
-
- if (ctx->output) {
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "saved: %uz", ctx->saved);
-
- if (ctx->saved) {
-
- if (ctx->free) {
- cl = ctx->free;
- ctx->free = ctx->free->next;
- b = cl->buf;
- ngx_memzero(b, sizeof(ngx_buf_t));
-
- } else {
- b = ngx_calloc_buf(r->pool);
- if (b == NULL) {
- return NGX_ERROR;
- }
-
- cl = ngx_alloc_chain_link(r->pool);
- if (cl == NULL) {
- return NGX_ERROR;
- }
-
- cl->buf = b;
- }
-
- b->memory = 1;
- b->pos = ngx_http_ssi_string;
- b->last = ngx_http_ssi_string + ctx->saved;
-
- *ctx->last_out = cl;
- ctx->last_out = &cl->next;
-
- ctx->saved = 0;
- }
-
- if (ctx->free) {
- cl = ctx->free;
- ctx->free = ctx->free->next;
- b = cl->buf;
-
- } else {
- b = ngx_alloc_buf(r->pool);
- if (b == NULL) {
- return NGX_ERROR;
- }
-
- cl = ngx_alloc_chain_link(r->pool);
- if (cl == NULL) {
- return NGX_ERROR;
- }
-
- cl->buf = b;
- }
-
- ngx_memcpy(b, ctx->buf, sizeof(ngx_buf_t));
-
- b->pos = ctx->copy_start;
- b->last = ctx->copy_end;
- b->shadow = NULL;
- b->last_buf = 0;
- b->recycled = 0;
-
- if (b->in_file) {
- if (slcf->min_file_chunk < (size_t) (b->last - b->pos))
- {
- b->file_last = b->file_pos
- + (b->last - ctx->buf->pos);
- b->file_pos += b->pos - ctx->buf->pos;
-
- } else {
- b->in_file = 0;
- }
- }
-
- cl->next = NULL;
- *ctx->last_out = cl;
- ctx->last_out = &cl->next;
-
- } else {
- if (ctx->block
- && ctx->saved + (ctx->copy_end - ctx->copy_start))
- {
- b = ngx_create_temp_buf(r->pool,
- ctx->saved + (ctx->copy_end - ctx->copy_start));
-
- if (b == NULL) {
- return NGX_ERROR;
- }
-
- if (ctx->saved) {
- b->last = ngx_cpymem(b->pos, ngx_http_ssi_string,
- ctx->saved);
- }
-
- b->last = ngx_cpymem(b->last, ctx->copy_start,
- ctx->copy_end - ctx->copy_start);
-
- cl = ngx_alloc_chain_link(r->pool);
- if (cl == NULL) {
- return NGX_ERROR;
- }
-
- cl->buf = b;
- cl->next = NULL;
-
- b = NULL;
-
- mctx = ngx_http_get_module_ctx(r->main,
- ngx_http_ssi_filter_module);
- bl = mctx->blocks->elts;
- for (ll = &bl[mctx->blocks->nelts - 1].bufs;
- *ll;
- ll = &(*ll)->next)
- {
- /* void */
- }
-
- *ll = cl;
- }
-
- ctx->saved = 0;
- }
- }
-
- if (ctx->state == ssi_start_state) {
- ctx->copy_start = ctx->pos;
- ctx->copy_end = ctx->pos;
-
- } else {
- ctx->copy_start = NULL;
- ctx->copy_end = NULL;
- }
-
- if (rc == NGX_AGAIN) {
- continue;
- }
-
-
- b = NULL;
-
- if (rc == NGX_OK) {
-
- smcf = ngx_http_get_module_main_conf(r,
- ngx_http_ssi_filter_module);
-
- cmd = ngx_hash_find(&smcf->hash, ctx->key, ctx->command.data,
- ctx->command.len);
-
- if (cmd == NULL) {
- if (ctx->output) {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "invalid SSI command: \"%V\"",
- &ctx->command);
- goto ssi_error;
- }
-
- continue;
- }
-
- if (!ctx->output && !cmd->block) {
-
- if (ctx->block) {
-
- /* reconstruct the SSI command text */
-
- len = 5 + ctx->command.len + 4;
-
- param = ctx->params.elts;
- for (i = 0; i < ctx->params.nelts; i++) {
- len += 1 + param[i].key.len + 2
- + param[i].value.len + 1;
- }
-
- b = ngx_create_temp_buf(r->pool, len);
-
- if (b == NULL) {
- return NGX_ERROR;
- }
-
- cl = ngx_alloc_chain_link(r->pool);
- if (cl == NULL) {
- return NGX_ERROR;
- }
-
- cl->buf = b;
- cl->next = NULL;
-
- *b->last++ = '<';
- *b->last++ = '!';
- *b->last++ = '-';
- *b->last++ = '-';
- *b->last++ = '#';
-
- b->last = ngx_cpymem(b->last, ctx->command.data,
- ctx->command.len);
-
- for (i = 0; i < ctx->params.nelts; i++) {
- *b->last++ = ' ';
- b->last = ngx_cpymem(b->last, param[i].key.data,
- param[i].key.len);
- *b->last++ = '=';
- *b->last++ = '"';
- b->last = ngx_cpymem(b->last, param[i].value.data,
- param[i].value.len);
- *b->last++ = '"';
- }
-
- *b->last++ = ' ';
- *b->last++ = '-';
- *b->last++ = '-';
- *b->last++ = '>';
-
- mctx = ngx_http_get_module_ctx(r->main,
- ngx_http_ssi_filter_module);
- bl = mctx->blocks->elts;
- for (ll = &bl[mctx->blocks->nelts - 1].bufs;
- *ll;
- ll = &(*ll)->next)
- {
- /* void */
- }
-
- *ll = cl;
-
- b = NULL;
-
- continue;
- }
-
- if (cmd->conditional == 0) {
- continue;
- }
- }
-
- if (cmd->conditional
- && (ctx->conditional == 0
- || ctx->conditional > cmd->conditional))
- {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "invalid context of SSI command: \"%V\"",
- &ctx->command);
- goto ssi_error;
- }
-
- if (ctx->params.nelts > NGX_HTTP_SSI_MAX_PARAMS) {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "too many SSI command parameters: \"%V\"",
- &ctx->command);
- goto ssi_error;
- }
-
- ngx_memzero(params,
- (NGX_HTTP_SSI_MAX_PARAMS + 1) * sizeof(ngx_str_t *));
-
- param = ctx->params.elts;
-
- for (i = 0; i < ctx->params.nelts; i++) {
-
- for (prm = cmd->params; prm->name.len; prm++) {
-
- if (param[i].key.len != prm->name.len
- || ngx_strncmp(param[i].key.data, prm->name.data,
- prm->name.len) != 0)
- {
- continue;
- }
-
- if (!prm->multiple) {
- if (params[prm->index]) {
- ngx_log_error(NGX_LOG_ERR,
- r->connection->log, 0,
- "duplicate \"%V\" parameter "
- "in \"%V\" SSI command",
- &param[i].key, &ctx->command);
-
- goto ssi_error;
- }
-
- params[prm->index] = &param[i].value;
-
- break;
- }
-
- for (index = prm->index; params[index]; index++) {
- /* void */
- }
-
- params[index] = &param[i].value;
-
- break;
- }
-
- if (prm->name.len == 0) {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "invalid parameter name: \"%V\" "
- "in \"%V\" SSI command",
- &param[i].key, &ctx->command);
-
- goto ssi_error;
- }
- }
-
- for (prm = cmd->params; prm->name.len; prm++) {
- if (prm->mandatory && params[prm->index] == 0) {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "mandatory \"%V\" parameter is absent "
- "in \"%V\" SSI command",
- &prm->name, &ctx->command);
-
- goto ssi_error;
- }
- }
-
- if (cmd->flush && ctx->out) {
-
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "ssi flush");
-
- if (ngx_http_ssi_output(r, ctx) == NGX_ERROR) {
- return NGX_ERROR;
- }
- }
-
- rc = cmd->handler(r, ctx, params);
-
- if (rc == NGX_OK) {
- continue;
- }
-
- if (rc == NGX_DONE || rc == NGX_AGAIN || rc == NGX_ERROR) {
- ngx_http_ssi_buffered(r, ctx);
- return rc;
- }
- }
-
-
- /* rc == NGX_HTTP_SSI_ERROR */
-
- ssi_error:
-
- if (slcf->silent_errors) {
- continue;
- }
-
- if (ctx->free) {
- cl = ctx->free;
- ctx->free = ctx->free->next;
- b = cl->buf;
- ngx_memzero(b, sizeof(ngx_buf_t));
-
- } else {
- b = ngx_calloc_buf(r->pool);
- if (b == NULL) {
- return NGX_ERROR;
- }
-
- cl = ngx_alloc_chain_link(r->pool);
- if (cl == NULL) {
- return NGX_ERROR;
- }
-
- cl->buf = b;
- }
-
- b->memory = 1;
- b->pos = ctx->errmsg.data;
- b->last = ctx->errmsg.data + ctx->errmsg.len;
-
- cl->next = NULL;
- *ctx->last_out = cl;
- ctx->last_out = &cl->next;
-
- continue;
- }
-
- if (ctx->buf->last_buf || ngx_buf_in_memory(ctx->buf)) {
- if (b == NULL) {
- if (ctx->free) {
- cl = ctx->free;
- ctx->free = ctx->free->next;
- b = cl->buf;
- ngx_memzero(b, sizeof(ngx_buf_t));
-
- } else {
- b = ngx_calloc_buf(r->pool);
- if (b == NULL) {
- return NGX_ERROR;
- }
-
- cl = ngx_alloc_chain_link(r->pool);
- if (cl == NULL) {
- return NGX_ERROR;
- }
-
- cl->buf = b;
- }
-
- b->sync = 1;
-
- cl->next = NULL;
- *ctx->last_out = cl;
- ctx->last_out = &cl->next;
- }
-
- b->last_buf = ctx->buf->last_buf;
- b->shadow = ctx->buf;
-
- if (slcf->ignore_recycled_buffers == 0) {
- b->recycled = ctx->buf->recycled;
- }
- }
-
- ctx->buf = NULL;
-
- ctx->saved = ctx->looked;
- }
-
- if (ctx->out == NULL && ctx->busy == NULL) {
- return NGX_OK;
- }
-
- return ngx_http_ssi_output(r, ctx);
-}
-
-
-static ngx_int_t
-ngx_http_ssi_output(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx)
-{
- ngx_int_t rc;
- ngx_buf_t *b;
- ngx_chain_t *cl;
-
-#if 1
- b = NULL;
- for (cl = ctx->out; cl; cl = cl->next) {
- ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "ssi out: %p %p", cl->buf, cl->buf->pos);
- if (cl->buf == b) {
- ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
- "the same buf was used in ssi");
- ngx_debug_point();
- return NGX_ERROR;
- }
- b = cl->buf;
- }
-#endif
-
- rc = ngx_http_next_body_filter(r, ctx->out);
-
- if (ctx->busy == NULL) {
- ctx->busy = ctx->out;
-
- } else {
- for (cl = ctx->busy; cl->next; cl = cl->next) { /* void */ }
- cl->next = ctx->out;
- }
-
- ctx->out = NULL;
- ctx->last_out = &ctx->out;
-
- while (ctx->busy) {
-
- cl = ctx->busy;
- b = cl->buf;
-
- if (ngx_buf_size(b) != 0) {
- break;
- }
-
- if (b->shadow) {
- b->shadow->pos = b->shadow->last;
- }
-
- ctx->busy = cl->next;
-
- if (ngx_buf_in_memory(b) || b->in_file) {
- /* add data bufs only to the free buf chain */
-
- cl->next = ctx->free;
- ctx->free = cl;
- }
- }
-
- ngx_http_ssi_buffered(r, ctx);
-
- return rc;
-}
-
-
-static void
-ngx_http_ssi_buffered(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx)
-{
- if (ctx->in || ctx->buf) {
- r->buffered |= NGX_HTTP_SSI_BUFFERED;
-
- } else {
- r->buffered &= ~NGX_HTTP_SSI_BUFFERED;
- }
-}
-
-
-static ngx_int_t
-ngx_http_ssi_parse(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx)
-{
- u_char *p, *value, *last, *copy_end, ch;
- size_t looked;
- ngx_http_ssi_state_e state;
-
- state = ctx->state;
- looked = ctx->looked;
- last = ctx->buf->last;
- copy_end = ctx->copy_end;
-
- for (p = ctx->pos; p < last; p++) {
-
- ch = *p;
-
- if (state == ssi_start_state) {
-
- /* the tight loop */
-
- for ( ;; ) {
- if (ch == '<') {
- copy_end = p;
- looked = 1;
- state = ssi_tag_state;
-
- goto tag_started;
- }
-
- if (++p == last) {
- break;
- }
-
- ch = *p;
- }
-
- ctx->state = state;
- ctx->pos = p;
- ctx->looked = looked;
- ctx->copy_end = p;
-
- if (ctx->copy_start == NULL) {
- ctx->copy_start = ctx->buf->pos;
- }
-
- return NGX_AGAIN;
-
- tag_started:
-
- continue;
- }
-
- switch (state) {
-
- case ssi_start_state:
- /* not reached */
- break;
-
- case ssi_tag_state:
- switch (ch) {
- case '!':
- looked = 2;
- state = ssi_comment0_state;
- break;
-
- case '<':
- copy_end = p;
- break;
-
- default:
- copy_end = p;
- looked = 0;
- state = ssi_start_state;
- break;
- }
-
- break;
-
- case ssi_comment0_state:
- switch (ch) {
- case '-':
- looked = 3;
- state = ssi_comment1_state;
- break;
-
- case '<':
- copy_end = p;
- looked = 1;
- state = ssi_tag_state;
- break;
-
- default:
- copy_end = p;
- looked = 0;
- state = ssi_start_state;
- break;
- }
-
- break;
-
- case ssi_comment1_state:
- switch (ch) {
- case '-':
- looked = 4;
- state = ssi_sharp_state;
- break;
-
- case '<':
- copy_end = p;
- looked = 1;
- state = ssi_tag_state;
- break;
-
- default:
- copy_end = p;
- looked = 0;
- state = ssi_start_state;
- break;
- }
-
- break;
-
- case ssi_sharp_state:
- switch (ch) {
- case '#':
- if (p - ctx->pos < 4) {
- ctx->saved = 0;
- }
- looked = 0;
- state = ssi_precommand_state;
- break;
-
- case '<':
- copy_end = p;
- looked = 1;
- state = ssi_tag_state;
- break;
-
- default:
- copy_end = p;
- looked = 0;
- state = ssi_start_state;
- break;
- }
-
- break;
-
- case ssi_precommand_state:
- switch (ch) {
- case ' ':
- case CR:
- case LF:
- case '\t':
- break;
-
- default:
- ctx->command.len = 1;
- ctx->command.data = ngx_pnalloc(r->pool,
- NGX_HTTP_SSI_COMMAND_LEN);
- if (ctx->command.data == NULL) {
- return NGX_ERROR;
- }
-
- ctx->command.data[0] = ch;
-
- ctx->key = 0;
- ctx->key = ngx_hash(ctx->key, ch);
-
- ctx->params.nelts = 0;
-
- state = ssi_command_state;
- break;
- }
-
- break;
-
- case ssi_command_state:
- switch (ch) {
- case ' ':
- case CR:
- case LF:
- case '\t':
- state = ssi_preparam_state;
- break;
-
- case '-':
- state = ssi_comment_end0_state;
- break;
-
- default:
- if (ctx->command.len == NGX_HTTP_SSI_COMMAND_LEN) {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "the \"%V%c...\" SSI command is too long",
- &ctx->command, ch);
-
- state = ssi_error_state;
- break;
- }
-
- ctx->command.data[ctx->command.len++] = ch;
- ctx->key = ngx_hash(ctx->key, ch);
- }
-
- break;
-
- case ssi_preparam_state:
- switch (ch) {
- case ' ':
- case CR:
- case LF:
- case '\t':
- break;
-
- case '-':
- state = ssi_comment_end0_state;
- break;
-
- default:
- ctx->param = ngx_array_push(&ctx->params);
- if (ctx->param == NULL) {
- return NGX_ERROR;
- }
-
- ctx->param->key.len = 1;
- ctx->param->key.data = ngx_pnalloc(r->pool,
- NGX_HTTP_SSI_PARAM_LEN);
- if (ctx->param->key.data == NULL) {
- return NGX_ERROR;
- }
-
- ctx->param->key.data[0] = ch;
-
- ctx->param->value.len = 0;
-
- if (ctx->value_buf == NULL) {
- ctx->param->value.data = ngx_pnalloc(r->pool,
- ctx->value_len + 1);
- if (ctx->param->value.data == NULL) {
- return NGX_ERROR;
- }
-
- } else {
- ctx->param->value.data = ctx->value_buf;
- }
-
- state = ssi_param_state;
- break;
- }
-
- break;
-
- case ssi_param_state:
- switch (ch) {
- case ' ':
- case CR:
- case LF:
- case '\t':
- state = ssi_preequal_state;
- break;
-
- case '=':
- state = ssi_prevalue_state;
- break;
-
- case '-':
- state = ssi_error_end0_state;
-
- ctx->param->key.data[ctx->param->key.len++] = ch;
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "invalid \"%V\" parameter in \"%V\" SSI command",
- &ctx->param->key, &ctx->command);
- break;
-
- default:
- if (ctx->param->key.len == NGX_HTTP_SSI_PARAM_LEN) {
- state = ssi_error_state;
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "too long \"%V%c...\" parameter in "
- "\"%V\" SSI command",
- &ctx->param->key, ch, &ctx->command);
- break;
- }
-
- ctx->param->key.data[ctx->param->key.len++] = ch;
- }
-
- break;
-
- case ssi_preequal_state:
- switch (ch) {
- case ' ':
- case CR:
- case LF:
- case '\t':
- break;
-
- case '=':
- state = ssi_prevalue_state;
- break;
-
- default:
- if (ch == '-') {
- state = ssi_error_end0_state;
- } else {
- state = ssi_error_state;
- }
-
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "unexpected \"%c\" symbol after \"%V\" "
- "parameter in \"%V\" SSI command",
- ch, &ctx->param->key, &ctx->command);
- break;
- }
-
- break;
-
- case ssi_prevalue_state:
- switch (ch) {
- case ' ':
- case CR:
- case LF:
- case '\t':
- break;
-
- case '"':
- state = ssi_double_quoted_value_state;
- break;
-
- case '\'':
- state = ssi_quoted_value_state;
- break;
-
- default:
- if (ch == '-') {
- state = ssi_error_end0_state;
- } else {
- state = ssi_error_state;
- }
-
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "unexpected \"%c\" symbol before value of "
- "\"%V\" parameter in \"%V\" SSI command",
- ch, &ctx->param->key, &ctx->command);
- break;
- }
-
- break;
-
- case ssi_double_quoted_value_state:
- switch (ch) {
- case '"':
- state = ssi_postparam_state;
- break;
-
- case '\\':
- ctx->saved_state = ssi_double_quoted_value_state;
- state = ssi_quoted_symbol_state;
-
- /* fall through */
-
- default:
- if (ctx->param->value.len == ctx->value_len) {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "too long \"%V%c...\" value of \"%V\" "
- "parameter in \"%V\" SSI command",
- &ctx->param->value, ch, &ctx->param->key,
- &ctx->command);
- state = ssi_error_state;
- break;
- }
-
- ctx->param->value.data[ctx->param->value.len++] = ch;
- }
-
- break;
-
- case ssi_quoted_value_state:
- switch (ch) {
- case '\'':
- state = ssi_postparam_state;
- break;
-
- case '\\':
- ctx->saved_state = ssi_quoted_value_state;
- state = ssi_quoted_symbol_state;
-
- /* fall through */
-
- default:
- if (ctx->param->value.len == ctx->value_len) {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "too long \"%V%c...\" value of \"%V\" "
- "parameter in \"%V\" SSI command",
- &ctx->param->value, ch, &ctx->param->key,
- &ctx->command);
- state = ssi_error_state;
- break;
- }
-
- ctx->param->value.data[ctx->param->value.len++] = ch;
- }
-
- break;
-
- case ssi_quoted_symbol_state:
- state = ctx->saved_state;
-
- if (ctx->param->value.len == ctx->value_len) {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "too long \"%V%c...\" value of \"%V\" "
- "parameter in \"%V\" SSI command",
- &ctx->param->value, ch, &ctx->param->key,
- &ctx->command);
- state = ssi_error_state;
- break;
- }
-
- ctx->param->value.data[ctx->param->value.len++] = ch;
-
- break;
-
- case ssi_postparam_state:
-
- if (ctx->param->value.len + 1 < ctx->value_len / 2) {
- value = ngx_pnalloc(r->pool, ctx->param->value.len + 1);
- if (value == NULL) {
- return NGX_ERROR;
- }
-
- ngx_memcpy(value, ctx->param->value.data,
- ctx->param->value.len);
-
- ctx->value_buf = ctx->param->value.data;
- ctx->param->value.data = value;
-
- } else {
- ctx->value_buf = NULL;
- }
-
- switch (ch) {
- case ' ':
- case CR:
- case LF:
- case '\t':
- state = ssi_preparam_state;
- break;
-
- case '-':
- state = ssi_comment_end0_state;
- break;
-
- default:
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "unexpected \"%c\" symbol after \"%V\" value "
- "of \"%V\" parameter in \"%V\" SSI command",
- ch, &ctx->param->value, &ctx->param->key,
- &ctx->command);
- state = ssi_error_state;
- break;
- }
-
- break;
-
- case ssi_comment_end0_state:
- switch (ch) {
- case '-':
- state = ssi_comment_end1_state;
- break;
-
- default:
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "unexpected \"%c\" symbol in \"%V\" SSI command",
- ch, &ctx->command);
- state = ssi_error_state;
- break;
- }
-
- break;
-
- case ssi_comment_end1_state:
- switch (ch) {
- case '>':
- ctx->state = ssi_start_state;
- ctx->pos = p + 1;
- ctx->looked = looked;
- ctx->copy_end = copy_end;
-
- if (ctx->copy_start == NULL && copy_end) {
- ctx->copy_start = ctx->buf->pos;
- }
-
- return NGX_OK;
-
- default:
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "unexpected \"%c\" symbol in \"%V\" SSI command",
- ch, &ctx->command);
- state = ssi_error_state;
- break;
- }
-
- break;
-
- case ssi_error_state:
- switch (ch) {
- case '-':
- state = ssi_error_end0_state;
- break;
-
- default:
- break;
- }
-
- break;
-
- case ssi_error_end0_state:
- switch (ch) {
- case '-':
- state = ssi_error_end1_state;
- break;
-
- default:
- state = ssi_error_state;
- break;
- }
-
- break;
-
- case ssi_error_end1_state:
- switch (ch) {
- case '>':
- ctx->state = ssi_start_state;
- ctx->pos = p + 1;
- ctx->looked = looked;
- ctx->copy_end = copy_end;
-
- if (ctx->copy_start == NULL && copy_end) {
- ctx->copy_start = ctx->buf->pos;
- }
-
- return NGX_HTTP_SSI_ERROR;
-
- default:
- state = ssi_error_state;
- break;
- }
-
- break;
- }
- }
-
- ctx->state = state;
- ctx->pos = p;
- ctx->looked = looked;
-
- ctx->copy_end = (state == ssi_start_state) ? p : copy_end;
-
- if (ctx->copy_start == NULL && ctx->copy_end) {
- ctx->copy_start = ctx->buf->pos;
- }
-
- return NGX_AGAIN;
-}
-
-
-static ngx_str_t *
-ngx_http_ssi_get_variable(ngx_http_request_t *r, ngx_str_t *name,
- ngx_uint_t key)
-{
- ngx_uint_t i;
- ngx_list_part_t *part;
- ngx_http_ssi_var_t *var;
- ngx_http_ssi_ctx_t *ctx;
-
- ctx = ngx_http_get_module_ctx(r->main, ngx_http_ssi_filter_module);
-
-#if (NGX_PCRE)
- {
- ngx_str_t *value;
-
- if (key >= '0' && key <= '9') {
- i = key - '0';
-
- if (i < ctx->ncaptures) {
- value = ngx_palloc(r->pool, sizeof(ngx_str_t));
- if (value == NULL) {
- return NULL;
- }
-
- i *= 2;
-
- value->data = ctx->captures_data + ctx->captures[i];
- value->len = ctx->captures[i + 1] - ctx->captures[i];
-
- return value;
- }
- }
- }
-#endif
-
- if (ctx->variables == NULL) {
- return NULL;
- }
-
- part = &ctx->variables->part;
- var = part->elts;
-
- for (i = 0; /* void */ ; i++) {
-
- if (i >= part->nelts) {
- if (part->next == NULL) {
- break;
- }
-
- part = part->next;
- var = part->elts;
- i = 0;
- }
-
- if (name->len != var[i].name.len) {
- continue;
- }
-
- if (key != var[i].key) {
- continue;
- }
-
- if (ngx_strncmp(name->data, var[i].name.data, name->len) == 0) {
- return &var[i].value;
- }
- }
-
- return NULL;
-}
-
-
-static ngx_int_t
-ngx_http_ssi_evaluate_string(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx,
- ngx_str_t *text, ngx_uint_t flags)
-{
- u_char ch, *p, **value, *data, *part_data;
- size_t *size, len, prefix, part_len;
- ngx_str_t var, *val;
- ngx_uint_t i, n, bracket, quoted, key;
- ngx_array_t lengths, values;
- ngx_http_variable_value_t *vv;
-
- n = ngx_http_script_variables_count(text);
-
- if (n == 0) {
-
- data = text->data;
- p = data;
-
- if ((flags & NGX_HTTP_SSI_ADD_PREFIX) && text->data[0] != '/') {
-
- for (prefix = r->uri.len; prefix; prefix--) {
- if (r->uri.data[prefix - 1] == '/') {
- break;
- }
- }
-
- if (prefix) {
- len = prefix + text->len;
-
- data = ngx_pnalloc(r->pool, len);
- if (data == NULL) {
- return NGX_ERROR;
- }
-
- p = ngx_copy(data, r->uri.data, prefix);
- }
- }
-
- quoted = 0;
-
- for (i = 0; i < text->len; i++) {
- ch = text->data[i];
-
- if (!quoted) {
-
- if (ch == '\\') {
- quoted = 1;
- continue;
- }
-
- } else {
- quoted = 0;
-
- if (ch != '\\' && ch != '\'' && ch != '"' && ch != '$') {
- *p++ = '\\';
- }
- }
-
- *p++ = ch;
- }
-
- text->len = p - data;
- text->data = data;
-
- return NGX_OK;
- }
-
- if (ngx_array_init(&lengths, r->pool, 8, sizeof(size_t *)) != NGX_OK) {
- return NGX_ERROR;
- }
-
- if (ngx_array_init(&values, r->pool, 8, sizeof(u_char *)) != NGX_OK) {
- return NGX_ERROR;
- }
-
- len = 0;
- i = 0;
-
- while (i < text->len) {
-
- if (text->data[i] == '$') {
-
- var.len = 0;
-
- if (++i == text->len) {
- goto invalid_variable;
- }
-
- if (text->data[i] == '{') {
- bracket = 1;
-
- if (++i == text->len) {
- goto invalid_variable;
- }
-
- var.data = &text->data[i];
-
- } else {
- bracket = 0;
- var.data = &text->data[i];
- }
-
- for ( /* void */ ; i < text->len; i++, var.len++) {
- ch = text->data[i];
-
- if (ch == '}' && bracket) {
- i++;
- bracket = 0;
- break;
- }
-
- if ((ch >= 'A' && ch <= 'Z')
- || (ch >= 'a' && ch <= 'z')
- || (ch >= '0' && ch <= '9')
- || ch == '_')
- {
- continue;
- }
-
- break;
- }
-
- if (bracket) {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "the closing bracket in \"%V\" "
- "variable is missing", &var);
- return NGX_HTTP_SSI_ERROR;
- }
-
- if (var.len == 0) {
- goto invalid_variable;
- }
-
- key = ngx_hash_strlow(var.data, var.data, var.len);
-
- val = ngx_http_ssi_get_variable(r, &var, key);
-
- if (val == NULL) {
- vv = ngx_http_get_variable(r, &var, key);
- if (vv == NULL) {
- return NGX_ERROR;
- }
-
- if (vv->not_found) {
- continue;
- }
-
- part_data = vv->data;
- part_len = vv->len;
-
- } else {
- part_data = val->data;
- part_len = val->len;
- }
-
- } else {
- part_data = &text->data[i];
- quoted = 0;
-
- for (p = part_data; i < text->len; i++) {
- ch = text->data[i];
-
- if (!quoted) {
-
- if (ch == '\\') {
- quoted = 1;
- continue;
- }
-
- if (ch == '$') {
- break;
- }
-
- } else {
- quoted = 0;
-
- if (ch != '\\' && ch != '\'' && ch != '"' && ch != '$') {
- *p++ = '\\';
- }
- }
-
- *p++ = ch;
- }
-
- part_len = p - part_data;
- }
-
- len += part_len;
-
- size = ngx_array_push(&lengths);
- if (size == NULL) {
- return NGX_ERROR;
- }
-
- *size = part_len;
-
- value = ngx_array_push(&values);
- if (value == NULL) {
- return NGX_ERROR;
- }
-
- *value = part_data;
- }
-
- prefix = 0;
-
- size = lengths.elts;
- value = values.elts;
-
- if (flags & NGX_HTTP_SSI_ADD_PREFIX) {
- for (i = 0; i < values.nelts; i++) {
- if (size[i] != 0) {
- if (*value[i] != '/') {
- for (prefix = r->uri.len; prefix; prefix--) {
- if (r->uri.data[prefix - 1] == '/') {
- len += prefix;
- break;
- }
- }
- }
-
- break;
- }
- }
- }
-
- p = ngx_pnalloc(r->pool, len + ((flags & NGX_HTTP_SSI_ADD_ZERO) ? 1 : 0));
- if (p == NULL) {
- return NGX_ERROR;
- }
-
- text->len = len;
- text->data = p;
-
- p = ngx_copy(p, r->uri.data, prefix);
-
- for (i = 0; i < values.nelts; i++) {
- p = ngx_copy(p, value[i], size[i]);
- }
-
- return NGX_OK;
-
-invalid_variable:
-
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "invalid variable name in \"%V\"", text);
-
- return NGX_HTTP_SSI_ERROR;
-}
-
-
-static ngx_int_t
-ngx_http_ssi_regex_match(ngx_http_request_t *r, ngx_str_t *pattern,
- ngx_str_t *str)
-{
-#if (NGX_PCRE)
- int rc, *captures;
- u_char *p, errstr[NGX_MAX_CONF_ERRSTR];
- size_t size;
- ngx_str_t *vv, name, value;
- ngx_uint_t i, n, key;
- ngx_http_ssi_ctx_t *ctx;
- ngx_http_ssi_var_t *var;
- ngx_regex_compile_t rgc;
-
- ngx_memzero(&rgc, sizeof(ngx_regex_compile_t));
-
- rgc.pattern = *pattern;
- rgc.pool = r->pool;
- rgc.err.len = NGX_MAX_CONF_ERRSTR;
- rgc.err.data = errstr;
-
- if (ngx_regex_compile(&rgc) != NGX_OK) {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "%V", &rgc.err);
- return NGX_HTTP_SSI_ERROR;
- }
-
- n = (rgc.captures + 1) * 3;
-
- captures = ngx_palloc(r->pool, n * sizeof(int));
- if (captures == NULL) {
- return NGX_ERROR;
- }
-
- rc = ngx_regex_exec(rgc.regex, str, captures, n);
-
- if (rc < NGX_REGEX_NO_MATCHED) {
- ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
- ngx_regex_exec_n " failed: %d on \"%V\" using \"%V\"",
- rc, str, pattern);
- return NGX_HTTP_SSI_ERROR;
- }
-
- if (rc == NGX_REGEX_NO_MATCHED) {
- return NGX_DECLINED;
- }
-
- ctx = ngx_http_get_module_ctx(r->main, ngx_http_ssi_filter_module);
-
- ctx->ncaptures = rc;
- ctx->captures = captures;
- ctx->captures_data = str->data;
-
- if (rgc.named_captures > 0) {
-
- if (ctx->variables == NULL) {
- ctx->variables = ngx_list_create(r->pool, 4,
- sizeof(ngx_http_ssi_var_t));
- if (ctx->variables == NULL) {
- return NGX_ERROR;
- }
- }
-
- size = rgc.name_size;
- p = rgc.names;
-
- for (i = 0; i < (ngx_uint_t) rgc.named_captures; i++, p += size) {
-
- name.data = &p[2];
- name.len = ngx_strlen(name.data);
-
- n = 2 * ((p[0] << 8) + p[1]);
-
- value.data = &str->data[captures[n]];
- value.len = captures[n + 1] - captures[n];
-
- key = ngx_hash_strlow(name.data, name.data, name.len);
-
- vv = ngx_http_ssi_get_variable(r, &name, key);
-
- if (vv) {
- *vv = value;
- continue;
- }
-
- var = ngx_list_push(ctx->variables);
- if (var == NULL) {
- return NGX_ERROR;
- }
-
- var->name = name;
- var->key = key;
- var->value = value;
- }
- }
-
- return NGX_OK;
-
-#else
-
- ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
- "the using of the regex \"%V\" in SSI requires PCRE library",
- pattern);
- return NGX_HTTP_SSI_ERROR;
-
-#endif
-}
-
-
-static ngx_int_t
-ngx_http_ssi_include(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx,
- ngx_str_t **params)
-{
- ngx_int_t rc;
- ngx_str_t *uri, *file, *wait, *set, *stub, args;
- ngx_buf_t *b;
- ngx_uint_t flags, i, key;
- ngx_chain_t *cl, *tl, **ll, *out;
- ngx_http_request_t *sr;
- ngx_http_ssi_var_t *var;
- ngx_http_ssi_ctx_t *mctx;
- ngx_http_ssi_block_t *bl;
- ngx_http_post_subrequest_t *psr;
-
- uri = params[NGX_HTTP_SSI_INCLUDE_VIRTUAL];
- file = params[NGX_HTTP_SSI_INCLUDE_FILE];
- wait = params[NGX_HTTP_SSI_INCLUDE_WAIT];
- set = params[NGX_HTTP_SSI_INCLUDE_SET];
- stub = params[NGX_HTTP_SSI_INCLUDE_STUB];
-
- if (uri && file) {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "inclusion may be either virtual=\"%V\" or file=\"%V\"",
- uri, file);
- return NGX_HTTP_SSI_ERROR;
- }
-
- if (uri == NULL && file == NULL) {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "no parameter in \"include\" SSI command");
- return NGX_HTTP_SSI_ERROR;
- }
-
- if (set && stub) {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "\"set\" and \"stub\" cannot be used together "
- "in \"include\" SSI command");
- return NGX_HTTP_SSI_ERROR;
- }
-
- if (wait) {
- if (uri == NULL) {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "\"wait\" cannot be used with file=\"%V\"", file);
- return NGX_HTTP_SSI_ERROR;
- }
-
- if (wait->len == 2
- && ngx_strncasecmp(wait->data, (u_char *) "no", 2) == 0)
- {
- wait = NULL;
-
- } else if (wait->len != 3
- || ngx_strncasecmp(wait->data, (u_char *) "yes", 3) != 0)
- {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "invalid value \"%V\" in the \"wait\" parameter",
- wait);
- return NGX_HTTP_SSI_ERROR;
- }
- }
-
- if (uri == NULL) {
- uri = file;
- wait = (ngx_str_t *) -1;
- }
-
- rc = ngx_http_ssi_evaluate_string(r, ctx, uri, NGX_HTTP_SSI_ADD_PREFIX);
-
- if (rc != NGX_OK) {
- return rc;
- }
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "ssi include: \"%V\"", uri);
-
- ngx_str_null(&args);
- flags = NGX_HTTP_LOG_UNSAFE;
-
- if (ngx_http_parse_unsafe_uri(r, uri, &args, &flags) != NGX_OK) {
- return NGX_HTTP_SSI_ERROR;
- }
-
- psr = NULL;
-
- mctx = ngx_http_get_module_ctx(r->main, ngx_http_ssi_filter_module);
-
- if (stub) {
- if (mctx->blocks) {
- bl = mctx->blocks->elts;
- for (i = 0; i < mctx->blocks->nelts; i++) {
- if (stub->len == bl[i].name.len
- && ngx_strncmp(stub->data, bl[i].name.data, stub->len) == 0)
- {
- goto found;
- }
- }
- }
-
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "\"stub\"=\"%V\" for \"include\" not found", stub);
- return NGX_HTTP_SSI_ERROR;
-
- found:
-
- psr = ngx_palloc(r->pool, sizeof(ngx_http_post_subrequest_t));
- if (psr == NULL) {
- return NGX_ERROR;
- }
-
- psr->handler = ngx_http_ssi_stub_output;
-
- if (bl[i].count++) {
-
- out = NULL;
- ll = &out;
-
- for (tl = bl[i].bufs; tl; tl = tl->next) {
-
- if (ctx->free) {
- cl = ctx->free;
- ctx->free = ctx->free->next;
- b = cl->buf;
-
- } else {
- b = ngx_alloc_buf(r->pool);
- if (b == NULL) {
- return NGX_ERROR;
- }
-
- cl = ngx_alloc_chain_link(r->pool);
- if (cl == NULL) {
- return NGX_ERROR;
- }
-
- cl->buf = b;
- }
-
- ngx_memcpy(b, tl->buf, sizeof(ngx_buf_t));
-
- b->pos = b->start;
-
- *ll = cl;
- cl->next = NULL;
- ll = &cl->next;
- }
-
- psr->data = out;
-
- } else {
- psr->data = bl[i].bufs;
- }
- }
-
- if (wait) {
- flags |= NGX_HTTP_SUBREQUEST_WAITED;
- }
-
- if (set) {
- key = ngx_hash_strlow(set->data, set->data, set->len);
-
- psr = ngx_palloc(r->pool, sizeof(ngx_http_post_subrequest_t));
- if (psr == NULL) {
- return NGX_ERROR;
- }
-
- psr->handler = ngx_http_ssi_set_variable;
- psr->data = ngx_http_ssi_get_variable(r, set, key);
-
- if (psr->data == NULL) {
-
- if (mctx->variables == NULL) {
- mctx->variables = ngx_list_create(r->pool, 4,
- sizeof(ngx_http_ssi_var_t));
- if (mctx->variables == NULL) {
- return NGX_ERROR;
- }
- }
-
- var = ngx_list_push(mctx->variables);
- if (var == NULL) {
- return NGX_ERROR;
- }
-
- var->name = *set;
- var->key = key;
- var->value = ngx_http_ssi_null_string;
- psr->data = &var->value;
- }
-
- flags |= NGX_HTTP_SUBREQUEST_IN_MEMORY|NGX_HTTP_SUBREQUEST_WAITED;
- }
-
- if (ngx_http_subrequest(r, uri, &args, &sr, psr, flags) != NGX_OK) {
- return NGX_HTTP_SSI_ERROR;
- }
-
- if (wait == NULL && set == NULL) {
- return NGX_OK;
- }
-
- if (ctx->wait == NULL) {
- ctx->wait = sr;
-
- return NGX_AGAIN;
-
- } else {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "can only wait for one subrequest at a time");
- }
-
- return NGX_OK;
-}
-
-
-static ngx_int_t
-ngx_http_ssi_stub_output(ngx_http_request_t *r, void *data, ngx_int_t rc)
-{
- ngx_chain_t *out;
-
- if (rc == NGX_ERROR || r->connection->error || r->request_output) {
- return rc;
- }
-
- ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "ssi stub output: \"%V?%V\"", &r->uri, &r->args);
-
- out = data;
-
- if (!r->header_sent) {
- r->headers_out.content_type_len =
- r->parent->headers_out.content_type_len;
- r->headers_out.content_type = r->parent->headers_out.content_type;
-
- if (ngx_http_send_header(r) == NGX_ERROR) {
- return NGX_ERROR;
- }
- }
-
- return ngx_http_output_filter(r, out);
-}
-
-
-static ngx_int_t
-ngx_http_ssi_set_variable(ngx_http_request_t *r, void *data, ngx_int_t rc)
-{
- ngx_str_t *value = data;
-
- if (r->headers_out.status < NGX_HTTP_SPECIAL_RESPONSE
- && r->out && r->out->buf)
- {
- value->len = r->out->buf->last - r->out->buf->pos;
- value->data = r->out->buf->pos;
- }
-
- return rc;
-}
-
-
-static ngx_int_t
-ngx_http_ssi_echo(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx,
- ngx_str_t **params)
-{
- u_char *p;
- uintptr_t len;
- ngx_buf_t *b;
- ngx_str_t *var, *value, *enc, text;
- ngx_uint_t key;
- ngx_chain_t *cl;
- ngx_http_variable_value_t *vv;
-
- var = params[NGX_HTTP_SSI_ECHO_VAR];
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "ssi echo \"%V\"", var);
-
- key = ngx_hash_strlow(var->data, var->data, var->len);
-
- value = ngx_http_ssi_get_variable(r, var, key);
-
- if (value == NULL) {
- vv = ngx_http_get_variable(r, var, key);
-
- if (vv == NULL) {
- return NGX_HTTP_SSI_ERROR;
- }
-
- if (!vv->not_found) {
- text.data = vv->data;
- text.len = vv->len;
- value = &text;
- }
- }
-
- if (value == NULL) {
- value = params[NGX_HTTP_SSI_ECHO_DEFAULT];
-
- if (value == NULL) {
- value = &ngx_http_ssi_none;
-
- } else if (value->len == 0) {
- return NGX_OK;
- }
-
- } else {
- if (value->len == 0) {
- return NGX_OK;
- }
- }
-
- enc = params[NGX_HTTP_SSI_ECHO_ENCODING];
-
- if (enc) {
- if (enc->len == 4 && ngx_strncmp(enc->data, "none", 4) == 0) {
-
- ctx->encoding = NGX_HTTP_SSI_NO_ENCODING;
-
- } else if (enc->len == 3 && ngx_strncmp(enc->data, "url", 3) == 0) {
-
- ctx->encoding = NGX_HTTP_SSI_URL_ENCODING;
-
- } else if (enc->len == 6 && ngx_strncmp(enc->data, "entity", 6) == 0) {
-
- ctx->encoding = NGX_HTTP_SSI_ENTITY_ENCODING;
-
- } else {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "unknown encoding \"%V\" in the \"echo\" command",
- enc);
- }
- }
-
- p = value->data;
-
- switch (ctx->encoding) {
-
- case NGX_HTTP_SSI_URL_ENCODING:
- len = 2 * ngx_escape_uri(NULL, value->data, value->len,
- NGX_ESCAPE_HTML);
-
- if (len) {
- p = ngx_pnalloc(r->pool, value->len + len);
- if (p == NULL) {
- return NGX_HTTP_SSI_ERROR;
- }
-
- (void) ngx_escape_uri(p, value->data, value->len, NGX_ESCAPE_HTML);
- }
-
- len += value->len;
- break;
-
- case NGX_HTTP_SSI_ENTITY_ENCODING:
- len = ngx_escape_html(NULL, value->data, value->len);
-
- if (len) {
- p = ngx_pnalloc(r->pool, value->len + len);
- if (p == NULL) {
- return NGX_HTTP_SSI_ERROR;
- }
-
- (void) ngx_escape_html(p, value->data, value->len);
- }
-
- len += value->len;
- break;
-
- default: /* NGX_HTTP_SSI_NO_ENCODING */
- len = value->len;
- break;
- }
-
- b = ngx_calloc_buf(r->pool);
- if (b == NULL) {
- return NGX_HTTP_SSI_ERROR;
- }
-
- cl = ngx_alloc_chain_link(r->pool);
- if (cl == NULL) {
- return NGX_HTTP_SSI_ERROR;
- }
-
- b->memory = 1;
- b->pos = p;
- b->last = p + len;
-
- cl->buf = b;
- cl->next = NULL;
- *ctx->last_out = cl;
- ctx->last_out = &cl->next;
-
- return NGX_OK;
-}
-
-
-static ngx_int_t
-ngx_http_ssi_config(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx,
- ngx_str_t **params)
-{
- ngx_str_t *value;
-
- value = params[NGX_HTTP_SSI_CONFIG_TIMEFMT];
-
- if (value) {
- ctx->timefmt.len = value->len;
- ctx->timefmt.data = ngx_pnalloc(r->pool, value->len + 1);
- if (ctx->timefmt.data == NULL) {
- return NGX_ERROR;
- }
-
- ngx_cpystrn(ctx->timefmt.data, value->data, value->len + 1);
- }
-
- value = params[NGX_HTTP_SSI_CONFIG_ERRMSG];
-
- if (value) {
- ctx->errmsg = *value;
- }
-
- return NGX_OK;
-}
-
-
-static ngx_int_t
-ngx_http_ssi_set(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx,
- ngx_str_t **params)
-{
- ngx_int_t rc;
- ngx_str_t *name, *value, *vv;
- ngx_uint_t key;
- ngx_http_ssi_var_t *var;
- ngx_http_ssi_ctx_t *mctx;
-
- mctx = ngx_http_get_module_ctx(r->main, ngx_http_ssi_filter_module);
-
- if (mctx->variables == NULL) {
- mctx->variables = ngx_list_create(r->pool, 4,
- sizeof(ngx_http_ssi_var_t));
- if (mctx->variables == NULL) {
- return NGX_ERROR;
- }
- }
-
- name = params[NGX_HTTP_SSI_SET_VAR];
- value = params[NGX_HTTP_SSI_SET_VALUE];
-
- ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "ssi set \"%V\" \"%V\"", name, value);
-
- rc = ngx_http_ssi_evaluate_string(r, ctx, value, 0);
-
- if (rc != NGX_OK) {
- return rc;
- }
-
- key = ngx_hash_strlow(name->data, name->data, name->len);
-
- vv = ngx_http_ssi_get_variable(r, name, key);
-
- if (vv) {
- *vv = *value;
- return NGX_OK;
- }
-
- var = ngx_list_push(mctx->variables);
- if (var == NULL) {
- return NGX_ERROR;
- }
-
- var->name = *name;
- var->key = key;
- var->value = *value;
-
- ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "set: \"%V\"=\"%V\"", name, value);
-
- return NGX_OK;
-}
-
-
-static ngx_int_t
-ngx_http_ssi_if(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx,
- ngx_str_t **params)
-{
- u_char *p, *last;
- ngx_str_t *expr, left, right;
- ngx_int_t rc;
- ngx_uint_t negative, noregex, flags;
-
- if (ctx->command.len == 2) {
- if (ctx->conditional) {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "the \"if\" command inside the \"if\" command");
- return NGX_HTTP_SSI_ERROR;
- }
- }
-
- if (ctx->output_chosen) {
- ctx->output = 0;
- return NGX_OK;
- }
-
- expr = params[NGX_HTTP_SSI_IF_EXPR];
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "ssi if expr=\"%V\"", expr);
-
- left.data = expr->data;
- last = expr->data + expr->len;
-
- for (p = left.data; p < last; p++) {
- if (*p >= 'A' && *p <= 'Z') {
- *p |= 0x20;
- continue;
- }
-
- if ((*p >= 'a' && *p <= 'z')
- || (*p >= '0' && *p <= '9')
- || *p == '$' || *p == '{' || *p == '}' || *p == '_'
- || *p == '"' || *p == '\'')
- {
- continue;
- }
-
- break;
- }
-
- left.len = p - left.data;
-
- while (p < last && *p == ' ') {
- p++;
- }
-
- flags = 0;
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "left: \"%V\"", &left);
-
- rc = ngx_http_ssi_evaluate_string(r, ctx, &left, flags);
-
- if (rc != NGX_OK) {
- return rc;
- }
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "evaluated left: \"%V\"", &left);
-
- if (p == last) {
- if (left.len) {
- ctx->output = 1;
- ctx->output_chosen = 1;
-
- } else {
- ctx->output = 0;
- }
-
- ctx->conditional = NGX_HTTP_SSI_COND_IF;
-
- return NGX_OK;
- }
-
- if (p < last && *p == '=') {
- negative = 0;
- p++;
-
- } else if (p + 1 < last && *p == '!' && *(p + 1) == '=') {
- negative = 1;
- p += 2;
-
- } else {
- goto invalid_expression;
- }
-
- while (p < last && *p == ' ') {
- p++;
- }
-
- if (p < last - 1 && *p == '/') {
- if (*(last - 1) != '/') {
- goto invalid_expression;
- }
-
- noregex = 0;
- flags = NGX_HTTP_SSI_ADD_ZERO;
- last--;
- p++;
-
- } else {
- noregex = 1;
- flags = 0;
-
- if (p < last - 1 && p[0] == '\\' && p[1] == '/') {
- p++;
- }
- }
-
- right.len = last - p;
- right.data = p;
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "right: \"%V\"", &right);
-
- rc = ngx_http_ssi_evaluate_string(r, ctx, &right, flags);
-
- if (rc != NGX_OK) {
- return rc;
- }
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "evaluated right: \"%V\"", &right);
-
- if (noregex) {
- if (left.len != right.len) {
- rc = -1;
-
- } else {
- rc = ngx_strncmp(left.data, right.data, right.len);
- }
-
- } else {
- right.data[right.len] = '\0';
-
- rc = ngx_http_ssi_regex_match(r, &right, &left);
-
- if (rc == NGX_OK) {
- rc = 0;
- } else if (rc == NGX_DECLINED) {
- rc = -1;
- } else {
- return rc;
- }
- }
-
- if ((rc == 0 && !negative) || (rc != 0 && negative)) {
- ctx->output = 1;
- ctx->output_chosen = 1;
-
- } else {
- ctx->output = 0;
- }
-
- ctx->conditional = NGX_HTTP_SSI_COND_IF;
-
- return NGX_OK;
-
-invalid_expression:
-
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "invalid expression in \"%V\"", expr);
-
- return NGX_HTTP_SSI_ERROR;
-}
-
-
-static ngx_int_t
-ngx_http_ssi_else(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx,
- ngx_str_t **params)
-{
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "ssi else");
-
- if (ctx->output_chosen) {
- ctx->output = 0;
- } else {
- ctx->output = 1;
- }
-
- ctx->conditional = NGX_HTTP_SSI_COND_ELSE;
-
- return NGX_OK;
-}
-
-
-static ngx_int_t
-ngx_http_ssi_endif(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx,
- ngx_str_t **params)
-{
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "ssi endif");
-
- ctx->output = 1;
- ctx->output_chosen = 0;
- ctx->conditional = 0;
-
- return NGX_OK;
-}
-
-
-static ngx_int_t
-ngx_http_ssi_block(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx,
- ngx_str_t **params)
-{
- ngx_http_ssi_ctx_t *mctx;
- ngx_http_ssi_block_t *bl;
-
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "ssi block");
-
- mctx = ngx_http_get_module_ctx(r->main, ngx_http_ssi_filter_module);
-
- if (mctx->blocks == NULL) {
- mctx->blocks = ngx_array_create(r->pool, 4,
- sizeof(ngx_http_ssi_block_t));
- if (mctx->blocks == NULL) {
- return NGX_HTTP_SSI_ERROR;
- }
- }
-
- bl = ngx_array_push(mctx->blocks);
- if (bl == NULL) {
- return NGX_HTTP_SSI_ERROR;
- }
-
- bl->name = *params[NGX_HTTP_SSI_BLOCK_NAME];
- bl->bufs = NULL;
- bl->count = 0;
-
- ctx->output = 0;
- ctx->block = 1;
-
- return NGX_OK;
-}
-
-
-static ngx_int_t
-ngx_http_ssi_endblock(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx,
- ngx_str_t **params)
-{
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "ssi endblock");
-
- ctx->output = 1;
- ctx->block = 0;
-
- return NGX_OK;
-}
-
-
-static ngx_int_t
-ngx_http_ssi_date_gmt_local_variable(ngx_http_request_t *r,
- ngx_http_variable_value_t *v, uintptr_t gmt)
-{
- time_t now;
- ngx_http_ssi_ctx_t *ctx;
- ngx_str_t *timefmt;
- struct tm tm;
- char buf[NGX_HTTP_SSI_DATE_LEN];
-
- v->valid = 1;
- v->no_cacheable = 0;
- v->not_found = 0;
-
- now = ngx_time();
-
- ctx = ngx_http_get_module_ctx(r, ngx_http_ssi_filter_module);
-
- timefmt = ctx ? &ctx->timefmt : &ngx_http_ssi_timefmt;
-
- if (timefmt->len == sizeof("%s") - 1
- && timefmt->data[0] == '%' && timefmt->data[1] == 's')
- {
- v->data = ngx_pnalloc(r->pool, NGX_TIME_T_LEN);
- if (v->data == NULL) {
- return NGX_ERROR;
- }
-
- v->len = ngx_sprintf(v->data, "%T", now) - v->data;
-
- return NGX_OK;
- }
-
- if (gmt) {
- ngx_libc_gmtime(now, &tm);
- } else {
- ngx_libc_localtime(now, &tm);
- }
-
- v->len = strftime(buf, NGX_HTTP_SSI_DATE_LEN,
- (char *) timefmt->data, &tm);
- if (v->len == 0) {
- return NGX_ERROR;
- }
-
- v->data = ngx_pnalloc(r->pool, v->len);
- if (v->data == NULL) {
- return NGX_ERROR;
- }
-
- ngx_memcpy(v->data, buf, v->len);
-
- return NGX_OK;
-}
-
-
-static ngx_int_t
-ngx_http_ssi_preconfiguration(ngx_conf_t *cf)
-{
- ngx_int_t rc;
- ngx_http_variable_t *var, *v;
- ngx_http_ssi_command_t *cmd;
- ngx_http_ssi_main_conf_t *smcf;
-
- for (v = ngx_http_ssi_vars; v->name.len; v++) {
- var = ngx_http_add_variable(cf, &v->name, v->flags);
- if (var == NULL) {
- return NGX_ERROR;
- }
-
- var->get_handler = v->get_handler;
- var->data = v->data;
- }
-
- smcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_ssi_filter_module);
-
- for (cmd = ngx_http_ssi_commands; cmd->name.len; cmd++) {
- rc = ngx_hash_add_key(&smcf->commands, &cmd->name, cmd,
- NGX_HASH_READONLY_KEY);
-
- if (rc == NGX_OK) {
- continue;
- }
-
- if (rc == NGX_BUSY) {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "conflicting SSI command \"%V\"", &cmd->name);
- }
-
- return NGX_ERROR;
- }
-
- return NGX_OK;
-}
-
-
-static void *
-ngx_http_ssi_create_main_conf(ngx_conf_t *cf)
-{
- ngx_http_ssi_main_conf_t *smcf;
-
- smcf = ngx_pcalloc(cf->pool, sizeof(ngx_http_ssi_main_conf_t));
- if (smcf == NULL) {
- return NULL;
- }
-
- smcf->commands.pool = cf->pool;
- smcf->commands.temp_pool = cf->temp_pool;
-
- if (ngx_hash_keys_array_init(&smcf->commands, NGX_HASH_SMALL) != NGX_OK) {
- return NULL;
- }
-
- return smcf;
-}
-
-
-static char *
-ngx_http_ssi_init_main_conf(ngx_conf_t *cf, void *conf)
-{
- ngx_http_ssi_main_conf_t *smcf = conf;
-
- ngx_hash_init_t hash;
-
- hash.hash = &smcf->hash;
- hash.key = ngx_hash_key;
- hash.max_size = 1024;
- hash.bucket_size = ngx_cacheline_size;
- hash.name = "ssi_command_hash";
- hash.pool = cf->pool;
- hash.temp_pool = NULL;
-
- if (ngx_hash_init(&hash, smcf->commands.keys.elts,
- smcf->commands.keys.nelts)
- != NGX_OK)
- {
- return NGX_CONF_ERROR;
- }
-
- return NGX_CONF_OK;
-}
-
-
-static void *
-ngx_http_ssi_create_loc_conf(ngx_conf_t *cf)
-{
- ngx_http_ssi_loc_conf_t *slcf;
-
- slcf = ngx_pcalloc(cf->pool, sizeof(ngx_http_ssi_loc_conf_t));
- if (slcf == NULL) {
- return NULL;
- }
-
- /*
- * set by ngx_pcalloc():
- *
- * conf->types = { NULL };
- * conf->types_keys = NULL;
- */
-
- slcf->enable = NGX_CONF_UNSET;
- slcf->silent_errors = NGX_CONF_UNSET;
- slcf->ignore_recycled_buffers = NGX_CONF_UNSET;
- slcf->last_modified = NGX_CONF_UNSET;
-
- slcf->min_file_chunk = NGX_CONF_UNSET_SIZE;
- slcf->value_len = NGX_CONF_UNSET_SIZE;
-
- return slcf;
-}
-
-
-static char *
-ngx_http_ssi_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
-{
- ngx_http_ssi_loc_conf_t *prev = parent;
- ngx_http_ssi_loc_conf_t *conf = child;
-
- ngx_conf_merge_value(conf->enable, prev->enable, 0);
- ngx_conf_merge_value(conf->silent_errors, prev->silent_errors, 0);
- ngx_conf_merge_value(conf->ignore_recycled_buffers,
- prev->ignore_recycled_buffers, 0);
- ngx_conf_merge_value(conf->last_modified, prev->last_modified, 0);
-
- ngx_conf_merge_size_value(conf->min_file_chunk, prev->min_file_chunk, 1024);
- ngx_conf_merge_size_value(conf->value_len, prev->value_len, 255);
-
- if (ngx_http_merge_types(cf, &conf->types_keys, &conf->types,
- &prev->types_keys, &prev->types,
- ngx_http_html_default_types)
- != NGX_OK)
- {
- return NGX_CONF_ERROR;
- }
-
- return NGX_CONF_OK;
-}
-
-
-static ngx_int_t
-ngx_http_ssi_filter_init(ngx_conf_t *cf)
-{
- ngx_http_next_header_filter = ngx_http_top_header_filter;
- ngx_http_top_header_filter = ngx_http_ssi_header_filter;
-
- ngx_http_next_body_filter = ngx_http_top_body_filter;
- ngx_http_top_body_filter = ngx_http_ssi_body_filter;
-
- return NGX_OK;
-}
diff --git a/nginx/src/http/modules/ngx_http_ssi_filter_module.h b/nginx/src/http/modules/ngx_http_ssi_filter_module.h
deleted file mode 100644
index 0bd01a0..0000000
--- a/nginx/src/http/modules/ngx_http_ssi_filter_module.h
+++ /dev/null
@@ -1,114 +0,0 @@
-
-/*
- * Copyright (C) Igor Sysoev
- * Copyright (C) Nginx, Inc.
- */
-
-
-#ifndef _NGX_HTTP_SSI_FILTER_H_INCLUDED_
-#define _NGX_HTTP_SSI_FILTER_H_INCLUDED_
-
-
-#include <ngx_config.h>
-#include <ngx_core.h>
-#include <ngx_http.h>
-
-
-#define NGX_HTTP_SSI_MAX_PARAMS 16
-
-#define NGX_HTTP_SSI_COMMAND_LEN 32
-#define NGX_HTTP_SSI_PARAM_LEN 32
-#define NGX_HTTP_SSI_PARAMS_N 4
-
-
-#define NGX_HTTP_SSI_COND_IF 1
-#define NGX_HTTP_SSI_COND_ELSE 2
-
-
-#define NGX_HTTP_SSI_NO_ENCODING 0
-#define NGX_HTTP_SSI_URL_ENCODING 1
-#define NGX_HTTP_SSI_ENTITY_ENCODING 2
-
-
-typedef struct {
- ngx_hash_t hash;
- ngx_hash_keys_arrays_t commands;
-} ngx_http_ssi_main_conf_t;
-
-
-typedef struct {
- ngx_buf_t *buf;
-
- u_char *pos;
- u_char *copy_start;
- u_char *copy_end;
-
- ngx_uint_t key;
- ngx_str_t command;
- ngx_array_t params;
- ngx_table_elt_t *param;
- ngx_table_elt_t params_array[NGX_HTTP_SSI_PARAMS_N];
-
- ngx_chain_t *in;
- ngx_chain_t *out;
- ngx_chain_t **last_out;
- ngx_chain_t *busy;
- ngx_chain_t *free;
-
- ngx_uint_t state;
- ngx_uint_t saved_state;
- size_t saved;
- size_t looked;
-
- size_t value_len;
-
- ngx_list_t *variables;
- ngx_array_t *blocks;
-
-#if (NGX_PCRE)
- ngx_uint_t ncaptures;
- int *captures;
- u_char *captures_data;
-#endif
-
- unsigned conditional:2;
- unsigned encoding:2;
- unsigned block:1;
- unsigned output:1;
- unsigned output_chosen:1;
-
- ngx_http_request_t *wait;
- void *value_buf;
- ngx_str_t timefmt;
- ngx_str_t errmsg;
-} ngx_http_ssi_ctx_t;
-
-
-typedef ngx_int_t (*ngx_http_ssi_command_pt) (ngx_http_request_t *r,
- ngx_http_ssi_ctx_t *ctx, ngx_str_t **);
-
-
-typedef struct {
- ngx_str_t name;
- ngx_uint_t index;
-
- unsigned mandatory:1;
- unsigned multiple:1;
-} ngx_http_ssi_param_t;
-
-
-typedef struct {
- ngx_str_t name;
- ngx_http_ssi_command_pt handler;
- ngx_http_ssi_param_t *params;
-
- unsigned conditional:2;
- unsigned block:1;
- unsigned flush:1;
-} ngx_http_ssi_command_t;
-
-
-extern ngx_module_t ngx_http_ssi_filter_module;
-
-
-#endif /* _NGX_HTTP_SSI_FILTER_H_INCLUDED_ */
diff --git a/nginx/src/http/modules/ngx_http_ssl_module.c b/nginx/src/http/modules/ngx_http_ssl_module.c
deleted file mode 100644
index 7d62176..0000000
--- a/nginx/src/http/modules/ngx_http_ssl_module.c
+++ /dev/null
@@ -1,997 +0,0 @@
-
-/*
- * Copyright (C) Igor Sysoev
- * Copyright (C) Nginx, Inc.
- */
-
-
-#include <ngx_config.h>
-#include <ngx_core.h>
-#include <ngx_http.h>
-
-
-typedef ngx_int_t (*ngx_ssl_variable_handler_pt)(ngx_connection_t *c,
- ngx_pool_t *pool, ngx_str_t *s);
-
-
-#define NGX_DEFAULT_CIPHERS "HIGH:!aNULL:!MD5"
-#define NGX_DEFAULT_ECDH_CURVE "auto"
-
-#define NGX_HTTP_NPN_ADVERTISE "\x08http/1.1"
-
-
-#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
-static int ngx_http_ssl_alpn_select(ngx_ssl_conn_t *ssl_conn,
- const unsigned char **out, unsigned char *outlen,
- const unsigned char *in, unsigned int inlen, void *arg);
-#endif
-
-#ifdef TLSEXT_TYPE_next_proto_neg
-static int ngx_http_ssl_npn_advertised(ngx_ssl_conn_t *ssl_conn,
- const unsigned char **out, unsigned int *outlen, void *arg);
-#endif
-
-static ngx_int_t ngx_http_ssl_static_variable(ngx_http_request_t *r,
- ngx_http_variable_value_t *v, uintptr_t data);
-static ngx_int_t ngx_http_ssl_variable(ngx_http_request_t *r,
- ngx_http_variable_value_t *v, uintptr_t data);
-
-static ngx_int_t ngx_http_ssl_add_variables(ngx_conf_t *cf);
-static void *ngx_http_ssl_create_srv_conf(ngx_conf_t *cf);
-static char *ngx_http_ssl_merge_srv_conf(ngx_conf_t *cf,
- void *parent, void *child);
-
-static char *ngx_http_ssl_enable(ngx_conf_t *cf, ngx_command_t *cmd,
- void *conf);
-static char *ngx_http_ssl_password_file(ngx_conf_t *cf, ngx_command_t *cmd,
- void *conf);
-static char *ngx_http_ssl_session_cache(ngx_conf_t *cf, ngx_command_t *cmd,
- void *conf);
-
-static ngx_int_t ngx_http_ssl_init(ngx_conf_t *cf);
-
-
-static ngx_conf_bitmask_t ngx_http_ssl_protocols[] = {
- { ngx_string("SSLv2"), NGX_SSL_SSLv2 },
- { ngx_string("SSLv3"), NGX_SSL_SSLv3 },
- { ngx_string("TLSv1"), NGX_SSL_TLSv1 },
- { ngx_string("TLSv1.1"), NGX_SSL_TLSv1_1 },
- { ngx_string("TLSv1.2"), NGX_SSL_TLSv1_2 },
- { ngx_string("TLSv1.3"), NGX_SSL_TLSv1_3 },
- { ngx_null_string, 0 }
-};
-
-
-static ngx_conf_enum_t ngx_http_ssl_verify[] = {
- { ngx_string("off"), 0 },
- { ngx_string("on"), 1 },
- { ngx_string("optional"), 2 },
- { ngx_string("optional_no_ca"), 3 },
- { ngx_null_string, 0 }
-};
-
-
-static ngx_command_t ngx_http_ssl_commands[] = {
-
- { ngx_string("ssl"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_FLAG,
- ngx_http_ssl_enable,
- NGX_HTTP_SRV_CONF_OFFSET,
- offsetof(ngx_http_ssl_srv_conf_t, enable),
- NULL },
-
- { ngx_string("ssl_certificate"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_str_array_slot,
- NGX_HTTP_SRV_CONF_OFFSET,
- offsetof(ngx_http_ssl_srv_conf_t, certificates),
- NULL },
-
- { ngx_string("ssl_certificate_key"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_str_array_slot,
- NGX_HTTP_SRV_CONF_OFFSET,
- offsetof(ngx_http_ssl_srv_conf_t, certificate_keys),
- NULL },
-
- { ngx_string("ssl_password_file"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
- ngx_http_ssl_password_file,
- NGX_HTTP_SRV_CONF_OFFSET,
- 0,
- NULL },
-
- { ngx_string("ssl_dhparam"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_str_slot,
- NGX_HTTP_SRV_CONF_OFFSET,
- offsetof(ngx_http_ssl_srv_conf_t, dhparam),
- NULL },
-
- { ngx_string("ssl_ecdh_curve"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_str_slot,
- NGX_HTTP_SRV_CONF_OFFSET,
- offsetof(ngx_http_ssl_srv_conf_t, ecdh_curve),
- NULL },
-
- { ngx_string("ssl_protocols"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_1MORE,
- ngx_conf_set_bitmask_slot,
- NGX_HTTP_SRV_CONF_OFFSET,
- offsetof(ngx_http_ssl_srv_conf_t, protocols),
- &ngx_http_ssl_protocols },
-
- { ngx_string("ssl_ciphers"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_str_slot,
- NGX_HTTP_SRV_CONF_OFFSET,
- offsetof(ngx_http_ssl_srv_conf_t, ciphers),
- NULL },
-
- { ngx_string("ssl_buffer_size"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_size_slot,
- NGX_HTTP_SRV_CONF_OFFSET,
- offsetof(ngx_http_ssl_srv_conf_t, buffer_size),
- NULL },
-
- { ngx_string("ssl_verify_client"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_enum_slot,
- NGX_HTTP_SRV_CONF_OFFSET,
- offsetof(ngx_http_ssl_srv_conf_t, verify),
- &ngx_http_ssl_verify },
-
- { ngx_string("ssl_verify_depth"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_num_slot,
- NGX_HTTP_SRV_CONF_OFFSET,
- offsetof(ngx_http_ssl_srv_conf_t, verify_depth),
- NULL },
-
- { ngx_string("ssl_client_certificate"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_str_slot,
- NGX_HTTP_SRV_CONF_OFFSET,
- offsetof(ngx_http_ssl_srv_conf_t, client_certificate),
- NULL },
-
- { ngx_string("ssl_trusted_certificate"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_str_slot,
- NGX_HTTP_SRV_CONF_OFFSET,
- offsetof(ngx_http_ssl_srv_conf_t, trusted_certificate),
- NULL },
-
- { ngx_string("ssl_prefer_server_ciphers"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_FLAG,
- ngx_conf_set_flag_slot,
- NGX_HTTP_SRV_CONF_OFFSET,
- offsetof(ngx_http_ssl_srv_conf_t, prefer_server_ciphers),
- NULL },
-
- { ngx_string("ssl_session_cache"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE12,
- ngx_http_ssl_session_cache,
- NGX_HTTP_SRV_CONF_OFFSET,
- 0,
- NULL },
-
- { ngx_string("ssl_session_tickets"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_FLAG,
- ngx_conf_set_flag_slot,
- NGX_HTTP_SRV_CONF_OFFSET,
- offsetof(ngx_http_ssl_srv_conf_t, session_tickets),
- NULL },
-
- { ngx_string("ssl_session_ticket_key"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_str_array_slot,
- NGX_HTTP_SRV_CONF_OFFSET,
- offsetof(ngx_http_ssl_srv_conf_t, session_ticket_keys),
- NULL },
-
- { ngx_string("ssl_session_timeout"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_sec_slot,
- NGX_HTTP_SRV_CONF_OFFSET,
- offsetof(ngx_http_ssl_srv_conf_t, session_timeout),
- NULL },
-
- { ngx_string("ssl_crl"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_str_slot,
- NGX_HTTP_SRV_CONF_OFFSET,
- offsetof(ngx_http_ssl_srv_conf_t, crl),
- NULL },
-
- { ngx_string("ssl_stapling"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_FLAG,
- ngx_conf_set_flag_slot,
- NGX_HTTP_SRV_CONF_OFFSET,
- offsetof(ngx_http_ssl_srv_conf_t, stapling),
- NULL },
-
- { ngx_string("ssl_stapling_file"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_str_slot,
- NGX_HTTP_SRV_CONF_OFFSET,
- offsetof(ngx_http_ssl_srv_conf_t, stapling_file),
- NULL },
-
- { ngx_string("ssl_stapling_responder"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_str_slot,
- NGX_HTTP_SRV_CONF_OFFSET,
- offsetof(ngx_http_ssl_srv_conf_t, stapling_responder),
- NULL },
-
- { ngx_string("ssl_stapling_verify"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_FLAG,
- ngx_conf_set_flag_slot,
- NGX_HTTP_SRV_CONF_OFFSET,
- offsetof(ngx_http_ssl_srv_conf_t, stapling_verify),
- NULL },
-
- ngx_null_command
-};
-
-
-static ngx_http_module_t ngx_http_ssl_module_ctx = {
- ngx_http_ssl_add_variables, /* preconfiguration */
- ngx_http_ssl_init, /* postconfiguration */
-
- NULL, /* create main configuration */
- NULL, /* init main configuration */
-
- ngx_http_ssl_create_srv_conf, /* create server configuration */
- ngx_http_ssl_merge_srv_conf, /* merge server configuration */
-
- NULL, /* create location configuration */
- NULL /* merge location configuration */
-};
-
-
-ngx_module_t ngx_http_ssl_module = {
- NGX_MODULE_V1,
- &ngx_http_ssl_module_ctx, /* module context */
- ngx_http_ssl_commands, /* module directives */
- NGX_HTTP_MODULE, /* module type */
- NULL, /* init master */
- NULL, /* init module */
- NULL, /* init process */
- NULL, /* init thread */
- NULL, /* exit thread */
- NULL, /* exit process */
- NULL, /* exit master */
- NGX_MODULE_V1_PADDING
-};
-
-
-static ngx_http_variable_t ngx_http_ssl_vars[] = {
-
- { ngx_string("ssl_protocol"), NULL, ngx_http_ssl_static_variable,
- (uintptr_t) ngx_ssl_get_protocol, NGX_HTTP_VAR_CHANGEABLE, 0 },
-
- { ngx_string("ssl_cipher"), NULL, ngx_http_ssl_static_variable,
- (uintptr_t) ngx_ssl_get_cipher_name, NGX_HTTP_VAR_CHANGEABLE, 0 },
-
- { ngx_string("ssl_ciphers"), NULL, ngx_http_ssl_variable,
- (uintptr_t) ngx_ssl_get_ciphers, NGX_HTTP_VAR_CHANGEABLE, 0 },
-
- { ngx_string("ssl_curves"), NULL, ngx_http_ssl_variable,
- (uintptr_t) ngx_ssl_get_curves, NGX_HTTP_VAR_CHANGEABLE, 0 },
-
- { ngx_string("ssl_session_id"), NULL, ngx_http_ssl_variable,
- (uintptr_t) ngx_ssl_get_session_id, NGX_HTTP_VAR_CHANGEABLE, 0 },
-
- { ngx_string("ssl_session_reused"), NULL, ngx_http_ssl_variable,
- (uintptr_t) ngx_ssl_get_session_reused, NGX_HTTP_VAR_CHANGEABLE, 0 },
-
- { ngx_string("ssl_server_name"), NULL, ngx_http_ssl_variable,
- (uintptr_t) ngx_ssl_get_server_name, NGX_HTTP_VAR_CHANGEABLE, 0 },
-
- { ngx_string("ssl_client_cert"), NULL, ngx_http_ssl_variable,
- (uintptr_t) ngx_ssl_get_certificate, NGX_HTTP_VAR_CHANGEABLE, 0 },
-
- { ngx_string("ssl_client_raw_cert"), NULL, ngx_http_ssl_variable,
- (uintptr_t) ngx_ssl_get_raw_certificate,
- NGX_HTTP_VAR_CHANGEABLE, 0 },
-
- { ngx_string("ssl_client_escaped_cert"), NULL, ngx_http_ssl_variable,
- (uintptr_t) ngx_ssl_get_escaped_certificate,
- NGX_HTTP_VAR_CHANGEABLE, 0 },
-
- { ngx_string("ssl_client_s_dn"), NULL, ngx_http_ssl_variable,
- (uintptr_t) ngx_ssl_get_subject_dn, NGX_HTTP_VAR_CHANGEABLE, 0 },
-
- { ngx_string("ssl_client_i_dn"), NULL, ngx_http_ssl_variable,
- (uintptr_t) ngx_ssl_get_issuer_dn, NGX_HTTP_VAR_CHANGEABLE, 0 },
-
- { ngx_string("ssl_client_s_dn_legacy"), NULL, ngx_http_ssl_variable,
- (uintptr_t) ngx_ssl_get_subject_dn_legacy, NGX_HTTP_VAR_CHANGEABLE, 0 },
-
- { ngx_string("ssl_client_i_dn_legacy"), NULL, ngx_http_ssl_variable,
- (uintptr_t) ngx_ssl_get_issuer_dn_legacy, NGX_HTTP_VAR_CHANGEABLE, 0 },
-
- { ngx_string("ssl_client_serial"), NULL, ngx_http_ssl_variable,
- (uintptr_t) ngx_ssl_get_serial_number, NGX_HTTP_VAR_CHANGEABLE, 0 },
-
- { ngx_string("ssl_client_fingerprint"), NULL, ngx_http_ssl_variable,
- (uintptr_t) ngx_ssl_get_fingerprint, NGX_HTTP_VAR_CHANGEABLE, 0 },
-
- { ngx_string("ssl_client_verify"), NULL, ngx_http_ssl_variable,
- (uintptr_t) ngx_ssl_get_client_verify, NGX_HTTP_VAR_CHANGEABLE, 0 },
-
- { ngx_string("ssl_client_v_start"), NULL, ngx_http_ssl_variable,
- (uintptr_t) ngx_ssl_get_client_v_start, NGX_HTTP_VAR_CHANGEABLE, 0 },
-
- { ngx_string("ssl_client_v_end"), NULL, ngx_http_ssl_variable,
- (uintptr_t) ngx_ssl_get_client_v_end, NGX_HTTP_VAR_CHANGEABLE, 0 },
-
- { ngx_string("ssl_client_v_remain"), NULL, ngx_http_ssl_variable,
- (uintptr_t) ngx_ssl_get_client_v_remain, NGX_HTTP_VAR_CHANGEABLE, 0 },
-
- ngx_http_null_variable
-};
-
-
-static ngx_str_t ngx_http_ssl_sess_id_ctx = ngx_string("HTTP");
-
-
-#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
-
-static int
-ngx_http_ssl_alpn_select(ngx_ssl_conn_t *ssl_conn, const unsigned char **out,
- unsigned char *outlen, const unsigned char *in, unsigned int inlen,
- void *arg)
-{
- unsigned int srvlen;
- unsigned char *srv;
-#if (NGX_DEBUG)
- unsigned int i;
-#endif
-#if (NGX_HTTP_V2)
- ngx_http_connection_t *hc;
-#endif
-#if (NGX_HTTP_V2 || NGX_DEBUG)
- ngx_connection_t *c;
-
- c = ngx_ssl_get_connection(ssl_conn);
-#endif
-
-#if (NGX_DEBUG)
- for (i = 0; i < inlen; i += in[i] + 1) {
- ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
- "SSL ALPN supported by client: %*s",
- (size_t) in[i], &in[i + 1]);
- }
-#endif
-
-#if (NGX_HTTP_V2)
- hc = c->data;
-
- if (hc->addr_conf->http2) {
- srv =
- (unsigned char *) NGX_HTTP_V2_ALPN_ADVERTISE NGX_HTTP_NPN_ADVERTISE;
- srvlen = sizeof(NGX_HTTP_V2_ALPN_ADVERTISE NGX_HTTP_NPN_ADVERTISE) - 1;
-
- } else
-#endif
- {
- srv = (unsigned char *) NGX_HTTP_NPN_ADVERTISE;
- srvlen = sizeof(NGX_HTTP_NPN_ADVERTISE) - 1;
- }
-
- if (SSL_select_next_proto((unsigned char **) out, outlen, srv, srvlen,
- in, inlen)
- != OPENSSL_NPN_NEGOTIATED)
- {
- return SSL_TLSEXT_ERR_NOACK;
- }
-
- ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
- "SSL ALPN selected: %*s", (size_t) *outlen, *out);
-
- return SSL_TLSEXT_ERR_OK;
-}
-
-#endif
-
-
-#ifdef TLSEXT_TYPE_next_proto_neg
-
-static int
-ngx_http_ssl_npn_advertised(ngx_ssl_conn_t *ssl_conn,
- const unsigned char **out, unsigned int *outlen, void *arg)
-{
-#if (NGX_HTTP_V2 || NGX_DEBUG)
- ngx_connection_t *c;
-
- c = ngx_ssl_get_connection(ssl_conn);
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "SSL NPN advertised");
-#endif
-
-#if (NGX_HTTP_V2)
- {
- ngx_http_connection_t *hc;
-
- hc = c->data;
-
- if (hc->addr_conf->http2) {
- *out =
- (unsigned char *) NGX_HTTP_V2_NPN_ADVERTISE NGX_HTTP_NPN_ADVERTISE;
- *outlen = sizeof(NGX_HTTP_V2_NPN_ADVERTISE NGX_HTTP_NPN_ADVERTISE) - 1;
-
- return SSL_TLSEXT_ERR_OK;
- }
- }
-#endif
-
- *out = (unsigned char *) NGX_HTTP_NPN_ADVERTISE;
- *outlen = sizeof(NGX_HTTP_NPN_ADVERTISE) - 1;
-
- return SSL_TLSEXT_ERR_OK;
-}
-
-#endif
-
-
-static ngx_int_t
-ngx_http_ssl_static_variable(ngx_http_request_t *r,
- ngx_http_variable_value_t *v, uintptr_t data)
-{
- ngx_ssl_variable_handler_pt handler = (ngx_ssl_variable_handler_pt) data;
-
- size_t len;
- ngx_str_t s;
-
- if (r->connection->ssl) {
-
- (void) handler(r->connection, NULL, &s);
-
- v->data = s.data;
-
- for (len = 0; v->data[len]; len++) { /* void */ }
-
- v->len = len;
- v->valid = 1;
- v->no_cacheable = 0;
- v->not_found = 0;
-
- return NGX_OK;
- }
-
- v->not_found = 1;
-
- return NGX_OK;
-}
-
-
-static ngx_int_t
-ngx_http_ssl_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v,
- uintptr_t data)
-{
- ngx_ssl_variable_handler_pt handler = (ngx_ssl_variable_handler_pt) data;
-
- ngx_str_t s;
-
- if (r->connection->ssl) {
-
- if (handler(r->connection, r->pool, &s) != NGX_OK) {
- return NGX_ERROR;
- }
-
- v->len = s.len;
- v->data = s.data;
-
- if (v->len) {
- v->valid = 1;
- v->no_cacheable = 0;
- v->not_found = 0;
-
- return NGX_OK;
- }
- }
-
- v->not_found = 1;
-
- return NGX_OK;
-}
-
-
-static ngx_int_t
-ngx_http_ssl_add_variables(ngx_conf_t *cf)
-{
- ngx_http_variable_t *var, *v;
-
- for (v = ngx_http_ssl_vars; v->name.len; v++) {
- var = ngx_http_add_variable(cf, &v->name, v->flags);
- if (var == NULL) {
- return NGX_ERROR;
- }
-
- var->get_handler = v->get_handler;
- var->data = v->data;
- }
-
- return NGX_OK;
-}
-
-
-static void *
-ngx_http_ssl_create_srv_conf(ngx_conf_t *cf)
-{
- ngx_http_ssl_srv_conf_t *sscf;
-
- sscf = ngx_pcalloc(cf->pool, sizeof(ngx_http_ssl_srv_conf_t));
- if (sscf == NULL) {
- return NULL;
- }
-
- /*
- * set by ngx_pcalloc():
- *
- * sscf->protocols = 0;
- * sscf->dhparam = { 0, NULL };
- * sscf->ecdh_curve = { 0, NULL };
- * sscf->client_certificate = { 0, NULL };
- * sscf->trusted_certificate = { 0, NULL };
- * sscf->crl = { 0, NULL };
- * sscf->ciphers = { 0, NULL };
- * sscf->shm_zone = NULL;
- * sscf->stapling_file = { 0, NULL };
- * sscf->stapling_responder = { 0, NULL };
- */
-
- sscf->enable = NGX_CONF_UNSET;
- sscf->prefer_server_ciphers = NGX_CONF_UNSET;
- sscf->buffer_size = NGX_CONF_UNSET_SIZE;
- sscf->verify = NGX_CONF_UNSET_UINT;
- sscf->verify_depth = NGX_CONF_UNSET_UINT;
- sscf->certificates = NGX_CONF_UNSET_PTR;
- sscf->certificate_keys = NGX_CONF_UNSET_PTR;
- sscf->passwords = NGX_CONF_UNSET_PTR;
- sscf->builtin_session_cache = NGX_CONF_UNSET;
- sscf->session_timeout = NGX_CONF_UNSET;
- sscf->session_tickets = NGX_CONF_UNSET;
- sscf->session_ticket_keys = NGX_CONF_UNSET_PTR;
- sscf->stapling = NGX_CONF_UNSET;
- sscf->stapling_verify = NGX_CONF_UNSET;
-
- return sscf;
-}
-
-
-static char *
-ngx_http_ssl_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
-{
- ngx_http_ssl_srv_conf_t *prev = parent;
- ngx_http_ssl_srv_conf_t *conf = child;
-
- ngx_pool_cleanup_t *cln;
-
- if (conf->enable == NGX_CONF_UNSET) {
- if (prev->enable == NGX_CONF_UNSET) {
- conf->enable = 0;
-
- } else {
- conf->enable = prev->enable;
- conf->file = prev->file;
- conf->line = prev->line;
- }
- }
-
- ngx_conf_merge_value(conf->session_timeout,
- prev->session_timeout, 300);
-
- ngx_conf_merge_value(conf->prefer_server_ciphers,
- prev->prefer_server_ciphers, 0);
-
- ngx_conf_merge_bitmask_value(conf->protocols, prev->protocols,
- (NGX_CONF_BITMASK_SET|NGX_SSL_TLSv1
- |NGX_SSL_TLSv1_1|NGX_SSL_TLSv1_2));
-
- ngx_conf_merge_size_value(conf->buffer_size, prev->buffer_size,
- NGX_SSL_BUFSIZE);
-
- ngx_conf_merge_uint_value(conf->verify, prev->verify, 0);
- ngx_conf_merge_uint_value(conf->verify_depth, prev->verify_depth, 1);
-
- ngx_conf_merge_ptr_value(conf->certificates, prev->certificates, NULL);
- ngx_conf_merge_ptr_value(conf->certificate_keys, prev->certificate_keys,
- NULL);
-
- ngx_conf_merge_ptr_value(conf->passwords, prev->passwords, NULL);
-
- ngx_conf_merge_str_value(conf->dhparam, prev->dhparam, "");
-
- ngx_conf_merge_str_value(conf->client_certificate, prev->client_certificate,
- "");
- ngx_conf_merge_str_value(conf->trusted_certificate,
- prev->trusted_certificate, "");
- ngx_conf_merge_str_value(conf->crl, prev->crl, "");
-
- ngx_conf_merge_str_value(conf->ecdh_curve, prev->ecdh_curve,
- NGX_DEFAULT_ECDH_CURVE);
-
- ngx_conf_merge_str_value(conf->ciphers, prev->ciphers, NGX_DEFAULT_CIPHERS);
-
- ngx_conf_merge_value(conf->stapling, prev->stapling, 0);
- ngx_conf_merge_value(conf->stapling_verify, prev->stapling_verify, 0);
- ngx_conf_merge_str_value(conf->stapling_file, prev->stapling_file, "");
- ngx_conf_merge_str_value(conf->stapling_responder,
- prev->stapling_responder, "");
-
- conf->ssl.log = cf->log;
-
- if (conf->enable) {
-
- if (conf->certificates == NULL) {
- ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
- "no \"ssl_certificate\" is defined for "
- "the \"ssl\" directive in %s:%ui",
- conf->file, conf->line);
- return NGX_CONF_ERROR;
- }
-
- if (conf->certificate_keys == NULL) {
- ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
- "no \"ssl_certificate_key\" is defined for "
- "the \"ssl\" directive in %s:%ui",
- conf->file, conf->line);
- return NGX_CONF_ERROR;
- }
-
- if (conf->certificate_keys->nelts < conf->certificates->nelts) {
- ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
- "no \"ssl_certificate_key\" is defined "
- "for certificate \"%V\" and "
- "the \"ssl\" directive in %s:%ui",
- ((ngx_str_t *) conf->certificates->elts)
- + conf->certificates->nelts - 1,
- conf->file, conf->line);
- return NGX_CONF_ERROR;
- }
-
- } else {
-
- if (conf->certificates == NULL) {
- return NGX_CONF_OK;
- }
-
- if (conf->certificate_keys == NULL
- || conf->certificate_keys->nelts < conf->certificates->nelts)
- {
- ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
- "no \"ssl_certificate_key\" is defined "
- "for certificate \"%V\"",
- ((ngx_str_t *) conf->certificates->elts)
- + conf->certificates->nelts - 1);
- return NGX_CONF_ERROR;
- }
- }
-
- if (ngx_ssl_create(&conf->ssl, conf->protocols, conf) != NGX_OK) {
- return NGX_CONF_ERROR;
- }
-
-#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
-
- if (SSL_CTX_set_tlsext_servername_callback(conf->ssl.ctx,
- ngx_http_ssl_servername)
- == 0)
- {
- ngx_log_error(NGX_LOG_WARN, cf->log, 0,
- "nginx was built with SNI support, however, now it is linked "
- "dynamically to an OpenSSL library which has no tlsext support, "
- "therefore SNI is not available");
- }
-
-#endif
-
-#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
- SSL_CTX_set_alpn_select_cb(conf->ssl.ctx, ngx_http_ssl_alpn_select, NULL);
-#endif
-
-#ifdef TLSEXT_TYPE_next_proto_neg
- SSL_CTX_set_next_protos_advertised_cb(conf->ssl.ctx,
- ngx_http_ssl_npn_advertised, NULL);
-#endif
-
- cln = ngx_pool_cleanup_add(cf->pool, 0);
- if (cln == NULL) {
- return NGX_CONF_ERROR;
- }
-
- cln->handler = ngx_ssl_cleanup_ctx;
- cln->data = &conf->ssl;
-
- if (ngx_ssl_certificates(cf, &conf->ssl, conf->certificates,
- conf->certificate_keys, conf->passwords)
- != NGX_OK)
- {
- return NGX_CONF_ERROR;
- }
-
- if (ngx_ssl_ciphers(cf, &conf->ssl, &conf->ciphers,
- conf->prefer_server_ciphers)
- != NGX_OK)
- {
- return NGX_CONF_ERROR;
- }
-
- conf->ssl.buffer_size = conf->buffer_size;
-
- if (conf->verify) {
-
- if (conf->client_certificate.len == 0 && conf->verify != 3) {
- ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
- "no ssl_client_certificate for ssl_client_verify");
- return NGX_CONF_ERROR;
- }
-
- if (ngx_ssl_client_certificate(cf, &conf->ssl,
- &conf->client_certificate,
- conf->verify_depth)
- != NGX_OK)
- {
- return NGX_CONF_ERROR;
- }
- }
-
- if (ngx_ssl_trusted_certificate(cf, &conf->ssl,
- &conf->trusted_certificate,
- conf->verify_depth)
- != NGX_OK)
- {
- return NGX_CONF_ERROR;
- }
-
- if (ngx_ssl_crl(cf, &conf->ssl, &conf->crl) != NGX_OK) {
- return NGX_CONF_ERROR;
- }
-
- if (ngx_ssl_dhparam(cf, &conf->ssl, &conf->dhparam) != NGX_OK) {
- return NGX_CONF_ERROR;
- }
-
- if (ngx_ssl_ecdh_curve(cf, &conf->ssl, &conf->ecdh_curve) != NGX_OK) {
- return NGX_CONF_ERROR;
- }
-
- ngx_conf_merge_value(conf->builtin_session_cache,
- prev->builtin_session_cache, NGX_SSL_NONE_SCACHE);
-
- if (conf->shm_zone == NULL) {
- conf->shm_zone = prev->shm_zone;
- }
-
- if (ngx_ssl_session_cache(&conf->ssl, &ngx_http_ssl_sess_id_ctx,
- conf->builtin_session_cache,
- conf->shm_zone, conf->session_timeout)
- != NGX_OK)
- {
- return NGX_CONF_ERROR;
- }
-
- ngx_conf_merge_value(conf->session_tickets, prev->session_tickets, 1);
-
-#ifdef SSL_OP_NO_TICKET
- if (!conf->session_tickets) {
- SSL_CTX_set_options(conf->ssl.ctx, SSL_OP_NO_TICKET);
- }
-#endif
-
- ngx_conf_merge_ptr_value(conf->session_ticket_keys,
- prev->session_ticket_keys, NULL);
-
- if (ngx_ssl_session_ticket_keys(cf, &conf->ssl, conf->session_ticket_keys)
- != NGX_OK)
- {
- return NGX_CONF_ERROR;
- }
-
- if (conf->stapling) {
-
- if (ngx_ssl_stapling(cf, &conf->ssl, &conf->stapling_file,
- &conf->stapling_responder, conf->stapling_verify)
- != NGX_OK)
- {
- return NGX_CONF_ERROR;
- }
-
- }
-
- return NGX_CONF_OK;
-}
-
-
-static char *
-ngx_http_ssl_enable(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
-{
- ngx_http_ssl_srv_conf_t *sscf = conf;
-
- char *rv;
-
- rv = ngx_conf_set_flag_slot(cf, cmd, conf);
-
- if (rv != NGX_CONF_OK) {
- return rv;
- }
-
- sscf->file = cf->conf_file->file.name.data;
- sscf->line = cf->conf_file->line;
-
- return NGX_CONF_OK;
-}
-
-
-static char *
-ngx_http_ssl_password_file(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
-{
- ngx_http_ssl_srv_conf_t *sscf = conf;
-
- ngx_str_t *value;
-
- if (sscf->passwords != NGX_CONF_UNSET_PTR) {
- return "is duplicate";
- }
-
- value = cf->args->elts;
-
- sscf->passwords = ngx_ssl_read_password_file(cf, &value[1]);
-
- if (sscf->passwords == NULL) {
- return NGX_CONF_ERROR;
- }
-
- return NGX_CONF_OK;
-}
-
-
-static char *
-ngx_http_ssl_session_cache(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
-{
- ngx_http_ssl_srv_conf_t *sscf = conf;
-
- size_t len;
- ngx_str_t *value, name, size;
- ngx_int_t n;
- ngx_uint_t i, j;
-
- value = cf->args->elts;
-
- for (i = 1; i < cf->args->nelts; i++) {
-
- if (ngx_strcmp(value[i].data, "off") == 0) {
- sscf->builtin_session_cache = NGX_SSL_NO_SCACHE;
- continue;
- }
-
- if (ngx_strcmp(value[i].data, "none") == 0) {
- sscf->builtin_session_cache = NGX_SSL_NONE_SCACHE;
- continue;
- }
-
- if (ngx_strcmp(value[i].data, "builtin") == 0) {
- sscf->builtin_session_cache = NGX_SSL_DFLT_BUILTIN_SCACHE;
- continue;
- }
-
- if (value[i].len > sizeof("builtin:") - 1
- && ngx_strncmp(value[i].data, "builtin:", sizeof("builtin:") - 1)
- == 0)
- {
- n = ngx_atoi(value[i].data + sizeof("builtin:") - 1,
- value[i].len - (sizeof("builtin:") - 1));
-
- if (n == NGX_ERROR) {
- goto invalid;
- }
-
- sscf->builtin_session_cache = n;
-
- continue;
- }
-
- if (value[i].len > sizeof("shared:") - 1
- && ngx_strncmp(value[i].data, "shared:", sizeof("shared:") - 1)
- == 0)
- {
- len = 0;
-
- for (j = sizeof("shared:") - 1; j < value[i].len; j++) {
- if (value[i].data[j] == ':') {
- break;
- }
-
- len++;
- }
-
- if (len == 0) {
- goto invalid;
- }
-
- name.len = len;
- name.data = value[i].data + sizeof("shared:") - 1;
-
- size.len = value[i].len - j - 1;
- size.data = name.data + len + 1;
-
- n = ngx_parse_size(&size);
-
- if (n == NGX_ERROR) {
- goto invalid;
- }
-
- if (n < (ngx_int_t) (8 * ngx_pagesize)) {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "session cache \"%V\" is too small",
- &value[i]);
-
- return NGX_CONF_ERROR;
- }
-
- sscf->shm_zone = ngx_shared_memory_add(cf, &name, n,
- &ngx_http_ssl_module);
- if (sscf->shm_zone == NULL) {
- return NGX_CONF_ERROR;
- }
-
- sscf->shm_zone->init = ngx_ssl_session_cache_init;
-
- continue;
- }
-
- goto invalid;
- }
-
- if (sscf->shm_zone && sscf->builtin_session_cache == NGX_CONF_UNSET) {
- sscf->builtin_session_cache = NGX_SSL_NO_BUILTIN_SCACHE;
- }
-
- return NGX_CONF_OK;
-
-invalid:
-
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "invalid session cache \"%V\"", &value[i]);
-
- return NGX_CONF_ERROR;
-}
-
-
-static ngx_int_t
-ngx_http_ssl_init(ngx_conf_t *cf)
-{
- ngx_uint_t s;
- ngx_http_ssl_srv_conf_t *sscf;
- ngx_http_core_loc_conf_t *clcf;
- ngx_http_core_srv_conf_t **cscfp;
- ngx_http_core_main_conf_t *cmcf;
-
- cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);
- cscfp = cmcf->servers.elts;
-
- for (s = 0; s < cmcf->servers.nelts; s++) {
-
- sscf = cscfp[s]->ctx->srv_conf[ngx_http_ssl_module.ctx_index];
-
- if (sscf->ssl.ctx == NULL || !sscf->stapling) {
- continue;
- }
-
- clcf = cscfp[s]->ctx->loc_conf[ngx_http_core_module.ctx_index];
-
- if (ngx_ssl_stapling_resolver(cf, &sscf->ssl, clcf->resolver,
- clcf->resolver_timeout)
- != NGX_OK)
- {
- return NGX_ERROR;
- }
- }
-
- return NGX_OK;
-}
diff --git a/nginx/src/http/modules/ngx_http_ssl_module.h b/nginx/src/http/modules/ngx_http_ssl_module.h
deleted file mode 100644
index 57f5941..0000000
--- a/nginx/src/http/modules/ngx_http_ssl_module.h
+++ /dev/null
@@ -1,66 +0,0 @@
-
-/*
- * Copyright (C) Igor Sysoev
- * Copyright (C) Nginx, Inc.
- */
-
-
-#ifndef _NGX_HTTP_SSL_H_INCLUDED_
-#define _NGX_HTTP_SSL_H_INCLUDED_
-
-
-#include <ngx_config.h>
-#include <ngx_core.h>
-#include <ngx_http.h>
-
-
-typedef struct {
- ngx_flag_t enable;
-
- ngx_ssl_t ssl;
-
- ngx_flag_t prefer_server_ciphers;
-
- ngx_uint_t protocols;
-
- ngx_uint_t verify;
- ngx_uint_t verify_depth;
-
- size_t buffer_size;
-
- ssize_t builtin_session_cache;
-
- time_t session_timeout;
-
- ngx_array_t *certificates;
- ngx_array_t *certificate_keys;
-
- ngx_str_t dhparam;
- ngx_str_t ecdh_curve;
- ngx_str_t client_certificate;
- ngx_str_t trusted_certificate;
- ngx_str_t crl;
-
- ngx_str_t ciphers;
-
- ngx_array_t *passwords;
-
- ngx_shm_zone_t *shm_zone;
-
- ngx_flag_t session_tickets;
- ngx_array_t *session_ticket_keys;
-
- ngx_flag_t stapling;
- ngx_flag_t stapling_verify;
- ngx_str_t stapling_file;
- ngx_str_t stapling_responder;
-
- u_char *file;
- ngx_uint_t line;
-} ngx_http_ssl_srv_conf_t;
-
-
-extern ngx_module_t ngx_http_ssl_module;
-
-
-#endif /* _NGX_HTTP_SSL_H_INCLUDED_ */
diff --git a/nginx/src/http/modules/ngx_http_static_module.c b/nginx/src/http/modules/ngx_http_static_module.c
deleted file mode 100644
index 0e16c05..0000000
--- a/nginx/src/http/modules/ngx_http_static_module.c
+++ /dev/null
@@ -1,288 +0,0 @@
-
-/*
- * Copyright (C) Igor Sysoev
- * Copyright (C) Nginx, Inc.
- */
-
-
-#include <ngx_config.h>
-#include <ngx_core.h>
-#include <ngx_http.h>
-
-
-static ngx_int_t ngx_http_static_handler(ngx_http_request_t *r);
-static ngx_int_t ngx_http_static_init(ngx_conf_t *cf);
-
-
-static ngx_http_module_t ngx_http_static_module_ctx = {
- NULL, /* preconfiguration */
- ngx_http_static_init, /* postconfiguration */
-
- NULL, /* create main configuration */
- NULL, /* init main configuration */
-
- NULL, /* create server configuration */
- NULL, /* merge server configuration */
-
- NULL, /* create location configuration */
- NULL /* merge location configuration */
-};
-
-
-ngx_module_t ngx_http_static_module = {
- NGX_MODULE_V1,
- &ngx_http_static_module_ctx, /* module context */
- NULL, /* module directives */
- NGX_HTTP_MODULE, /* module type */
- NULL, /* init master */
- NULL, /* init module */
- NULL, /* init process */
- NULL, /* init thread */
- NULL, /* exit thread */
- NULL, /* exit process */
- NULL, /* exit master */
- NGX_MODULE_V1_PADDING
-};
-
-
-static ngx_int_t
-ngx_http_static_handler(ngx_http_request_t *r)
-{
- u_char *last, *location;
- size_t root, len;
- ngx_str_t path;
- ngx_int_t rc;
- ngx_uint_t level;
- ngx_log_t *log;
- ngx_buf_t *b;
- ngx_chain_t out;
- ngx_open_file_info_t of;
- ngx_http_core_loc_conf_t *clcf;
-
- if (!(r->method & (NGX_HTTP_GET|NGX_HTTP_HEAD|NGX_HTTP_POST))) {
- return NGX_HTTP_NOT_ALLOWED;
- }
-
- if (r->uri.data[r->uri.len - 1] == '/') {
- return NGX_DECLINED;
- }
-
- log = r->connection->log;
-
- /*
- * ngx_http_map_uri_to_path() allocates memory for terminating '\0'
- * so we do not need to reserve memory for '/' for possible redirect
- */
-
- last = ngx_http_map_uri_to_path(r, &path, &root, 0);
- if (last == NULL) {
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
-
- path.len = last - path.data;
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0,
- "http filename: \"%s\"", path.data);
-
- clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
-
- ngx_memzero(&of, sizeof(ngx_open_file_info_t));
-
- of.read_ahead = clcf->read_ahead;
- of.directio = clcf->directio;
- of.valid = clcf->open_file_cache_valid;
- of.min_uses = clcf->open_file_cache_min_uses;
- of.errors = clcf->open_file_cache_errors;
- of.events = clcf->open_file_cache_events;
-
- if (ngx_http_set_disable_symlinks(r, clcf, &path, &of) != NGX_OK) {
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
-
- if (ngx_open_cached_file(clcf->open_file_cache, &path, &of, r->pool)
- != NGX_OK)
- {
- switch (of.err) {
-
- case 0:
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
-
- case NGX_ENOENT:
- case NGX_ENOTDIR:
- case NGX_ENAMETOOLONG:
-
- level = NGX_LOG_ERR;
- rc = NGX_HTTP_NOT_FOUND;
- break;
-
- case NGX_EACCES:
-#if (NGX_HAVE_OPENAT)
- case NGX_EMLINK:
- case NGX_ELOOP:
-#endif
-
- level = NGX_LOG_ERR;
- rc = NGX_HTTP_FORBIDDEN;
- break;
-
- default:
-
- level = NGX_LOG_CRIT;
- rc = NGX_HTTP_INTERNAL_SERVER_ERROR;
- break;
- }
-
- if (rc != NGX_HTTP_NOT_FOUND || clcf->log_not_found) {
- ngx_log_error(level, log, of.err,
- "%s \"%s\" failed", of.failed, path.data);
- }
-
- return rc;
- }
-
- r->root_tested = !r->error_page;
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0, "http static fd: %d", of.fd);
-
- if (of.is_dir) {
-
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, log, 0, "http dir");
-
- ngx_http_clear_location(r);
-
- r->headers_out.location = ngx_list_push(&r->headers_out.headers);
- if (r->headers_out.location == NULL) {
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
-
- len = r->uri.len + 1;
-
- if (!clcf->alias && clcf->root_lengths == NULL && r->args.len == 0) {
- location = path.data + clcf->root.len;
-
- *last = '/';
-
- } else {
- if (r->args.len) {
- len += r->args.len + 1;
- }
-
- location = ngx_pnalloc(r->pool, len);
- if (location == NULL) {
- ngx_http_clear_location(r);
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
-
- last = ngx_copy(location, r->uri.data, r->uri.len);
-
- *last = '/';
-
- if (r->args.len) {
- *++last = '?';
- ngx_memcpy(++last, r->args.data, r->args.len);
- }
- }
-
- r->headers_out.location->hash = 1;
- ngx_str_set(&r->headers_out.location->key, "Location");
- r->headers_out.location->value.len = len;
- r->headers_out.location->value.data = location;
-
- return NGX_HTTP_MOVED_PERMANENTLY;
- }
-
-#if !(NGX_WIN32) /* the not regular files are probably Unix specific */
-
- if (!of.is_file) {
- ngx_log_error(NGX_LOG_CRIT, log, 0,
- "\"%s\" is not a regular file", path.data);
-
- return NGX_HTTP_NOT_FOUND;
- }
-
-#endif
-
- if (r->method == NGX_HTTP_POST) {
- return NGX_HTTP_NOT_ALLOWED;
- }
-
- rc = ngx_http_discard_request_body(r);
-
- if (rc != NGX_OK) {
- return rc;
- }
-
- log->action = "sending response to client";
-
- r->headers_out.status = NGX_HTTP_OK;
- r->headers_out.content_length_n = of.size;
- r->headers_out.last_modified_time = of.mtime;
-
- if (ngx_http_set_etag(r) != NGX_OK) {
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
-
- if (ngx_http_set_content_type(r) != NGX_OK) {
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
-
- if (r != r->main && of.size == 0) {
- return ngx_http_send_header(r);
- }
-
- r->allow_ranges = 1;
-
- /* we need to allocate all before the header would be sent */
-
- b = ngx_calloc_buf(r->pool);
- if (b == NULL) {
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
-
- b->file = ngx_pcalloc(r->pool, sizeof(ngx_file_t));
- if (b->file == NULL) {
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
-
- rc = ngx_http_send_header(r);
-
- if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) {
- return rc;
- }
-
- b->file_pos = 0;
- b->file_last = of.size;
-
- b->in_file = b->file_last ? 1: 0;
- b->last_buf = (r == r->main) ? 1: 0;
- b->last_in_chain = 1;
-
- b->file->fd = of.fd;
- b->file->name = path;
- b->file->log = log;
- b->file->directio = of.is_directio;
-
- out.buf = b;
- out.next = NULL;
-
- return ngx_http_output_filter(r, &out);
-}
-
-
-static ngx_int_t
-ngx_http_static_init(ngx_conf_t *cf)
-{
- ngx_http_handler_pt *h;
- ngx_http_core_main_conf_t *cmcf;
-
- cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);
-
- h = ngx_array_push(&cmcf->phases[NGX_HTTP_CONTENT_PHASE].handlers);
- if (h == NULL) {
- return NGX_ERROR;
- }
-
- *h = ngx_http_static_handler;
-
- return NGX_OK;
-}
diff --git a/nginx/src/http/modules/ngx_http_stub_status_module.c b/nginx/src/http/modules/ngx_http_stub_status_module.c
deleted file mode 100644
index 9bdf881..0000000
--- a/nginx/src/http/modules/ngx_http_stub_status_module.c
+++ /dev/null
@@ -1,236 +0,0 @@
-
-/*
- * Copyright (C) Igor Sysoev
- * Copyright (C) Nginx, Inc.
- */
-
-
-#include <ngx_config.h>
-#include <ngx_core.h>
-#include <ngx_http.h>
-
-
-static ngx_int_t ngx_http_stub_status_handler(ngx_http_request_t *r);
-static ngx_int_t ngx_http_stub_status_variable(ngx_http_request_t *r,
- ngx_http_variable_value_t *v, uintptr_t data);
-static ngx_int_t ngx_http_stub_status_add_variables(ngx_conf_t *cf);
-static char *ngx_http_set_stub_status(ngx_conf_t *cf, ngx_command_t *cmd,
- void *conf);
-
-
-static ngx_command_t ngx_http_status_commands[] = {
-
- { ngx_string("stub_status"),
- NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_NOARGS|NGX_CONF_TAKE1,
- ngx_http_set_stub_status,
- 0,
- 0,
- NULL },
-
- ngx_null_command
-};
-
-
-static ngx_http_module_t ngx_http_stub_status_module_ctx = {
- ngx_http_stub_status_add_variables, /* preconfiguration */
- NULL, /* postconfiguration */
-
- NULL, /* create main configuration */
- NULL, /* init main configuration */
-
- NULL, /* create server configuration */
- NULL, /* merge server configuration */
-
- NULL, /* create location configuration */
- NULL /* merge location configuration */
-};
-
-
-ngx_module_t ngx_http_stub_status_module = {
- NGX_MODULE_V1,
- &ngx_http_stub_status_module_ctx, /* module context */
- ngx_http_status_commands, /* module directives */
- NGX_HTTP_MODULE, /* module type */
- NULL, /* init master */
- NULL, /* init module */
- NULL, /* init process */
- NULL, /* init thread */
- NULL, /* exit thread */
- NULL, /* exit process */
- NULL, /* exit master */
- NGX_MODULE_V1_PADDING
-};
-
-
-static ngx_http_variable_t ngx_http_stub_status_vars[] = {
-
- { ngx_string("connections_active"), NULL, ngx_http_stub_status_variable,
- 0, NGX_HTTP_VAR_NOCACHEABLE, 0 },
-
- { ngx_string("connections_reading"), NULL, ngx_http_stub_status_variable,
- 1, NGX_HTTP_VAR_NOCACHEABLE, 0 },
-
- { ngx_string("connections_writing"), NULL, ngx_http_stub_status_variable,
- 2, NGX_HTTP_VAR_NOCACHEABLE, 0 },
-
- { ngx_string("connections_waiting"), NULL, ngx_http_stub_status_variable,
- 3, NGX_HTTP_VAR_NOCACHEABLE, 0 },
-
- ngx_http_null_variable
-};
-
-
-static ngx_int_t
-ngx_http_stub_status_handler(ngx_http_request_t *r)
-{
- size_t size;
- ngx_int_t rc;
- ngx_buf_t *b;
- ngx_chain_t out;
- ngx_atomic_int_t ap, hn, ac, rq, rd, wr, wa;
-
- if (!(r->method & (NGX_HTTP_GET|NGX_HTTP_HEAD))) {
- return NGX_HTTP_NOT_ALLOWED;
- }
-
- rc = ngx_http_discard_request_body(r);
-
- if (rc != NGX_OK) {
- return rc;
- }
-
- r->headers_out.content_type_len = sizeof("text/plain") - 1;
- ngx_str_set(&r->headers_out.content_type, "text/plain");
- r->headers_out.content_type_lowcase = NULL;
-
- if (r->method == NGX_HTTP_HEAD) {
- r->headers_out.status = NGX_HTTP_OK;
-
- rc = ngx_http_send_header(r);
-
- if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) {
- return rc;
- }
- }
-
- size = sizeof("Active connections: \n") + NGX_ATOMIC_T_LEN
- + sizeof("server accepts handled requests\n") - 1
- + 6 + 3 * NGX_ATOMIC_T_LEN
- + sizeof("Reading: Writing: Waiting: \n") + 3 * NGX_ATOMIC_T_LEN;
-
- b = ngx_create_temp_buf(r->pool, size);
- if (b == NULL) {
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
-
- out.buf = b;
- out.next = NULL;
-
- ap = *ngx_stat_accepted;
- hn = *ngx_stat_handled;
- ac = *ngx_stat_active;
- rq = *ngx_stat_requests;
- rd = *ngx_stat_reading;
- wr = *ngx_stat_writing;
- wa = *ngx_stat_waiting;
-
- b->last = ngx_sprintf(b->last, "Active connections: %uA \n", ac);
-
- b->last = ngx_cpymem(b->last, "server accepts handled requests\n",
- sizeof("server accepts handled requests\n") - 1);
-
- b->last = ngx_sprintf(b->last, " %uA %uA %uA \n", ap, hn, rq);
-
- b->last = ngx_sprintf(b->last, "Reading: %uA Writing: %uA Waiting: %uA \n",
- rd, wr, wa);
-
- r->headers_out.status = NGX_HTTP_OK;
- r->headers_out.content_length_n = b->last - b->pos;
-
- b->last_buf = (r == r->main) ? 1 : 0;
- b->last_in_chain = 1;
-
- rc = ngx_http_send_header(r);
-
- if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) {
- return rc;
- }
-
- return ngx_http_output_filter(r, &out);
-}
-
-
-static ngx_int_t
-ngx_http_stub_status_variable(ngx_http_request_t *r,
- ngx_http_variable_value_t *v, uintptr_t data)
-{
- u_char *p;
- ngx_atomic_int_t value;
-
- p = ngx_pnalloc(r->pool, NGX_ATOMIC_T_LEN);
- if (p == NULL) {
- return NGX_ERROR;
- }
-
- switch (data) {
- case 0:
- value = *ngx_stat_active;
- break;
-
- case 1:
- value = *ngx_stat_reading;
- break;
-
- case 2:
- value = *ngx_stat_writing;
- break;
-
- case 3:
- value = *ngx_stat_waiting;
- break;
-
- /* suppress warning */
- default:
- value = 0;
- break;
- }
-
- v->len = ngx_sprintf(p, "%uA", value) - p;
- v->valid = 1;
- v->no_cacheable = 0;
- v->not_found = 0;
- v->data = p;
-
- return NGX_OK;
-}
-
-
-static ngx_int_t
-ngx_http_stub_status_add_variables(ngx_conf_t *cf)
-{
- ngx_http_variable_t *var, *v;
-
- for (v = ngx_http_stub_status_vars; v->name.len; v++) {
- var = ngx_http_add_variable(cf, &v->name, v->flags);
- if (var == NULL) {
- return NGX_ERROR;
- }
-
- var->get_handler = v->get_handler;
- var->data = v->data;
- }
-
- return NGX_OK;
-}
-
-
-static char *
-ngx_http_set_stub_status(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
-{
- ngx_http_core_loc_conf_t *clcf;
-
- clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);
- clcf->handler = ngx_http_stub_status_handler;
-
- return NGX_CONF_OK;
-}
diff --git a/nginx/src/http/modules/ngx_http_sub_filter_module.c b/nginx/src/http/modules/ngx_http_sub_filter_module.c
deleted file mode 100644
index 6d3de59..0000000
--- a/nginx/src/http/modules/ngx_http_sub_filter_module.c
+++ /dev/null
@@ -1,1018 +0,0 @@
-
-/*
- * Copyright (C) Igor Sysoev
- * Copyright (C) Nginx, Inc.
- */
-
-
-#include <ngx_config.h>
-#include <ngx_core.h>
-#include <ngx_http.h>
-
-
-typedef struct {
- ngx_http_complex_value_t match;
- ngx_http_complex_value_t value;
-} ngx_http_sub_pair_t;
-
-
-typedef struct {
- ngx_str_t match;
- ngx_http_complex_value_t *value;
-} ngx_http_sub_match_t;
-
-
-typedef struct {
- ngx_uint_t min_match_len;
- ngx_uint_t max_match_len;
-
- u_char index[257];
- u_char shift[256];
-} ngx_http_sub_tables_t;
-
-
-typedef struct {
- ngx_uint_t dynamic; /* unsigned dynamic:1; */
-
- ngx_array_t *pairs;
-
- ngx_http_sub_tables_t *tables;
-
- ngx_hash_t types;
-
- ngx_flag_t once;
- ngx_flag_t last_modified;
-
- ngx_array_t *types_keys;
- ngx_array_t *matches;
-} ngx_http_sub_loc_conf_t;
-
-
-typedef struct {
- ngx_str_t saved;
- ngx_str_t looked;
-
- ngx_uint_t once; /* unsigned once:1 */
-
- ngx_buf_t *buf;
-
- u_char *pos;
- u_char *copy_start;
- u_char *copy_end;
-
- ngx_chain_t *in;
- ngx_chain_t *out;
- ngx_chain_t **last_out;
- ngx_chain_t *busy;
- ngx_chain_t *free;
-
- ngx_str_t *sub;
- ngx_uint_t applied;
-
- ngx_int_t offset;
- ngx_uint_t index;
-
- ngx_http_sub_tables_t *tables;
- ngx_array_t *matches;
-} ngx_http_sub_ctx_t;
-
-
-static ngx_uint_t ngx_http_sub_cmp_index;
-
-
-static ngx_int_t ngx_http_sub_output(ngx_http_request_t *r,
- ngx_http_sub_ctx_t *ctx);
-static ngx_int_t ngx_http_sub_parse(ngx_http_request_t *r,
- ngx_http_sub_ctx_t *ctx, ngx_uint_t flush);
-static ngx_int_t ngx_http_sub_match(ngx_http_sub_ctx_t *ctx, ngx_int_t start,
- ngx_str_t *m);
-
-static char * ngx_http_sub_filter(ngx_conf_t *cf, ngx_command_t *cmd,
- void *conf);
-static void *ngx_http_sub_create_conf(ngx_conf_t *cf);
-static char *ngx_http_sub_merge_conf(ngx_conf_t *cf,
- void *parent, void *child);
-static void ngx_http_sub_init_tables(ngx_http_sub_tables_t *tables,
- ngx_http_sub_match_t *match, ngx_uint_t n);
-static ngx_int_t ngx_http_sub_cmp_matches(const void *one, const void *two);
-static ngx_int_t ngx_http_sub_filter_init(ngx_conf_t *cf);
-
-
-static ngx_command_t ngx_http_sub_filter_commands[] = {
-
- { ngx_string("sub_filter"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE2,
- ngx_http_sub_filter,
- NGX_HTTP_LOC_CONF_OFFSET,
- 0,
- NULL },
-
- { ngx_string("sub_filter_types"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
- ngx_http_types_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_sub_loc_conf_t, types_keys),
- &ngx_http_html_default_types[0] },
-
- { ngx_string("sub_filter_once"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
- ngx_conf_set_flag_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_sub_loc_conf_t, once),
- NULL },
-
- { ngx_string("sub_filter_last_modified"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
- ngx_conf_set_flag_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_sub_loc_conf_t, last_modified),
- NULL },
-
- ngx_null_command
-};
-
-
-static ngx_http_module_t ngx_http_sub_filter_module_ctx = {
- NULL, /* preconfiguration */
- ngx_http_sub_filter_init, /* postconfiguration */
-
- NULL, /* create main configuration */
- NULL, /* init main configuration */
-
- NULL, /* create server configuration */
- NULL, /* merge server configuration */
-
- ngx_http_sub_create_conf, /* create location configuration */
- ngx_http_sub_merge_conf /* merge location configuration */
-};
-
-
-ngx_module_t ngx_http_sub_filter_module = {
- NGX_MODULE_V1,
- &ngx_http_sub_filter_module_ctx, /* module context */
- ngx_http_sub_filter_commands, /* module directives */
- NGX_HTTP_MODULE, /* module type */
- NULL, /* init master */
- NULL, /* init module */
- NULL, /* init process */
- NULL, /* init thread */
- NULL, /* exit thread */
- NULL, /* exit process */
- NULL, /* exit master */
- NGX_MODULE_V1_PADDING
-};
-
-
-static ngx_http_output_header_filter_pt ngx_http_next_header_filter;
-static ngx_http_output_body_filter_pt ngx_http_next_body_filter;
-
-
-static ngx_int_t
-ngx_http_sub_header_filter(ngx_http_request_t *r)
-{
- ngx_str_t *m;
- ngx_uint_t i, j, n;
- ngx_http_sub_ctx_t *ctx;
- ngx_http_sub_pair_t *pairs;
- ngx_http_sub_match_t *matches;
- ngx_http_sub_loc_conf_t *slcf;
-
- slcf = ngx_http_get_module_loc_conf(r, ngx_http_sub_filter_module);
-
- if (slcf->pairs == NULL
- || r->headers_out.content_length_n == 0
- || ngx_http_test_content_type(r, &slcf->types) == NULL)
- {
- return ngx_http_next_header_filter(r);
- }
-
- ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_sub_ctx_t));
- if (ctx == NULL) {
- return NGX_ERROR;
- }
-
- if (slcf->dynamic == 0) {
- ctx->tables = slcf->tables;
- ctx->matches = slcf->matches;
-
- } else {
- pairs = slcf->pairs->elts;
- n = slcf->pairs->nelts;
-
- matches = ngx_pcalloc(r->pool, sizeof(ngx_http_sub_match_t) * n);
- if (matches == NULL) {
- return NGX_ERROR;
- }
-
- j = 0;
- for (i = 0; i < n; i++) {
- matches[j].value = &pairs[i].value;
-
- if (pairs[i].match.lengths == NULL) {
- matches[j].match = pairs[i].match.value;
- j++;
- continue;
- }
-
- m = &matches[j].match;
- if (ngx_http_complex_value(r, &pairs[i].match, m) != NGX_OK) {
- return NGX_ERROR;
- }
-
- if (m->len == 0) {
- continue;
- }
-
- ngx_strlow(m->data, m->data, m->len);
- j++;
- }
-
- if (j == 0) {
- return ngx_http_next_header_filter(r);
- }
-
- ctx->matches = ngx_palloc(r->pool, sizeof(ngx_array_t));
- if (ctx->matches == NULL) {
- return NGX_ERROR;
- }
-
- ctx->matches->elts = matches;
- ctx->matches->nelts = j;
-
- ctx->tables = ngx_palloc(r->pool, sizeof(ngx_http_sub_tables_t));
- if (ctx->tables == NULL) {
- return NGX_ERROR;
- }
-
- ngx_http_sub_init_tables(ctx->tables, ctx->matches->elts,
- ctx->matches->nelts);
- }
-
- ctx->saved.data = ngx_pnalloc(r->pool, ctx->tables->max_match_len - 1);
- if (ctx->saved.data == NULL) {
- return NGX_ERROR;
- }
-
- ctx->looked.data = ngx_pnalloc(r->pool, ctx->tables->max_match_len - 1);
- if (ctx->looked.data == NULL) {
- return NGX_ERROR;
- }
-
- ngx_http_set_ctx(r, ctx, ngx_http_sub_filter_module);
-
- ctx->offset = ctx->tables->min_match_len - 1;
- ctx->last_out = &ctx->out;
-
- r->filter_need_in_memory = 1;
-
- if (r == r->main) {
- ngx_http_clear_content_length(r);
-
- if (!slcf->last_modified) {
- ngx_http_clear_last_modified(r);
- ngx_http_clear_etag(r);
-
- } else {
- ngx_http_weak_etag(r);
- }
- }
-
- return ngx_http_next_header_filter(r);
-}
-
-
-static ngx_int_t
-ngx_http_sub_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
-{
- ngx_int_t rc;
- ngx_buf_t *b;
- ngx_str_t *sub;
- ngx_uint_t flush, last;
- ngx_chain_t *cl;
- ngx_http_sub_ctx_t *ctx;
- ngx_http_sub_match_t *match;
- ngx_http_sub_loc_conf_t *slcf;
-
- ctx = ngx_http_get_module_ctx(r, ngx_http_sub_filter_module);
-
- if (ctx == NULL) {
- return ngx_http_next_body_filter(r, in);
- }
-
- if ((in == NULL
- && ctx->buf == NULL
- && ctx->in == NULL
- && ctx->busy == NULL))
- {
- return ngx_http_next_body_filter(r, in);
- }
-
- if (ctx->once && (ctx->buf == NULL || ctx->in == NULL)) {
-
- if (ctx->busy) {
- if (ngx_http_sub_output(r, ctx) == NGX_ERROR) {
- return NGX_ERROR;
- }
- }
-
- return ngx_http_next_body_filter(r, in);
- }
-
- /* add the incoming chain to the chain ctx->in */
-
- if (in) {
- if (ngx_chain_add_copy(r->pool, &ctx->in, in) != NGX_OK) {
- return NGX_ERROR;
- }
- }
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "http sub filter \"%V\"", &r->uri);
-
- flush = 0;
- last = 0;
-
- while (ctx->in || ctx->buf) {
-
- if (ctx->buf == NULL) {
- ctx->buf = ctx->in->buf;
- ctx->in = ctx->in->next;
- ctx->pos = ctx->buf->pos;
- }
-
- if (ctx->buf->flush || ctx->buf->recycled) {
- flush = 1;
- }
-
- if (ctx->in == NULL) {
- last = flush;
- }
-
- b = NULL;
-
- while (ctx->pos < ctx->buf->last) {
-
- rc = ngx_http_sub_parse(r, ctx, last);
-
- ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "parse: %i, looked: \"%V\" %p-%p",
- rc, &ctx->looked, ctx->copy_start, ctx->copy_end);
-
- if (rc == NGX_ERROR) {
- return rc;
- }
-
- if (ctx->saved.len) {
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "saved: \"%V\"", &ctx->saved);
-
- cl = ngx_chain_get_free_buf(r->pool, &ctx->free);
- if (cl == NULL) {
- return NGX_ERROR;
- }
-
- b = cl->buf;
-
- ngx_memzero(b, sizeof(ngx_buf_t));
-
- b->pos = ngx_pnalloc(r->pool, ctx->saved.len);
- if (b->pos == NULL) {
- return NGX_ERROR;
- }
-
- ngx_memcpy(b->pos, ctx->saved.data, ctx->saved.len);
- b->last = b->pos + ctx->saved.len;
- b->memory = 1;
-
- *ctx->last_out = cl;
- ctx->last_out = &cl->next;
-
- ctx->saved.len = 0;
- }
-
- if (ctx->copy_start != ctx->copy_end) {
-
- cl = ngx_chain_get_free_buf(r->pool, &ctx->free);
- if (cl == NULL) {
- return NGX_ERROR;
- }
-
- b = cl->buf;
-
- ngx_memcpy(b, ctx->buf, sizeof(ngx_buf_t));
-
- b->pos = ctx->copy_start;
- b->last = ctx->copy_end;
- b->shadow = NULL;
- b->last_buf = 0;
- b->last_in_chain = 0;
- b->recycled = 0;
-
- if (b->in_file) {
- b->file_last = b->file_pos + (b->last - ctx->buf->pos);
- b->file_pos += b->pos - ctx->buf->pos;
- }
-
- *ctx->last_out = cl;
- ctx->last_out = &cl->next;
- }
-
- if (rc == NGX_AGAIN) {
- continue;
- }
-
-
- /* rc == NGX_OK */
-
- cl = ngx_chain_get_free_buf(r->pool, &ctx->free);
- if (cl == NULL) {
- return NGX_ERROR;
- }
-
- b = cl->buf;
-
- ngx_memzero(b, sizeof(ngx_buf_t));
-
- slcf = ngx_http_get_module_loc_conf(r, ngx_http_sub_filter_module);
-
- if (ctx->sub == NULL) {
- ctx->sub = ngx_pcalloc(r->pool, sizeof(ngx_str_t)
- * ctx->matches->nelts);
- if (ctx->sub == NULL) {
- return NGX_ERROR;
- }
- }
-
- sub = &ctx->sub[ctx->index];
-
- if (sub->data == NULL) {
- match = ctx->matches->elts;
-
- if (ngx_http_complex_value(r, match[ctx->index].value, sub)
- != NGX_OK)
- {
- return NGX_ERROR;
- }
- }
-
- if (sub->len) {
- b->memory = 1;
- b->pos = sub->data;
- b->last = sub->data + sub->len;
-
- } else {
- b->sync = 1;
- }
-
- *ctx->last_out = cl;
- ctx->last_out = &cl->next;
-
- ctx->index = 0;
- ctx->once = slcf->once && (++ctx->applied == ctx->matches->nelts);
-
- continue;
- }
-
- if (ctx->looked.len
- && (ctx->buf->last_buf || ctx->buf->last_in_chain))
- {
- cl = ngx_chain_get_free_buf(r->pool, &ctx->free);
- if (cl == NULL) {
- return NGX_ERROR;
- }
-
- b = cl->buf;
-
- ngx_memzero(b, sizeof(ngx_buf_t));
-
- b->pos = ctx->looked.data;
- b->last = b->pos + ctx->looked.len;
- b->memory = 1;
-
- *ctx->last_out = cl;
- ctx->last_out = &cl->next;
-
- ctx->looked.len = 0;
- }
-
- if (ctx->buf->last_buf || ctx->buf->flush || ctx->buf->sync
- || ngx_buf_in_memory(ctx->buf))
- {
- if (b == NULL) {
- cl = ngx_chain_get_free_buf(r->pool, &ctx->free);
- if (cl == NULL) {
- return NGX_ERROR;
- }
-
- b = cl->buf;
-
- ngx_memzero(b, sizeof(ngx_buf_t));
-
- b->sync = 1;
-
- *ctx->last_out = cl;
- ctx->last_out = &cl->next;
- }
-
- b->last_buf = ctx->buf->last_buf;
- b->last_in_chain = ctx->buf->last_in_chain;
- b->flush = ctx->buf->flush;
- b->shadow = ctx->buf;
-
- b->recycled = ctx->buf->recycled;
- }
-
- ctx->buf = NULL;
- }
-
- if (ctx->out == NULL && ctx->busy == NULL) {
- return NGX_OK;
- }
-
- return ngx_http_sub_output(r, ctx);
-}
-
-
-static ngx_int_t
-ngx_http_sub_output(ngx_http_request_t *r, ngx_http_sub_ctx_t *ctx)
-{
- ngx_int_t rc;
- ngx_buf_t *b;
- ngx_chain_t *cl;
-
-#if 1
- b = NULL;
- for (cl = ctx->out; cl; cl = cl->next) {
- ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "sub out: %p %p", cl->buf, cl->buf->pos);
- if (cl->buf == b) {
- ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
- "the same buf was used in sub");
- ngx_debug_point();
- return NGX_ERROR;
- }
- b = cl->buf;
- }
-#endif
-
- rc = ngx_http_next_body_filter(r, ctx->out);
-
- if (ctx->busy == NULL) {
- ctx->busy = ctx->out;
-
- } else {
- for (cl = ctx->busy; cl->next; cl = cl->next) { /* void */ }
- cl->next = ctx->out;
- }
-
- ctx->out = NULL;
- ctx->last_out = &ctx->out;
-
- while (ctx->busy) {
-
- cl = ctx->busy;
- b = cl->buf;
-
- if (ngx_buf_size(b) != 0) {
- break;
- }
-
- if (b->shadow) {
- b->shadow->pos = b->shadow->last;
- }
-
- ctx->busy = cl->next;
-
- if (ngx_buf_in_memory(b) || b->in_file) {
- /* add data bufs only to the free buf chain */
-
- cl->next = ctx->free;
- ctx->free = cl;
- }
- }
-
- if (ctx->in || ctx->buf) {
- r->buffered |= NGX_HTTP_SUB_BUFFERED;
-
- } else {
- r->buffered &= ~NGX_HTTP_SUB_BUFFERED;
- }
-
- return rc;
-}
-
-
-static ngx_int_t
-ngx_http_sub_parse(ngx_http_request_t *r, ngx_http_sub_ctx_t *ctx,
- ngx_uint_t flush)
-{
- u_char *p, c;
- ngx_str_t *m;
- ngx_int_t offset, start, next, end, len, rc;
- ngx_uint_t shift, i, j;
- ngx_http_sub_match_t *match;
- ngx_http_sub_tables_t *tables;
- ngx_http_sub_loc_conf_t *slcf;
-
- slcf = ngx_http_get_module_loc_conf(r, ngx_http_sub_filter_module);
- tables = ctx->tables;
- match = ctx->matches->elts;
-
- offset = ctx->offset;
- end = ctx->buf->last - ctx->pos;
-
- if (ctx->once) {
- /* sets start and next to end */
- offset = end + (ngx_int_t) tables->min_match_len - 1;
- goto again;
- }
-
- while (offset < end) {
-
- c = offset < 0 ? ctx->looked.data[ctx->looked.len + offset]
- : ctx->pos[offset];
-
- c = ngx_tolower(c);
-
- shift = tables->shift[c];
- if (shift > 0) {
- offset += shift;
- continue;
- }
-
- /* a potential match */
-
- start = offset - (ngx_int_t) tables->min_match_len + 1;
-
- i = ngx_max((ngx_uint_t) tables->index[c], ctx->index);
- j = tables->index[c + 1];
-
- while (i != j) {
-
- if (slcf->once && ctx->sub && ctx->sub[i].data) {
- goto next;
- }
-
- m = &match[i].match;
-
- rc = ngx_http_sub_match(ctx, start, m);
-
- if (rc == NGX_DECLINED) {
- goto next;
- }
-
- ctx->index = i;
-
- if (rc == NGX_AGAIN) {
- goto again;
- }
-
- ctx->offset = offset + (ngx_int_t) m->len;
- next = start + (ngx_int_t) m->len;
- end = ngx_max(next, 0);
- rc = NGX_OK;
-
- goto done;
-
- next:
-
- i++;
- }
-
- offset++;
- ctx->index = 0;
- }
-
- if (flush) {
- for ( ;; ) {
- start = offset - (ngx_int_t) tables->min_match_len + 1;
-
- if (start >= end) {
- break;
- }
-
- for (i = 0; i < ctx->matches->nelts; i++) {
- m = &match[i].match;
-
- if (ngx_http_sub_match(ctx, start, m) == NGX_AGAIN) {
- goto again;
- }
- }
-
- offset++;
- }
- }
-
-again:
-
- ctx->offset = offset;
- start = offset - (ngx_int_t) tables->min_match_len + 1;
- next = start;
- rc = NGX_AGAIN;
-
-done:
-
- /* send [ - looked.len, start ] to client */
-
- ctx->saved.len = ctx->looked.len + ngx_min(start, 0);
- ngx_memcpy(ctx->saved.data, ctx->looked.data, ctx->saved.len);
-
- ctx->copy_start = ctx->pos;
- ctx->copy_end = ctx->pos + ngx_max(start, 0);
-
- /* save [ next, end ] in looked */
-
- len = ngx_min(next, 0);
- p = ctx->looked.data;
- p = ngx_movemem(p, p + ctx->looked.len + len, - len);
-
- len = ngx_max(next, 0);
- p = ngx_cpymem(p, ctx->pos + len, end - len);
- ctx->looked.len = p - ctx->looked.data;
-
- /* update position */
-
- ctx->pos += end;
- ctx->offset -= end;
-
- return rc;
-}
-
-
-static ngx_int_t
-ngx_http_sub_match(ngx_http_sub_ctx_t *ctx, ngx_int_t start, ngx_str_t *m)
-{
- u_char *p, *last, *pat, *pat_end;
-
- pat = m->data;
- pat_end = m->data + m->len;
-
- if (start >= 0) {
- p = ctx->pos + start;
-
- } else {
- last = ctx->looked.data + ctx->looked.len;
- p = last + start;
-
- while (p < last && pat < pat_end) {
- if (ngx_tolower(*p) != *pat) {
- return NGX_DECLINED;
- }
-
- p++;
- pat++;
- }
-
- p = ctx->pos;
- }
-
- while (p < ctx->buf->last && pat < pat_end) {
- if (ngx_tolower(*p) != *pat) {
- return NGX_DECLINED;
- }
-
- p++;
- pat++;
- }
-
- if (pat != pat_end) {
- /* partial match */
- return NGX_AGAIN;
- }
-
- return NGX_OK;
-}
-
-
-static char *
-ngx_http_sub_filter(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
-{
- ngx_http_sub_loc_conf_t *slcf = conf;
-
- ngx_str_t *value;
- ngx_http_sub_pair_t *pair;
- ngx_http_compile_complex_value_t ccv;
-
- value = cf->args->elts;
-
- if (value[1].len == 0) {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "empty search pattern");
- return NGX_CONF_ERROR;
- }
-
- if (slcf->pairs == NULL) {
- slcf->pairs = ngx_array_create(cf->pool, 1,
- sizeof(ngx_http_sub_pair_t));
- if (slcf->pairs == NULL) {
- return NGX_CONF_ERROR;
- }
- }
-
- if (slcf->pairs->nelts == 255) {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "number of search patterns exceeds 255");
- return NGX_CONF_ERROR;
- }
-
- ngx_strlow(value[1].data, value[1].data, value[1].len);
-
- pair = ngx_array_push(slcf->pairs);
- if (pair == NULL) {
- return NGX_CONF_ERROR;
- }
-
- ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));
-
- ccv.cf = cf;
- ccv.value = &value[1];
- ccv.complex_value = &pair->match;
-
- if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
- return NGX_CONF_ERROR;
- }
-
- if (ccv.complex_value->lengths != NULL) {
- slcf->dynamic = 1;
-
- } else {
- ngx_strlow(pair->match.value.data, pair->match.value.data,
- pair->match.value.len);
- }
-
- ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));
-
- ccv.cf = cf;
- ccv.value = &value[2];
- ccv.complex_value = &pair->value;
-
- if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
- return NGX_CONF_ERROR;
- }
-
- return NGX_CONF_OK;
-}
-
-
-static void *
-ngx_http_sub_create_conf(ngx_conf_t *cf)
-{
- ngx_http_sub_loc_conf_t *slcf;
-
- slcf = ngx_pcalloc(cf->pool, sizeof(ngx_http_sub_loc_conf_t));
- if (slcf == NULL) {
- return NULL;
- }
-
- /*
- * set by ngx_pcalloc():
- *
- * conf->dynamic = 0;
- * conf->pairs = NULL;
- * conf->tables = NULL;
- * conf->types = { NULL };
- * conf->types_keys = NULL;
- * conf->matches = NULL;
- */
-
- slcf->once = NGX_CONF_UNSET;
- slcf->last_modified = NGX_CONF_UNSET;
-
- return slcf;
-}
-
-
-static char *
-ngx_http_sub_merge_conf(ngx_conf_t *cf, void *parent, void *child)
-{
- ngx_uint_t i, n;
- ngx_http_sub_pair_t *pairs;
- ngx_http_sub_match_t *matches;
- ngx_http_sub_loc_conf_t *prev = parent;
- ngx_http_sub_loc_conf_t *conf = child;
-
- ngx_conf_merge_value(conf->once, prev->once, 1);
- ngx_conf_merge_value(conf->last_modified, prev->last_modified, 0);
-
- if (ngx_http_merge_types(cf, &conf->types_keys, &conf->types,
- &prev->types_keys, &prev->types,
- ngx_http_html_default_types)
- != NGX_OK)
- {
- return NGX_CONF_ERROR;
- }
-
- if (conf->pairs == NULL) {
- conf->dynamic = prev->dynamic;
- conf->pairs = prev->pairs;
- conf->matches = prev->matches;
- conf->tables = prev->tables;
- }
-
- if (conf->pairs && conf->dynamic == 0 && conf->tables == NULL) {
- pairs = conf->pairs->elts;
- n = conf->pairs->nelts;
-
- matches = ngx_palloc(cf->pool, sizeof(ngx_http_sub_match_t) * n);
- if (matches == NULL) {
- return NGX_CONF_ERROR;
- }
-
- for (i = 0; i < n; i++) {
- matches[i].match = pairs[i].match.value;
- matches[i].value = &pairs[i].value;
- }
-
- conf->matches = ngx_palloc(cf->pool, sizeof(ngx_array_t));
- if (conf->matches == NULL) {
- return NGX_CONF_ERROR;
- }
-
- conf->matches->elts = matches;
- conf->matches->nelts = n;
-
- conf->tables = ngx_palloc(cf->pool, sizeof(ngx_http_sub_tables_t));
- if (conf->tables == NULL) {
- return NGX_CONF_ERROR;
- }
-
- ngx_http_sub_init_tables(conf->tables, conf->matches->elts,
- conf->matches->nelts);
- }
-
- return NGX_CONF_OK;
-}
-
-
-static void
-ngx_http_sub_init_tables(ngx_http_sub_tables_t *tables,
- ngx_http_sub_match_t *match, ngx_uint_t n)
-{
- u_char c;
- ngx_uint_t i, j, min, max, ch;
-
- min = match[0].match.len;
- max = match[0].match.len;
-
- for (i = 1; i < n; i++) {
- min = ngx_min(min, match[i].match.len);
- max = ngx_max(max, match[i].match.len);
- }
-
- tables->min_match_len = min;
- tables->max_match_len = max;
-
- ngx_http_sub_cmp_index = tables->min_match_len - 1;
- ngx_sort(match, n, sizeof(ngx_http_sub_match_t), ngx_http_sub_cmp_matches);
-
- min = ngx_min(min, 255);
- ngx_memset(tables->shift, min, 256);
-
- ch = 0;
-
- for (i = 0; i < n; i++) {
-
- for (j = 0; j < min; j++) {
- c = match[i].match.data[tables->min_match_len - 1 - j];
- tables->shift[c] = ngx_min(tables->shift[c], (u_char) j);
- }
-
- c = match[i].match.data[tables->min_match_len - 1];
- while (ch <= (ngx_uint_t) c) {
- tables->index[ch++] = (u_char) i;
- }
- }
-
- while (ch < 257) {
- tables->index[ch++] = (u_char) n;
- }
-}
-
-
-static ngx_int_t
-ngx_http_sub_cmp_matches(const void *one, const void *two)
-{
- ngx_int_t c1, c2;
- ngx_http_sub_match_t *first, *second;
-
- first = (ngx_http_sub_match_t *) one;
- second = (ngx_http_sub_match_t *) two;
-
- c1 = first->match.data[ngx_http_sub_cmp_index];
- c2 = second->match.data[ngx_http_sub_cmp_index];
-
- return c1 - c2;
-}
-
-
-static ngx_int_t
-ngx_http_sub_filter_init(ngx_conf_t *cf)
-{
- ngx_http_next_header_filter = ngx_http_top_header_filter;
- ngx_http_top_header_filter = ngx_http_sub_header_filter;
-
- ngx_http_next_body_filter = ngx_http_top_body_filter;
- ngx_http_top_body_filter = ngx_http_sub_body_filter;
-
- return NGX_OK;
-}
diff --git a/nginx/src/http/modules/ngx_http_try_files_module.c b/nginx/src/http/modules/ngx_http_try_files_module.c
deleted file mode 100644
index ce783a2..0000000
--- a/nginx/src/http/modules/ngx_http_try_files_module.c
+++ /dev/null
@@ -1,404 +0,0 @@
-
-/*
- * Copyright (C) Igor Sysoev
- * Copyright (C) Nginx, Inc.
- */
-
-
-#include <ngx_config.h>
-#include <ngx_core.h>
-#include <ngx_http.h>
-
-
-typedef struct {
- ngx_array_t *lengths;
- ngx_array_t *values;
- ngx_str_t name;
-
- unsigned code:10;
- unsigned test_dir:1;
-} ngx_http_try_file_t;
-
-
-typedef struct {
- ngx_http_try_file_t *try_files;
-} ngx_http_try_files_loc_conf_t;
-
-
-static ngx_int_t ngx_http_try_files_handler(ngx_http_request_t *r);
-static char *ngx_http_try_files(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
-static void *ngx_http_try_files_create_loc_conf(ngx_conf_t *cf);
-static ngx_int_t ngx_http_try_files_init(ngx_conf_t *cf);
-
-
-static ngx_command_t ngx_http_try_files_commands[] = {
-
- { ngx_string("try_files"),
- NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_2MORE,
- ngx_http_try_files,
- NGX_HTTP_LOC_CONF_OFFSET,
- 0,
- NULL },
-
- ngx_null_command
-};
-
-
-static ngx_http_module_t ngx_http_try_files_module_ctx = {
- NULL, /* preconfiguration */
- ngx_http_try_files_init, /* postconfiguration */
-
- NULL, /* create main configuration */
- NULL, /* init main configuration */
-
- NULL, /* create server configuration */
- NULL, /* merge server configuration */
-
- ngx_http_try_files_create_loc_conf, /* create location configuration */
- NULL /* merge location configuration */
-};
-
-
-ngx_module_t ngx_http_try_files_module = {
- NGX_MODULE_V1,
- &ngx_http_try_files_module_ctx, /* module context */
- ngx_http_try_files_commands, /* module directives */
- NGX_HTTP_MODULE, /* module type */
- NULL, /* init master */
- NULL, /* init module */
- NULL, /* init process */
- NULL, /* init thread */
- NULL, /* exit thread */
- NULL, /* exit process */
- NULL, /* exit master */
- NGX_MODULE_V1_PADDING
-};
-
-
-static ngx_int_t
-ngx_http_try_files_handler(ngx_http_request_t *r)
-{
- size_t len, root, alias, reserve, allocated;
- u_char *p, *name;
- ngx_str_t path, args;
- ngx_uint_t test_dir;
- ngx_http_try_file_t *tf;
- ngx_open_file_info_t of;
- ngx_http_script_code_pt code;
- ngx_http_script_engine_t e;
- ngx_http_core_loc_conf_t *clcf;
- ngx_http_script_len_code_pt lcode;
- ngx_http_try_files_loc_conf_t *tlcf;
-
- tlcf = ngx_http_get_module_loc_conf(r, ngx_http_try_files_module);
-
- if (tlcf->try_files == NULL) {
- return NGX_DECLINED;
- }
-
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "try files handler");
-
- allocated = 0;
- root = 0;
- name = NULL;
- /* suppress MSVC warning */
- path.data = NULL;
-
- tf = tlcf->try_files;
-
- clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
-
- alias = clcf->alias;
-
- for ( ;; ) {
-
- if (tf->lengths) {
- ngx_memzero(&e, sizeof(ngx_http_script_engine_t));
-
- e.ip = tf->lengths->elts;
- e.request = r;
-
- /* 1 is for terminating '\0' as in static names */
- len = 1;
-
- while (*(uintptr_t *) e.ip) {
- lcode = *(ngx_http_script_len_code_pt *) e.ip;
- len += lcode(&e);
- }
-
- } else {
- len = tf->name.len;
- }
-
- if (!alias) {
- reserve = len > r->uri.len ? len - r->uri.len : 0;
-
- } else if (alias == NGX_MAX_SIZE_T_VALUE) {
- reserve = len;
-
- } else {
- reserve = len > r->uri.len - alias ? len - (r->uri.len - alias) : 0;
- }
-
- if (reserve > allocated || !allocated) {
-
- /* 16 bytes are preallocation */
- allocated = reserve + 16;
-
- if (ngx_http_map_uri_to_path(r, &path, &root, allocated) == NULL) {
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
-
- name = path.data + root;
- }
-
- if (tf->values == NULL) {
-
- /* tf->name.len includes the terminating '\0' */
-
- ngx_memcpy(name, tf->name.data, tf->name.len);
-
- path.len = (name + tf->name.len - 1) - path.data;
-
- } else {
- e.ip = tf->values->elts;
- e.pos = name;
- e.flushed = 1;
-
- while (*(uintptr_t *) e.ip) {
- code = *(ngx_http_script_code_pt *) e.ip;
- code((ngx_http_script_engine_t *) &e);
- }
-
- path.len = e.pos - path.data;
-
- *e.pos = '\0';
-
- if (alias && alias != NGX_MAX_SIZE_T_VALUE
- && ngx_strncmp(name, r->uri.data, alias) == 0)
- {
- ngx_memmove(name, name + alias, len - alias);
- path.len -= alias;
- }
- }
-
- test_dir = tf->test_dir;
-
- tf++;
-
- ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "trying to use %s: \"%s\" \"%s\"",
- test_dir ? "dir" : "file", name, path.data);
-
- if (tf->lengths == NULL && tf->name.len == 0) {
-
- if (tf->code) {
- return tf->code;
- }
-
- path.len -= root;
- path.data += root;
-
- if (path.data[0] == '@') {
- (void) ngx_http_named_location(r, &path);
-
- } else {
- ngx_http_split_args(r, &path, &args);
-
- (void) ngx_http_internal_redirect(r, &path, &args);
- }
-
- ngx_http_finalize_request(r, NGX_DONE);
- return NGX_DONE;
- }
-
- ngx_memzero(&of, sizeof(ngx_open_file_info_t));
-
- of.read_ahead = clcf->read_ahead;
- of.directio = clcf->directio;
- of.valid = clcf->open_file_cache_valid;
- of.min_uses = clcf->open_file_cache_min_uses;
- of.test_only = 1;
- of.errors = clcf->open_file_cache_errors;
- of.events = clcf->open_file_cache_events;
-
- if (ngx_http_set_disable_symlinks(r, clcf, &path, &of) != NGX_OK) {
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
-
- if (ngx_open_cached_file(clcf->open_file_cache, &path, &of, r->pool)
- != NGX_OK)
- {
- if (of.err == 0) {
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
-
- if (of.err != NGX_ENOENT
- && of.err != NGX_ENOTDIR
- && of.err != NGX_ENAMETOOLONG)
- {
- ngx_log_error(NGX_LOG_CRIT, r->connection->log, of.err,
- "%s \"%s\" failed", of.failed, path.data);
- }
-
- continue;
- }
-
- if (of.is_dir != test_dir) {
- continue;
- }
-
- path.len -= root;
- path.data += root;
-
- if (!alias) {
- r->uri = path;
-
- } else if (alias == NGX_MAX_SIZE_T_VALUE) {
- if (!test_dir) {
- r->uri = path;
- r->add_uri_to_alias = 1;
- }
-
- } else {
- name = r->uri.data;
-
- r->uri.len = alias + path.len;
- r->uri.data = ngx_pnalloc(r->pool, r->uri.len);
- if (r->uri.data == NULL) {
- r->uri.len = 0;
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
-
- p = ngx_copy(r->uri.data, name, alias);
- ngx_memcpy(p, path.data, path.len);
- }
-
- ngx_http_set_exten(r);
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "try file uri: \"%V\"", &r->uri);
-
- return NGX_DECLINED;
- }
-
- /* not reached */
-}
-
-
-static char *
-ngx_http_try_files(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
-{
- ngx_http_try_files_loc_conf_t *tlcf = conf;
-
- ngx_str_t *value;
- ngx_int_t code;
- ngx_uint_t i, n;
- ngx_http_try_file_t *tf;
- ngx_http_script_compile_t sc;
-
- if (tlcf->try_files) {
- return "is duplicate";
- }
-
- tf = ngx_pcalloc(cf->pool, cf->args->nelts * sizeof(ngx_http_try_file_t));
- if (tf == NULL) {
- return NGX_CONF_ERROR;
- }
-
- tlcf->try_files = tf;
-
- value = cf->args->elts;
-
- for (i = 0; i < cf->args->nelts - 1; i++) {
-
- tf[i].name = value[i + 1];
-
- if (tf[i].name.len > 0
- && tf[i].name.data[tf[i].name.len - 1] == '/'
- && i + 2 < cf->args->nelts)
- {
- tf[i].test_dir = 1;
- tf[i].name.len--;
- tf[i].name.data[tf[i].name.len] = '\0';
- }
-
- n = ngx_http_script_variables_count(&tf[i].name);
-
- if (n) {
- ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));
-
- sc.cf = cf;
- sc.source = &tf[i].name;
- sc.lengths = &tf[i].lengths;
- sc.values = &tf[i].values;
- sc.variables = n;
- sc.complete_lengths = 1;
- sc.complete_values = 1;
-
- if (ngx_http_script_compile(&sc) != NGX_OK) {
- return NGX_CONF_ERROR;
- }
-
- } else {
- /* add trailing '\0' to length */
- tf[i].name.len++;
- }
- }
-
- if (tf[i - 1].name.data[0] == '=') {
-
- code = ngx_atoi(tf[i - 1].name.data + 1, tf[i - 1].name.len - 2);
-
- if (code == NGX_ERROR || code > 999) {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "invalid code \"%*s\"",
- tf[i - 1].name.len - 1, tf[i - 1].name.data);
- return NGX_CONF_ERROR;
- }
-
- tf[i].code = code;
- }
-
- return NGX_CONF_OK;
-}
-
-
-static void *
-ngx_http_try_files_create_loc_conf(ngx_conf_t *cf)
-{
- ngx_http_try_files_loc_conf_t *tlcf;
-
- tlcf = ngx_pcalloc(cf->pool, sizeof(ngx_http_try_files_loc_conf_t));
- if (tlcf == NULL) {
- return NULL;
- }
-
- /*
- * set by ngx_pcalloc():
- *
- * tlcf->try_files = NULL;
- */
-
- return tlcf;
-}
-
-
-static ngx_int_t
-ngx_http_try_files_init(ngx_conf_t *cf)
-{
- ngx_http_handler_pt *h;
- ngx_http_core_main_conf_t *cmcf;
-
- cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);
-
- h = ngx_array_push(&cmcf->phases[NGX_HTTP_PRECONTENT_PHASE].handlers);
- if (h == NULL) {
- return NGX_ERROR;
- }
-
- *h = ngx_http_try_files_handler;
-
- return NGX_OK;
-}
diff --git a/nginx/src/http/modules/ngx_http_upstream_hash_module.c b/nginx/src/http/modules/ngx_http_upstream_hash_module.c
deleted file mode 100644
index d67f34d..0000000
--- a/nginx/src/http/modules/ngx_http_upstream_hash_module.c
+++ /dev/null
@@ -1,680 +0,0 @@
-
-/*
- * Copyright (C) Roman Arutyunyan
- * Copyright (C) Nginx, Inc.
- */
-
-
-#include <ngx_config.h>
-#include <ngx_core.h>
-#include <ngx_http.h>
-
-
-typedef struct {
- uint32_t hash;
- ngx_str_t *server;
-} ngx_http_upstream_chash_point_t;
-
-
-typedef struct {
- ngx_uint_t number;
- ngx_http_upstream_chash_point_t point[1];
-} ngx_http_upstream_chash_points_t;
-
-
-typedef struct {
- ngx_http_complex_value_t key;
- ngx_http_upstream_chash_points_t *points;
-} ngx_http_upstream_hash_srv_conf_t;
-
-
-typedef struct {
- /* the round robin data must be first */
- ngx_http_upstream_rr_peer_data_t rrp;
- ngx_http_upstream_hash_srv_conf_t *conf;
- ngx_str_t key;
- ngx_uint_t tries;
- ngx_uint_t rehash;
- uint32_t hash;
- ngx_event_get_peer_pt get_rr_peer;
-} ngx_http_upstream_hash_peer_data_t;
-
-
-static ngx_int_t ngx_http_upstream_init_hash(ngx_conf_t *cf,
- ngx_http_upstream_srv_conf_t *us);
-static ngx_int_t ngx_http_upstream_init_hash_peer(ngx_http_request_t *r,
- ngx_http_upstream_srv_conf_t *us);
-static ngx_int_t ngx_http_upstream_get_hash_peer(ngx_peer_connection_t *pc,
- void *data);
-
-static ngx_int_t ngx_http_upstream_init_chash(ngx_conf_t *cf,
- ngx_http_upstream_srv_conf_t *us);
-static int ngx_libc_cdecl
- ngx_http_upstream_chash_cmp_points(const void *one, const void *two);
-static ngx_uint_t ngx_http_upstream_find_chash_point(
- ngx_http_upstream_chash_points_t *points, uint32_t hash);
-static ngx_int_t ngx_http_upstream_init_chash_peer(ngx_http_request_t *r,
- ngx_http_upstream_srv_conf_t *us);
-static ngx_int_t ngx_http_upstream_get_chash_peer(ngx_peer_connection_t *pc,
- void *data);
-
-static void *ngx_http_upstream_hash_create_conf(ngx_conf_t *cf);
-static char *ngx_http_upstream_hash(ngx_conf_t *cf, ngx_command_t *cmd,
- void *conf);
-
-
-static ngx_command_t ngx_http_upstream_hash_commands[] = {
-
- { ngx_string("hash"),
- NGX_HTTP_UPS_CONF|NGX_CONF_TAKE12,
- ngx_http_upstream_hash,
- NGX_HTTP_SRV_CONF_OFFSET,
- 0,
- NULL },
-
- ngx_null_command
-};
-
-
-static ngx_http_module_t ngx_http_upstream_hash_module_ctx = {
- NULL, /* preconfiguration */
- NULL, /* postconfiguration */
-
- NULL, /* create main configuration */
- NULL, /* init main configuration */
-
- ngx_http_upstream_hash_create_conf, /* create server configuration */
- NULL, /* merge server configuration */
-
- NULL, /* create location configuration */
- NULL /* merge location configuration */
-};
-
-
-ngx_module_t ngx_http_upstream_hash_module = {
- NGX_MODULE_V1,
- &ngx_http_upstream_hash_module_ctx, /* module context */
- ngx_http_upstream_hash_commands, /* module directives */
- NGX_HTTP_MODULE, /* module type */
- NULL, /* init master */
- NULL, /* init module */
- NULL, /* init process */
- NULL, /* init thread */
- NULL, /* exit thread */
- NULL, /* exit process */
- NULL, /* exit master */
- NGX_MODULE_V1_PADDING
-};
-
-
-static ngx_int_t
-ngx_http_upstream_init_hash(ngx_conf_t *cf, ngx_http_upstream_srv_conf_t *us)
-{
- if (ngx_http_upstream_init_round_robin(cf, us) != NGX_OK) {
- return NGX_ERROR;
- }
-
- us->peer.init = ngx_http_upstream_init_hash_peer;
-
- return NGX_OK;
-}
-
-
-static ngx_int_t
-ngx_http_upstream_init_hash_peer(ngx_http_request_t *r,
- ngx_http_upstream_srv_conf_t *us)
-{
- ngx_http_upstream_hash_srv_conf_t *hcf;
- ngx_http_upstream_hash_peer_data_t *hp;
-
- hp = ngx_palloc(r->pool, sizeof(ngx_http_upstream_hash_peer_data_t));
- if (hp == NULL) {
- return NGX_ERROR;
- }
-
- r->upstream->peer.data = &hp->rrp;
-
- if (ngx_http_upstream_init_round_robin_peer(r, us) != NGX_OK) {
- return NGX_ERROR;
- }
-
- r->upstream->peer.get = ngx_http_upstream_get_hash_peer;
-
- hcf = ngx_http_conf_upstream_srv_conf(us, ngx_http_upstream_hash_module);
-
- if (ngx_http_complex_value(r, &hcf->key, &hp->key) != NGX_OK) {
- return NGX_ERROR;
- }
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "upstream hash key:\"%V\"", &hp->key);
-
- hp->conf = hcf;
- hp->tries = 0;
- hp->rehash = 0;
- hp->hash = 0;
- hp->get_rr_peer = ngx_http_upstream_get_round_robin_peer;
-
- return NGX_OK;
-}
-
-
-static ngx_int_t
-ngx_http_upstream_get_hash_peer(ngx_peer_connection_t *pc, void *data)
-{
- ngx_http_upstream_hash_peer_data_t *hp = data;
-
- time_t now;
- u_char buf[NGX_INT_T_LEN];
- size_t size;
- uint32_t hash;
- ngx_int_t w;
- uintptr_t m;
- ngx_uint_t n, p;
- ngx_http_upstream_rr_peer_t *peer;
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, pc->log, 0,
- "get hash peer, try: %ui", pc->tries);
-
- ngx_http_upstream_rr_peers_wlock(hp->rrp.peers);
-
- if (hp->tries > 20 || hp->rrp.peers->single) {
- ngx_http_upstream_rr_peers_unlock(hp->rrp.peers);
- return hp->get_rr_peer(pc, &hp->rrp);
- }
-
- now = ngx_time();
-
- pc->cached = 0;
- pc->connection = NULL;
-
- for ( ;; ) {
-
- /*
- * Hash expression is compatible with Cache::Memcached:
- * ((crc32([REHASH] KEY) >> 16) & 0x7fff) + PREV_HASH
- * with REHASH omitted at the first iteration.
- */
-
- ngx_crc32_init(hash);
-
- if (hp->rehash > 0) {
- size = ngx_sprintf(buf, "%ui", hp->rehash) - buf;
- ngx_crc32_update(&hash, buf, size);
- }
-
- ngx_crc32_update(&hash, hp->key.data, hp->key.len);
- ngx_crc32_final(hash);
-
- hash = (hash >> 16) & 0x7fff;
-
- hp->hash += hash;
- hp->rehash++;
-
- w = hp->hash % hp->rrp.peers->total_weight;
- peer = hp->rrp.peers->peer;
- p = 0;
-
- while (w >= peer->weight) {
- w -= peer->weight;
- peer = peer->next;
- p++;
- }
-
- n = p / (8 * sizeof(uintptr_t));
- m = (uintptr_t) 1 << p % (8 * sizeof(uintptr_t));
-
- if (hp->rrp.tried[n] & m) {
- goto next;
- }
-
- ngx_log_debug2(NGX_LOG_DEBUG_HTTP, pc->log, 0,
- "get hash peer, value:%uD, peer:%ui", hp->hash, p);
-
- if (peer->down) {
- goto next;
- }
-
- if (peer->max_fails
- && peer->fails >= peer->max_fails
- && now - peer->checked <= peer->fail_timeout)
- {
- goto next;
- }
-
- if (peer->max_conns && peer->conns >= peer->max_conns) {
- goto next;
- }
-
- break;
-
- next:
-
- if (++hp->tries > 20) {
- ngx_http_upstream_rr_peers_unlock(hp->rrp.peers);
- return hp->get_rr_peer(pc, &hp->rrp);
- }
- }
-
- hp->rrp.current = peer;
-
- pc->sockaddr = peer->sockaddr;
- pc->socklen = peer->socklen;
- pc->name = &peer->name;
-
- peer->conns++;
-
- if (now - peer->checked > peer->fail_timeout) {
- peer->checked = now;
- }
-
- ngx_http_upstream_rr_peers_unlock(hp->rrp.peers);
-
- hp->rrp.tried[n] |= m;
-
- return NGX_OK;
-}
-
-
-static ngx_int_t
-ngx_http_upstream_init_chash(ngx_conf_t *cf, ngx_http_upstream_srv_conf_t *us)
-{
- u_char *host, *port, c;
- size_t host_len, port_len, size;
- uint32_t hash, base_hash;
- ngx_str_t *server;
- ngx_uint_t npoints, i, j;
- ngx_http_upstream_rr_peer_t *peer;
- ngx_http_upstream_rr_peers_t *peers;
- ngx_http_upstream_chash_points_t *points;
- ngx_http_upstream_hash_srv_conf_t *hcf;
- union {
- uint32_t value;
- u_char byte[4];
- } prev_hash;
-
- if (ngx_http_upstream_init_round_robin(cf, us) != NGX_OK) {
- return NGX_ERROR;
- }
-
- us->peer.init = ngx_http_upstream_init_chash_peer;
-
- peers = us->peer.data;
- npoints = peers->total_weight * 160;
-
- size = sizeof(ngx_http_upstream_chash_points_t)
- + sizeof(ngx_http_upstream_chash_point_t) * (npoints - 1);
-
- points = ngx_palloc(cf->pool, size);
- if (points == NULL) {
- return NGX_ERROR;
- }
-
- points->number = 0;
-
- for (peer = peers->peer; peer; peer = peer->next) {
- server = &peer->server;
-
- /*
- * Hash expression is compatible with Cache::Memcached::Fast:
- * crc32(HOST \0 PORT PREV_HASH).
- */
-
- if (server->len >= 5
- && ngx_strncasecmp(server->data, (u_char *) "unix:", 5) == 0)
- {
- host = server->data + 5;
- host_len = server->len - 5;
- port = NULL;
- port_len = 0;
- goto done;
- }
-
- for (j = 0; j < server->len; j++) {
- c = server->data[server->len - j - 1];
-
- if (c == ':') {
- host = server->data;
- host_len = server->len - j - 1;
- port = server->data + server->len - j;
- port_len = j;
- goto done;
- }
-
- if (c < '0' || c > '9') {
- break;
- }
- }
-
- host = server->data;
- host_len = server->len;
- port = NULL;
- port_len = 0;
-
- done:
-
- ngx_crc32_init(base_hash);
- ngx_crc32_update(&base_hash, host, host_len);
- ngx_crc32_update(&base_hash, (u_char *) "", 1);
- ngx_crc32_update(&base_hash, port, port_len);
-
- prev_hash.value = 0;
- npoints = peer->weight * 160;
-
- for (j = 0; j < npoints; j++) {
- hash = base_hash;
-
- ngx_crc32_update(&hash, prev_hash.byte, 4);
- ngx_crc32_final(hash);
-
- points->point[points->number].hash = hash;
- points->point[points->number].server = server;
- points->number++;
-
-#if (NGX_HAVE_LITTLE_ENDIAN)
- prev_hash.value = hash;
-#else
- prev_hash.byte[0] = (u_char) (hash & 0xff);
- prev_hash.byte[1] = (u_char) ((hash >> 8) & 0xff);
- prev_hash.byte[2] = (u_char) ((hash >> 16) & 0xff);
- prev_hash.byte[3] = (u_char) ((hash >> 24) & 0xff);
-#endif
- }
- }
-
- ngx_qsort(points->point,
- points->number,
- sizeof(ngx_http_upstream_chash_point_t),
- ngx_http_upstream_chash_cmp_points);
-
- for (i = 0, j = 1; j < points->number; j++) {
- if (points->point[i].hash != points->point[j].hash) {
- points->point[++i] = points->point[j];
- }
- }
-
- points->number = i + 1;
-
- hcf = ngx_http_conf_upstream_srv_conf(us, ngx_http_upstream_hash_module);
- hcf->points = points;
-
- return NGX_OK;
-}
-
-
-static int ngx_libc_cdecl
-ngx_http_upstream_chash_cmp_points(const void *one, const void *two)
-{
- ngx_http_upstream_chash_point_t *first =
- (ngx_http_upstream_chash_point_t *) one;
- ngx_http_upstream_chash_point_t *second =
- (ngx_http_upstream_chash_point_t *) two;
-
- if (first->hash < second->hash) {
- return -1;
-
- } else if (first->hash > second->hash) {
- return 1;
-
- } else {
- return 0;
- }
-}
-
-
-static ngx_uint_t
-ngx_http_upstream_find_chash_point(ngx_http_upstream_chash_points_t *points,
- uint32_t hash)
-{
- ngx_uint_t i, j, k;
- ngx_http_upstream_chash_point_t *point;
-
- /* find first point >= hash */
-
- point = &points->point[0];
-
- i = 0;
- j = points->number;
-
- while (i < j) {
- k = (i + j) / 2;
-
- if (hash > point[k].hash) {
- i = k + 1;
-
- } else if (hash < point[k].hash) {
- j = k;
-
- } else {
- return k;
- }
- }
-
- return i;
-}
-
-
-static ngx_int_t
-ngx_http_upstream_init_chash_peer(ngx_http_request_t *r,
- ngx_http_upstream_srv_conf_t *us)
-{
- uint32_t hash;
- ngx_http_upstream_hash_srv_conf_t *hcf;
- ngx_http_upstream_hash_peer_data_t *hp;
-
- if (ngx_http_upstream_init_hash_peer(r, us) != NGX_OK) {
- return NGX_ERROR;
- }
-
- r->upstream->peer.get = ngx_http_upstream_get_chash_peer;
-
- hp = r->upstream->peer.data;
- hcf = ngx_http_conf_upstream_srv_conf(us, ngx_http_upstream_hash_module);
-
- hash = ngx_crc32_long(hp->key.data, hp->key.len);
-
- ngx_http_upstream_rr_peers_rlock(hp->rrp.peers);
-
- hp->hash = ngx_http_upstream_find_chash_point(hcf->points, hash);
-
- ngx_http_upstream_rr_peers_unlock(hp->rrp.peers);
-
- return NGX_OK;
-}
-
-
-static ngx_int_t
-ngx_http_upstream_get_chash_peer(ngx_peer_connection_t *pc, void *data)
-{
- ngx_http_upstream_hash_peer_data_t *hp = data;
-
- time_t now;
- intptr_t m;
- ngx_str_t *server;
- ngx_int_t total;
- ngx_uint_t i, n, best_i;
- ngx_http_upstream_rr_peer_t *peer, *best;
- ngx_http_upstream_chash_point_t *point;
- ngx_http_upstream_chash_points_t *points;
- ngx_http_upstream_hash_srv_conf_t *hcf;
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, pc->log, 0,
- "get consistent hash peer, try: %ui", pc->tries);
-
- ngx_http_upstream_rr_peers_wlock(hp->rrp.peers);
-
- if (hp->tries > 20 || hp->rrp.peers->single) {
- ngx_http_upstream_rr_peers_unlock(hp->rrp.peers);
- return hp->get_rr_peer(pc, &hp->rrp);
- }
-
- pc->cached = 0;
- pc->connection = NULL;
-
- now = ngx_time();
- hcf = hp->conf;
-
- points = hcf->points;
- point = &points->point[0];
-
- for ( ;; ) {
- server = point[hp->hash % points->number].server;
-
- ngx_log_debug2(NGX_LOG_DEBUG_HTTP, pc->log, 0,
- "consistent hash peer:%uD, server:\"%V\"",
- hp->hash, server);
-
- best = NULL;
- best_i = 0;
- total = 0;
-
- for (peer = hp->rrp.peers->peer, i = 0;
- peer;
- peer = peer->next, i++)
- {
- n = i / (8 * sizeof(uintptr_t));
- m = (uintptr_t) 1 << i % (8 * sizeof(uintptr_t));
-
- if (hp->rrp.tried[n] & m) {
- continue;
- }
-
- if (peer->down) {
- continue;
- }
-
- if (peer->max_fails
- && peer->fails >= peer->max_fails
- && now - peer->checked <= peer->fail_timeout)
- {
- continue;
- }
-
- if (peer->max_conns && peer->conns >= peer->max_conns) {
- continue;
- }
-
- if (peer->server.len != server->len
- || ngx_strncmp(peer->server.data, server->data, server->len)
- != 0)
- {
- continue;
- }
-
- peer->current_weight += peer->effective_weight;
- total += peer->effective_weight;
-
- if (peer->effective_weight < peer->weight) {
- peer->effective_weight++;
- }
-
- if (best == NULL || peer->current_weight > best->current_weight) {
- best = peer;
- best_i = i;
- }
- }
-
- if (best) {
- best->current_weight -= total;
- goto found;
- }
-
- hp->hash++;
- hp->tries++;
-
- if (hp->tries > 20) {
- ngx_http_upstream_rr_peers_unlock(hp->rrp.peers);
- return hp->get_rr_peer(pc, &hp->rrp);
- }
- }
-
-found:
-
- hp->rrp.current = best;
-
- pc->sockaddr = best->sockaddr;
- pc->socklen = best->socklen;
- pc->name = &best->name;
-
- best->conns++;
-
- if (now - best->checked > best->fail_timeout) {
- best->checked = now;
- }
-
- ngx_http_upstream_rr_peers_unlock(hp->rrp.peers);
-
- n = best_i / (8 * sizeof(uintptr_t));
- m = (uintptr_t) 1 << best_i % (8 * sizeof(uintptr_t));
-
- hp->rrp.tried[n] |= m;
-
- return NGX_OK;
-}
-
-
-static void *
-ngx_http_upstream_hash_create_conf(ngx_conf_t *cf)
-{
- ngx_http_upstream_hash_srv_conf_t *conf;
-
- conf = ngx_palloc(cf->pool, sizeof(ngx_http_upstream_hash_srv_conf_t));
- if (conf == NULL) {
- return NULL;
- }
-
- conf->points = NULL;
-
- return conf;
-}
-
-
-static char *
-ngx_http_upstream_hash(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
-{
- ngx_http_upstream_hash_srv_conf_t *hcf = conf;
-
- ngx_str_t *value;
- ngx_http_upstream_srv_conf_t *uscf;
- 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 = &hcf->key;
-
- if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
- return NGX_CONF_ERROR;
- }
-
- uscf = ngx_http_conf_get_module_srv_conf(cf, ngx_http_upstream_module);
-
- if (uscf->peer.init_upstream) {
- ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
- "load balancing method redefined");
- }
-
- uscf->flags = NGX_HTTP_UPSTREAM_CREATE
- |NGX_HTTP_UPSTREAM_WEIGHT
- |NGX_HTTP_UPSTREAM_MAX_CONNS
- |NGX_HTTP_UPSTREAM_MAX_FAILS
- |NGX_HTTP_UPSTREAM_FAIL_TIMEOUT
- |NGX_HTTP_UPSTREAM_DOWN;
-
- if (cf->args->nelts == 2) {
- uscf->peer.init_upstream = ngx_http_upstream_init_hash;
-
- } else if (ngx_strcmp(value[2].data, "consistent") == 0) {
- uscf->peer.init_upstream = ngx_http_upstream_init_chash;
-
- } else {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "invalid parameter \"%V\"", &value[2]);
- return NGX_CONF_ERROR;
- }
-
- return NGX_CONF_OK;
-}
diff --git a/nginx/src/http/modules/ngx_http_upstream_ip_hash_module.c b/nginx/src/http/modules/ngx_http_upstream_ip_hash_module.c
deleted file mode 100644
index 296108f..0000000
--- a/nginx/src/http/modules/ngx_http_upstream_ip_hash_module.c
+++ /dev/null
@@ -1,272 +0,0 @@
-
-/*
- * Copyright (C) Igor Sysoev
- * Copyright (C) Nginx, Inc.
- */
-
-
-#include <ngx_config.h>
-#include <ngx_core.h>
-#include <ngx_http.h>
-
-
-typedef struct {
- /* the round robin data must be first */
- ngx_http_upstream_rr_peer_data_t rrp;
-
- ngx_uint_t hash;
-
- u_char addrlen;
- u_char *addr;
-
- u_char tries;
-
- ngx_event_get_peer_pt get_rr_peer;
-} ngx_http_upstream_ip_hash_peer_data_t;
-
-
-static ngx_int_t ngx_http_upstream_init_ip_hash_peer(ngx_http_request_t *r,
- ngx_http_upstream_srv_conf_t *us);
-static ngx_int_t ngx_http_upstream_get_ip_hash_peer(ngx_peer_connection_t *pc,
- void *data);
-static char *ngx_http_upstream_ip_hash(ngx_conf_t *cf, ngx_command_t *cmd,
- void *conf);
-
-
-static ngx_command_t ngx_http_upstream_ip_hash_commands[] = {
-
- { ngx_string("ip_hash"),
- NGX_HTTP_UPS_CONF|NGX_CONF_NOARGS,
- ngx_http_upstream_ip_hash,
- 0,
- 0,
- NULL },
-
- ngx_null_command
-};
-
-
-static ngx_http_module_t ngx_http_upstream_ip_hash_module_ctx = {
- NULL, /* preconfiguration */
- NULL, /* postconfiguration */
-
- NULL, /* create main configuration */
- NULL, /* init main configuration */
-
- NULL, /* create server configuration */
- NULL, /* merge server configuration */
-
- NULL, /* create location configuration */
- NULL /* merge location configuration */
-};
-
-
-ngx_module_t ngx_http_upstream_ip_hash_module = {
- NGX_MODULE_V1,
- &ngx_http_upstream_ip_hash_module_ctx, /* module context */
- ngx_http_upstream_ip_hash_commands, /* module directives */
- NGX_HTTP_MODULE, /* module type */
- NULL, /* init master */
- NULL, /* init module */
- NULL, /* init process */
- NULL, /* init thread */
- NULL, /* exit thread */
- NULL, /* exit process */
- NULL, /* exit master */
- NGX_MODULE_V1_PADDING
-};
-
-
-static u_char ngx_http_upstream_ip_hash_pseudo_addr[3];
-
-
-static ngx_int_t
-ngx_http_upstream_init_ip_hash(ngx_conf_t *cf, ngx_http_upstream_srv_conf_t *us)
-{
- if (ngx_http_upstream_init_round_robin(cf, us) != NGX_OK) {
- return NGX_ERROR;
- }
-
- us->peer.init = ngx_http_upstream_init_ip_hash_peer;
-
- return NGX_OK;
-}
-
-
-static ngx_int_t
-ngx_http_upstream_init_ip_hash_peer(ngx_http_request_t *r,
- ngx_http_upstream_srv_conf_t *us)
-{
- struct sockaddr_in *sin;
-#if (NGX_HAVE_INET6)
- struct sockaddr_in6 *sin6;
-#endif
- ngx_http_upstream_ip_hash_peer_data_t *iphp;
-
- iphp = ngx_palloc(r->pool, sizeof(ngx_http_upstream_ip_hash_peer_data_t));
- if (iphp == NULL) {
- return NGX_ERROR;
- }
-
- r->upstream->peer.data = &iphp->rrp;
-
- if (ngx_http_upstream_init_round_robin_peer(r, us) != NGX_OK) {
- return NGX_ERROR;
- }
-
- r->upstream->peer.get = ngx_http_upstream_get_ip_hash_peer;
-
- switch (r->connection->sockaddr->sa_family) {
-
- case AF_INET:
- sin = (struct sockaddr_in *) r->connection->sockaddr;
- iphp->addr = (u_char *) &sin->sin_addr.s_addr;
- iphp->addrlen = 3;
- break;
-
-#if (NGX_HAVE_INET6)
- case AF_INET6:
- sin6 = (struct sockaddr_in6 *) r->connection->sockaddr;
- iphp->addr = (u_char *) &sin6->sin6_addr.s6_addr;
- iphp->addrlen = 16;
- break;
-#endif
-
- default:
- iphp->addr = ngx_http_upstream_ip_hash_pseudo_addr;
- iphp->addrlen = 3;
- }
-
- iphp->hash = 89;
- iphp->tries = 0;
- iphp->get_rr_peer = ngx_http_upstream_get_round_robin_peer;
-
- return NGX_OK;
-}
-
-
-static ngx_int_t
-ngx_http_upstream_get_ip_hash_peer(ngx_peer_connection_t *pc, void *data)
-{
- ngx_http_upstream_ip_hash_peer_data_t *iphp = data;
-
- time_t now;
- ngx_int_t w;
- uintptr_t m;
- ngx_uint_t i, n, p, hash;
- ngx_http_upstream_rr_peer_t *peer;
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, pc->log, 0,
- "get ip hash peer, try: %ui", pc->tries);
-
- /* TODO: cached */
-
- ngx_http_upstream_rr_peers_wlock(iphp->rrp.peers);
-
- if (iphp->tries > 20 || iphp->rrp.peers->single) {
- ngx_http_upstream_rr_peers_unlock(iphp->rrp.peers);
- return iphp->get_rr_peer(pc, &iphp->rrp);
- }
-
- now = ngx_time();
-
- pc->cached = 0;
- pc->connection = NULL;
-
- hash = iphp->hash;
-
- for ( ;; ) {
-
- for (i = 0; i < (ngx_uint_t) iphp->addrlen; i++) {
- hash = (hash * 113 + iphp->addr[i]) % 6271;
- }
-
- w = hash % iphp->rrp.peers->total_weight;
- peer = iphp->rrp.peers->peer;
- p = 0;
-
- while (w >= peer->weight) {
- w -= peer->weight;
- peer = peer->next;
- p++;
- }
-
- n = p / (8 * sizeof(uintptr_t));
- m = (uintptr_t) 1 << p % (8 * sizeof(uintptr_t));
-
- if (iphp->rrp.tried[n] & m) {
- goto next;
- }
-
- ngx_log_debug2(NGX_LOG_DEBUG_HTTP, pc->log, 0,
- "get ip hash peer, hash: %ui %04XL", p, (uint64_t) m);
-
- if (peer->down) {
- goto next;
- }
-
- if (peer->max_fails
- && peer->fails >= peer->max_fails
- && now - peer->checked <= peer->fail_timeout)
- {
- goto next;
- }
-
- if (peer->max_conns && peer->conns >= peer->max_conns) {
- goto next;
- }
-
- break;
-
- next:
-
- if (++iphp->tries > 20) {
- ngx_http_upstream_rr_peers_unlock(iphp->rrp.peers);
- return iphp->get_rr_peer(pc, &iphp->rrp);
- }
- }
-
- iphp->rrp.current = peer;
-
- pc->sockaddr = peer->sockaddr;
- pc->socklen = peer->socklen;
- pc->name = &peer->name;
-
- peer->conns++;
-
- if (now - peer->checked > peer->fail_timeout) {
- peer->checked = now;
- }
-
- ngx_http_upstream_rr_peers_unlock(iphp->rrp.peers);
-
- iphp->rrp.tried[n] |= m;
- iphp->hash = hash;
-
- return NGX_OK;
-}
-
-
-static char *
-ngx_http_upstream_ip_hash(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
-{
- ngx_http_upstream_srv_conf_t *uscf;
-
- uscf = ngx_http_conf_get_module_srv_conf(cf, ngx_http_upstream_module);
-
- if (uscf->peer.init_upstream) {
- ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
- "load balancing method redefined");
- }
-
- uscf->peer.init_upstream = ngx_http_upstream_init_ip_hash;
-
- uscf->flags = NGX_HTTP_UPSTREAM_CREATE
- |NGX_HTTP_UPSTREAM_WEIGHT
- |NGX_HTTP_UPSTREAM_MAX_CONNS
- |NGX_HTTP_UPSTREAM_MAX_FAILS
- |NGX_HTTP_UPSTREAM_FAIL_TIMEOUT
- |NGX_HTTP_UPSTREAM_DOWN;
-
- return NGX_CONF_OK;
-}
diff --git a/nginx/src/http/modules/ngx_http_upstream_keepalive_module.c b/nginx/src/http/modules/ngx_http_upstream_keepalive_module.c
deleted file mode 100644
index 2283023..0000000
--- a/nginx/src/http/modules/ngx_http_upstream_keepalive_module.c
+++ /dev/null
@@ -1,530 +0,0 @@
-
-/*
- * Copyright (C) Maxim Dounin
- * Copyright (C) Nginx, Inc.
- */
-
-
-#include <ngx_config.h>
-#include <ngx_core.h>
-#include <ngx_http.h>
-
-
-typedef struct {
- ngx_uint_t max_cached;
-
- ngx_queue_t cache;
- ngx_queue_t free;
-
- ngx_http_upstream_init_pt original_init_upstream;
- ngx_http_upstream_init_peer_pt original_init_peer;
-
-} ngx_http_upstream_keepalive_srv_conf_t;
-
-
-typedef struct {
- ngx_http_upstream_keepalive_srv_conf_t *conf;
-
- ngx_queue_t queue;
- ngx_connection_t *connection;
-
- socklen_t socklen;
- ngx_sockaddr_t sockaddr;
-
-} ngx_http_upstream_keepalive_cache_t;
-
-
-typedef struct {
- ngx_http_upstream_keepalive_srv_conf_t *conf;
-
- ngx_http_upstream_t *upstream;
-
- void *data;
-
- ngx_event_get_peer_pt original_get_peer;
- ngx_event_free_peer_pt original_free_peer;
-
-#if (NGX_HTTP_SSL)
- ngx_event_set_peer_session_pt original_set_session;
- ngx_event_save_peer_session_pt original_save_session;
-#endif
-
-} ngx_http_upstream_keepalive_peer_data_t;
-
-
-static ngx_int_t ngx_http_upstream_init_keepalive_peer(ngx_http_request_t *r,
- ngx_http_upstream_srv_conf_t *us);
-static ngx_int_t ngx_http_upstream_get_keepalive_peer(ngx_peer_connection_t *pc,
- void *data);
-static void ngx_http_upstream_free_keepalive_peer(ngx_peer_connection_t *pc,
- void *data, ngx_uint_t state);
-
-static void ngx_http_upstream_keepalive_dummy_handler(ngx_event_t *ev);
-static void ngx_http_upstream_keepalive_close_handler(ngx_event_t *ev);
-static void ngx_http_upstream_keepalive_close(ngx_connection_t *c);
-
-#if (NGX_HTTP_SSL)
-static ngx_int_t ngx_http_upstream_keepalive_set_session(
- ngx_peer_connection_t *pc, void *data);
-static void ngx_http_upstream_keepalive_save_session(ngx_peer_connection_t *pc,
- void *data);
-#endif
-
-static void *ngx_http_upstream_keepalive_create_conf(ngx_conf_t *cf);
-static char *ngx_http_upstream_keepalive(ngx_conf_t *cf, ngx_command_t *cmd,
- void *conf);
-
-
-static ngx_command_t ngx_http_upstream_keepalive_commands[] = {
-
- { ngx_string("keepalive"),
- NGX_HTTP_UPS_CONF|NGX_CONF_TAKE1,
- ngx_http_upstream_keepalive,
- NGX_HTTP_SRV_CONF_OFFSET,
- 0,
- NULL },
-
- ngx_null_command
-};
-
-
-static ngx_http_module_t ngx_http_upstream_keepalive_module_ctx = {
- NULL, /* preconfiguration */
- NULL, /* postconfiguration */
-
- NULL, /* create main configuration */
- NULL, /* init main configuration */
-
- ngx_http_upstream_keepalive_create_conf, /* create server configuration */
- NULL, /* merge server configuration */
-
- NULL, /* create location configuration */
- NULL /* merge location configuration */
-};
-
-
-ngx_module_t ngx_http_upstream_keepalive_module = {
- NGX_MODULE_V1,
- &ngx_http_upstream_keepalive_module_ctx, /* module context */
- ngx_http_upstream_keepalive_commands, /* module directives */
- NGX_HTTP_MODULE, /* module type */
- NULL, /* init master */
- NULL, /* init module */
- NULL, /* init process */
- NULL, /* init thread */
- NULL, /* exit thread */
- NULL, /* exit process */
- NULL, /* exit master */
- NGX_MODULE_V1_PADDING
-};
-
-
-static ngx_int_t
-ngx_http_upstream_init_keepalive(ngx_conf_t *cf,
- ngx_http_upstream_srv_conf_t *us)
-{
- ngx_uint_t i;
- ngx_http_upstream_keepalive_srv_conf_t *kcf;
- ngx_http_upstream_keepalive_cache_t *cached;
-
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, cf->log, 0,
- "init keepalive");
-
- kcf = ngx_http_conf_upstream_srv_conf(us,
- ngx_http_upstream_keepalive_module);
-
- if (kcf->original_init_upstream(cf, us) != NGX_OK) {
- return NGX_ERROR;
- }
-
- kcf->original_init_peer = us->peer.init;
-
- us->peer.init = ngx_http_upstream_init_keepalive_peer;
-
- /* allocate cache items and add to free queue */
-
- cached = ngx_pcalloc(cf->pool,
- sizeof(ngx_http_upstream_keepalive_cache_t) * kcf->max_cached);
- if (cached == NULL) {
- return NGX_ERROR;
- }
-
- ngx_queue_init(&kcf->cache);
- ngx_queue_init(&kcf->free);
-
- for (i = 0; i < kcf->max_cached; i++) {
- ngx_queue_insert_head(&kcf->free, &cached[i].queue);
- cached[i].conf = kcf;
- }
-
- return NGX_OK;
-}
-
-
-static ngx_int_t
-ngx_http_upstream_init_keepalive_peer(ngx_http_request_t *r,
- ngx_http_upstream_srv_conf_t *us)
-{
- ngx_http_upstream_keepalive_peer_data_t *kp;
- ngx_http_upstream_keepalive_srv_conf_t *kcf;
-
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "init keepalive peer");
-
- kcf = ngx_http_conf_upstream_srv_conf(us,
- ngx_http_upstream_keepalive_module);
-
- kp = ngx_palloc(r->pool, sizeof(ngx_http_upstream_keepalive_peer_data_t));
- if (kp == NULL) {
- return NGX_ERROR;
- }
-
- if (kcf->original_init_peer(r, us) != NGX_OK) {
- return NGX_ERROR;
- }
-
- kp->conf = kcf;
- kp->upstream = r->upstream;
- kp->data = r->upstream->peer.data;
- kp->original_get_peer = r->upstream->peer.get;
- kp->original_free_peer = r->upstream->peer.free;
-
- r->upstream->peer.data = kp;
- r->upstream->peer.get = ngx_http_upstream_get_keepalive_peer;
- r->upstream->peer.free = ngx_http_upstream_free_keepalive_peer;
-
-#if (NGX_HTTP_SSL)
- kp->original_set_session = r->upstream->peer.set_session;
- kp->original_save_session = r->upstream->peer.save_session;
- r->upstream->peer.set_session = ngx_http_upstream_keepalive_set_session;
- r->upstream->peer.save_session = ngx_http_upstream_keepalive_save_session;
-#endif
-
- return NGX_OK;
-}
-
-
-static ngx_int_t
-ngx_http_upstream_get_keepalive_peer(ngx_peer_connection_t *pc, void *data)
-{
- ngx_http_upstream_keepalive_peer_data_t *kp = data;
- ngx_http_upstream_keepalive_cache_t *item;
-
- ngx_int_t rc;
- ngx_queue_t *q, *cache;
- ngx_connection_t *c;
-
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, pc->log, 0,
- "get keepalive peer");
-
- /* ask balancer */
-
- rc = kp->original_get_peer(pc, kp->data);
-
- if (rc != NGX_OK) {
- return rc;
- }
-
- /* search cache for suitable connection */
-
- cache = &kp->conf->cache;
-
- for (q = ngx_queue_head(cache);
- q != ngx_queue_sentinel(cache);
- q = ngx_queue_next(q))
- {
- item = ngx_queue_data(q, ngx_http_upstream_keepalive_cache_t, queue);
- c = item->connection;
-
- if (ngx_memn2cmp((u_char *) &item->sockaddr, (u_char *) pc->sockaddr,
- item->socklen, pc->socklen)
- == 0)
- {
- ngx_queue_remove(q);
- ngx_queue_insert_head(&kp->conf->free, q);
-
- goto found;
- }
- }
-
- return NGX_OK;
-
-found:
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, pc->log, 0,
- "get keepalive peer: using connection %p", c);
-
- c->idle = 0;
- c->sent = 0;
- c->log = pc->log;
- c->read->log = pc->log;
- c->write->log = pc->log;
- c->pool->log = pc->log;
-
- pc->connection = c;
- pc->cached = 1;
-
- return NGX_DONE;
-}
-
-
-static void
-ngx_http_upstream_free_keepalive_peer(ngx_peer_connection_t *pc, void *data,
- ngx_uint_t state)
-{
- ngx_http_upstream_keepalive_peer_data_t *kp = data;
- ngx_http_upstream_keepalive_cache_t *item;
-
- ngx_queue_t *q;
- ngx_connection_t *c;
- ngx_http_upstream_t *u;
-
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, pc->log, 0,
- "free keepalive peer");
-
- /* cache valid connections */
-
- u = kp->upstream;
- c = pc->connection;
-
- if (state & NGX_PEER_FAILED
- || c == NULL
- || c->read->eof
- || c->read->error
- || c->read->timedout
- || c->write->error
- || c->write->timedout)
- {
- goto invalid;
- }
-
- if (!u->keepalive) {
- goto invalid;
- }
-
- if (!u->request_body_sent) {
- goto invalid;
- }
-
- if (ngx_terminate || ngx_exiting) {
- goto invalid;
- }
-
- if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
- goto invalid;
- }
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, pc->log, 0,
- "free keepalive peer: saving connection %p", c);
-
- if (ngx_queue_empty(&kp->conf->free)) {
-
- q = ngx_queue_last(&kp->conf->cache);
- ngx_queue_remove(q);
-
- item = ngx_queue_data(q, ngx_http_upstream_keepalive_cache_t, queue);
-
- ngx_http_upstream_keepalive_close(item->connection);
-
- } else {
- q = ngx_queue_head(&kp->conf->free);
- ngx_queue_remove(q);
-
- item = ngx_queue_data(q, ngx_http_upstream_keepalive_cache_t, queue);
- }
-
- ngx_queue_insert_head(&kp->conf->cache, q);
-
- item->connection = c;
-
- pc->connection = NULL;
-
- if (c->read->timer_set) {
- c->read->delayed = 0;
- ngx_del_timer(c->read);
- }
- if (c->write->timer_set) {
- ngx_del_timer(c->write);
- }
-
- c->write->handler = ngx_http_upstream_keepalive_dummy_handler;
- c->read->handler = ngx_http_upstream_keepalive_close_handler;
-
- c->data = item;
- c->idle = 1;
- c->log = ngx_cycle->log;
- c->read->log = ngx_cycle->log;
- c->write->log = ngx_cycle->log;
- c->pool->log = ngx_cycle->log;
-
- item->socklen = pc->socklen;
- ngx_memcpy(&item->sockaddr, pc->sockaddr, pc->socklen);
-
- if (c->read->ready) {
- ngx_http_upstream_keepalive_close_handler(c->read);
- }
-
-invalid:
-
- kp->original_free_peer(pc, kp->data, state);
-}
-
-
-static void
-ngx_http_upstream_keepalive_dummy_handler(ngx_event_t *ev)
-{
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, ev->log, 0,
- "keepalive dummy handler");
-}
-
-
-static void
-ngx_http_upstream_keepalive_close_handler(ngx_event_t *ev)
-{
- ngx_http_upstream_keepalive_srv_conf_t *conf;
- ngx_http_upstream_keepalive_cache_t *item;
-
- int n;
- char buf[1];
- ngx_connection_t *c;
-
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, ev->log, 0,
- "keepalive close handler");
-
- c = ev->data;
-
- if (c->close) {
- goto close;
- }
-
- n = ngxvcl_recv(c->fd, buf, 1, MSG_PEEK);
-
- if (n == -1 && ngx_socket_errno == NGX_EAGAIN) {
- ev->ready = 0;
-
- if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
- goto close;
- }
-
- return;
- }
-
-close:
-
- item = c->data;
- conf = item->conf;
-
- ngx_http_upstream_keepalive_close(c);
-
- ngx_queue_remove(&item->queue);
- ngx_queue_insert_head(&conf->free, &item->queue);
-}
-
-
-static void
-ngx_http_upstream_keepalive_close(ngx_connection_t *c)
-{
-
-#if (NGX_HTTP_SSL)
-
- if (c->ssl) {
- c->ssl->no_wait_shutdown = 1;
- c->ssl->no_send_shutdown = 1;
-
- if (ngx_ssl_shutdown(c) == NGX_AGAIN) {
- c->ssl->handler = ngx_http_upstream_keepalive_close;
- return;
- }
- }
-
-#endif
-
- ngx_destroy_pool(c->pool);
- ngx_close_connection(c);
-}
-
-
-#if (NGX_HTTP_SSL)
-
-static ngx_int_t
-ngx_http_upstream_keepalive_set_session(ngx_peer_connection_t *pc, void *data)
-{
- ngx_http_upstream_keepalive_peer_data_t *kp = data;
-
- return kp->original_set_session(pc, kp->data);
-}
-
-
-static void
-ngx_http_upstream_keepalive_save_session(ngx_peer_connection_t *pc, void *data)
-{
- ngx_http_upstream_keepalive_peer_data_t *kp = data;
-
- kp->original_save_session(pc, kp->data);
- return;
-}
-
-#endif
-
-
-static void *
-ngx_http_upstream_keepalive_create_conf(ngx_conf_t *cf)
-{
- ngx_http_upstream_keepalive_srv_conf_t *conf;
-
- conf = ngx_pcalloc(cf->pool,
- sizeof(ngx_http_upstream_keepalive_srv_conf_t));
- if (conf == NULL) {
- return NULL;
- }
-
- /*
- * set by ngx_pcalloc():
- *
- * conf->original_init_upstream = NULL;
- * conf->original_init_peer = NULL;
- * conf->max_cached = 0;
- */
-
- return conf;
-}
-
-
-static char *
-ngx_http_upstream_keepalive(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
-{
- ngx_http_upstream_srv_conf_t *uscf;
- ngx_http_upstream_keepalive_srv_conf_t *kcf = conf;
-
- ngx_int_t n;
- ngx_str_t *value;
-
- if (kcf->max_cached) {
- return "is duplicate";
- }
-
- /* read options */
-
- value = cf->args->elts;
-
- n = ngx_atoi(value[1].data, value[1].len);
-
- if (n == NGX_ERROR || n == 0) {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "invalid value \"%V\" in \"%V\" directive",
- &value[1], &cmd->name);
- return NGX_CONF_ERROR;
- }
-
- kcf->max_cached = n;
-
- uscf = ngx_http_conf_get_module_srv_conf(cf, ngx_http_upstream_module);
-
- kcf->original_init_upstream = uscf->peer.init_upstream
- ? uscf->peer.init_upstream
- : ngx_http_upstream_init_round_robin;
-
- uscf->peer.init_upstream = ngx_http_upstream_init_keepalive;
-
- return NGX_CONF_OK;
-}
diff --git a/nginx/src/http/modules/ngx_http_upstream_least_conn_module.c b/nginx/src/http/modules/ngx_http_upstream_least_conn_module.c
deleted file mode 100644
index ebe0627..0000000
--- a/nginx/src/http/modules/ngx_http_upstream_least_conn_module.c
+++ /dev/null
@@ -1,314 +0,0 @@
-
-/*
- * Copyright (C) Maxim Dounin
- * Copyright (C) Nginx, Inc.
- */
-
-
-#include <ngx_config.h>
-#include <ngx_core.h>
-#include <ngx_http.h>
-
-
-static ngx_int_t ngx_http_upstream_init_least_conn_peer(ngx_http_request_t *r,
- ngx_http_upstream_srv_conf_t *us);
-static ngx_int_t ngx_http_upstream_get_least_conn_peer(
- ngx_peer_connection_t *pc, void *data);
-static char *ngx_http_upstream_least_conn(ngx_conf_t *cf, ngx_command_t *cmd,
- void *conf);
-
-
-static ngx_command_t ngx_http_upstream_least_conn_commands[] = {
-
- { ngx_string("least_conn"),
- NGX_HTTP_UPS_CONF|NGX_CONF_NOARGS,
- ngx_http_upstream_least_conn,
- 0,
- 0,
- NULL },
-
- ngx_null_command
-};
-
-
-static ngx_http_module_t ngx_http_upstream_least_conn_module_ctx = {
- NULL, /* preconfiguration */
- NULL, /* postconfiguration */
-
- NULL, /* create main configuration */
- NULL, /* init main configuration */
-
- NULL, /* create server configuration */
- NULL, /* merge server configuration */
-
- NULL, /* create location configuration */
- NULL /* merge location configuration */
-};
-
-
-ngx_module_t ngx_http_upstream_least_conn_module = {
- NGX_MODULE_V1,
- &ngx_http_upstream_least_conn_module_ctx, /* module context */
- ngx_http_upstream_least_conn_commands, /* module directives */
- NGX_HTTP_MODULE, /* module type */
- NULL, /* init master */
- NULL, /* init module */
- NULL, /* init process */
- NULL, /* init thread */
- NULL, /* exit thread */
- NULL, /* exit process */
- NULL, /* exit master */
- NGX_MODULE_V1_PADDING
-};
-
-
-static ngx_int_t
-ngx_http_upstream_init_least_conn(ngx_conf_t *cf,
- ngx_http_upstream_srv_conf_t *us)
-{
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, cf->log, 0,
- "init least conn");
-
- if (ngx_http_upstream_init_round_robin(cf, us) != NGX_OK) {
- return NGX_ERROR;
- }
-
- us->peer.init = ngx_http_upstream_init_least_conn_peer;
-
- return NGX_OK;
-}
-
-
-static ngx_int_t
-ngx_http_upstream_init_least_conn_peer(ngx_http_request_t *r,
- ngx_http_upstream_srv_conf_t *us)
-{
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "init least conn peer");
-
- if (ngx_http_upstream_init_round_robin_peer(r, us) != NGX_OK) {
- return NGX_ERROR;
- }
-
- r->upstream->peer.get = ngx_http_upstream_get_least_conn_peer;
-
- return NGX_OK;
-}
-
-
-static ngx_int_t
-ngx_http_upstream_get_least_conn_peer(ngx_peer_connection_t *pc, void *data)
-{
- ngx_http_upstream_rr_peer_data_t *rrp = data;
-
- time_t now;
- uintptr_t m;
- ngx_int_t rc, total;
- ngx_uint_t i, n, p, many;
- ngx_http_upstream_rr_peer_t *peer, *best;
- ngx_http_upstream_rr_peers_t *peers;
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, pc->log, 0,
- "get least conn peer, try: %ui", pc->tries);
-
- if (rrp->peers->single) {
- return ngx_http_upstream_get_round_robin_peer(pc, rrp);
- }
-
- pc->cached = 0;
- pc->connection = NULL;
-
- now = ngx_time();
-
- peers = rrp->peers;
-
- ngx_http_upstream_rr_peers_wlock(peers);
-
- best = NULL;
- total = 0;
-
-#if (NGX_SUPPRESS_WARN)
- many = 0;
- p = 0;
-#endif
-
- for (peer = peers->peer, i = 0;
- peer;
- peer = peer->next, i++)
- {
- n = i / (8 * sizeof(uintptr_t));
- m = (uintptr_t) 1 << i % (8 * sizeof(uintptr_t));
-
- if (rrp->tried[n] & m) {
- continue;
- }
-
- if (peer->down) {
- continue;
- }
-
- if (peer->max_fails
- && peer->fails >= peer->max_fails
- && now - peer->checked <= peer->fail_timeout)
- {
- continue;
- }
-
- if (peer->max_conns && peer->conns >= peer->max_conns) {
- continue;
- }
-
- /*
- * select peer with least number of connections; if there are
- * multiple peers with the same number of connections, select
- * based on round-robin
- */
-
- if (best == NULL
- || peer->conns * best->weight < best->conns * peer->weight)
- {
- best = peer;
- many = 0;
- p = i;
-
- } else if (peer->conns * best->weight == best->conns * peer->weight) {
- many = 1;
- }
- }
-
- if (best == NULL) {
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, pc->log, 0,
- "get least conn peer, no peer found");
-
- goto failed;
- }
-
- if (many) {
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, pc->log, 0,
- "get least conn peer, many");
-
- for (peer = best, i = p;
- peer;
- peer = peer->next, i++)
- {
- n = i / (8 * sizeof(uintptr_t));
- m = (uintptr_t) 1 << i % (8 * sizeof(uintptr_t));
-
- if (rrp->tried[n] & m) {
- continue;
- }
-
- if (peer->down) {
- continue;
- }
-
- if (peer->conns * best->weight != best->conns * peer->weight) {
- continue;
- }
-
- if (peer->max_fails
- && peer->fails >= peer->max_fails
- && now - peer->checked <= peer->fail_timeout)
- {
- continue;
- }
-
- if (peer->max_conns && peer->conns >= peer->max_conns) {
- continue;
- }
-
- peer->current_weight += peer->effective_weight;
- total += peer->effective_weight;
-
- if (peer->effective_weight < peer->weight) {
- peer->effective_weight++;
- }
-
- if (peer->current_weight > best->current_weight) {
- best = peer;
- p = i;
- }
- }
- }
-
- best->current_weight -= total;
-
- if (now - best->checked > best->fail_timeout) {
- best->checked = now;
- }
-
- pc->sockaddr = best->sockaddr;
- pc->socklen = best->socklen;
- pc->name = &best->name;
-
- best->conns++;
-
- rrp->current = best;
-
- n = p / (8 * sizeof(uintptr_t));
- m = (uintptr_t) 1 << p % (8 * sizeof(uintptr_t));
-
- rrp->tried[n] |= m;
-
- ngx_http_upstream_rr_peers_unlock(peers);
-
- return NGX_OK;
-
-failed:
-
- if (peers->next) {
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, pc->log, 0,
- "get least conn peer, backup servers");
-
- rrp->peers = peers->next;
-
- n = (rrp->peers->number + (8 * sizeof(uintptr_t) - 1))
- / (8 * sizeof(uintptr_t));
-
- for (i = 0; i < n; i++) {
- rrp->tried[i] = 0;
- }
-
- ngx_http_upstream_rr_peers_unlock(peers);
-
- rc = ngx_http_upstream_get_least_conn_peer(pc, rrp);
-
- if (rc != NGX_BUSY) {
- return rc;
- }
-
- ngx_http_upstream_rr_peers_wlock(peers);
- }
-
- ngx_http_upstream_rr_peers_unlock(peers);
-
- pc->name = peers->name;
-
- return NGX_BUSY;
-}
-
-
-static char *
-ngx_http_upstream_least_conn(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
-{
- ngx_http_upstream_srv_conf_t *uscf;
-
- uscf = ngx_http_conf_get_module_srv_conf(cf, ngx_http_upstream_module);
-
- if (uscf->peer.init_upstream) {
- ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
- "load balancing method redefined");
- }
-
- uscf->peer.init_upstream = ngx_http_upstream_init_least_conn;
-
- uscf->flags = NGX_HTTP_UPSTREAM_CREATE
- |NGX_HTTP_UPSTREAM_WEIGHT
- |NGX_HTTP_UPSTREAM_MAX_CONNS
- |NGX_HTTP_UPSTREAM_MAX_FAILS
- |NGX_HTTP_UPSTREAM_FAIL_TIMEOUT
- |NGX_HTTP_UPSTREAM_DOWN
- |NGX_HTTP_UPSTREAM_BACKUP;
-
- return NGX_CONF_OK;
-}
diff --git a/nginx/src/http/modules/ngx_http_upstream_zone_module.c b/nginx/src/http/modules/ngx_http_upstream_zone_module.c
deleted file mode 100644
index 3229cfe..0000000
--- a/nginx/src/http/modules/ngx_http_upstream_zone_module.c
+++ /dev/null
@@ -1,325 +0,0 @@
-
-/*
- * Copyright (C) Ruslan Ermilov
- * Copyright (C) Nginx, Inc.
- */
-
-
-#include <ngx_config.h>
-#include <ngx_core.h>
-#include <ngx_http.h>
-
-
-static char *ngx_http_upstream_zone(ngx_conf_t *cf, ngx_command_t *cmd,
- void *conf);
-static ngx_int_t ngx_http_upstream_init_zone(ngx_shm_zone_t *shm_zone,
- void *data);
-static ngx_http_upstream_rr_peers_t *ngx_http_upstream_zone_copy_peers(
- ngx_slab_pool_t *shpool, ngx_http_upstream_srv_conf_t *uscf);
-static ngx_http_upstream_rr_peer_t *ngx_http_upstream_zone_copy_peer(
- ngx_http_upstream_rr_peers_t *peers, ngx_http_upstream_rr_peer_t *src);
-
-
-static ngx_command_t ngx_http_upstream_zone_commands[] = {
-
- { ngx_string("zone"),
- NGX_HTTP_UPS_CONF|NGX_CONF_TAKE12,
- ngx_http_upstream_zone,
- 0,
- 0,
- NULL },
-
- ngx_null_command
-};
-
-
-static ngx_http_module_t ngx_http_upstream_zone_module_ctx = {
- NULL, /* preconfiguration */
- NULL, /* postconfiguration */
-
- NULL, /* create main configuration */
- NULL, /* init main configuration */
-
- NULL, /* create server configuration */
- NULL, /* merge server configuration */
-
- NULL, /* create location configuration */
- NULL /* merge location configuration */
-};
-
-
-ngx_module_t ngx_http_upstream_zone_module = {
- NGX_MODULE_V1,
- &ngx_http_upstream_zone_module_ctx, /* module context */
- ngx_http_upstream_zone_commands, /* module directives */
- NGX_HTTP_MODULE, /* module type */
- NULL, /* init master */
- NULL, /* init module */
- NULL, /* init process */
- NULL, /* init thread */
- NULL, /* exit thread */
- NULL, /* exit process */
- NULL, /* exit master */
- NGX_MODULE_V1_PADDING
-};
-
-
-static char *
-ngx_http_upstream_zone(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
-{
- ssize_t size;
- ngx_str_t *value;
- ngx_http_upstream_srv_conf_t *uscf;
- ngx_http_upstream_main_conf_t *umcf;
-
- uscf = ngx_http_conf_get_module_srv_conf(cf, ngx_http_upstream_module);
- umcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_upstream_module);
-
- value = cf->args->elts;
-
- if (!value[1].len) {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "invalid zone name \"%V\"", &value[1]);
- return NGX_CONF_ERROR;
- }
-
- if (cf->args->nelts == 3) {
- size = ngx_parse_size(&value[2]);
-
- if (size == NGX_ERROR) {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "invalid zone size \"%V\"", &value[2]);
- return NGX_CONF_ERROR;
- }
-
- if (size < (ssize_t) (8 * ngx_pagesize)) {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "zone \"%V\" is too small", &value[1]);
- return NGX_CONF_ERROR;
- }
-
- } else {
- size = 0;
- }
-
- uscf->shm_zone = ngx_shared_memory_add(cf, &value[1], size,
- &ngx_http_upstream_module);
- if (uscf->shm_zone == NULL) {
- return NGX_CONF_ERROR;
- }
-
- uscf->shm_zone->init = ngx_http_upstream_init_zone;
- uscf->shm_zone->data = umcf;
-
- uscf->shm_zone->noreuse = 1;
-
- return NGX_CONF_OK;
-}
-
-
-static ngx_int_t
-ngx_http_upstream_init_zone(ngx_shm_zone_t *shm_zone, void *data)
-{
- size_t len;
- ngx_uint_t i;
- ngx_slab_pool_t *shpool;
- ngx_http_upstream_rr_peers_t *peers, **peersp;
- ngx_http_upstream_srv_conf_t *uscf, **uscfp;
- ngx_http_upstream_main_conf_t *umcf;
-
- shpool = (ngx_slab_pool_t *) shm_zone->shm.addr;
- umcf = shm_zone->data;
- uscfp = umcf->upstreams.elts;
-
- if (shm_zone->shm.exists) {
- peers = shpool->data;
-
- for (i = 0; i < umcf->upstreams.nelts; i++) {
- uscf = uscfp[i];
-
- if (uscf->shm_zone != shm_zone) {
- continue;
- }
-
- uscf->peer.data = peers;
- peers = peers->zone_next;
- }
-
- return NGX_OK;
- }
-
- len = sizeof(" in upstream zone \"\"") + shm_zone->shm.name.len;
-
- shpool->log_ctx = ngx_slab_alloc(shpool, len);
- if (shpool->log_ctx == NULL) {
- return NGX_ERROR;
- }
-
- ngx_sprintf(shpool->log_ctx, " in upstream zone \"%V\"%Z",
- &shm_zone->shm.name);
-
-
- /* copy peers to shared memory */
-
- peersp = (ngx_http_upstream_rr_peers_t **) (void *) &shpool->data;
-
- for (i = 0; i < umcf->upstreams.nelts; i++) {
- uscf = uscfp[i];
-
- if (uscf->shm_zone != shm_zone) {
- continue;
- }
-
- peers = ngx_http_upstream_zone_copy_peers(shpool, uscf);
- if (peers == NULL) {
- return NGX_ERROR;
- }
-
- *peersp = peers;
- peersp = &peers->zone_next;
- }
-
- return NGX_OK;
-}
-
-
-static ngx_http_upstream_rr_peers_t *
-ngx_http_upstream_zone_copy_peers(ngx_slab_pool_t *shpool,
- ngx_http_upstream_srv_conf_t *uscf)
-{
- ngx_str_t *name;
- ngx_http_upstream_rr_peer_t *peer, **peerp;
- ngx_http_upstream_rr_peers_t *peers, *backup;
-
- peers = ngx_slab_alloc(shpool, sizeof(ngx_http_upstream_rr_peers_t));
- if (peers == NULL) {
- return NULL;
- }
-
- ngx_memcpy(peers, uscf->peer.data, sizeof(ngx_http_upstream_rr_peers_t));
-
- name = ngx_slab_alloc(shpool, sizeof(ngx_str_t));
- if (name == NULL) {
- return NULL;
- }
-
- name->data = ngx_slab_alloc(shpool, peers->name->len);
- if (name->data == NULL) {
- return NULL;
- }
-
- ngx_memcpy(name->data, peers->name->data, peers->name->len);
- name->len = peers->name->len;
-
- peers->name = name;
-
- peers->shpool = shpool;
-
- for (peerp = &peers->peer; *peerp; peerp = &peer->next) {
- /* pool is unlocked */
- peer = ngx_http_upstream_zone_copy_peer(peers, *peerp);
- if (peer == NULL) {
- return NULL;
- }
-
- *peerp = peer;
- }
-
- if (peers->next == NULL) {
- goto done;
- }
-
- backup = ngx_slab_alloc(shpool, sizeof(ngx_http_upstream_rr_peers_t));
- if (backup == NULL) {
- return NULL;
- }
-
- ngx_memcpy(backup, peers->next, sizeof(ngx_http_upstream_rr_peers_t));
-
- backup->name = name;
-
- backup->shpool = shpool;
-
- for (peerp = &backup->peer; *peerp; peerp = &peer->next) {
- /* pool is unlocked */
- peer = ngx_http_upstream_zone_copy_peer(backup, *peerp);
- if (peer == NULL) {
- return NULL;
- }
-
- *peerp = peer;
- }
-
- peers->next = backup;
-
-done:
-
- uscf->peer.data = peers;
-
- return peers;
-}
-
-
-static ngx_http_upstream_rr_peer_t *
-ngx_http_upstream_zone_copy_peer(ngx_http_upstream_rr_peers_t *peers,
- ngx_http_upstream_rr_peer_t *src)
-{
- ngx_slab_pool_t *pool;
- ngx_http_upstream_rr_peer_t *dst;
-
- pool = peers->shpool;
-
- dst = ngx_slab_calloc_locked(pool, sizeof(ngx_http_upstream_rr_peer_t));
- if (dst == NULL) {
- return NULL;
- }
-
- if (src) {
- ngx_memcpy(dst, src, sizeof(ngx_http_upstream_rr_peer_t));
- dst->sockaddr = NULL;
- dst->name.data = NULL;
- dst->server.data = NULL;
- }
-
- dst->sockaddr = ngx_slab_calloc_locked(pool, sizeof(ngx_sockaddr_t));
- if (dst->sockaddr == NULL) {
- goto failed;
- }
-
- dst->name.data = ngx_slab_calloc_locked(pool, NGX_SOCKADDR_STRLEN);
- if (dst->name.data == NULL) {
- goto failed;
- }
-
- if (src) {
- ngx_memcpy(dst->sockaddr, src->sockaddr, src->socklen);
- ngx_memcpy(dst->name.data, src->name.data, src->name.len);
-
- dst->server.data = ngx_slab_alloc_locked(pool, src->server.len);
- if (dst->server.data == NULL) {
- goto failed;
- }
-
- ngx_memcpy(dst->server.data, src->server.data, src->server.len);
- }
-
- return dst;
-
-failed:
-
- if (dst->server.data) {
- ngx_slab_free_locked(pool, dst->server.data);
- }
-
- if (dst->name.data) {
- ngx_slab_free_locked(pool, dst->name.data);
- }
-
- if (dst->sockaddr) {
- ngx_slab_free_locked(pool, dst->sockaddr);
- }
-
- ngx_slab_free_locked(pool, dst);
-
- return NULL;
-}
diff --git a/nginx/src/http/modules/ngx_http_userid_filter_module.c b/nginx/src/http/modules/ngx_http_userid_filter_module.c
deleted file mode 100644
index a1a5493..0000000
--- a/nginx/src/http/modules/ngx_http_userid_filter_module.c
+++ /dev/null
@@ -1,846 +0,0 @@
-
-/*
- * Copyright (C) Igor Sysoev
- * Copyright (C) Nginx, Inc.
- */
-
-
-#include <ngx_config.h>
-#include <ngx_core.h>
-#include <ngx_http.h>
-
-
-#define NGX_HTTP_USERID_OFF 0
-#define NGX_HTTP_USERID_LOG 1
-#define NGX_HTTP_USERID_V1 2
-#define NGX_HTTP_USERID_ON 3
-
-/* 31 Dec 2037 23:55:55 GMT */
-#define NGX_HTTP_USERID_MAX_EXPIRES 2145916555
-
-
-typedef struct {
- ngx_uint_t enable;
-
- ngx_int_t service;
-
- ngx_str_t name;
- ngx_str_t domain;
- ngx_str_t path;
- ngx_str_t p3p;
-
- time_t expires;
-
- u_char mark;
-} ngx_http_userid_conf_t;
-
-
-typedef struct {
- uint32_t uid_got[4];
- uint32_t uid_set[4];
- ngx_str_t cookie;
- ngx_uint_t reset;
-} ngx_http_userid_ctx_t;
-
-
-static ngx_http_userid_ctx_t *ngx_http_userid_get_uid(ngx_http_request_t *r,
- ngx_http_userid_conf_t *conf);
-static ngx_int_t ngx_http_userid_variable(ngx_http_request_t *r,
- ngx_http_variable_value_t *v, ngx_str_t *name, uint32_t *uid);
-static ngx_int_t ngx_http_userid_set_uid(ngx_http_request_t *r,
- ngx_http_userid_ctx_t *ctx, ngx_http_userid_conf_t *conf);
-static ngx_int_t ngx_http_userid_create_uid(ngx_http_request_t *r,
- ngx_http_userid_ctx_t *ctx, ngx_http_userid_conf_t *conf);
-
-static ngx_int_t ngx_http_userid_add_variables(ngx_conf_t *cf);
-static ngx_int_t ngx_http_userid_init(ngx_conf_t *cf);
-static void *ngx_http_userid_create_conf(ngx_conf_t *cf);
-static char *ngx_http_userid_merge_conf(ngx_conf_t *cf, void *parent,
- void *child);
-static char *ngx_http_userid_domain(ngx_conf_t *cf, void *post, void *data);
-static char *ngx_http_userid_path(ngx_conf_t *cf, void *post, void *data);
-static char *ngx_http_userid_expires(ngx_conf_t *cf, ngx_command_t *cmd,
- void *conf);
-static char *ngx_http_userid_p3p(ngx_conf_t *cf, void *post, void *data);
-static char *ngx_http_userid_mark(ngx_conf_t *cf, ngx_command_t *cmd,
- void *conf);
-static ngx_int_t ngx_http_userid_init_worker(ngx_cycle_t *cycle);
-
-
-
-static uint32_t start_value;
-static uint32_t sequencer_v1 = 1;
-static uint32_t sequencer_v2 = 0x03030302;
-
-
-static u_char expires[] = "; expires=Thu, 31-Dec-37 23:55:55 GMT";
-
-
-static ngx_http_output_header_filter_pt ngx_http_next_header_filter;
-
-
-static ngx_conf_enum_t ngx_http_userid_state[] = {
- { ngx_string("off"), NGX_HTTP_USERID_OFF },
- { ngx_string("log"), NGX_HTTP_USERID_LOG },
- { ngx_string("v1"), NGX_HTTP_USERID_V1 },
- { ngx_string("on"), NGX_HTTP_USERID_ON },
- { ngx_null_string, 0 }
-};
-
-
-static ngx_conf_post_handler_pt ngx_http_userid_domain_p =
- ngx_http_userid_domain;
-static ngx_conf_post_handler_pt ngx_http_userid_path_p = ngx_http_userid_path;
-static ngx_conf_post_handler_pt ngx_http_userid_p3p_p = ngx_http_userid_p3p;
-
-
-static ngx_command_t ngx_http_userid_commands[] = {
-
- { ngx_string("userid"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_enum_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_userid_conf_t, enable),
- ngx_http_userid_state },
-
- { ngx_string("userid_service"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_num_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_userid_conf_t, service),
- NULL },
-
- { ngx_string("userid_name"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_str_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_userid_conf_t, name),
- NULL },
-
- { ngx_string("userid_domain"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_str_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_userid_conf_t, domain),
- &ngx_http_userid_domain_p },
-
- { ngx_string("userid_path"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_str_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_userid_conf_t, path),
- &ngx_http_userid_path_p },
-
- { ngx_string("userid_expires"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_http_userid_expires,
- NGX_HTTP_LOC_CONF_OFFSET,
- 0,
- NULL },
-
- { ngx_string("userid_p3p"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_str_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_userid_conf_t, p3p),
- &ngx_http_userid_p3p_p },
-
- { ngx_string("userid_mark"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_http_userid_mark,
- NGX_HTTP_LOC_CONF_OFFSET,
- 0,
- NULL },
-
- ngx_null_command
-};
-
-
-static ngx_http_module_t ngx_http_userid_filter_module_ctx = {
- ngx_http_userid_add_variables, /* preconfiguration */
- ngx_http_userid_init, /* postconfiguration */
-
- NULL, /* create main configuration */
- NULL, /* init main configuration */
-
- NULL, /* create server configuration */
- NULL, /* merge server configuration */
-
- ngx_http_userid_create_conf, /* create location configuration */
- ngx_http_userid_merge_conf /* merge location configuration */
-};
-
-
-ngx_module_t ngx_http_userid_filter_module = {
- NGX_MODULE_V1,
- &ngx_http_userid_filter_module_ctx, /* module context */
- ngx_http_userid_commands, /* module directives */
- NGX_HTTP_MODULE, /* module type */
- NULL, /* init master */
- NULL, /* init module */
- ngx_http_userid_init_worker, /* init process */
- NULL, /* init thread */
- NULL, /* exit thread */
- NULL, /* exit process */
- NULL, /* exit master */
- NGX_MODULE_V1_PADDING
-};
-
-
-static ngx_str_t ngx_http_userid_got = ngx_string("uid_got");
-static ngx_str_t ngx_http_userid_set = ngx_string("uid_set");
-static ngx_str_t ngx_http_userid_reset = ngx_string("uid_reset");
-static ngx_uint_t ngx_http_userid_reset_index;
-
-
-static ngx_int_t
-ngx_http_userid_filter(ngx_http_request_t *r)
-{
- ngx_http_userid_ctx_t *ctx;
- ngx_http_userid_conf_t *conf;
-
- if (r != r->main) {
- return ngx_http_next_header_filter(r);
- }
-
- conf = ngx_http_get_module_loc_conf(r, ngx_http_userid_filter_module);
-
- if (conf->enable < NGX_HTTP_USERID_V1) {
- return ngx_http_next_header_filter(r);
- }
-
- ctx = ngx_http_userid_get_uid(r, conf);
-
- if (ctx == NULL) {
- return NGX_ERROR;
- }
-
- if (ngx_http_userid_set_uid(r, ctx, conf) == NGX_OK) {
- return ngx_http_next_header_filter(r);
- }
-
- return NGX_ERROR;
-}
-
-
-static ngx_int_t
-ngx_http_userid_got_variable(ngx_http_request_t *r,
- ngx_http_variable_value_t *v, uintptr_t data)
-{
- ngx_http_userid_ctx_t *ctx;
- ngx_http_userid_conf_t *conf;
-
- conf = ngx_http_get_module_loc_conf(r->main, ngx_http_userid_filter_module);
-
- if (conf->enable == NGX_HTTP_USERID_OFF) {
- v->not_found = 1;
- return NGX_OK;
- }
-
- ctx = ngx_http_userid_get_uid(r->main, conf);
-
- if (ctx == NULL) {
- return NGX_ERROR;
- }
-
- if (ctx->uid_got[3] != 0) {
- return ngx_http_userid_variable(r->main, v, &conf->name, ctx->uid_got);
- }
-
- v->not_found = 1;
-
- return NGX_OK;
-}
-
-
-static ngx_int_t
-ngx_http_userid_set_variable(ngx_http_request_t *r,
- ngx_http_variable_value_t *v, uintptr_t data)
-{
- ngx_http_userid_ctx_t *ctx;
- ngx_http_userid_conf_t *conf;
-
- conf = ngx_http_get_module_loc_conf(r->main, ngx_http_userid_filter_module);
-
- if (conf->enable < NGX_HTTP_USERID_V1) {
- v->not_found = 1;
- return NGX_OK;
- }
-
- ctx = ngx_http_userid_get_uid(r->main, conf);
-
- if (ctx == NULL) {
- return NGX_ERROR;
- }
-
- if (ngx_http_userid_create_uid(r->main, ctx, conf) != NGX_OK) {
- return NGX_ERROR;
- }
-
- if (ctx->uid_set[3] == 0) {
- v->not_found = 1;
- return NGX_OK;
- }
-
- return ngx_http_userid_variable(r->main, v, &conf->name, ctx->uid_set);
-}
-
-
-static ngx_http_userid_ctx_t *
-ngx_http_userid_get_uid(ngx_http_request_t *r, ngx_http_userid_conf_t *conf)
-{
- ngx_int_t n;
- ngx_str_t src, dst;
- ngx_table_elt_t **cookies;
- ngx_http_userid_ctx_t *ctx;
-
- ctx = ngx_http_get_module_ctx(r, ngx_http_userid_filter_module);
-
- if (ctx) {
- return ctx;
- }
-
- if (ctx == NULL) {
- ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_userid_ctx_t));
- if (ctx == NULL) {
- return NULL;
- }
-
- ngx_http_set_ctx(r, ctx, ngx_http_userid_filter_module);
- }
-
- n = ngx_http_parse_multi_header_lines(&r->headers_in.cookies, &conf->name,
- &ctx->cookie);
- if (n == NGX_DECLINED) {
- return ctx;
- }
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "uid cookie: \"%V\"", &ctx->cookie);
-
- if (ctx->cookie.len < 22) {
- cookies = r->headers_in.cookies.elts;
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "client sent too short userid cookie \"%V\"",
- &cookies[n]->value);
- return ctx;
- }
-
- src = ctx->cookie;
-
- /*
- * we have to limit the encoded string to 22 characters because
- * 1) cookie may be marked by "userid_mark",
- * 2) and there are already the millions cookies with a garbage
- * instead of the correct base64 trail "=="
- */
-
- src.len = 22;
-
- dst.data = (u_char *) ctx->uid_got;
-
- if (ngx_decode_base64(&dst, &src) == NGX_ERROR) {
- cookies = r->headers_in.cookies.elts;
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "client sent invalid userid cookie \"%V\"",
- &cookies[n]->value);
- return ctx;
- }
-
- ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "uid: %08XD%08XD%08XD%08XD",
- ctx->uid_got[0], ctx->uid_got[1],
- ctx->uid_got[2], ctx->uid_got[3]);
-
- return ctx;
-}
-
-
-static ngx_int_t
-ngx_http_userid_set_uid(ngx_http_request_t *r, ngx_http_userid_ctx_t *ctx,
- ngx_http_userid_conf_t *conf)
-{
- u_char *cookie, *p;
- size_t len;
- ngx_str_t src, dst;
- ngx_table_elt_t *set_cookie, *p3p;
-
- if (ngx_http_userid_create_uid(r, ctx, conf) != NGX_OK) {
- return NGX_ERROR;
- }
-
- if (ctx->uid_set[3] == 0) {
- return NGX_OK;
- }
-
- len = conf->name.len + 1 + ngx_base64_encoded_length(16) + conf->path.len;
-
- if (conf->expires) {
- len += sizeof(expires) - 1 + 2;
- }
-
- if (conf->domain.len) {
- len += conf->domain.len;
- }
-
- cookie = ngx_pnalloc(r->pool, len);
- if (cookie == NULL) {
- return NGX_ERROR;
- }
-
- p = ngx_copy(cookie, conf->name.data, conf->name.len);
- *p++ = '=';
-
- if (ctx->uid_got[3] == 0 || ctx->reset) {
- src.len = 16;
- src.data = (u_char *) ctx->uid_set;
- dst.data = p;
-
- ngx_encode_base64(&dst, &src);
-
- p += dst.len;
-
- if (conf->mark) {
- *(p - 2) = conf->mark;
- }
-
- } else {
- p = ngx_cpymem(p, ctx->cookie.data, 22);
- *p++ = conf->mark;
- *p++ = '=';
- }
-
- if (conf->expires == NGX_HTTP_USERID_MAX_EXPIRES) {
- p = ngx_cpymem(p, expires, sizeof(expires) - 1);
-
- } else if (conf->expires) {
- p = ngx_cpymem(p, expires, sizeof("; expires=") - 1);
- p = ngx_http_cookie_time(p, ngx_time() + conf->expires);
- }
-
- p = ngx_copy(p, conf->domain.data, conf->domain.len);
-
- p = ngx_copy(p, conf->path.data, conf->path.len);
-
- set_cookie = ngx_list_push(&r->headers_out.headers);
- if (set_cookie == NULL) {
- return NGX_ERROR;
- }
-
- set_cookie->hash = 1;
- ngx_str_set(&set_cookie->key, "Set-Cookie");
- set_cookie->value.len = p - cookie;
- set_cookie->value.data = cookie;
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "uid cookie: \"%V\"", &set_cookie->value);
-
- if (conf->p3p.len == 0) {
- return NGX_OK;
- }
-
- p3p = ngx_list_push(&r->headers_out.headers);
- if (p3p == NULL) {
- return NGX_ERROR;
- }
-
- p3p->hash = 1;
- ngx_str_set(&p3p->key, "P3P");
- p3p->value = conf->p3p;
-
- return NGX_OK;
-}
-
-
-static ngx_int_t
-ngx_http_userid_create_uid(ngx_http_request_t *r, ngx_http_userid_ctx_t *ctx,
- ngx_http_userid_conf_t *conf)
-{
- ngx_connection_t *c;
- struct sockaddr_in *sin;
- ngx_http_variable_value_t *vv;
-#if (NGX_HAVE_INET6)
- u_char *p;
- struct sockaddr_in6 *sin6;
-#endif
-
- if (ctx->uid_set[3] != 0) {
- return NGX_OK;
- }
-
- if (ctx->uid_got[3] != 0) {
-
- vv = ngx_http_get_indexed_variable(r, ngx_http_userid_reset_index);
-
- if (vv == NULL || vv->not_found) {
- return NGX_ERROR;
- }
-
- if (vv->len == 0 || (vv->len == 1 && vv->data[0] == '0')) {
-
- if (conf->mark == '\0'
- || (ctx->cookie.len > 23
- && ctx->cookie.data[22] == conf->mark
- && ctx->cookie.data[23] == '='))
- {
- return NGX_OK;
- }
-
- ctx->uid_set[0] = ctx->uid_got[0];
- ctx->uid_set[1] = ctx->uid_got[1];
- ctx->uid_set[2] = ctx->uid_got[2];
- ctx->uid_set[3] = ctx->uid_got[3];
-
- return NGX_OK;
-
- } else {
- ctx->reset = 1;
-
- if (vv->len == 3 && ngx_strncmp(vv->data, "log", 3) == 0) {
- ngx_log_error(NGX_LOG_NOTICE, r->connection->log, 0,
- "userid cookie \"%V=%08XD%08XD%08XD%08XD\" was reset",
- &conf->name, ctx->uid_got[0], ctx->uid_got[1],
- ctx->uid_got[2], ctx->uid_got[3]);
- }
- }
- }
-
- /*
- * TODO: in the threaded mode the sequencers should be in TLS and their
- * ranges should be divided between threads
- */
-
- if (conf->enable == NGX_HTTP_USERID_V1) {
- if (conf->service == NGX_CONF_UNSET) {
- ctx->uid_set[0] = 0;
- } else {
- ctx->uid_set[0] = conf->service;
- }
- ctx->uid_set[1] = (uint32_t) ngx_time();
- ctx->uid_set[2] = start_value;
- ctx->uid_set[3] = sequencer_v1;
- sequencer_v1 += 0x100;
-
- } else {
- if (conf->service == NGX_CONF_UNSET) {
-
- c = r->connection;
-
- if (ngx_connection_local_sockaddr(c, NULL, 0) != NGX_OK) {
- return NGX_ERROR;
- }
-
- switch (c->local_sockaddr->sa_family) {
-
-#if (NGX_HAVE_INET6)
- case AF_INET6:
- sin6 = (struct sockaddr_in6 *) c->local_sockaddr;
-
- p = (u_char *) &ctx->uid_set[0];
-
- *p++ = sin6->sin6_addr.s6_addr[12];
- *p++ = sin6->sin6_addr.s6_addr[13];
- *p++ = sin6->sin6_addr.s6_addr[14];
- *p = sin6->sin6_addr.s6_addr[15];
-
- break;
-#endif
- default: /* AF_INET */
- sin = (struct sockaddr_in *) c->local_sockaddr;
- ctx->uid_set[0] = sin->sin_addr.s_addr;
- break;
- }
-
- } else {
- ctx->uid_set[0] = htonl(conf->service);
- }
-
- ctx->uid_set[1] = htonl((uint32_t) ngx_time());
- ctx->uid_set[2] = htonl(start_value);
- ctx->uid_set[3] = htonl(sequencer_v2);
- sequencer_v2 += 0x100;
- if (sequencer_v2 < 0x03030302) {
- sequencer_v2 = 0x03030302;
- }
- }
-
- return NGX_OK;
-}
-
-
-static ngx_int_t
-ngx_http_userid_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v,
- ngx_str_t *name, uint32_t *uid)
-{
- v->len = name->len + sizeof("=00001111222233334444555566667777") - 1;
- v->data = ngx_pnalloc(r->pool, v->len);
- if (v->data == NULL) {
- return NGX_ERROR;
- }
-
- v->valid = 1;
- v->no_cacheable = 0;
- v->not_found = 0;
-
- ngx_sprintf(v->data, "%V=%08XD%08XD%08XD%08XD",
- name, uid[0], uid[1], uid[2], uid[3]);
-
- return NGX_OK;
-}
-
-
-static ngx_int_t
-ngx_http_userid_reset_variable(ngx_http_request_t *r,
- ngx_http_variable_value_t *v, uintptr_t data)
-{
- *v = ngx_http_variable_null_value;
-
- return NGX_OK;
-}
-
-
-static ngx_int_t
-ngx_http_userid_add_variables(ngx_conf_t *cf)
-{
- ngx_int_t n;
- ngx_http_variable_t *var;
-
- var = ngx_http_add_variable(cf, &ngx_http_userid_got, 0);
- if (var == NULL) {
- return NGX_ERROR;
- }
-
- var->get_handler = ngx_http_userid_got_variable;
-
- var = ngx_http_add_variable(cf, &ngx_http_userid_set, 0);
- if (var == NULL) {
- return NGX_ERROR;
- }
-
- var->get_handler = ngx_http_userid_set_variable;
-
- var = ngx_http_add_variable(cf, &ngx_http_userid_reset,
- NGX_HTTP_VAR_CHANGEABLE);
- if (var == NULL) {
- return NGX_ERROR;
- }
-
- var->get_handler = ngx_http_userid_reset_variable;
-
- n = ngx_http_get_variable_index(cf, &ngx_http_userid_reset);
- if (n == NGX_ERROR) {
- return NGX_ERROR;
- }
-
- ngx_http_userid_reset_index = n;
-
- return NGX_OK;
-}
-
-
-static void *
-ngx_http_userid_create_conf(ngx_conf_t *cf)
-{
- ngx_http_userid_conf_t *conf;
-
- conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_userid_conf_t));
- if (conf == NULL) {
- return NULL;
- }
-
- /*
- * set by ngx_pcalloc():
- *
- * conf->name = { 0, NULL };
- * conf->domain = { 0, NULL };
- * conf->path = { 0, NULL };
- * conf->p3p = { 0, NULL };
- */
-
- conf->enable = NGX_CONF_UNSET_UINT;
- conf->service = NGX_CONF_UNSET;
- conf->expires = NGX_CONF_UNSET;
- conf->mark = (u_char) '\xFF';
-
- return conf;
-}
-
-
-static char *
-ngx_http_userid_merge_conf(ngx_conf_t *cf, void *parent, void *child)
-{
- ngx_http_userid_conf_t *prev = parent;
- ngx_http_userid_conf_t *conf = child;
-
- ngx_conf_merge_uint_value(conf->enable, prev->enable,
- NGX_HTTP_USERID_OFF);
-
- ngx_conf_merge_str_value(conf->name, prev->name, "uid");
- ngx_conf_merge_str_value(conf->domain, prev->domain, "");
- ngx_conf_merge_str_value(conf->path, prev->path, "; path=/");
- ngx_conf_merge_str_value(conf->p3p, prev->p3p, "");
-
- ngx_conf_merge_value(conf->service, prev->service, NGX_CONF_UNSET);
- ngx_conf_merge_sec_value(conf->expires, prev->expires, 0);
-
- if (conf->mark == (u_char) '\xFF') {
- if (prev->mark == (u_char) '\xFF') {
- conf->mark = '\0';
- } else {
- conf->mark = prev->mark;
- }
- }
-
- return NGX_CONF_OK;
-}
-
-
-static ngx_int_t
-ngx_http_userid_init(ngx_conf_t *cf)
-{
- ngx_http_next_header_filter = ngx_http_top_header_filter;
- ngx_http_top_header_filter = ngx_http_userid_filter;
-
- return NGX_OK;
-}
-
-
-static char *
-ngx_http_userid_domain(ngx_conf_t *cf, void *post, void *data)
-{
- ngx_str_t *domain = data;
-
- u_char *p, *new;
-
- if (ngx_strcmp(domain->data, "none") == 0) {
- ngx_str_set(domain, "");
- return NGX_CONF_OK;
- }
-
- new = ngx_pnalloc(cf->pool, sizeof("; domain=") - 1 + domain->len);
- if (new == NULL) {
- return NGX_CONF_ERROR;
- }
-
- p = ngx_cpymem(new, "; domain=", sizeof("; domain=") - 1);
- ngx_memcpy(p, domain->data, domain->len);
-
- domain->len += sizeof("; domain=") - 1;
- domain->data = new;
-
- return NGX_CONF_OK;
-}
-
-
-static char *
-ngx_http_userid_path(ngx_conf_t *cf, void *post, void *data)
-{
- ngx_str_t *path = data;
-
- u_char *p, *new;
-
- new = ngx_pnalloc(cf->pool, sizeof("; path=") - 1 + path->len);
- if (new == NULL) {
- return NGX_CONF_ERROR;
- }
-
- p = ngx_cpymem(new, "; path=", sizeof("; path=") - 1);
- ngx_memcpy(p, path->data, path->len);
-
- path->len += sizeof("; path=") - 1;
- path->data = new;
-
- return NGX_CONF_OK;
-}
-
-
-static char *
-ngx_http_userid_expires(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
-{
- ngx_http_userid_conf_t *ucf = conf;
-
- ngx_str_t *value;
-
- if (ucf->expires != NGX_CONF_UNSET) {
- return "is duplicate";
- }
-
- value = cf->args->elts;
-
- if (ngx_strcmp(value[1].data, "max") == 0) {
- ucf->expires = NGX_HTTP_USERID_MAX_EXPIRES;
- return NGX_CONF_OK;
- }
-
- if (ngx_strcmp(value[1].data, "off") == 0) {
- ucf->expires = 0;
- return NGX_CONF_OK;
- }
-
- ucf->expires = ngx_parse_time(&value[1], 1);
- if (ucf->expires == (time_t) NGX_ERROR) {
- return "invalid value";
- }
-
- return NGX_CONF_OK;
-}
-
-
-static char *
-ngx_http_userid_p3p(ngx_conf_t *cf, void *post, void *data)
-{
- ngx_str_t *p3p = data;
-
- if (ngx_strcmp(p3p->data, "none") == 0) {
- ngx_str_set(p3p, "");
- }
-
- return NGX_CONF_OK;
-}
-
-
-static char *
-ngx_http_userid_mark(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
-{
- ngx_http_userid_conf_t *ucf = conf;
-
- ngx_str_t *value;
-
- if (ucf->mark != (u_char) '\xFF') {
- return "is duplicate";
- }
-
- value = cf->args->elts;
-
- if (ngx_strcmp(value[1].data, "off") == 0) {
- ucf->mark = '\0';
- return NGX_CONF_OK;
- }
-
- if (value[1].len != 1
- || !((value[1].data[0] >= '0' && value[1].data[0] <= '9')
- || (value[1].data[0] >= 'A' && value[1].data[0] <= 'Z')
- || (value[1].data[0] >= 'a' && value[1].data[0] <= 'z')
- || value[1].data[0] == '='))
- {
- return "value must be \"off\" or a single letter, digit or \"=\"";
- }
-
- ucf->mark = value[1].data[0];
-
- return NGX_CONF_OK;
-}
-
-
-static ngx_int_t
-ngx_http_userid_init_worker(ngx_cycle_t *cycle)
-{
- struct timeval tp;
-
- ngx_gettimeofday(&tp);
-
- /* use the most significant usec part that fits to 16 bits */
- start_value = (((uint32_t) tp.tv_usec / 20) << 16) | ngx_pid;
-
- return NGX_OK;
-}
diff --git a/nginx/src/http/modules/ngx_http_uwsgi_module.c b/nginx/src/http/modules/ngx_http_uwsgi_module.c
deleted file mode 100644
index 238bcf8..0000000
--- a/nginx/src/http/modules/ngx_http_uwsgi_module.c
+++ /dev/null
@@ -1,2397 +0,0 @@
-
-/*
- * Copyright (C) Unbit S.a.s. 2009-2010
- * Copyright (C) 2008 Manlio Perillo (manlio.perillo@gmail.com)
- * Copyright (C) Igor Sysoev
- * Copyright (C) Nginx, Inc.
- */
-
-
-#include <ngx_config.h>
-#include <ngx_core.h>
-#include <ngx_http.h>
-
-
-typedef struct {
- ngx_array_t caches; /* ngx_http_file_cache_t * */
-} ngx_http_uwsgi_main_conf_t;
-
-
-typedef struct {
- ngx_array_t *flushes;
- ngx_array_t *lengths;
- ngx_array_t *values;
- ngx_uint_t number;
- ngx_hash_t hash;
-} ngx_http_uwsgi_params_t;
-
-
-typedef struct {
- ngx_http_upstream_conf_t upstream;
-
- ngx_http_uwsgi_params_t params;
-#if (NGX_HTTP_CACHE)
- ngx_http_uwsgi_params_t params_cache;
-#endif
- ngx_array_t *params_source;
-
- ngx_array_t *uwsgi_lengths;
- ngx_array_t *uwsgi_values;
-
-#if (NGX_HTTP_CACHE)
- ngx_http_complex_value_t cache_key;
-#endif
-
- ngx_str_t uwsgi_string;
-
- ngx_uint_t modifier1;
- ngx_uint_t modifier2;
-
-#if (NGX_HTTP_SSL)
- ngx_uint_t ssl;
- ngx_uint_t ssl_protocols;
- ngx_str_t ssl_ciphers;
- ngx_uint_t ssl_verify_depth;
- ngx_str_t ssl_trusted_certificate;
- ngx_str_t ssl_crl;
- ngx_str_t ssl_certificate;
- ngx_str_t ssl_certificate_key;
- ngx_array_t *ssl_passwords;
-#endif
-} ngx_http_uwsgi_loc_conf_t;
-
-
-static ngx_int_t ngx_http_uwsgi_eval(ngx_http_request_t *r,
- ngx_http_uwsgi_loc_conf_t *uwcf);
-static ngx_int_t ngx_http_uwsgi_create_request(ngx_http_request_t *r);
-static ngx_int_t ngx_http_uwsgi_reinit_request(ngx_http_request_t *r);
-static ngx_int_t ngx_http_uwsgi_process_status_line(ngx_http_request_t *r);
-static ngx_int_t ngx_http_uwsgi_process_header(ngx_http_request_t *r);
-static void ngx_http_uwsgi_abort_request(ngx_http_request_t *r);
-static void ngx_http_uwsgi_finalize_request(ngx_http_request_t *r,
- ngx_int_t rc);
-
-static void *ngx_http_uwsgi_create_main_conf(ngx_conf_t *cf);
-static void *ngx_http_uwsgi_create_loc_conf(ngx_conf_t *cf);
-static char *ngx_http_uwsgi_merge_loc_conf(ngx_conf_t *cf, void *parent,
- void *child);
-static ngx_int_t ngx_http_uwsgi_init_params(ngx_conf_t *cf,
- ngx_http_uwsgi_loc_conf_t *conf, ngx_http_uwsgi_params_t *params,
- ngx_keyval_t *default_params);
-
-static char *ngx_http_uwsgi_pass(ngx_conf_t *cf, ngx_command_t *cmd,
- void *conf);
-static char *ngx_http_uwsgi_store(ngx_conf_t *cf, ngx_command_t *cmd,
- void *conf);
-
-#if (NGX_HTTP_CACHE)
-static ngx_int_t ngx_http_uwsgi_create_key(ngx_http_request_t *r);
-static char *ngx_http_uwsgi_cache(ngx_conf_t *cf, ngx_command_t *cmd,
- void *conf);
-static char *ngx_http_uwsgi_cache_key(ngx_conf_t *cf, ngx_command_t *cmd,
- void *conf);
-#endif
-
-#if (NGX_HTTP_SSL)
-static char *ngx_http_uwsgi_ssl_password_file(ngx_conf_t *cf,
- ngx_command_t *cmd, void *conf);
-static ngx_int_t ngx_http_uwsgi_set_ssl(ngx_conf_t *cf,
- ngx_http_uwsgi_loc_conf_t *uwcf);
-#endif
-
-
-static ngx_conf_num_bounds_t ngx_http_uwsgi_modifier_bounds = {
- ngx_conf_check_num_bounds, 0, 255
-};
-
-
-static ngx_conf_bitmask_t ngx_http_uwsgi_next_upstream_masks[] = {
- { ngx_string("error"), NGX_HTTP_UPSTREAM_FT_ERROR },
- { ngx_string("timeout"), NGX_HTTP_UPSTREAM_FT_TIMEOUT },
- { ngx_string("invalid_header"), NGX_HTTP_UPSTREAM_FT_INVALID_HEADER },
- { ngx_string("non_idempotent"), NGX_HTTP_UPSTREAM_FT_NON_IDEMPOTENT },
- { ngx_string("http_500"), NGX_HTTP_UPSTREAM_FT_HTTP_500 },
- { ngx_string("http_503"), NGX_HTTP_UPSTREAM_FT_HTTP_503 },
- { ngx_string("http_403"), NGX_HTTP_UPSTREAM_FT_HTTP_403 },
- { ngx_string("http_404"), NGX_HTTP_UPSTREAM_FT_HTTP_404 },
- { ngx_string("http_429"), NGX_HTTP_UPSTREAM_FT_HTTP_429 },
- { ngx_string("updating"), NGX_HTTP_UPSTREAM_FT_UPDATING },
- { ngx_string("off"), NGX_HTTP_UPSTREAM_FT_OFF },
- { ngx_null_string, 0 }
-};
-
-
-#if (NGX_HTTP_SSL)
-
-static ngx_conf_bitmask_t ngx_http_uwsgi_ssl_protocols[] = {
- { ngx_string("SSLv2"), NGX_SSL_SSLv2 },
- { ngx_string("SSLv3"), NGX_SSL_SSLv3 },
- { ngx_string("TLSv1"), NGX_SSL_TLSv1 },
- { ngx_string("TLSv1.1"), NGX_SSL_TLSv1_1 },
- { ngx_string("TLSv1.2"), NGX_SSL_TLSv1_2 },
- { ngx_string("TLSv1.3"), NGX_SSL_TLSv1_3 },
- { ngx_null_string, 0 }
-};
-
-#endif
-
-
-ngx_module_t ngx_http_uwsgi_module;
-
-
-static ngx_command_t ngx_http_uwsgi_commands[] = {
-
- { ngx_string("uwsgi_pass"),
- NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF|NGX_CONF_TAKE1,
- ngx_http_uwsgi_pass,
- NGX_HTTP_LOC_CONF_OFFSET,
- 0,
- NULL },
-
- { ngx_string("uwsgi_modifier1"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_num_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_uwsgi_loc_conf_t, modifier1),
- &ngx_http_uwsgi_modifier_bounds },
-
- { ngx_string("uwsgi_modifier2"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_num_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_uwsgi_loc_conf_t, modifier2),
- &ngx_http_uwsgi_modifier_bounds },
-
- { ngx_string("uwsgi_store"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_http_uwsgi_store,
- NGX_HTTP_LOC_CONF_OFFSET,
- 0,
- NULL },
-
- { ngx_string("uwsgi_store_access"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE123,
- ngx_conf_set_access_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_uwsgi_loc_conf_t, upstream.store_access),
- NULL },
-
- { ngx_string("uwsgi_buffering"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
- ngx_conf_set_flag_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_uwsgi_loc_conf_t, upstream.buffering),
- NULL },
-
- { ngx_string("uwsgi_request_buffering"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
- ngx_conf_set_flag_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_uwsgi_loc_conf_t, upstream.request_buffering),
- NULL },
-
- { ngx_string("uwsgi_ignore_client_abort"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
- ngx_conf_set_flag_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_uwsgi_loc_conf_t, upstream.ignore_client_abort),
- NULL },
-
- { ngx_string("uwsgi_bind"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE12,
- ngx_http_upstream_bind_set_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_uwsgi_loc_conf_t, upstream.local),
- NULL },
-
- { ngx_string("uwsgi_connect_timeout"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_msec_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_uwsgi_loc_conf_t, upstream.connect_timeout),
- NULL },
-
- { ngx_string("uwsgi_send_timeout"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_msec_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_uwsgi_loc_conf_t, upstream.send_timeout),
- NULL },
-
- { ngx_string("uwsgi_buffer_size"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_size_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_uwsgi_loc_conf_t, upstream.buffer_size),
- NULL },
-
- { ngx_string("uwsgi_pass_request_headers"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
- ngx_conf_set_flag_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_uwsgi_loc_conf_t, upstream.pass_request_headers),
- NULL },
-
- { ngx_string("uwsgi_pass_request_body"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
- ngx_conf_set_flag_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_uwsgi_loc_conf_t, upstream.pass_request_body),
- NULL },
-
- { ngx_string("uwsgi_intercept_errors"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
- ngx_conf_set_flag_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_uwsgi_loc_conf_t, upstream.intercept_errors),
- NULL },
-
- { ngx_string("uwsgi_read_timeout"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_msec_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_uwsgi_loc_conf_t, upstream.read_timeout),
- NULL },
-
- { ngx_string("uwsgi_buffers"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE2,
- ngx_conf_set_bufs_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_uwsgi_loc_conf_t, upstream.bufs),
- NULL },
-
- { ngx_string("uwsgi_busy_buffers_size"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_size_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_uwsgi_loc_conf_t, upstream.busy_buffers_size_conf),
- NULL },
-
- { ngx_string("uwsgi_force_ranges"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
- ngx_conf_set_flag_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_uwsgi_loc_conf_t, upstream.force_ranges),
- NULL },
-
- { ngx_string("uwsgi_limit_rate"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_size_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_uwsgi_loc_conf_t, upstream.limit_rate),
- NULL },
-
-#if (NGX_HTTP_CACHE)
-
- { ngx_string("uwsgi_cache"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_http_uwsgi_cache,
- NGX_HTTP_LOC_CONF_OFFSET,
- 0,
- NULL },
-
- { ngx_string("uwsgi_cache_key"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_http_uwsgi_cache_key,
- NGX_HTTP_LOC_CONF_OFFSET,
- 0,
- NULL },
-
- { ngx_string("uwsgi_cache_path"),
- NGX_HTTP_MAIN_CONF|NGX_CONF_2MORE,
- ngx_http_file_cache_set_slot,
- NGX_HTTP_MAIN_CONF_OFFSET,
- offsetof(ngx_http_uwsgi_main_conf_t, caches),
- &ngx_http_uwsgi_module },
-
- { ngx_string("uwsgi_cache_bypass"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
- ngx_http_set_predicate_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_uwsgi_loc_conf_t, upstream.cache_bypass),
- NULL },
-
- { ngx_string("uwsgi_no_cache"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
- ngx_http_set_predicate_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_uwsgi_loc_conf_t, upstream.no_cache),
- NULL },
-
- { ngx_string("uwsgi_cache_valid"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
- ngx_http_file_cache_valid_set_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_uwsgi_loc_conf_t, upstream.cache_valid),
- NULL },
-
- { ngx_string("uwsgi_cache_min_uses"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_num_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_uwsgi_loc_conf_t, upstream.cache_min_uses),
- NULL },
-
- { ngx_string("uwsgi_cache_max_range_offset"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_off_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_uwsgi_loc_conf_t, upstream.cache_max_range_offset),
- NULL },
-
- { ngx_string("uwsgi_cache_use_stale"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
- ngx_conf_set_bitmask_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_uwsgi_loc_conf_t, upstream.cache_use_stale),
- &ngx_http_uwsgi_next_upstream_masks },
-
- { ngx_string("uwsgi_cache_methods"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
- ngx_conf_set_bitmask_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_uwsgi_loc_conf_t, upstream.cache_methods),
- &ngx_http_upstream_cache_method_mask },
-
- { ngx_string("uwsgi_cache_lock"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
- ngx_conf_set_flag_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_uwsgi_loc_conf_t, upstream.cache_lock),
- NULL },
-
- { ngx_string("uwsgi_cache_lock_timeout"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_msec_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_uwsgi_loc_conf_t, upstream.cache_lock_timeout),
- NULL },
-
- { ngx_string("uwsgi_cache_lock_age"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_msec_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_uwsgi_loc_conf_t, upstream.cache_lock_age),
- NULL },
-
- { ngx_string("uwsgi_cache_revalidate"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
- ngx_conf_set_flag_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_uwsgi_loc_conf_t, upstream.cache_revalidate),
- NULL },
-
- { ngx_string("uwsgi_cache_background_update"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_flag_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_uwsgi_loc_conf_t, upstream.cache_background_update),
- NULL },
-
-#endif
-
- { ngx_string("uwsgi_temp_path"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1234,
- ngx_conf_set_path_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_uwsgi_loc_conf_t, upstream.temp_path),
- NULL },
-
- { ngx_string("uwsgi_max_temp_file_size"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_size_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_uwsgi_loc_conf_t, upstream.max_temp_file_size_conf),
- NULL },
-
- { ngx_string("uwsgi_temp_file_write_size"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_size_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_uwsgi_loc_conf_t, upstream.temp_file_write_size_conf),
- NULL },
-
- { ngx_string("uwsgi_next_upstream"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
- ngx_conf_set_bitmask_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_uwsgi_loc_conf_t, upstream.next_upstream),
- &ngx_http_uwsgi_next_upstream_masks },
-
- { ngx_string("uwsgi_next_upstream_tries"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_num_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_uwsgi_loc_conf_t, upstream.next_upstream_tries),
- NULL },
-
- { ngx_string("uwsgi_next_upstream_timeout"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_msec_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_uwsgi_loc_conf_t, upstream.next_upstream_timeout),
- NULL },
-
- { ngx_string("uwsgi_param"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE23,
- ngx_http_upstream_param_set_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_uwsgi_loc_conf_t, params_source),
- NULL },
-
- { ngx_string("uwsgi_string"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_str_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_uwsgi_loc_conf_t, uwsgi_string),
- NULL },
-
- { ngx_string("uwsgi_pass_header"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_str_array_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_uwsgi_loc_conf_t, upstream.pass_headers),
- NULL },
-
- { ngx_string("uwsgi_hide_header"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_str_array_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_uwsgi_loc_conf_t, upstream.hide_headers),
- NULL },
-
- { ngx_string("uwsgi_ignore_headers"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
- ngx_conf_set_bitmask_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_uwsgi_loc_conf_t, upstream.ignore_headers),
- &ngx_http_upstream_ignore_headers_masks },
-
-#if (NGX_HTTP_SSL)
-
- { ngx_string("uwsgi_ssl_session_reuse"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
- ngx_conf_set_flag_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_uwsgi_loc_conf_t, upstream.ssl_session_reuse),
- NULL },
-
- { ngx_string("uwsgi_ssl_protocols"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
- ngx_conf_set_bitmask_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_uwsgi_loc_conf_t, ssl_protocols),
- &ngx_http_uwsgi_ssl_protocols },
-
- { ngx_string("uwsgi_ssl_ciphers"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_str_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_uwsgi_loc_conf_t, ssl_ciphers),
- NULL },
-
- { ngx_string("uwsgi_ssl_name"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_http_set_complex_value_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_uwsgi_loc_conf_t, upstream.ssl_name),
- NULL },
-
- { ngx_string("uwsgi_ssl_server_name"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
- ngx_conf_set_flag_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_uwsgi_loc_conf_t, upstream.ssl_server_name),
- NULL },
-
- { ngx_string("uwsgi_ssl_verify"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
- ngx_conf_set_flag_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_uwsgi_loc_conf_t, upstream.ssl_verify),
- NULL },
-
- { ngx_string("uwsgi_ssl_verify_depth"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_num_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_uwsgi_loc_conf_t, ssl_verify_depth),
- NULL },
-
- { ngx_string("uwsgi_ssl_trusted_certificate"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_str_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_uwsgi_loc_conf_t, ssl_trusted_certificate),
- NULL },
-
- { ngx_string("uwsgi_ssl_crl"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_str_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_uwsgi_loc_conf_t, ssl_crl),
- NULL },
-
- { ngx_string("uwsgi_ssl_certificate"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_str_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_uwsgi_loc_conf_t, ssl_certificate),
- NULL },
-
- { ngx_string("uwsgi_ssl_certificate_key"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_str_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_uwsgi_loc_conf_t, ssl_certificate_key),
- NULL },
-
- { ngx_string("uwsgi_ssl_password_file"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_http_uwsgi_ssl_password_file,
- NGX_HTTP_LOC_CONF_OFFSET,
- 0,
- NULL },
-
-#endif
-
- ngx_null_command
-};
-
-
-static ngx_http_module_t ngx_http_uwsgi_module_ctx = {
- NULL, /* preconfiguration */
- NULL, /* postconfiguration */
-
- ngx_http_uwsgi_create_main_conf, /* create main configuration */
- NULL, /* init main configuration */
-
- NULL, /* create server configuration */
- NULL, /* merge server configuration */
-
- ngx_http_uwsgi_create_loc_conf, /* create location configuration */
- ngx_http_uwsgi_merge_loc_conf /* merge location configuration */
-};
-
-
-ngx_module_t ngx_http_uwsgi_module = {
- NGX_MODULE_V1,
- &ngx_http_uwsgi_module_ctx, /* module context */
- ngx_http_uwsgi_commands, /* module directives */
- NGX_HTTP_MODULE, /* module type */
- NULL, /* init master */
- NULL, /* init module */
- NULL, /* init process */
- NULL, /* init thread */
- NULL, /* exit thread */
- NULL, /* exit process */
- NULL, /* exit master */
- NGX_MODULE_V1_PADDING
-};
-
-
-static ngx_str_t ngx_http_uwsgi_hide_headers[] = {
- ngx_string("X-Accel-Expires"),
- ngx_string("X-Accel-Redirect"),
- ngx_string("X-Accel-Limit-Rate"),
- ngx_string("X-Accel-Buffering"),
- ngx_string("X-Accel-Charset"),
- ngx_null_string
-};
-
-
-#if (NGX_HTTP_CACHE)
-
-static ngx_keyval_t ngx_http_uwsgi_cache_headers[] = {
- { ngx_string("HTTP_IF_MODIFIED_SINCE"),
- ngx_string("$upstream_cache_last_modified") },
- { ngx_string("HTTP_IF_UNMODIFIED_SINCE"), ngx_string("") },
- { ngx_string("HTTP_IF_NONE_MATCH"), ngx_string("$upstream_cache_etag") },
- { ngx_string("HTTP_IF_MATCH"), ngx_string("") },
- { ngx_string("HTTP_RANGE"), ngx_string("") },
- { ngx_string("HTTP_IF_RANGE"), ngx_string("") },
- { ngx_null_string, ngx_null_string }
-};
-
-#endif
-
-
-static ngx_path_init_t ngx_http_uwsgi_temp_path = {
- ngx_string(NGX_HTTP_UWSGI_TEMP_PATH), { 1, 2, 0 }
-};
-
-
-static ngx_int_t
-ngx_http_uwsgi_handler(ngx_http_request_t *r)
-{
- ngx_int_t rc;
- ngx_http_status_t *status;
- ngx_http_upstream_t *u;
- ngx_http_uwsgi_loc_conf_t *uwcf;
-#if (NGX_HTTP_CACHE)
- ngx_http_uwsgi_main_conf_t *uwmcf;
-#endif
-
- if (ngx_http_upstream_create(r) != NGX_OK) {
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
-
- status = ngx_pcalloc(r->pool, sizeof(ngx_http_status_t));
- if (status == NULL) {
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
-
- ngx_http_set_ctx(r, status, ngx_http_uwsgi_module);
-
- uwcf = ngx_http_get_module_loc_conf(r, ngx_http_uwsgi_module);
-
- u = r->upstream;
-
- if (uwcf->uwsgi_lengths == NULL) {
-
-#if (NGX_HTTP_SSL)
- u->ssl = (uwcf->upstream.ssl != NULL);
-
- if (u->ssl) {
- ngx_str_set(&u->schema, "suwsgi://");
-
- } else {
- ngx_str_set(&u->schema, "uwsgi://");
- }
-#else
- ngx_str_set(&u->schema, "uwsgi://");
-#endif
-
- } else {
- if (ngx_http_uwsgi_eval(r, uwcf) != NGX_OK) {
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
- }
-
- u->output.tag = (ngx_buf_tag_t) &ngx_http_uwsgi_module;
-
- u->conf = &uwcf->upstream;
-
-#if (NGX_HTTP_CACHE)
- uwmcf = ngx_http_get_module_main_conf(r, ngx_http_uwsgi_module);
-
- u->caches = &uwmcf->caches;
- u->create_key = ngx_http_uwsgi_create_key;
-#endif
-
- u->create_request = ngx_http_uwsgi_create_request;
- u->reinit_request = ngx_http_uwsgi_reinit_request;
- u->process_header = ngx_http_uwsgi_process_status_line;
- u->abort_request = ngx_http_uwsgi_abort_request;
- u->finalize_request = ngx_http_uwsgi_finalize_request;
- r->state = 0;
-
- u->buffering = uwcf->upstream.buffering;
-
- u->pipe = ngx_pcalloc(r->pool, sizeof(ngx_event_pipe_t));
- if (u->pipe == NULL) {
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
-
- u->pipe->input_filter = ngx_event_pipe_copy_input_filter;
- u->pipe->input_ctx = r;
-
- if (!uwcf->upstream.request_buffering
- && uwcf->upstream.pass_request_body
- && !r->headers_in.chunked)
- {
- r->request_body_no_buffering = 1;
- }
-
- rc = ngx_http_read_client_request_body(r, ngx_http_upstream_init);
-
- if (rc >= NGX_HTTP_SPECIAL_RESPONSE) {
- return rc;
- }
-
- return NGX_DONE;
-}
-
-
-static ngx_int_t
-ngx_http_uwsgi_eval(ngx_http_request_t *r, ngx_http_uwsgi_loc_conf_t * uwcf)
-{
- size_t add;
- ngx_url_t url;
- ngx_http_upstream_t *u;
-
- ngx_memzero(&url, sizeof(ngx_url_t));
-
- if (ngx_http_script_run(r, &url.url, uwcf->uwsgi_lengths->elts, 0,
- uwcf->uwsgi_values->elts)
- == NULL)
- {
- return NGX_ERROR;
- }
-
- if (url.url.len > 8
- && ngx_strncasecmp(url.url.data, (u_char *) "uwsgi://", 8) == 0)
- {
- add = 8;
-
- } else if (url.url.len > 9
- && ngx_strncasecmp(url.url.data, (u_char *) "suwsgi://", 9) == 0)
- {
-
-#if (NGX_HTTP_SSL)
- add = 9;
- r->upstream->ssl = 1;
-#else
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "suwsgi protocol requires SSL support");
- return NGX_ERROR;
-#endif
-
- } else {
- add = 0;
- }
-
- u = r->upstream;
-
- if (add) {
- u->schema.len = add;
- u->schema.data = url.url.data;
-
- url.url.data += add;
- url.url.len -= add;
-
- } else {
- ngx_str_set(&u->schema, "uwsgi://");
- }
-
- url.no_resolve = 1;
-
- if (ngx_parse_url(r->pool, &url) != NGX_OK) {
- if (url.err) {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "%s in upstream \"%V\"", url.err, &url.url);
- }
-
- return NGX_ERROR;
- }
-
- u->resolved = ngx_pcalloc(r->pool, sizeof(ngx_http_upstream_resolved_t));
- if (u->resolved == NULL) {
- return NGX_ERROR;
- }
-
- if (url.addrs) {
- u->resolved->sockaddr = url.addrs[0].sockaddr;
- u->resolved->socklen = url.addrs[0].socklen;
- u->resolved->name = url.addrs[0].name;
- u->resolved->naddrs = 1;
- }
-
- u->resolved->host = url.host;
- u->resolved->port = url.port;
- u->resolved->no_port = url.no_port;
-
- return NGX_OK;
-}
-
-
-#if (NGX_HTTP_CACHE)
-
-static ngx_int_t
-ngx_http_uwsgi_create_key(ngx_http_request_t *r)
-{
- ngx_str_t *key;
- ngx_http_uwsgi_loc_conf_t *uwcf;
-
- key = ngx_array_push(&r->cache->keys);
- if (key == NULL) {
- return NGX_ERROR;
- }
-
- uwcf = ngx_http_get_module_loc_conf(r, ngx_http_uwsgi_module);
-
- if (ngx_http_complex_value(r, &uwcf->cache_key, key) != NGX_OK) {
- return NGX_ERROR;
- }
-
- return NGX_OK;
-}
-
-#endif
-
-
-static ngx_int_t
-ngx_http_uwsgi_create_request(ngx_http_request_t *r)
-{
- u_char ch, *lowcase_key;
- size_t key_len, val_len, len, allocated;
- ngx_uint_t i, n, hash, skip_empty, header_params;
- ngx_buf_t *b;
- ngx_chain_t *cl, *body;
- ngx_list_part_t *part;
- ngx_table_elt_t *header, **ignored;
- ngx_http_uwsgi_params_t *params;
- ngx_http_script_code_pt code;
- ngx_http_script_engine_t e, le;
- ngx_http_uwsgi_loc_conf_t *uwcf;
- ngx_http_script_len_code_pt lcode;
-
- len = 0;
- header_params = 0;
- ignored = NULL;
-
- uwcf = ngx_http_get_module_loc_conf(r, ngx_http_uwsgi_module);
-
-#if (NGX_HTTP_CACHE)
- params = r->upstream->cacheable ? &uwcf->params_cache : &uwcf->params;
-#else
- params = &uwcf->params;
-#endif
-
- if (params->lengths) {
- ngx_memzero(&le, sizeof(ngx_http_script_engine_t));
-
- ngx_http_script_flush_no_cacheable_variables(r, params->flushes);
- le.flushed = 1;
-
- le.ip = params->lengths->elts;
- le.request = r;
-
- while (*(uintptr_t *) le.ip) {
-
- lcode = *(ngx_http_script_len_code_pt *) le.ip;
- key_len = lcode(&le);
-
- lcode = *(ngx_http_script_len_code_pt *) le.ip;
- skip_empty = lcode(&le);
-
- for (val_len = 0; *(uintptr_t *) le.ip; val_len += lcode(&le)) {
- lcode = *(ngx_http_script_len_code_pt *) le.ip;
- }
- le.ip += sizeof(uintptr_t);
-
- if (skip_empty && val_len == 0) {
- continue;
- }
-
- len += 2 + key_len + 2 + val_len;
- }
- }
-
- if (uwcf->upstream.pass_request_headers) {
-
- allocated = 0;
- lowcase_key = NULL;
-
- if (params->number) {
- n = 0;
- part = &r->headers_in.headers.part;
-
- while (part) {
- n += part->nelts;
- part = part->next;
- }
-
- ignored = ngx_palloc(r->pool, n * sizeof(void *));
- if (ignored == NULL) {
- return NGX_ERROR;
- }
- }
-
- part = &r->headers_in.headers.part;
- header = part->elts;
-
- for (i = 0; /* void */ ; i++) {
-
- if (i >= part->nelts) {
- if (part->next == NULL) {
- break;
- }
-
- part = part->next;
- header = part->elts;
- i = 0;
- }
-
- if (params->number) {
- if (allocated < header[i].key.len) {
- allocated = header[i].key.len + 16;
- lowcase_key = ngx_pnalloc(r->pool, allocated);
- if (lowcase_key == NULL) {
- return NGX_ERROR;
- }
- }
-
- hash = 0;
-
- for (n = 0; n < header[i].key.len; n++) {
- ch = header[i].key.data[n];
-
- if (ch >= 'A' && ch <= 'Z') {
- ch |= 0x20;
-
- } else if (ch == '-') {
- ch = '_';
- }
-
- hash = ngx_hash(hash, ch);
- lowcase_key[n] = ch;
- }
-
- if (ngx_hash_find(&params->hash, hash, lowcase_key, n)) {
- ignored[header_params++] = &header[i];
- continue;
- }
- }
-
- len += 2 + sizeof("HTTP_") - 1 + header[i].key.len
- + 2 + header[i].value.len;
- }
- }
-
- len += uwcf->uwsgi_string.len;
-
-#if 0
- /* allow custom uwsgi packet */
- if (len > 0 && len < 2) {
- ngx_log_error (NGX_LOG_ALERT, r->connection->log, 0,
- "uwsgi request is too little: %uz", len);
- return NGX_ERROR;
- }
-#endif
-
- b = ngx_create_temp_buf(r->pool, len + 4);
- if (b == NULL) {
- return NGX_ERROR;
- }
-
- cl = ngx_alloc_chain_link(r->pool);
- if (cl == NULL) {
- return NGX_ERROR;
- }
-
- cl->buf = b;
-
- *b->last++ = (u_char) uwcf->modifier1;
- *b->last++ = (u_char) (len & 0xff);
- *b->last++ = (u_char) ((len >> 8) & 0xff);
- *b->last++ = (u_char) uwcf->modifier2;
-
- if (params->lengths) {
- ngx_memzero(&e, sizeof(ngx_http_script_engine_t));
-
- e.ip = params->values->elts;
- e.pos = b->last;
- e.request = r;
- e.flushed = 1;
-
- le.ip = params->lengths->elts;
-
- while (*(uintptr_t *) le.ip) {
-
- lcode = *(ngx_http_script_len_code_pt *) le.ip;
- key_len = (u_char) lcode(&le);
-
- lcode = *(ngx_http_script_len_code_pt *) le.ip;
- skip_empty = lcode(&le);
-
- for (val_len = 0; *(uintptr_t *) le.ip; val_len += lcode(&le)) {
- lcode = *(ngx_http_script_len_code_pt *) le.ip;
- }
- le.ip += sizeof(uintptr_t);
-
- if (skip_empty && val_len == 0) {
- e.skip = 1;
-
- while (*(uintptr_t *) e.ip) {
- code = *(ngx_http_script_code_pt *) e.ip;
- code((ngx_http_script_engine_t *) &e);
- }
- e.ip += sizeof(uintptr_t);
-
- e.skip = 0;
-
- continue;
- }
-
- *e.pos++ = (u_char) (key_len & 0xff);
- *e.pos++ = (u_char) ((key_len >> 8) & 0xff);
-
- code = *(ngx_http_script_code_pt *) e.ip;
- code((ngx_http_script_engine_t *) &e);
-
- *e.pos++ = (u_char) (val_len & 0xff);
- *e.pos++ = (u_char) ((val_len >> 8) & 0xff);
-
- while (*(uintptr_t *) e.ip) {
- code = *(ngx_http_script_code_pt *) e.ip;
- code((ngx_http_script_engine_t *) &e);
- }
-
- e.ip += sizeof(uintptr_t);
-
- ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "uwsgi param: \"%*s: %*s\"",
- key_len, e.pos - (key_len + 2 + val_len),
- val_len, e.pos - val_len);
- }
-
- b->last = e.pos;
- }
-
- if (uwcf->upstream.pass_request_headers) {
-
- part = &r->headers_in.headers.part;
- header = part->elts;
-
- for (i = 0; /* void */ ; i++) {
-
- if (i >= part->nelts) {
- if (part->next == NULL) {
- break;
- }
-
- part = part->next;
- header = part->elts;
- i = 0;
- }
-
- for (n = 0; n < header_params; n++) {
- if (&header[i] == ignored[n]) {
- goto next;
- }
- }
-
- key_len = sizeof("HTTP_") - 1 + header[i].key.len;
- *b->last++ = (u_char) (key_len & 0xff);
- *b->last++ = (u_char) ((key_len >> 8) & 0xff);
-
- b->last = ngx_cpymem(b->last, "HTTP_", sizeof("HTTP_") - 1);
- for (n = 0; n < header[i].key.len; n++) {
- ch = header[i].key.data[n];
-
- if (ch >= 'a' && ch <= 'z') {
- ch &= ~0x20;
-
- } else if (ch == '-') {
- ch = '_';
- }
-
- *b->last++ = ch;
- }
-
- val_len = header[i].value.len;
- *b->last++ = (u_char) (val_len & 0xff);
- *b->last++ = (u_char) ((val_len >> 8) & 0xff);
- b->last = ngx_copy(b->last, header[i].value.data, val_len);
-
- ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "uwsgi param: \"%*s: %*s\"",
- key_len, b->last - (key_len + 2 + val_len),
- val_len, b->last - val_len);
- next:
-
- continue;
- }
- }
-
- b->last = ngx_copy(b->last, uwcf->uwsgi_string.data,
- uwcf->uwsgi_string.len);
-
- if (r->request_body_no_buffering) {
- r->upstream->request_bufs = cl;
-
- } else if (uwcf->upstream.pass_request_body) {
- body = r->upstream->request_bufs;
- r->upstream->request_bufs = cl;
-
- while (body) {
- b = ngx_alloc_buf(r->pool);
- if (b == NULL) {
- return NGX_ERROR;
- }
-
- ngx_memcpy(b, body->buf, sizeof(ngx_buf_t));
-
- cl->next = ngx_alloc_chain_link(r->pool);
- if (cl->next == NULL) {
- return NGX_ERROR;
- }
-
- cl = cl->next;
- cl->buf = b;
-
- body = body->next;
- }
-
- } else {
- r->upstream->request_bufs = cl;
- }
-
- cl->next = NULL;
-
- return NGX_OK;
-}
-
-
-static ngx_int_t
-ngx_http_uwsgi_reinit_request(ngx_http_request_t *r)
-{
- ngx_http_status_t *status;
-
- status = ngx_http_get_module_ctx(r, ngx_http_uwsgi_module);
-
- if (status == NULL) {
- return NGX_OK;
- }
-
- status->code = 0;
- status->count = 0;
- status->start = NULL;
- status->end = NULL;
-
- r->upstream->process_header = ngx_http_uwsgi_process_status_line;
- r->state = 0;
-
- return NGX_OK;
-}
-
-
-static ngx_int_t
-ngx_http_uwsgi_process_status_line(ngx_http_request_t *r)
-{
- size_t len;
- ngx_int_t rc;
- ngx_http_status_t *status;
- ngx_http_upstream_t *u;
-
- status = ngx_http_get_module_ctx(r, ngx_http_uwsgi_module);
-
- if (status == NULL) {
- return NGX_ERROR;
- }
-
- u = r->upstream;
-
- rc = ngx_http_parse_status_line(r, &u->buffer, status);
-
- if (rc == NGX_AGAIN) {
- return rc;
- }
-
- if (rc == NGX_ERROR) {
- u->process_header = ngx_http_uwsgi_process_header;
- return ngx_http_uwsgi_process_header(r);
- }
-
- if (u->state && u->state->status == 0) {
- u->state->status = status->code;
- }
-
- u->headers_in.status_n = status->code;
-
- len = status->end - status->start;
- u->headers_in.status_line.len = len;
-
- u->headers_in.status_line.data = ngx_pnalloc(r->pool, len);
- if (u->headers_in.status_line.data == NULL) {
- return NGX_ERROR;
- }
-
- ngx_memcpy(u->headers_in.status_line.data, status->start, len);
-
- ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "http uwsgi status %ui \"%V\"",
- u->headers_in.status_n, &u->headers_in.status_line);
-
- u->process_header = ngx_http_uwsgi_process_header;
-
- return ngx_http_uwsgi_process_header(r);
-}
-
-
-static ngx_int_t
-ngx_http_uwsgi_process_header(ngx_http_request_t *r)
-{
- ngx_str_t *status_line;
- ngx_int_t rc, status;
- ngx_table_elt_t *h;
- ngx_http_upstream_t *u;
- ngx_http_upstream_header_t *hh;
- ngx_http_upstream_main_conf_t *umcf;
-
- umcf = ngx_http_get_module_main_conf(r, ngx_http_upstream_module);
-
- for ( ;; ) {
-
- rc = ngx_http_parse_header_line(r, &r->upstream->buffer, 1);
-
- if (rc == NGX_OK) {
-
- /* a header line has been parsed successfully */
-
- h = ngx_list_push(&r->upstream->headers_in.headers);
- if (h == NULL) {
- return NGX_ERROR;
- }
-
- h->hash = r->header_hash;
-
- h->key.len = r->header_name_end - r->header_name_start;
- h->value.len = r->header_end - r->header_start;
-
- h->key.data = ngx_pnalloc(r->pool,
- h->key.len + 1 + h->value.len + 1
- + h->key.len);
- if (h->key.data == NULL) {
- h->hash = 0;
- return NGX_ERROR;
- }
-
- h->value.data = h->key.data + h->key.len + 1;
- h->lowcase_key = h->key.data + h->key.len + 1 + h->value.len + 1;
-
- ngx_memcpy(h->key.data, r->header_name_start, h->key.len);
- h->key.data[h->key.len] = '\0';
- ngx_memcpy(h->value.data, r->header_start, h->value.len);
- h->value.data[h->value.len] = '\0';
-
- if (h->key.len == r->lowcase_index) {
- ngx_memcpy(h->lowcase_key, r->lowcase_header, h->key.len);
-
- } else {
- ngx_strlow(h->lowcase_key, h->key.data, h->key.len);
- }
-
- hh = ngx_hash_find(&umcf->headers_in_hash, h->hash,
- h->lowcase_key, h->key.len);
-
- if (hh && hh->handler(r, h, hh->offset) != NGX_OK) {
- return NGX_ERROR;
- }
-
- ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "http uwsgi header: \"%V: %V\"", &h->key, &h->value);
-
- continue;
- }
-
- if (rc == NGX_HTTP_PARSE_HEADER_DONE) {
-
- /* a whole header has been parsed successfully */
-
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "http uwsgi header done");
-
- u = r->upstream;
-
- if (u->headers_in.status_n) {
- goto done;
- }
-
- if (u->headers_in.status) {
- status_line = &u->headers_in.status->value;
-
- status = ngx_atoi(status_line->data, 3);
- if (status == NGX_ERROR) {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "upstream sent invalid status \"%V\"",
- status_line);
- return NGX_HTTP_UPSTREAM_INVALID_HEADER;
- }
-
- u->headers_in.status_n = status;
- u->headers_in.status_line = *status_line;
-
- } else if (u->headers_in.location) {
- u->headers_in.status_n = 302;
- ngx_str_set(&u->headers_in.status_line,
- "302 Moved Temporarily");
-
- } else {
- u->headers_in.status_n = 200;
- ngx_str_set(&u->headers_in.status_line, "200 OK");
- }
-
- if (u->state && u->state->status == 0) {
- u->state->status = u->headers_in.status_n;
- }
-
- done:
-
- if (u->headers_in.status_n == NGX_HTTP_SWITCHING_PROTOCOLS
- && r->headers_in.upgrade)
- {
- u->upgrade = 1;
- }
-
- return NGX_OK;
- }
-
- if (rc == NGX_AGAIN) {
- return NGX_AGAIN;
- }
-
- /* there was error while a header line parsing */
-
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "upstream sent invalid header");
-
- return NGX_HTTP_UPSTREAM_INVALID_HEADER;
- }
-}
-
-
-static void
-ngx_http_uwsgi_abort_request(ngx_http_request_t *r)
-{
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "abort http uwsgi request");
-
- return;
-}
-
-
-static void
-ngx_http_uwsgi_finalize_request(ngx_http_request_t *r, ngx_int_t rc)
-{
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "finalize http uwsgi request");
-
- return;
-}
-
-
-static void *
-ngx_http_uwsgi_create_main_conf(ngx_conf_t *cf)
-{
- ngx_http_uwsgi_main_conf_t *conf;
-
- conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_uwsgi_main_conf_t));
- if (conf == NULL) {
- return NULL;
- }
-
-#if (NGX_HTTP_CACHE)
- if (ngx_array_init(&conf->caches, cf->pool, 4,
- sizeof(ngx_http_file_cache_t *))
- != NGX_OK)
- {
- return NULL;
- }
-#endif
-
- return conf;
-}
-
-
-static void *
-ngx_http_uwsgi_create_loc_conf(ngx_conf_t *cf)
-{
- ngx_http_uwsgi_loc_conf_t *conf;
-
- conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_uwsgi_loc_conf_t));
- if (conf == NULL) {
- return NULL;
- }
-
- conf->modifier1 = NGX_CONF_UNSET_UINT;
- conf->modifier2 = NGX_CONF_UNSET_UINT;
-
- conf->upstream.store = NGX_CONF_UNSET;
- conf->upstream.store_access = NGX_CONF_UNSET_UINT;
- conf->upstream.next_upstream_tries = NGX_CONF_UNSET_UINT;
- conf->upstream.buffering = NGX_CONF_UNSET;
- conf->upstream.request_buffering = NGX_CONF_UNSET;
- conf->upstream.ignore_client_abort = NGX_CONF_UNSET;
- conf->upstream.force_ranges = NGX_CONF_UNSET;
-
- conf->upstream.local = NGX_CONF_UNSET_PTR;
-
- conf->upstream.connect_timeout = NGX_CONF_UNSET_MSEC;
- conf->upstream.send_timeout = NGX_CONF_UNSET_MSEC;
- conf->upstream.read_timeout = NGX_CONF_UNSET_MSEC;
- conf->upstream.next_upstream_timeout = NGX_CONF_UNSET_MSEC;
-
- conf->upstream.send_lowat = NGX_CONF_UNSET_SIZE;
- conf->upstream.buffer_size = NGX_CONF_UNSET_SIZE;
- conf->upstream.limit_rate = NGX_CONF_UNSET_SIZE;
-
- conf->upstream.busy_buffers_size_conf = NGX_CONF_UNSET_SIZE;
- conf->upstream.max_temp_file_size_conf = NGX_CONF_UNSET_SIZE;
- conf->upstream.temp_file_write_size_conf = NGX_CONF_UNSET_SIZE;
-
- conf->upstream.pass_request_headers = NGX_CONF_UNSET;
- conf->upstream.pass_request_body = NGX_CONF_UNSET;
-
-#if (NGX_HTTP_CACHE)
- conf->upstream.cache = NGX_CONF_UNSET;
- conf->upstream.cache_min_uses = NGX_CONF_UNSET_UINT;
- conf->upstream.cache_max_range_offset = NGX_CONF_UNSET;
- conf->upstream.cache_bypass = NGX_CONF_UNSET_PTR;
- conf->upstream.no_cache = NGX_CONF_UNSET_PTR;
- conf->upstream.cache_valid = NGX_CONF_UNSET_PTR;
- conf->upstream.cache_lock = NGX_CONF_UNSET;
- conf->upstream.cache_lock_timeout = NGX_CONF_UNSET_MSEC;
- conf->upstream.cache_lock_age = NGX_CONF_UNSET_MSEC;
- conf->upstream.cache_revalidate = NGX_CONF_UNSET;
- conf->upstream.cache_background_update = NGX_CONF_UNSET;
-#endif
-
- conf->upstream.hide_headers = NGX_CONF_UNSET_PTR;
- conf->upstream.pass_headers = NGX_CONF_UNSET_PTR;
-
- conf->upstream.intercept_errors = NGX_CONF_UNSET;
-
-#if (NGX_HTTP_SSL)
- conf->upstream.ssl_session_reuse = NGX_CONF_UNSET;
- conf->upstream.ssl_server_name = NGX_CONF_UNSET;
- conf->upstream.ssl_verify = NGX_CONF_UNSET;
- conf->ssl_verify_depth = NGX_CONF_UNSET_UINT;
- conf->ssl_passwords = NGX_CONF_UNSET_PTR;
-#endif
-
- /* "uwsgi_cyclic_temp_file" is disabled */
- conf->upstream.cyclic_temp_file = 0;
-
- conf->upstream.change_buffering = 1;
-
- ngx_str_set(&conf->upstream.module, "uwsgi");
-
- return conf;
-}
-
-
-static char *
-ngx_http_uwsgi_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
-{
- ngx_http_uwsgi_loc_conf_t *prev = parent;
- ngx_http_uwsgi_loc_conf_t *conf = child;
-
- size_t size;
- ngx_int_t rc;
- ngx_hash_init_t hash;
- ngx_http_core_loc_conf_t *clcf;
-
-#if (NGX_HTTP_CACHE)
-
- if (conf->upstream.store > 0) {
- conf->upstream.cache = 0;
- }
-
- if (conf->upstream.cache > 0) {
- conf->upstream.store = 0;
- }
-
-#endif
-
- if (conf->upstream.store == NGX_CONF_UNSET) {
- ngx_conf_merge_value(conf->upstream.store, prev->upstream.store, 0);
-
- conf->upstream.store_lengths = prev->upstream.store_lengths;
- conf->upstream.store_values = prev->upstream.store_values;
- }
-
- ngx_conf_merge_uint_value(conf->upstream.store_access,
- prev->upstream.store_access, 0600);
-
- ngx_conf_merge_uint_value(conf->upstream.next_upstream_tries,
- prev->upstream.next_upstream_tries, 0);
-
- ngx_conf_merge_value(conf->upstream.buffering,
- prev->upstream.buffering, 1);
-
- ngx_conf_merge_value(conf->upstream.request_buffering,
- prev->upstream.request_buffering, 1);
-
- ngx_conf_merge_value(conf->upstream.ignore_client_abort,
- prev->upstream.ignore_client_abort, 0);
-
- ngx_conf_merge_value(conf->upstream.force_ranges,
- prev->upstream.force_ranges, 0);
-
- ngx_conf_merge_ptr_value(conf->upstream.local,
- prev->upstream.local, NULL);
-
- ngx_conf_merge_msec_value(conf->upstream.connect_timeout,
- prev->upstream.connect_timeout, 60000);
-
- ngx_conf_merge_msec_value(conf->upstream.send_timeout,
- prev->upstream.send_timeout, 60000);
-
- ngx_conf_merge_msec_value(conf->upstream.read_timeout,
- prev->upstream.read_timeout, 60000);
-
- ngx_conf_merge_msec_value(conf->upstream.next_upstream_timeout,
- prev->upstream.next_upstream_timeout, 0);
-
- ngx_conf_merge_size_value(conf->upstream.send_lowat,
- prev->upstream.send_lowat, 0);
-
- ngx_conf_merge_size_value(conf->upstream.buffer_size,
- prev->upstream.buffer_size,
- (size_t) ngx_pagesize);
-
- ngx_conf_merge_size_value(conf->upstream.limit_rate,
- prev->upstream.limit_rate, 0);
-
-
- ngx_conf_merge_bufs_value(conf->upstream.bufs, prev->upstream.bufs,
- 8, ngx_pagesize);
-
- if (conf->upstream.bufs.num < 2) {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "there must be at least 2 \"uwsgi_buffers\"");
- return NGX_CONF_ERROR;
- }
-
-
- size = conf->upstream.buffer_size;
- if (size < conf->upstream.bufs.size) {
- size = conf->upstream.bufs.size;
- }
-
-
- ngx_conf_merge_size_value(conf->upstream.busy_buffers_size_conf,
- prev->upstream.busy_buffers_size_conf,
- NGX_CONF_UNSET_SIZE);
-
- if (conf->upstream.busy_buffers_size_conf == NGX_CONF_UNSET_SIZE) {
- conf->upstream.busy_buffers_size = 2 * size;
- } else {
- conf->upstream.busy_buffers_size =
- conf->upstream.busy_buffers_size_conf;
- }
-
- if (conf->upstream.busy_buffers_size < size) {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "\"uwsgi_busy_buffers_size\" must be equal to or greater "
- "than the maximum of the value of \"uwsgi_buffer_size\" and "
- "one of the \"uwsgi_buffers\"");
-
- return NGX_CONF_ERROR;
- }
-
- if (conf->upstream.busy_buffers_size
- > (conf->upstream.bufs.num - 1) * conf->upstream.bufs.size)
- {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "\"uwsgi_busy_buffers_size\" must be less than "
- "the size of all \"uwsgi_buffers\" minus one buffer");
-
- return NGX_CONF_ERROR;
- }
-
-
- ngx_conf_merge_size_value(conf->upstream.temp_file_write_size_conf,
- prev->upstream.temp_file_write_size_conf,
- NGX_CONF_UNSET_SIZE);
-
- if (conf->upstream.temp_file_write_size_conf == NGX_CONF_UNSET_SIZE) {
- conf->upstream.temp_file_write_size = 2 * size;
- } else {
- conf->upstream.temp_file_write_size =
- conf->upstream.temp_file_write_size_conf;
- }
-
- if (conf->upstream.temp_file_write_size < size) {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "\"uwsgi_temp_file_write_size\" must be equal to or greater than "
- "the maximum of the value of \"uwsgi_buffer_size\" and "
- "one of the \"uwsgi_buffers\"");
-
- return NGX_CONF_ERROR;
- }
-
-
- ngx_conf_merge_size_value(conf->upstream.max_temp_file_size_conf,
- prev->upstream.max_temp_file_size_conf,
- NGX_CONF_UNSET_SIZE);
-
- if (conf->upstream.max_temp_file_size_conf == NGX_CONF_UNSET_SIZE) {
- conf->upstream.max_temp_file_size = 1024 * 1024 * 1024;
- } else {
- conf->upstream.max_temp_file_size =
- conf->upstream.max_temp_file_size_conf;
- }
-
- if (conf->upstream.max_temp_file_size != 0
- && conf->upstream.max_temp_file_size < size)
- {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "\"uwsgi_max_temp_file_size\" must be equal to zero to disable "
- "temporary files usage or must be equal to or greater than "
- "the maximum of the value of \"uwsgi_buffer_size\" and "
- "one of the \"uwsgi_buffers\"");
-
- return NGX_CONF_ERROR;
- }
-
-
- ngx_conf_merge_bitmask_value(conf->upstream.ignore_headers,
- prev->upstream.ignore_headers,
- NGX_CONF_BITMASK_SET);
-
-
- ngx_conf_merge_bitmask_value(conf->upstream.next_upstream,
- prev->upstream.next_upstream,
- (NGX_CONF_BITMASK_SET
- |NGX_HTTP_UPSTREAM_FT_ERROR
- |NGX_HTTP_UPSTREAM_FT_TIMEOUT));
-
- if (conf->upstream.next_upstream & NGX_HTTP_UPSTREAM_FT_OFF) {
- conf->upstream.next_upstream = NGX_CONF_BITMASK_SET
- |NGX_HTTP_UPSTREAM_FT_OFF;
- }
-
- if (ngx_conf_merge_path_value(cf, &conf->upstream.temp_path,
- prev->upstream.temp_path,
- &ngx_http_uwsgi_temp_path)
- != NGX_OK)
- {
- return NGX_CONF_ERROR;
- }
-
-#if (NGX_HTTP_CACHE)
-
- if (conf->upstream.cache == NGX_CONF_UNSET) {
- ngx_conf_merge_value(conf->upstream.cache,
- prev->upstream.cache, 0);
-
- conf->upstream.cache_zone = prev->upstream.cache_zone;
- conf->upstream.cache_value = prev->upstream.cache_value;
- }
-
- if (conf->upstream.cache_zone && conf->upstream.cache_zone->data == NULL) {
- ngx_shm_zone_t *shm_zone;
-
- shm_zone = conf->upstream.cache_zone;
-
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "\"uwsgi_cache\" zone \"%V\" is unknown",
- &shm_zone->shm.name);
-
- return NGX_CONF_ERROR;
- }
-
- ngx_conf_merge_uint_value(conf->upstream.cache_min_uses,
- prev->upstream.cache_min_uses, 1);
-
- ngx_conf_merge_off_value(conf->upstream.cache_max_range_offset,
- prev->upstream.cache_max_range_offset,
- NGX_MAX_OFF_T_VALUE);
-
- ngx_conf_merge_bitmask_value(conf->upstream.cache_use_stale,
- prev->upstream.cache_use_stale,
- (NGX_CONF_BITMASK_SET
- |NGX_HTTP_UPSTREAM_FT_OFF));
-
- if (conf->upstream.cache_use_stale & NGX_HTTP_UPSTREAM_FT_OFF) {
- conf->upstream.cache_use_stale = NGX_CONF_BITMASK_SET
- |NGX_HTTP_UPSTREAM_FT_OFF;
- }
-
- if (conf->upstream.cache_use_stale & NGX_HTTP_UPSTREAM_FT_ERROR) {
- conf->upstream.cache_use_stale |= NGX_HTTP_UPSTREAM_FT_NOLIVE;
- }
-
- if (conf->upstream.cache_methods == 0) {
- conf->upstream.cache_methods = prev->upstream.cache_methods;
- }
-
- conf->upstream.cache_methods |= NGX_HTTP_GET|NGX_HTTP_HEAD;
-
- ngx_conf_merge_ptr_value(conf->upstream.cache_bypass,
- prev->upstream.cache_bypass, NULL);
-
- ngx_conf_merge_ptr_value(conf->upstream.no_cache,
- prev->upstream.no_cache, NULL);
-
- ngx_conf_merge_ptr_value(conf->upstream.cache_valid,
- prev->upstream.cache_valid, NULL);
-
- if (conf->cache_key.value.data == NULL) {
- conf->cache_key = prev->cache_key;
- }
-
- if (conf->upstream.cache && conf->cache_key.value.data == NULL) {
- ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
- "no \"uwsgi_cache_key\" for \"uwsgi_cache\"");
- }
-
- ngx_conf_merge_value(conf->upstream.cache_lock,
- prev->upstream.cache_lock, 0);
-
- ngx_conf_merge_msec_value(conf->upstream.cache_lock_timeout,
- prev->upstream.cache_lock_timeout, 5000);
-
- ngx_conf_merge_msec_value(conf->upstream.cache_lock_age,
- prev->upstream.cache_lock_age, 5000);
-
- ngx_conf_merge_value(conf->upstream.cache_revalidate,
- prev->upstream.cache_revalidate, 0);
-
- ngx_conf_merge_value(conf->upstream.cache_background_update,
- prev->upstream.cache_background_update, 0);
-
-#endif
-
- ngx_conf_merge_value(conf->upstream.pass_request_headers,
- prev->upstream.pass_request_headers, 1);
- ngx_conf_merge_value(conf->upstream.pass_request_body,
- prev->upstream.pass_request_body, 1);
-
- ngx_conf_merge_value(conf->upstream.intercept_errors,
- prev->upstream.intercept_errors, 0);
-
-#if (NGX_HTTP_SSL)
-
- ngx_conf_merge_value(conf->upstream.ssl_session_reuse,
- prev->upstream.ssl_session_reuse, 1);
-
- ngx_conf_merge_bitmask_value(conf->ssl_protocols, prev->ssl_protocols,
- (NGX_CONF_BITMASK_SET|NGX_SSL_TLSv1
- |NGX_SSL_TLSv1_1|NGX_SSL_TLSv1_2));
-
- ngx_conf_merge_str_value(conf->ssl_ciphers, prev->ssl_ciphers,
- "DEFAULT");
-
- if (conf->upstream.ssl_name == NULL) {
- conf->upstream.ssl_name = prev->upstream.ssl_name;
- }
-
- ngx_conf_merge_value(conf->upstream.ssl_server_name,
- prev->upstream.ssl_server_name, 0);
- ngx_conf_merge_value(conf->upstream.ssl_verify,
- prev->upstream.ssl_verify, 0);
- ngx_conf_merge_uint_value(conf->ssl_verify_depth,
- prev->ssl_verify_depth, 1);
- ngx_conf_merge_str_value(conf->ssl_trusted_certificate,
- prev->ssl_trusted_certificate, "");
- ngx_conf_merge_str_value(conf->ssl_crl, prev->ssl_crl, "");
-
- ngx_conf_merge_str_value(conf->ssl_certificate,
- prev->ssl_certificate, "");
- ngx_conf_merge_str_value(conf->ssl_certificate_key,
- prev->ssl_certificate_key, "");
- ngx_conf_merge_ptr_value(conf->ssl_passwords, prev->ssl_passwords, NULL);
-
- if (conf->ssl && ngx_http_uwsgi_set_ssl(cf, conf) != NGX_OK) {
- return NGX_CONF_ERROR;
- }
-
-#endif
-
- ngx_conf_merge_str_value(conf->uwsgi_string, prev->uwsgi_string, "");
-
- hash.max_size = 512;
- hash.bucket_size = ngx_align(64, ngx_cacheline_size);
- hash.name = "uwsgi_hide_headers_hash";
-
- if (ngx_http_upstream_hide_headers_hash(cf, &conf->upstream,
- &prev->upstream, ngx_http_uwsgi_hide_headers, &hash)
- != NGX_OK)
- {
- return NGX_CONF_ERROR;
- }
-
- clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);
-
- if (clcf->noname
- && conf->upstream.upstream == NULL && conf->uwsgi_lengths == NULL)
- {
- conf->upstream.upstream = prev->upstream.upstream;
-
- conf->uwsgi_lengths = prev->uwsgi_lengths;
- conf->uwsgi_values = prev->uwsgi_values;
-
-#if (NGX_HTTP_SSL)
- conf->upstream.ssl = prev->upstream.ssl;
-#endif
- }
-
- if (clcf->lmt_excpt && clcf->handler == NULL
- && (conf->upstream.upstream || conf->uwsgi_lengths))
- {
- clcf->handler = ngx_http_uwsgi_handler;
- }
-
- ngx_conf_merge_uint_value(conf->modifier1, prev->modifier1, 0);
- ngx_conf_merge_uint_value(conf->modifier2, prev->modifier2, 0);
-
- if (conf->params_source == NULL) {
- conf->params = prev->params;
-#if (NGX_HTTP_CACHE)
- conf->params_cache = prev->params_cache;
-#endif
- conf->params_source = prev->params_source;
- }
-
- rc = ngx_http_uwsgi_init_params(cf, conf, &conf->params, NULL);
- if (rc != NGX_OK) {
- return NGX_CONF_ERROR;
- }
-
-#if (NGX_HTTP_CACHE)
-
- if (conf->upstream.cache) {
- rc = ngx_http_uwsgi_init_params(cf, conf, &conf->params_cache,
- ngx_http_uwsgi_cache_headers);
- if (rc != NGX_OK) {
- return NGX_CONF_ERROR;
- }
- }
-
-#endif
-
- /*
- * special handling to preserve conf->params in the "http" section
- * to inherit it to all servers
- */
-
- if (prev->params.hash.buckets == NULL
- && conf->params_source == prev->params_source)
- {
- prev->params = conf->params;
-#if (NGX_HTTP_CACHE)
- prev->params_cache = conf->params_cache;
-#endif
- }
-
- return NGX_CONF_OK;
-}
-
-
-static ngx_int_t
-ngx_http_uwsgi_init_params(ngx_conf_t *cf, ngx_http_uwsgi_loc_conf_t *conf,
- ngx_http_uwsgi_params_t *params, ngx_keyval_t *default_params)
-{
- u_char *p;
- size_t size;
- uintptr_t *code;
- ngx_uint_t i, nsrc;
- ngx_array_t headers_names, params_merged;
- ngx_keyval_t *h;
- ngx_hash_key_t *hk;
- ngx_hash_init_t hash;
- ngx_http_upstream_param_t *src, *s;
- ngx_http_script_compile_t sc;
- ngx_http_script_copy_code_t *copy;
-
- if (params->hash.buckets) {
- return NGX_OK;
- }
-
- if (conf->params_source == NULL && default_params == NULL) {
- params->hash.buckets = (void *) 1;
- return NGX_OK;
- }
-
- params->lengths = ngx_array_create(cf->pool, 64, 1);
- if (params->lengths == NULL) {
- return NGX_ERROR;
- }
-
- params->values = ngx_array_create(cf->pool, 512, 1);
- if (params->values == NULL) {
- return NGX_ERROR;
- }
-
- if (ngx_array_init(&headers_names, cf->temp_pool, 4, sizeof(ngx_hash_key_t))
- != NGX_OK)
- {
- return NGX_ERROR;
- }
-
- if (conf->params_source) {
- src = conf->params_source->elts;
- nsrc = conf->params_source->nelts;
-
- } else {
- src = NULL;
- nsrc = 0;
- }
-
- if (default_params) {
- if (ngx_array_init(&params_merged, cf->temp_pool, 4,
- sizeof(ngx_http_upstream_param_t))
- != NGX_OK)
- {
- return NGX_ERROR;
- }
-
- for (i = 0; i < nsrc; i++) {
-
- s = ngx_array_push(&params_merged);
- if (s == NULL) {
- return NGX_ERROR;
- }
-
- *s = src[i];
- }
-
- h = default_params;
-
- while (h->key.len) {
-
- src = params_merged.elts;
- nsrc = params_merged.nelts;
-
- for (i = 0; i < nsrc; i++) {
- if (ngx_strcasecmp(h->key.data, src[i].key.data) == 0) {
- goto next;
- }
- }
-
- s = ngx_array_push(&params_merged);
- if (s == NULL) {
- return NGX_ERROR;
- }
-
- s->key = h->key;
- s->value = h->value;
- s->skip_empty = 1;
-
- next:
-
- h++;
- }
-
- src = params_merged.elts;
- nsrc = params_merged.nelts;
- }
-
- for (i = 0; i < nsrc; i++) {
-
- if (src[i].key.len > sizeof("HTTP_") - 1
- && ngx_strncmp(src[i].key.data, "HTTP_", sizeof("HTTP_") - 1) == 0)
- {
- hk = ngx_array_push(&headers_names);
- if (hk == NULL) {
- return NGX_ERROR;
- }
-
- hk->key.len = src[i].key.len - 5;
- hk->key.data = src[i].key.data + 5;
- hk->key_hash = ngx_hash_key_lc(hk->key.data, hk->key.len);
- hk->value = (void *) 1;
-
- if (src[i].value.len == 0) {
- continue;
- }
- }
-
- copy = ngx_array_push_n(params->lengths,
- sizeof(ngx_http_script_copy_code_t));
- if (copy == NULL) {
- return NGX_ERROR;
- }
-
- copy->code = (ngx_http_script_code_pt) (void *)
- ngx_http_script_copy_len_code;
- copy->len = src[i].key.len;
-
- copy = ngx_array_push_n(params->lengths,
- sizeof(ngx_http_script_copy_code_t));
- if (copy == NULL) {
- return NGX_ERROR;
- }
-
- copy->code = (ngx_http_script_code_pt) (void *)
- ngx_http_script_copy_len_code;
- copy->len = src[i].skip_empty;
-
-
- size = (sizeof(ngx_http_script_copy_code_t)
- + src[i].key.len + sizeof(uintptr_t) - 1)
- & ~(sizeof(uintptr_t) - 1);
-
- copy = ngx_array_push_n(params->values, size);
- if (copy == NULL) {
- return NGX_ERROR;
- }
-
- copy->code = ngx_http_script_copy_code;
- copy->len = src[i].key.len;
-
- p = (u_char *) copy + sizeof(ngx_http_script_copy_code_t);
- ngx_memcpy(p, src[i].key.data, src[i].key.len);
-
-
- ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));
-
- sc.cf = cf;
- sc.source = &src[i].value;
- sc.flushes = &params->flushes;
- sc.lengths = &params->lengths;
- sc.values = &params->values;
-
- if (ngx_http_script_compile(&sc) != NGX_OK) {
- return NGX_ERROR;
- }
-
- code = ngx_array_push_n(params->lengths, sizeof(uintptr_t));
- if (code == NULL) {
- return NGX_ERROR;
- }
-
- *code = (uintptr_t) NULL;
-
-
- code = ngx_array_push_n(params->values, sizeof(uintptr_t));
- if (code == NULL) {
- return NGX_ERROR;
- }
-
- *code = (uintptr_t) NULL;
- }
-
- code = ngx_array_push_n(params->lengths, sizeof(uintptr_t));
- if (code == NULL) {
- return NGX_ERROR;
- }
-
- *code = (uintptr_t) NULL;
-
- params->number = headers_names.nelts;
-
- hash.hash = &params->hash;
- hash.key = ngx_hash_key_lc;
- hash.max_size = 512;
- hash.bucket_size = 64;
- hash.name = "uwsgi_params_hash";
- hash.pool = cf->pool;
- hash.temp_pool = NULL;
-
- return ngx_hash_init(&hash, headers_names.elts, headers_names.nelts);
-}
-
-
-static char *
-ngx_http_uwsgi_pass(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
-{
- ngx_http_uwsgi_loc_conf_t *uwcf = conf;
-
- size_t add;
- ngx_url_t u;
- ngx_str_t *value, *url;
- ngx_uint_t n;
- ngx_http_core_loc_conf_t *clcf;
- ngx_http_script_compile_t sc;
-
- if (uwcf->upstream.upstream || uwcf->uwsgi_lengths) {
- return "is duplicate";
- }
-
- clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);
- clcf->handler = ngx_http_uwsgi_handler;
-
- value = cf->args->elts;
-
- url = &value[1];
-
- n = ngx_http_script_variables_count(url);
-
- if (n) {
-
- ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));
-
- sc.cf = cf;
- sc.source = url;
- sc.lengths = &uwcf->uwsgi_lengths;
- sc.values = &uwcf->uwsgi_values;
- sc.variables = n;
- sc.complete_lengths = 1;
- sc.complete_values = 1;
-
- if (ngx_http_script_compile(&sc) != NGX_OK) {
- return NGX_CONF_ERROR;
- }
-
-#if (NGX_HTTP_SSL)
- uwcf->ssl = 1;
-#endif
-
- return NGX_CONF_OK;
- }
-
- if (ngx_strncasecmp(url->data, (u_char *) "uwsgi://", 8) == 0) {
- add = 8;
-
- } else if (ngx_strncasecmp(url->data, (u_char *) "suwsgi://", 9) == 0) {
-
-#if (NGX_HTTP_SSL)
- add = 9;
- uwcf->ssl = 1;
-#else
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "suwsgi protocol requires SSL support");
- return NGX_CONF_ERROR;
-#endif
-
- } else {
- add = 0;
- }
-
- ngx_memzero(&u, sizeof(ngx_url_t));
-
- u.url.len = url->len - add;
- u.url.data = url->data + add;
- u.no_resolve = 1;
-
- uwcf->upstream.upstream = ngx_http_upstream_add(cf, &u, 0);
- if (uwcf->upstream.upstream == NULL) {
- return NGX_CONF_ERROR;
- }
-
- if (clcf->name.data[clcf->name.len - 1] == '/') {
- clcf->auto_redirect = 1;
- }
-
- return NGX_CONF_OK;
-}
-
-
-static char *
-ngx_http_uwsgi_store(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
-{
- ngx_http_uwsgi_loc_conf_t *uwcf = conf;
-
- ngx_str_t *value;
- ngx_http_script_compile_t sc;
-
- if (uwcf->upstream.store != NGX_CONF_UNSET) {
- return "is duplicate";
- }
-
- value = cf->args->elts;
-
- if (ngx_strcmp(value[1].data, "off") == 0) {
- uwcf->upstream.store = 0;
- return NGX_CONF_OK;
- }
-
-#if (NGX_HTTP_CACHE)
-
- if (uwcf->upstream.cache > 0) {
- return "is incompatible with \"uwsgi_cache\"";
- }
-
-#endif
-
- uwcf->upstream.store = 1;
-
- if (ngx_strcmp(value[1].data, "on") == 0) {
- return NGX_CONF_OK;
- }
-
- /* include the terminating '\0' into script */
- value[1].len++;
-
- ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));
-
- sc.cf = cf;
- sc.source = &value[1];
- sc.lengths = &uwcf->upstream.store_lengths;
- sc.values = &uwcf->upstream.store_values;
- sc.variables = ngx_http_script_variables_count(&value[1]);
- sc.complete_lengths = 1;
- sc.complete_values = 1;
-
- if (ngx_http_script_compile(&sc) != NGX_OK) {
- return NGX_CONF_ERROR;
- }
-
- return NGX_CONF_OK;
-}
-
-
-#if (NGX_HTTP_CACHE)
-
-static char *
-ngx_http_uwsgi_cache(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
-{
- ngx_http_uwsgi_loc_conf_t *uwcf = conf;
-
- ngx_str_t *value;
- ngx_http_complex_value_t cv;
- ngx_http_compile_complex_value_t ccv;
-
- value = cf->args->elts;
-
- if (uwcf->upstream.cache != NGX_CONF_UNSET) {
- return "is duplicate";
- }
-
- if (ngx_strcmp(value[1].data, "off") == 0) {
- uwcf->upstream.cache = 0;
- return NGX_CONF_OK;
- }
-
- if (uwcf->upstream.store > 0) {
- return "is incompatible with \"uwsgi_store\"";
- }
-
- uwcf->upstream.cache = 1;
-
- 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) {
-
- uwcf->upstream.cache_value = ngx_palloc(cf->pool,
- sizeof(ngx_http_complex_value_t));
- if (uwcf->upstream.cache_value == NULL) {
- return NGX_CONF_ERROR;
- }
-
- *uwcf->upstream.cache_value = cv;
-
- return NGX_CONF_OK;
- }
-
- uwcf->upstream.cache_zone = ngx_shared_memory_add(cf, &value[1], 0,
- &ngx_http_uwsgi_module);
- if (uwcf->upstream.cache_zone == NULL) {
- return NGX_CONF_ERROR;
- }
-
- return NGX_CONF_OK;
-}
-
-
-static char *
-ngx_http_uwsgi_cache_key(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
-{
- ngx_http_uwsgi_loc_conf_t *uwcf = conf;
-
- ngx_str_t *value;
- ngx_http_compile_complex_value_t ccv;
-
- value = cf->args->elts;
-
- if (uwcf->cache_key.value.data) {
- return "is duplicate";
- }
-
- ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));
-
- ccv.cf = cf;
- ccv.value = &value[1];
- ccv.complex_value = &uwcf->cache_key;
-
- if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
- return NGX_CONF_ERROR;
- }
-
- return NGX_CONF_OK;
-}
-
-#endif
-
-
-#if (NGX_HTTP_SSL)
-
-static char *
-ngx_http_uwsgi_ssl_password_file(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
-{
- ngx_http_uwsgi_loc_conf_t *uwcf = conf;
-
- ngx_str_t *value;
-
- if (uwcf->ssl_passwords != NGX_CONF_UNSET_PTR) {
- return "is duplicate";
- }
-
- value = cf->args->elts;
-
- uwcf->ssl_passwords = ngx_ssl_read_password_file(cf, &value[1]);
-
- if (uwcf->ssl_passwords == NULL) {
- return NGX_CONF_ERROR;
- }
-
- return NGX_CONF_OK;
-}
-
-
-static ngx_int_t
-ngx_http_uwsgi_set_ssl(ngx_conf_t *cf, ngx_http_uwsgi_loc_conf_t *uwcf)
-{
- ngx_pool_cleanup_t *cln;
-
- uwcf->upstream.ssl = ngx_pcalloc(cf->pool, sizeof(ngx_ssl_t));
- if (uwcf->upstream.ssl == NULL) {
- return NGX_ERROR;
- }
-
- uwcf->upstream.ssl->log = cf->log;
-
- if (ngx_ssl_create(uwcf->upstream.ssl, uwcf->ssl_protocols, NULL)
- != NGX_OK)
- {
- return NGX_ERROR;
- }
-
- cln = ngx_pool_cleanup_add(cf->pool, 0);
- if (cln == NULL) {
- return NGX_ERROR;
- }
-
- cln->handler = ngx_ssl_cleanup_ctx;
- cln->data = uwcf->upstream.ssl;
-
- if (uwcf->ssl_certificate.len) {
-
- if (uwcf->ssl_certificate_key.len == 0) {
- ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
- "no \"uwsgi_ssl_certificate_key\" is defined "
- "for certificate \"%V\"", &uwcf->ssl_certificate);
- return NGX_ERROR;
- }
-
- if (ngx_ssl_certificate(cf, uwcf->upstream.ssl, &uwcf->ssl_certificate,
- &uwcf->ssl_certificate_key, uwcf->ssl_passwords)
- != NGX_OK)
- {
- return NGX_ERROR;
- }
- }
-
- if (ngx_ssl_ciphers(cf, uwcf->upstream.ssl, &uwcf->ssl_ciphers, 0)
- != NGX_OK)
- {
- return NGX_ERROR;
- }
-
- if (uwcf->upstream.ssl_verify) {
- if (uwcf->ssl_trusted_certificate.len == 0) {
- ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
- "no uwsgi_ssl_trusted_certificate for uwsgi_ssl_verify");
- return NGX_ERROR;
- }
-
- if (ngx_ssl_trusted_certificate(cf, uwcf->upstream.ssl,
- &uwcf->ssl_trusted_certificate,
- uwcf->ssl_verify_depth)
- != NGX_OK)
- {
- return NGX_ERROR;
- }
-
- if (ngx_ssl_crl(cf, uwcf->upstream.ssl, &uwcf->ssl_crl) != NGX_OK) {
- return NGX_ERROR;
- }
- }
-
- return NGX_OK;
-}
-
-#endif
diff --git a/nginx/src/http/modules/ngx_http_xslt_filter_module.c b/nginx/src/http/modules/ngx_http_xslt_filter_module.c
deleted file mode 100644
index ea7ce2a..0000000
--- a/nginx/src/http/modules/ngx_http_xslt_filter_module.c
+++ /dev/null
@@ -1,1158 +0,0 @@
-
-/*
- * Copyright (C) Igor Sysoev
- * Copyright (C) Nginx, Inc.
- */
-
-
-#include <ngx_config.h>
-#include <ngx_core.h>
-#include <ngx_http.h>
-
-#include <libxml/parser.h>
-#include <libxml/tree.h>
-#include <libxslt/xslt.h>
-#include <libxslt/xsltInternals.h>
-#include <libxslt/transform.h>
-#include <libxslt/variables.h>
-#include <libxslt/xsltutils.h>
-
-#if (NGX_HAVE_EXSLT)
-#include <libexslt/exslt.h>
-#endif
-
-
-#ifndef NGX_HTTP_XSLT_REUSE_DTD
-#define NGX_HTTP_XSLT_REUSE_DTD 1
-#endif
-
-
-typedef struct {
- u_char *name;
- void *data;
-} ngx_http_xslt_file_t;
-
-
-typedef struct {
- ngx_array_t dtd_files; /* ngx_http_xslt_file_t */
- ngx_array_t sheet_files; /* ngx_http_xslt_file_t */
-} ngx_http_xslt_filter_main_conf_t;
-
-
-typedef struct {
- u_char *name;
- ngx_http_complex_value_t value;
- ngx_uint_t quote; /* unsigned quote:1; */
-} ngx_http_xslt_param_t;
-
-
-typedef struct {
- xsltStylesheetPtr stylesheet;
- ngx_array_t params; /* ngx_http_xslt_param_t */
-} ngx_http_xslt_sheet_t;
-
-
-typedef struct {
- xmlDtdPtr dtd;
- ngx_array_t sheets; /* ngx_http_xslt_sheet_t */
- ngx_hash_t types;
- ngx_array_t *types_keys;
- ngx_array_t *params; /* ngx_http_xslt_param_t */
- ngx_flag_t last_modified;
-} ngx_http_xslt_filter_loc_conf_t;
-
-
-typedef struct {
- xmlDocPtr doc;
- xmlParserCtxtPtr ctxt;
- xsltTransformContextPtr transform;
- ngx_http_request_t *request;
- ngx_array_t params;
-
- ngx_uint_t done; /* unsigned done:1; */
-} ngx_http_xslt_filter_ctx_t;
-
-
-static ngx_int_t ngx_http_xslt_send(ngx_http_request_t *r,
- ngx_http_xslt_filter_ctx_t *ctx, ngx_buf_t *b);
-static ngx_int_t ngx_http_xslt_add_chunk(ngx_http_request_t *r,
- ngx_http_xslt_filter_ctx_t *ctx, ngx_buf_t *b);
-
-
-static void ngx_http_xslt_sax_external_subset(void *data, const xmlChar *name,
- const xmlChar *externalId, const xmlChar *systemId);
-static void ngx_cdecl ngx_http_xslt_sax_error(void *data, const char *msg, ...);
-
-
-static ngx_buf_t *ngx_http_xslt_apply_stylesheet(ngx_http_request_t *r,
- ngx_http_xslt_filter_ctx_t *ctx);
-static ngx_int_t ngx_http_xslt_params(ngx_http_request_t *r,
- ngx_http_xslt_filter_ctx_t *ctx, ngx_array_t *params, ngx_uint_t final);
-static u_char *ngx_http_xslt_content_type(xsltStylesheetPtr s);
-static u_char *ngx_http_xslt_encoding(xsltStylesheetPtr s);
-static void ngx_http_xslt_cleanup(void *data);
-
-static char *ngx_http_xslt_entities(ngx_conf_t *cf, ngx_command_t *cmd,
- void *conf);
-static char *ngx_http_xslt_stylesheet(ngx_conf_t *cf, ngx_command_t *cmd,
- void *conf);
-static char *ngx_http_xslt_param(ngx_conf_t *cf, ngx_command_t *cmd,
- void *conf);
-static void ngx_http_xslt_cleanup_dtd(void *data);
-static void ngx_http_xslt_cleanup_stylesheet(void *data);
-static void *ngx_http_xslt_filter_create_main_conf(ngx_conf_t *cf);
-static void *ngx_http_xslt_filter_create_conf(ngx_conf_t *cf);
-static char *ngx_http_xslt_filter_merge_conf(ngx_conf_t *cf, void *parent,
- void *child);
-static ngx_int_t ngx_http_xslt_filter_preconfiguration(ngx_conf_t *cf);
-static ngx_int_t ngx_http_xslt_filter_init(ngx_conf_t *cf);
-static void ngx_http_xslt_filter_exit(ngx_cycle_t *cycle);
-
-
-static ngx_str_t ngx_http_xslt_default_types[] = {
- ngx_string("text/xml"),
- ngx_null_string
-};
-
-
-static ngx_command_t ngx_http_xslt_filter_commands[] = {
-
- { ngx_string("xml_entities"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
- ngx_http_xslt_entities,
- NGX_HTTP_LOC_CONF_OFFSET,
- 0,
- NULL },
-
- { ngx_string("xslt_stylesheet"),
- NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
- ngx_http_xslt_stylesheet,
- NGX_HTTP_LOC_CONF_OFFSET,
- 0,
- NULL },
-
- { ngx_string("xslt_param"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE2,
- ngx_http_xslt_param,
- NGX_HTTP_LOC_CONF_OFFSET,
- 0,
- NULL },
-
- { ngx_string("xslt_string_param"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE2,
- ngx_http_xslt_param,
- NGX_HTTP_LOC_CONF_OFFSET,
- 0,
- (void *) 1 },
-
- { ngx_string("xslt_types"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
- ngx_http_types_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_xslt_filter_loc_conf_t, types_keys),
- &ngx_http_xslt_default_types[0] },
-
- { ngx_string("xslt_last_modified"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
- ngx_conf_set_flag_slot,
- NGX_HTTP_LOC_CONF_OFFSET,
- offsetof(ngx_http_xslt_filter_loc_conf_t, last_modified),
- NULL },
-
- ngx_null_command
-};
-
-
-static ngx_http_module_t ngx_http_xslt_filter_module_ctx = {
- ngx_http_xslt_filter_preconfiguration, /* preconfiguration */
- ngx_http_xslt_filter_init, /* postconfiguration */
-
- ngx_http_xslt_filter_create_main_conf, /* create main configuration */
- NULL, /* init main configuration */
-
- NULL, /* create server configuration */
- NULL, /* merge server configuration */
-
- ngx_http_xslt_filter_create_conf, /* create location configuration */
- ngx_http_xslt_filter_merge_conf /* merge location configuration */
-};
-
-
-ngx_module_t ngx_http_xslt_filter_module = {
- NGX_MODULE_V1,
- &ngx_http_xslt_filter_module_ctx, /* module context */
- ngx_http_xslt_filter_commands, /* module directives */
- NGX_HTTP_MODULE, /* module type */
- NULL, /* init master */
- NULL, /* init module */
- NULL, /* init process */
- NULL, /* init thread */
- NULL, /* exit thread */
- ngx_http_xslt_filter_exit, /* exit process */
- ngx_http_xslt_filter_exit, /* exit master */
- NGX_MODULE_V1_PADDING
-};
-
-
-static ngx_http_output_header_filter_pt ngx_http_next_header_filter;
-static ngx_http_output_body_filter_pt ngx_http_next_body_filter;
-
-
-static ngx_int_t
-ngx_http_xslt_header_filter(ngx_http_request_t *r)
-{
- ngx_http_xslt_filter_ctx_t *ctx;
- ngx_http_xslt_filter_loc_conf_t *conf;
-
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "xslt filter header");
-
- if (r->headers_out.status == NGX_HTTP_NOT_MODIFIED) {
- return ngx_http_next_header_filter(r);
- }
-
- conf = ngx_http_get_module_loc_conf(r, ngx_http_xslt_filter_module);
-
- if (conf->sheets.nelts == 0
- || ngx_http_test_content_type(r, &conf->types) == NULL)
- {
- return ngx_http_next_header_filter(r);
- }
-
- ctx = ngx_http_get_module_ctx(r, ngx_http_xslt_filter_module);
-
- if (ctx) {
- return ngx_http_next_header_filter(r);
- }
-
- ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_xslt_filter_ctx_t));
- if (ctx == NULL) {
- return NGX_ERROR;
- }
-
- ngx_http_set_ctx(r, ctx, ngx_http_xslt_filter_module);
-
- r->main_filter_need_in_memory = 1;
-
- return NGX_OK;
-}
-
-
-static ngx_int_t
-ngx_http_xslt_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
-{
- int wellFormed;
- ngx_chain_t *cl;
- ngx_http_xslt_filter_ctx_t *ctx;
-
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "xslt filter body");
-
- if (in == NULL) {
- return ngx_http_next_body_filter(r, in);
- }
-
- ctx = ngx_http_get_module_ctx(r, ngx_http_xslt_filter_module);
-
- if (ctx == NULL || ctx->done) {
- return ngx_http_next_body_filter(r, in);
- }
-
- for (cl = in; cl; cl = cl->next) {
-
- if (ngx_http_xslt_add_chunk(r, ctx, cl->buf) != NGX_OK) {
-
- if (ctx->ctxt->myDoc) {
-
-#if (NGX_HTTP_XSLT_REUSE_DTD)
- ctx->ctxt->myDoc->extSubset = NULL;
-#endif
- xmlFreeDoc(ctx->ctxt->myDoc);
- }
-
- xmlFreeParserCtxt(ctx->ctxt);
-
- return ngx_http_xslt_send(r, ctx, NULL);
- }
-
- if (cl->buf->last_buf || cl->buf->last_in_chain) {
-
- ctx->doc = ctx->ctxt->myDoc;
-
-#if (NGX_HTTP_XSLT_REUSE_DTD)
- ctx->doc->extSubset = NULL;
-#endif
-
- wellFormed = ctx->ctxt->wellFormed;
-
- xmlFreeParserCtxt(ctx->ctxt);
-
- if (wellFormed) {
- return ngx_http_xslt_send(r, ctx,
- ngx_http_xslt_apply_stylesheet(r, ctx));
- }
-
- xmlFreeDoc(ctx->doc);
-
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "not well formed XML document");
-
- return ngx_http_xslt_send(r, ctx, NULL);
- }
- }
-
- return NGX_OK;
-}
-
-
-static ngx_int_t
-ngx_http_xslt_send(ngx_http_request_t *r, ngx_http_xslt_filter_ctx_t *ctx,
- ngx_buf_t *b)
-{
- ngx_int_t rc;
- ngx_chain_t out;
- ngx_pool_cleanup_t *cln;
- ngx_http_xslt_filter_loc_conf_t *conf;
-
- ctx->done = 1;
-
- if (b == NULL) {
- return ngx_http_filter_finalize_request(r, &ngx_http_xslt_filter_module,
- NGX_HTTP_INTERNAL_SERVER_ERROR);
- }
-
- cln = ngx_pool_cleanup_add(r->pool, 0);
-
- if (cln == NULL) {
- ngx_free(b->pos);
- return ngx_http_filter_finalize_request(r, &ngx_http_xslt_filter_module,
- NGX_HTTP_INTERNAL_SERVER_ERROR);
- }
-
- if (r == r->main) {
- r->headers_out.content_length_n = b->last - b->pos;
-
- if (r->headers_out.content_length) {
- r->headers_out.content_length->hash = 0;
- r->headers_out.content_length = NULL;
- }
-
- conf = ngx_http_get_module_loc_conf(r, ngx_http_xslt_filter_module);
-
- if (!conf->last_modified) {
- ngx_http_clear_last_modified(r);
- ngx_http_clear_etag(r);
-
- } else {
- ngx_http_weak_etag(r);
- }
- }
-
- rc = ngx_http_next_header_filter(r);
-
- if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) {
- ngx_free(b->pos);
- return rc;
- }
-
- cln->handler = ngx_http_xslt_cleanup;
- cln->data = b->pos;
-
- out.buf = b;
- out.next = NULL;
-
- return ngx_http_next_body_filter(r, &out);
-}
-
-
-static ngx_int_t
-ngx_http_xslt_add_chunk(ngx_http_request_t *r, ngx_http_xslt_filter_ctx_t *ctx,
- ngx_buf_t *b)
-{
- int err;
- xmlParserCtxtPtr ctxt;
-
- if (ctx->ctxt == NULL) {
-
- ctxt = xmlCreatePushParserCtxt(NULL, NULL, NULL, 0, NULL);
- if (ctxt == NULL) {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "xmlCreatePushParserCtxt() failed");
- return NGX_ERROR;
- }
- xmlCtxtUseOptions(ctxt, XML_PARSE_NOENT|XML_PARSE_DTDLOAD
- |XML_PARSE_NOWARNING);
-
- ctxt->sax->externalSubset = ngx_http_xslt_sax_external_subset;
- ctxt->sax->setDocumentLocator = NULL;
- ctxt->sax->error = ngx_http_xslt_sax_error;
- ctxt->sax->fatalError = ngx_http_xslt_sax_error;
- ctxt->sax->_private = ctx;
-
- ctx->ctxt = ctxt;
- ctx->request = r;
- }
-
- err = xmlParseChunk(ctx->ctxt, (char *) b->pos, (int) (b->last - b->pos),
- (b->last_buf) || (b->last_in_chain));
-
- if (err == 0) {
- b->pos = b->last;
- return NGX_OK;
- }
-
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "xmlParseChunk() failed, error:%d", err);
-
- return NGX_ERROR;
-}
-
-
-static void
-ngx_http_xslt_sax_external_subset(void *data, const xmlChar *name,
- const xmlChar *externalId, const xmlChar *systemId)
-{
- xmlParserCtxtPtr ctxt = data;
-
- xmlDocPtr doc;
- xmlDtdPtr dtd;
- ngx_http_request_t *r;
- ngx_http_xslt_filter_ctx_t *ctx;
- ngx_http_xslt_filter_loc_conf_t *conf;
-
- ctx = ctxt->sax->_private;
- r = ctx->request;
-
- conf = ngx_http_get_module_loc_conf(r, ngx_http_xslt_filter_module);
-
- ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "xslt filter extSubset: \"%s\" \"%s\" \"%s\"",
- name ? name : (xmlChar *) "",
- externalId ? externalId : (xmlChar *) "",
- systemId ? systemId : (xmlChar *) "");
-
- doc = ctxt->myDoc;
-
-#if (NGX_HTTP_XSLT_REUSE_DTD)
-
- dtd = conf->dtd;
-
-#else
-
- dtd = xmlCopyDtd(conf->dtd);
- if (dtd == NULL) {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "xmlCopyDtd() failed");
- return;
- }
-
- if (doc->children == NULL) {
- xmlAddChild((xmlNodePtr) doc, (xmlNodePtr) dtd);
-
- } else {
- xmlAddPrevSibling(doc->children, (xmlNodePtr) dtd);
- }
-
-#endif
-
- doc->extSubset = dtd;
-}
-
-
-static void ngx_cdecl
-ngx_http_xslt_sax_error(void *data, const char *msg, ...)
-{
- xmlParserCtxtPtr ctxt = data;
-
- size_t n;
- va_list args;
- ngx_http_xslt_filter_ctx_t *ctx;
- u_char buf[NGX_MAX_ERROR_STR];
-
- ctx = ctxt->sax->_private;
-
- buf[0] = '\0';
-
- va_start(args, msg);
- n = (size_t) vsnprintf((char *) buf, NGX_MAX_ERROR_STR, msg, args);
- va_end(args);
-
- while (--n && (buf[n] == CR || buf[n] == LF)) { /* void */ }
-
- ngx_log_error(NGX_LOG_ERR, ctx->request->connection->log, 0,
- "libxml2 error: \"%*s\"", n + 1, buf);
-}
-
-
-static ngx_buf_t *
-ngx_http_xslt_apply_stylesheet(ngx_http_request_t *r,
- ngx_http_xslt_filter_ctx_t *ctx)
-{
- int len, rc, doc_type;
- u_char *type, *encoding;
- ngx_buf_t *b;
- ngx_uint_t i;
- xmlChar *buf;
- xmlDocPtr doc, res;
- ngx_http_xslt_sheet_t *sheet;
- ngx_http_xslt_filter_loc_conf_t *conf;
-
- conf = ngx_http_get_module_loc_conf(r, ngx_http_xslt_filter_module);
- sheet = conf->sheets.elts;
- doc = ctx->doc;
-
- /* preallocate array for 4 params */
-
- if (ngx_array_init(&ctx->params, r->pool, 4 * 2 + 1, sizeof(char *))
- != NGX_OK)
- {
- xmlFreeDoc(doc);
- return NULL;
- }
-
- for (i = 0; i < conf->sheets.nelts; i++) {
-
- ctx->transform = xsltNewTransformContext(sheet[i].stylesheet, doc);
- if (ctx->transform == NULL) {
- xmlFreeDoc(doc);
- return NULL;
- }
-
- if (conf->params
- && ngx_http_xslt_params(r, ctx, conf->params, 0) != NGX_OK)
- {
- xsltFreeTransformContext(ctx->transform);
- xmlFreeDoc(doc);
- return NULL;
- }
-
- if (ngx_http_xslt_params(r, ctx, &sheet[i].params, 1) != NGX_OK) {
- xsltFreeTransformContext(ctx->transform);
- xmlFreeDoc(doc);
- return NULL;
- }
-
- res = xsltApplyStylesheetUser(sheet[i].stylesheet, doc,
- ctx->params.elts, NULL, NULL,
- ctx->transform);
-
- xsltFreeTransformContext(ctx->transform);
- xmlFreeDoc(doc);
-
- if (res == NULL) {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "xsltApplyStylesheet() failed");
- return NULL;
- }
-
- doc = res;
-
- /* reset array elements */
- ctx->params.nelts = 0;
- }
-
- /* there must be at least one stylesheet */
-
- if (r == r->main) {
- type = ngx_http_xslt_content_type(sheet[i - 1].stylesheet);
-
- } else {
- type = NULL;
- }
-
- encoding = ngx_http_xslt_encoding(sheet[i - 1].stylesheet);
- doc_type = doc->type;
-
- ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "xslt filter type: %d t:%s e:%s",
- doc_type, type ? type : (u_char *) "(null)",
- encoding ? encoding : (u_char *) "(null)");
-
- rc = xsltSaveResultToString(&buf, &len, doc, sheet[i - 1].stylesheet);
-
- xmlFreeDoc(doc);
-
- if (rc != 0) {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "xsltSaveResultToString() failed");
- return NULL;
- }
-
- if (len == 0) {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "xsltSaveResultToString() returned zero-length result");
- return NULL;
- }
-
- b = ngx_calloc_buf(r->pool);
- if (b == NULL) {
- ngx_free(buf);
- return NULL;
- }
-
- b->pos = buf;
- b->last = buf + len;
- b->memory = 1;
-
- if (encoding) {
- r->headers_out.charset.len = ngx_strlen(encoding);
- r->headers_out.charset.data = encoding;
- }
-
- if (r != r->main) {
- return b;
- }
-
- b->last_buf = 1;
-
- if (type) {
- len = ngx_strlen(type);
-
- r->headers_out.content_type_len = len;
- r->headers_out.content_type.len = len;
- r->headers_out.content_type.data = type;
-
- } else if (doc_type == XML_HTML_DOCUMENT_NODE) {
-
- r->headers_out.content_type_len = sizeof("text/html") - 1;
- ngx_str_set(&r->headers_out.content_type, "text/html");
- }
-
- r->headers_out.content_type_lowcase = NULL;
-
- return b;
-}
-
-
-static ngx_int_t
-ngx_http_xslt_params(ngx_http_request_t *r, ngx_http_xslt_filter_ctx_t *ctx,
- ngx_array_t *params, ngx_uint_t final)
-{
- u_char *p, *last, *value, *dst, *src, **s;
- size_t len;
- ngx_uint_t i;
- ngx_str_t string;
- ngx_http_xslt_param_t *param;
-
- param = params->elts;
-
- for (i = 0; i < params->nelts; i++) {
-
- if (ngx_http_complex_value(r, &param[i].value, &string) != NGX_OK) {
- return NGX_ERROR;
- }
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "xslt filter param: \"%s\"", string.data);
-
- if (param[i].name) {
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "xslt filter param name: \"%s\"", param[i].name);
-
- if (param[i].quote) {
- if (xsltQuoteOneUserParam(ctx->transform, param[i].name,
- string.data)
- != 0)
- {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "xsltQuoteOneUserParam(\"%s\", \"%s\") failed",
- param[i].name, string.data);
- return NGX_ERROR;
- }
-
- continue;
- }
-
- s = ngx_array_push(&ctx->params);
- if (s == NULL) {
- return NGX_ERROR;
- }
-
- *s = param[i].name;
-
- s = ngx_array_push(&ctx->params);
- if (s == NULL) {
- return NGX_ERROR;
- }
-
- *s = string.data;
-
- continue;
- }
-
- /*
- * parse param1=value1:param2=value2 syntax as used by parameters
- * specified in xslt_stylesheet directives
- */
-
- if (param[i].value.lengths) {
- p = string.data;
-
- } else {
- p = ngx_pnalloc(r->pool, string.len + 1);
- if (p == NULL) {
- return NGX_ERROR;
- }
-
- ngx_memcpy(p, string.data, string.len + 1);
- }
-
- last = p + string.len;
-
- while (p && *p) {
-
- value = p;
- p = (u_char *) ngx_strchr(p, '=');
- if (p == NULL) {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "invalid libxslt parameter \"%s\"", value);
- return NGX_ERROR;
- }
- *p++ = '\0';
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "xslt filter param name: \"%s\"", value);
-
- s = ngx_array_push(&ctx->params);
- if (s == NULL) {
- return NGX_ERROR;
- }
-
- *s = value;
-
- value = p;
- p = (u_char *) ngx_strchr(p, ':');
-
- if (p) {
- len = p - value;
- *p++ = '\0';
-
- } else {
- len = last - value;
- }
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "xslt filter param value: \"%s\"", value);
-
- dst = value;
- src = value;
-
- ngx_unescape_uri(&dst, &src, len, 0);
-
- *dst = '\0';
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "xslt filter param unescaped: \"%s\"", value);
-
- s = ngx_array_push(&ctx->params);
- if (s == NULL) {
- return NGX_ERROR;
- }
-
- *s = value;
- }
- }
-
- if (final) {
- s = ngx_array_push(&ctx->params);
- if (s == NULL) {
- return NGX_ERROR;
- }
-
- *s = NULL;
- }
-
- return NGX_OK;
-}
-
-
-static u_char *
-ngx_http_xslt_content_type(xsltStylesheetPtr s)
-{
- u_char *type;
-
- if (s->mediaType) {
- return s->mediaType;
- }
-
- for (s = s->imports; s; s = s->next) {
-
- type = ngx_http_xslt_content_type(s);
-
- if (type) {
- return type;
- }
- }
-
- return NULL;
-}
-
-
-static u_char *
-ngx_http_xslt_encoding(xsltStylesheetPtr s)
-{
- u_char *encoding;
-
- if (s->encoding) {
- return s->encoding;
- }
-
- for (s = s->imports; s; s = s->next) {
-
- encoding = ngx_http_xslt_encoding(s);
-
- if (encoding) {
- return encoding;
- }
- }
-
- return NULL;
-}
-
-
-static void
-ngx_http_xslt_cleanup(void *data)
-{
- ngx_free(data);
-}
-
-
-static char *
-ngx_http_xslt_entities(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
-{
- ngx_http_xslt_filter_loc_conf_t *xlcf = conf;
-
- ngx_str_t *value;
- ngx_uint_t i;
- ngx_pool_cleanup_t *cln;
- ngx_http_xslt_file_t *file;
- ngx_http_xslt_filter_main_conf_t *xmcf;
-
- if (xlcf->dtd) {
- return "is duplicate";
- }
-
- value = cf->args->elts;
-
- xmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_xslt_filter_module);
-
- file = xmcf->dtd_files.elts;
- for (i = 0; i < xmcf->dtd_files.nelts; i++) {
- if (ngx_strcmp(file[i].name, value[1].data) == 0) {
- xlcf->dtd = file[i].data;
- return NGX_CONF_OK;
- }
- }
-
- cln = ngx_pool_cleanup_add(cf->pool, 0);
- if (cln == NULL) {
- return NGX_CONF_ERROR;
- }
-
- xlcf->dtd = xmlParseDTD(NULL, (xmlChar *) value[1].data);
-
- if (xlcf->dtd == NULL) {
- ngx_conf_log_error(NGX_LOG_ERR, cf, 0, "xmlParseDTD() failed");
- return NGX_CONF_ERROR;
- }
-
- cln->handler = ngx_http_xslt_cleanup_dtd;
- cln->data = xlcf->dtd;
-
- file = ngx_array_push(&xmcf->dtd_files);
- if (file == NULL) {
- return NGX_CONF_ERROR;
- }
-
- file->name = value[1].data;
- file->data = xlcf->dtd;
-
- return NGX_CONF_OK;
-}
-
-
-
-static char *
-ngx_http_xslt_stylesheet(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
-{
- ngx_http_xslt_filter_loc_conf_t *xlcf = conf;
-
- ngx_str_t *value;
- ngx_uint_t i, n;
- ngx_pool_cleanup_t *cln;
- ngx_http_xslt_file_t *file;
- ngx_http_xslt_sheet_t *sheet;
- ngx_http_xslt_param_t *param;
- ngx_http_compile_complex_value_t ccv;
- ngx_http_xslt_filter_main_conf_t *xmcf;
-
- value = cf->args->elts;
-
- if (xlcf->sheets.elts == NULL) {
- if (ngx_array_init(&xlcf->sheets, cf->pool, 1,
- sizeof(ngx_http_xslt_sheet_t))
- != NGX_OK)
- {
- return NGX_CONF_ERROR;
- }
- }
-
- sheet = ngx_array_push(&xlcf->sheets);
- if (sheet == NULL) {
- return NGX_CONF_ERROR;
- }
-
- ngx_memzero(sheet, sizeof(ngx_http_xslt_sheet_t));
-
- if (ngx_conf_full_name(cf->cycle, &value[1], 0) != NGX_OK) {
- return NGX_CONF_ERROR;
- }
-
- xmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_xslt_filter_module);
-
- file = xmcf->sheet_files.elts;
- for (i = 0; i < xmcf->sheet_files.nelts; i++) {
- if (ngx_strcmp(file[i].name, value[1].data) == 0) {
- sheet->stylesheet = file[i].data;
- goto found;
- }
- }
-
- cln = ngx_pool_cleanup_add(cf->pool, 0);
- if (cln == NULL) {
- return NGX_CONF_ERROR;
- }
-
- sheet->stylesheet = xsltParseStylesheetFile(value[1].data);
- if (sheet->stylesheet == NULL) {
- ngx_conf_log_error(NGX_LOG_ERR, cf, 0,
- "xsltParseStylesheetFile(\"%s\") failed",
- value[1].data);
- return NGX_CONF_ERROR;
- }
-
- cln->handler = ngx_http_xslt_cleanup_stylesheet;
- cln->data = sheet->stylesheet;
-
- file = ngx_array_push(&xmcf->sheet_files);
- if (file == NULL) {
- return NGX_CONF_ERROR;
- }
-
- file->name = value[1].data;
- file->data = sheet->stylesheet;
-
-found:
-
- n = cf->args->nelts;
-
- if (n == 2) {
- return NGX_CONF_OK;
- }
-
- if (ngx_array_init(&sheet->params, cf->pool, n - 2,
- sizeof(ngx_http_xslt_param_t))
- != NGX_OK)
- {
- return NGX_CONF_ERROR;
- }
-
- for (i = 2; i < n; i++) {
-
- param = ngx_array_push(&sheet->params);
- if (param == NULL) {
- return NGX_CONF_ERROR;
- }
-
- ngx_memzero(param, sizeof(ngx_http_xslt_param_t));
- ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));
-
- ccv.cf = cf;
- ccv.value = &value[i];
- ccv.complex_value = &param->value;
- ccv.zero = 1;
-
- if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
- return NGX_CONF_ERROR;
- }
- }
-
- return NGX_CONF_OK;
-}
-
-
-static char *
-ngx_http_xslt_param(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
-{
- ngx_http_xslt_filter_loc_conf_t *xlcf = conf;
-
- ngx_http_xslt_param_t *param;
- ngx_http_compile_complex_value_t ccv;
- ngx_str_t *value;
-
- value = cf->args->elts;
-
- if (xlcf->params == NULL) {
- xlcf->params = ngx_array_create(cf->pool, 2,
- sizeof(ngx_http_xslt_param_t));
- if (xlcf->params == NULL) {
- return NGX_CONF_ERROR;
- }
- }
-
- param = ngx_array_push(xlcf->params);
- if (param == NULL) {
- return NGX_CONF_ERROR;
- }
-
- param->name = value[1].data;
- param->quote = (cmd->post == NULL) ? 0 : 1;
-
- ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));
-
- ccv.cf = cf;
- ccv.value = &value[2];
- ccv.complex_value = &param->value;
- ccv.zero = 1;
-
- if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
- return NGX_CONF_ERROR;
- }
-
- return NGX_CONF_OK;
-}
-
-
-static void
-ngx_http_xslt_cleanup_dtd(void *data)
-{
- xmlFreeDtd(data);
-}
-
-
-static void
-ngx_http_xslt_cleanup_stylesheet(void *data)
-{
- xsltFreeStylesheet(data);
-}
-
-
-static void *
-ngx_http_xslt_filter_create_main_conf(ngx_conf_t *cf)
-{
- ngx_http_xslt_filter_main_conf_t *conf;
-
- conf = ngx_palloc(cf->pool, sizeof(ngx_http_xslt_filter_main_conf_t));
- if (conf == NULL) {
- return NULL;
- }
-
- if (ngx_array_init(&conf->dtd_files, cf->pool, 1,
- sizeof(ngx_http_xslt_file_t))
- != NGX_OK)
- {
- return NULL;
- }
-
- if (ngx_array_init(&conf->sheet_files, cf->pool, 1,
- sizeof(ngx_http_xslt_file_t))
- != NGX_OK)
- {
- return NULL;
- }
-
- return conf;
-}
-
-
-static void *
-ngx_http_xslt_filter_create_conf(ngx_conf_t *cf)
-{
- ngx_http_xslt_filter_loc_conf_t *conf;
-
- conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_xslt_filter_loc_conf_t));
- if (conf == NULL) {
- return NULL;
- }
-
- /*
- * set by ngx_pcalloc():
- *
- * conf->dtd = NULL;
- * conf->sheets = { NULL };
- * conf->types = { NULL };
- * conf->types_keys = NULL;
- * conf->params = NULL;
- */
-
- conf->last_modified = NGX_CONF_UNSET;
-
- return conf;
-}
-
-
-static char *
-ngx_http_xslt_filter_merge_conf(ngx_conf_t *cf, void *parent, void *child)
-{
- ngx_http_xslt_filter_loc_conf_t *prev = parent;
- ngx_http_xslt_filter_loc_conf_t *conf = child;
-
- if (conf->dtd == NULL) {
- conf->dtd = prev->dtd;
- }
-
- if (conf->sheets.nelts == 0) {
- conf->sheets = prev->sheets;
- }
-
- if (conf->params == NULL) {
- conf->params = prev->params;
- }
-
- if (ngx_http_merge_types(cf, &conf->types_keys, &conf->types,
- &prev->types_keys, &prev->types,
- ngx_http_xslt_default_types)
- != NGX_OK)
- {
- return NGX_CONF_ERROR;
- }
-
- ngx_conf_merge_value(conf->last_modified, prev->last_modified, 0);
-
- return NGX_CONF_OK;
-}
-
-
-static ngx_int_t
-ngx_http_xslt_filter_preconfiguration(ngx_conf_t *cf)
-{
- xmlInitParser();
-
-#if (NGX_HAVE_EXSLT)
- exsltRegisterAll();
-#endif
-
- return NGX_OK;
-}
-
-
-static ngx_int_t
-ngx_http_xslt_filter_init(ngx_conf_t *cf)
-{
- ngx_http_next_header_filter = ngx_http_top_header_filter;
- ngx_http_top_header_filter = ngx_http_xslt_header_filter;
-
- ngx_http_next_body_filter = ngx_http_top_body_filter;
- ngx_http_top_body_filter = ngx_http_xslt_body_filter;
-
- return NGX_OK;
-}
-
-
-static void
-ngx_http_xslt_filter_exit(ngx_cycle_t *cycle)
-{
- xsltCleanupGlobals();
- xmlCleanupParser();
-}
diff --git a/nginx/src/http/modules/perl/Makefile.PL b/nginx/src/http/modules/perl/Makefile.PL
deleted file mode 100644
index 7edadcb..0000000
--- a/nginx/src/http/modules/perl/Makefile.PL
+++ /dev/null
@@ -1,35 +0,0 @@
-
-# Copyright (C) Igor Sysoev
-# Copyright (C) Nginx, Inc.
-
-use 5.006001;
-use ExtUtils::MakeMaker;
-
-WriteMakefile(
- NAME => 'nginx',
- VERSION_FROM => 'nginx.pm', # finds $VERSION
- PREREQ_PM => {}, # e.g., Module::Name => 1.1
-
- ABSTRACT_FROM => 'nginx.pm', # retrieve abstract from module
- AUTHOR => 'Igor Sysoev',
-
- CCFLAGS => "$ENV{NGX_PM_CFLAGS}",
- OPTIMIZE => '-O',
-
- LDDLFLAGS => "$ENV{NGX_PM_LDFLAGS}",
-
- INC => join(" ", map {
- m#^/# ? "-I $_" : "-I ../../../../../$_"
- } (split /\s+/, $ENV{NGX_INCS})),
-
- depend => {
- 'nginx.c' => join(" ", map {
- m#^/# ? $_ : "../../../../../$_"
- } (split(/\s+/, $ENV{NGX_DEPS}),
- "src/http/modules/perl/ngx_http_perl_module.h"))
- },
-
- PM => {
- 'nginx.pm' => '$(INST_LIBDIR)/nginx.pm'
- }
-);
diff --git a/nginx/src/http/modules/perl/nginx.pm b/nginx/src/http/modules/perl/nginx.pm
deleted file mode 100644
index d4663dc..0000000
--- a/nginx/src/http/modules/perl/nginx.pm
+++ /dev/null
@@ -1,140 +0,0 @@
-package nginx;
-
-use 5.006001;
-use strict;
-use warnings;
-
-require Exporter;
-
-our @ISA = qw(Exporter);
-
-our @EXPORT = qw(
- OK
- DECLINED
-
- HTTP_OK
- HTTP_CREATED
- HTTP_ACCEPTED
- HTTP_NO_CONTENT
- HTTP_PARTIAL_CONTENT
-
- HTTP_MOVED_PERMANENTLY
- HTTP_MOVED_TEMPORARILY
- HTTP_REDIRECT
- HTTP_SEE_OTHER
- HTTP_NOT_MODIFIED
- HTTP_TEMPORARY_REDIRECT
- HTTP_PERMANENT_REDIRECT
-
- HTTP_BAD_REQUEST
- HTTP_UNAUTHORIZED
- HTTP_PAYMENT_REQUIRED
- HTTP_FORBIDDEN
- HTTP_NOT_FOUND
- HTTP_NOT_ALLOWED
- HTTP_NOT_ACCEPTABLE
- HTTP_REQUEST_TIME_OUT
- HTTP_CONFLICT
- HTTP_GONE
- HTTP_LENGTH_REQUIRED
- HTTP_REQUEST_ENTITY_TOO_LARGE
- HTTP_REQUEST_URI_TOO_LARGE
- HTTP_UNSUPPORTED_MEDIA_TYPE
- HTTP_RANGE_NOT_SATISFIABLE
-
- HTTP_INTERNAL_SERVER_ERROR
- HTTP_SERVER_ERROR
- HTTP_NOT_IMPLEMENTED
- HTTP_BAD_GATEWAY
- HTTP_SERVICE_UNAVAILABLE
- HTTP_GATEWAY_TIME_OUT
- HTTP_INSUFFICIENT_STORAGE
-);
-
-our $VERSION = '%%VERSION%%';
-
-require XSLoader;
-XSLoader::load('nginx', $VERSION);
-
-# Preloaded methods go here.
-
-use constant OK => 0;
-use constant DECLINED => -5;
-
-use constant HTTP_OK => 200;
-use constant HTTP_CREATED => 201;
-use constant HTTP_ACCEPTED => 202;
-use constant HTTP_NO_CONTENT => 204;
-use constant HTTP_PARTIAL_CONTENT => 206;
-
-use constant HTTP_MOVED_PERMANENTLY => 301;
-use constant HTTP_MOVED_TEMPORARILY => 302;
-use constant HTTP_REDIRECT => 302;
-use constant HTTP_SEE_OTHER => 303;
-use constant HTTP_NOT_MODIFIED => 304;
-use constant HTTP_TEMPORARY_REDIRECT => 307;
-use constant HTTP_PERMANENT_REDIRECT => 308;
-
-use constant HTTP_BAD_REQUEST => 400;
-use constant HTTP_UNAUTHORIZED => 401;
-use constant HTTP_PAYMENT_REQUIRED => 402;
-use constant HTTP_FORBIDDEN => 403;
-use constant HTTP_NOT_FOUND => 404;
-use constant HTTP_NOT_ALLOWED => 405;
-use constant HTTP_NOT_ACCEPTABLE => 406;
-use constant HTTP_REQUEST_TIME_OUT => 408;
-use constant HTTP_CONFLICT => 409;
-use constant HTTP_GONE => 410;
-use constant HTTP_LENGTH_REQUIRED => 411;
-use constant HTTP_REQUEST_ENTITY_TOO_LARGE => 413;
-use constant HTTP_REQUEST_URI_TOO_LARGE => 414;
-use constant HTTP_UNSUPPORTED_MEDIA_TYPE => 415;
-use constant HTTP_RANGE_NOT_SATISFIABLE => 416;
-
-use constant HTTP_INTERNAL_SERVER_ERROR => 500;
-use constant HTTP_SERVER_ERROR => 500;
-use constant HTTP_NOT_IMPLEMENTED => 501;
-use constant HTTP_BAD_GATEWAY => 502;
-use constant HTTP_SERVICE_UNAVAILABLE => 503;
-use constant HTTP_GATEWAY_TIME_OUT => 504;
-use constant HTTP_INSUFFICIENT_STORAGE => 507;
-
-
-sub rflush {
- my $r = shift;
-
- $r->flush;
-}
-
-
-1;
-__END__
-
-=head1 NAME
-
-nginx - Perl interface to the nginx HTTP server API
-
-=head1 SYNOPSIS
-
- use nginx;
-
-=head1 DESCRIPTION
-
-This module provides a Perl interface to the nginx HTTP server API.
-
-
-=head1 SEE ALSO
-
-http://nginx.org/en/docs/http/ngx_http_perl_module.html
-
-=head1 AUTHOR
-
-Igor Sysoev
-
-=head1 COPYRIGHT AND LICENSE
-
-Copyright (C) Igor Sysoev
-Copyright (C) Nginx, Inc.
-
-
-=cut
diff --git a/nginx/src/http/modules/perl/nginx.xs b/nginx/src/http/modules/perl/nginx.xs
deleted file mode 100644
index ad12632..0000000
--- a/nginx/src/http/modules/perl/nginx.xs
+++ /dev/null
@@ -1,1041 +0,0 @@
-
-/*
- * Copyright (C) Igor Sysoev
- * Copyright (C) Nginx, Inc.
- */
-
-
-#define PERL_NO_GET_CONTEXT
-
-#include <ngx_config.h>
-#include <ngx_core.h>
-#include <ngx_http.h>
-#include <ngx_http_perl_module.h>
-
-#include "XSUB.h"
-
-
-#define ngx_http_perl_set_request(r) \
- r = INT2PTR(ngx_http_request_t *, SvIV((SV *) SvRV(ST(0))))
-
-
-#define ngx_http_perl_set_targ(p, len) \
- \
- SvUPGRADE(TARG, SVt_PV); \
- SvPOK_on(TARG); \
- sv_setpvn(TARG, (char *) p, len)
-
-
-static ngx_int_t
-ngx_http_perl_sv2str(pTHX_ ngx_http_request_t *r, ngx_str_t *s, SV *sv)
-{
- u_char *p;
- STRLEN len;
-
- if (SvROK(sv) && SvTYPE(SvRV(sv)) == SVt_PV) {
- sv = SvRV(sv);
- }
-
- p = (u_char *) SvPV(sv, len);
-
- s->len = len;
-
- if (SvREADONLY(sv) && SvPOK(sv)) {
- s->data = p;
-
- ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "perl sv2str: %08XD \"%V\"", sv->sv_flags, s);
-
- return NGX_OK;
- }
-
- s->data = ngx_pnalloc(r->pool, len);
- if (s->data == NULL) {
- return NGX_ERROR;
- }
-
- ngx_memcpy(s->data, p, len);
-
- ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "perl sv2str: %08XD \"%V\"", sv->sv_flags, s);
-
- return NGX_OK;
-}
-
-
-static ngx_int_t
-ngx_http_perl_output(ngx_http_request_t *r, ngx_buf_t *b)
-{
- ngx_chain_t out;
-#if (NGX_HTTP_SSI)
- ngx_chain_t *cl;
- ngx_http_perl_ctx_t *ctx;
-
- ctx = ngx_http_get_module_ctx(r, ngx_http_perl_module);
-
- if (ctx->ssi) {
- cl = ngx_alloc_chain_link(r->pool);
- if (cl == NULL) {
- return NGX_ERROR;
- }
-
- cl->buf = b;
- cl->next = NULL;
- *ctx->ssi->last_out = cl;
- ctx->ssi->last_out = &cl->next;
-
- return NGX_OK;
- }
-#endif
-
- out.buf = b;
- out.next = NULL;
-
- return ngx_http_output_filter(r, &out);
-}
-
-
-MODULE = nginx PACKAGE = nginx
-
-
-PROTOTYPES: DISABLE
-
-
-void
-status(r, code)
- CODE:
-
- ngx_http_request_t *r;
-
- ngx_http_perl_set_request(r);
-
- r->headers_out.status = SvIV(ST(1));
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "perl status: %d", r->headers_out.status);
-
- XSRETURN_UNDEF;
-
-
-void
-send_http_header(r, ...)
- CODE:
-
- ngx_http_request_t *r;
- SV *sv;
-
- ngx_http_perl_set_request(r);
-
- if (r->headers_out.status == 0) {
- r->headers_out.status = NGX_HTTP_OK;
- }
-
- if (items != 1) {
- sv = ST(1);
-
- if (ngx_http_perl_sv2str(aTHX_ r, &r->headers_out.content_type, sv)
- != NGX_OK)
- {
- XSRETURN_EMPTY;
- }
-
- r->headers_out.content_type_len = r->headers_out.content_type.len;
-
- } else {
- if (ngx_http_set_content_type(r) != NGX_OK) {
- XSRETURN_EMPTY;
- }
- }
-
- (void) ngx_http_send_header(r);
-
-
-void
-header_only(r)
- CODE:
-
- dXSTARG;
- ngx_http_request_t *r;
-
- ngx_http_perl_set_request(r);
-
- sv_upgrade(TARG, SVt_IV);
- sv_setiv(TARG, r->header_only);
-
- ST(0) = TARG;
-
-
-void
-uri(r)
- CODE:
-
- dXSTARG;
- ngx_http_request_t *r;
-
- ngx_http_perl_set_request(r);
- ngx_http_perl_set_targ(r->uri.data, r->uri.len);
-
- ST(0) = TARG;
-
-
-void
-args(r)
- CODE:
-
- dXSTARG;
- ngx_http_request_t *r;
-
- ngx_http_perl_set_request(r);
- ngx_http_perl_set_targ(r->args.data, r->args.len);
-
- ST(0) = TARG;
-
-
-void
-request_method(r)
- CODE:
-
- dXSTARG;
- ngx_http_request_t *r;
-
- ngx_http_perl_set_request(r);
- ngx_http_perl_set_targ(r->method_name.data, r->method_name.len);
-
- ST(0) = TARG;
-
-
-void
-remote_addr(r)
- CODE:
-
- dXSTARG;
- ngx_http_request_t *r;
-
- ngx_http_perl_set_request(r);
- ngx_http_perl_set_targ(r->connection->addr_text.data,
- r->connection->addr_text.len);
-
- ST(0) = TARG;
-
-
-void
-header_in(r, key)
- CODE:
-
- dXSTARG;
- ngx_http_request_t *r;
- SV *key;
- u_char *p, *lowcase_key, *value, sep;
- STRLEN len;
- ssize_t size;
- ngx_uint_t i, n, hash;
- ngx_array_t *a;
- ngx_list_part_t *part;
- ngx_table_elt_t *h, **ph;
- ngx_http_header_t *hh;
- ngx_http_core_main_conf_t *cmcf;
-
- ngx_http_perl_set_request(r);
-
- key = ST(1);
-
- if (SvROK(key) && SvTYPE(SvRV(key)) == SVt_PV) {
- key = SvRV(key);
- }
-
- p = (u_char *) SvPV(key, len);
-
- /* look up hashed headers */
-
- lowcase_key = ngx_pnalloc(r->pool, len);
- if (lowcase_key == NULL) {
- XSRETURN_UNDEF;
- }
-
- hash = ngx_hash_strlow(lowcase_key, p, len);
-
- cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
-
- hh = ngx_hash_find(&cmcf->headers_in_hash, hash, lowcase_key, len);
-
- if (hh) {
-
- if (hh->offset == offsetof(ngx_http_headers_in_t, cookies)) {
- sep = ';';
- goto multi;
- }
-#if (NGX_HTTP_X_FORWARDED_FOR)
- if (hh->offset == offsetof(ngx_http_headers_in_t, x_forwarded_for)) {
- sep = ',';
- goto multi;
- }
-#endif
-
- ph = (ngx_table_elt_t **) ((char *) &r->headers_in + hh->offset);
-
- if (*ph) {
- ngx_http_perl_set_targ((*ph)->value.data, (*ph)->value.len);
-
- goto done;
- }
-
- XSRETURN_UNDEF;
-
- multi:
-
- /* Cookie, X-Forwarded-For */
-
- a = (ngx_array_t *) ((char *) &r->headers_in + hh->offset);
-
- n = a->nelts;
-
- if (n == 0) {
- XSRETURN_UNDEF;
- }
-
- ph = a->elts;
-
- if (n == 1) {
- ngx_http_perl_set_targ((*ph)->value.data, (*ph)->value.len);
-
- goto done;
- }
-
- size = - (ssize_t) (sizeof("; ") - 1);
-
- for (i = 0; i < n; i++) {
- size += ph[i]->value.len + sizeof("; ") - 1;
- }
-
- value = ngx_pnalloc(r->pool, size);
- if (value == NULL) {
- XSRETURN_UNDEF;
- }
-
- p = value;
-
- for (i = 0; /* void */ ; i++) {
- p = ngx_copy(p, ph[i]->value.data, ph[i]->value.len);
-
- if (i == n - 1) {
- break;
- }
-
- *p++ = sep; *p++ = ' ';
- }
-
- ngx_http_perl_set_targ(value, size);
-
- goto done;
- }
-
- /* iterate over all headers */
-
- part = &r->headers_in.headers.part;
- h = part->elts;
-
- for (i = 0; /* void */ ; i++) {
-
- if (i >= part->nelts) {
- if (part->next == NULL) {
- break;
- }
-
- part = part->next;
- h = part->elts;
- i = 0;
- }
-
- if (len != h[i].key.len
- || ngx_strcasecmp(p, h[i].key.data) != 0)
- {
- continue;
- }
-
- ngx_http_perl_set_targ(h[i].value.data, h[i].value.len);
-
- goto done;
- }
-
- XSRETURN_UNDEF;
-
- done:
-
- ST(0) = TARG;
-
-
-void
-has_request_body(r, next)
- CODE:
-
- dXSTARG;
- ngx_http_request_t *r;
- ngx_http_perl_ctx_t *ctx;
-
- ngx_http_perl_set_request(r);
-
- if (r->headers_in.content_length_n <= 0 && !r->headers_in.chunked) {
- XSRETURN_UNDEF;
- }
-
- ctx = ngx_http_get_module_ctx(r, ngx_http_perl_module);
- ctx->next = SvRV(ST(1));
-
- r->request_body_in_single_buf = 1;
- r->request_body_in_persistent_file = 1;
- r->request_body_in_clean_file = 1;
-
- if (r->request_body_in_file_only) {
- r->request_body_file_log_level = 0;
- }
-
- ngx_http_read_client_request_body(r, ngx_http_perl_handle_request);
-
- sv_upgrade(TARG, SVt_IV);
- sv_setiv(TARG, 1);
-
- ST(0) = TARG;
-
-
-void
-request_body(r)
- CODE:
-
- dXSTARG;
- ngx_http_request_t *r;
- u_char *p, *data;
- size_t len;
- ngx_buf_t *buf;
- ngx_chain_t *cl;
-
- ngx_http_perl_set_request(r);
-
- if (r->request_body == NULL
- || r->request_body->temp_file
- || r->request_body->bufs == NULL)
- {
- XSRETURN_UNDEF;
- }
-
- cl = r->request_body->bufs;
- buf = cl->buf;
-
- if (cl->next == NULL) {
- len = buf->last - buf->pos;
- data = buf->pos;
- goto done;
- }
-
- len = buf->last - buf->pos;
- cl = cl->next;
-
- for ( /* void */ ; cl; cl = cl->next) {
- buf = cl->buf;
- len += buf->last - buf->pos;
- }
-
- p = ngx_pnalloc(r->pool, len);
- if (p == NULL) {
- XSRETURN_UNDEF;
- }
-
- data = p;
- cl = r->request_body->bufs;
-
- for ( /* void */ ; cl; cl = cl->next) {
- buf = cl->buf;
- p = ngx_cpymem(p, buf->pos, buf->last - buf->pos);
- }
-
- done:
-
- if (len == 0) {
- XSRETURN_UNDEF;
- }
-
- ngx_http_perl_set_targ(data, len);
-
- ST(0) = TARG;
-
-
-void
-request_body_file(r)
- CODE:
-
- dXSTARG;
- ngx_http_request_t *r;
-
- ngx_http_perl_set_request(r);
-
- if (r->request_body == NULL || r->request_body->temp_file == NULL) {
- XSRETURN_UNDEF;
- }
-
- ngx_http_perl_set_targ(r->request_body->temp_file->file.name.data,
- r->request_body->temp_file->file.name.len);
-
- ST(0) = TARG;
-
-
-void
-discard_request_body(r)
- CODE:
-
- ngx_http_request_t *r;
-
- ngx_http_perl_set_request(r);
-
- ngx_http_discard_request_body(r);
-
-
-void
-header_out(r, key, value)
- CODE:
-
- ngx_http_request_t *r;
- SV *key;
- SV *value;
- ngx_table_elt_t *header;
-
- ngx_http_perl_set_request(r);
-
- key = ST(1);
- value = ST(2);
-
- header = ngx_list_push(&r->headers_out.headers);
- if (header == NULL) {
- XSRETURN_EMPTY;
- }
-
- header->hash = 1;
-
- if (ngx_http_perl_sv2str(aTHX_ r, &header->key, key) != NGX_OK) {
- header->hash = 0;
- XSRETURN_EMPTY;
- }
-
- if (ngx_http_perl_sv2str(aTHX_ r, &header->value, value) != NGX_OK) {
- header->hash = 0;
- XSRETURN_EMPTY;
- }
-
- if (header->key.len == sizeof("Content-Length") - 1
- && ngx_strncasecmp(header->key.data, (u_char *) "Content-Length",
- sizeof("Content-Length") - 1) == 0)
- {
- r->headers_out.content_length_n = (off_t) SvIV(value);
- r->headers_out.content_length = header;
- }
-
- if (header->key.len == sizeof("Content-Encoding") - 1
- && ngx_strncasecmp(header->key.data, (u_char *) "Content-Encoding",
- sizeof("Content-Encoding") - 1) == 0)
- {
- r->headers_out.content_encoding = header;
- }
-
-
-void
-filename(r)
- CODE:
-
- dXSTARG;
- size_t root;
- ngx_http_request_t *r;
- ngx_http_perl_ctx_t *ctx;
-
- ngx_http_perl_set_request(r);
-
- ctx = ngx_http_get_module_ctx(r, ngx_http_perl_module);
- if (ctx->filename.data) {
- goto done;
- }
-
- if (ngx_http_map_uri_to_path(r, &ctx->filename, &root, 0) == NULL) {
- XSRETURN_UNDEF;
- }
-
- ctx->filename.len--;
- sv_setpv(PL_statname, (char *) ctx->filename.data);
-
- done:
-
- ngx_http_perl_set_targ(ctx->filename.data, ctx->filename.len);
-
- ST(0) = TARG;
-
-
-void
-print(r, ...)
- CODE:
-
- ngx_http_request_t *r;
- SV *sv;
- int i;
- u_char *p;
- size_t size;
- STRLEN len;
- ngx_buf_t *b;
-
- ngx_http_perl_set_request(r);
-
- if (items == 2) {
-
- /*
- * do zero copy for prolate single read-only SV:
- * $r->print("some text\n");
- */
-
- sv = ST(1);
-
- if (SvROK(sv) && SvTYPE(SvRV(sv)) == SVt_PV) {
- sv = SvRV(sv);
- }
-
- if (SvREADONLY(sv) && SvPOK(sv)) {
-
- p = (u_char *) SvPV(sv, len);
-
- if (len == 0) {
- XSRETURN_EMPTY;
- }
-
- b = ngx_calloc_buf(r->pool);
- if (b == NULL) {
- XSRETURN_EMPTY;
- }
-
- b->memory = 1;
- b->pos = p;
- b->last = p + len;
- b->start = p;
- b->end = b->last;
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "$r->print: read-only SV: %z", len);
-
- goto out;
- }
- }
-
- size = 0;
-
- for (i = 1; i < items; i++) {
-
- sv = ST(i);
-
- if (SvROK(sv) && SvTYPE(SvRV(sv)) == SVt_PV) {
- sv = SvRV(sv);
- }
-
- (void) SvPV(sv, len);
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "$r->print: copy SV: %z", len);
-
- size += len;
- }
-
- if (size == 0) {
- XSRETURN_EMPTY;
- }
-
- b = ngx_create_temp_buf(r->pool, size);
- if (b == NULL) {
- XSRETURN_EMPTY;
- }
-
- for (i = 1; i < items; i++) {
- sv = ST(i);
-
- if (SvROK(sv) && SvTYPE(SvRV(sv)) == SVt_PV) {
- sv = SvRV(sv);
- }
-
- p = (u_char *) SvPV(sv, len);
- b->last = ngx_cpymem(b->last, p, len);
- }
-
- out:
-
- (void) ngx_http_perl_output(r, b);
-
-
-void
-sendfile(r, filename, offset = -1, bytes = 0)
- CODE:
-
- ngx_http_request_t *r;
- char *filename;
- off_t offset;
- size_t bytes;
- ngx_str_t path;
- ngx_buf_t *b;
- ngx_open_file_info_t of;
- ngx_http_core_loc_conf_t *clcf;
-
- ngx_http_perl_set_request(r);
-
- filename = SvPV_nolen(ST(1));
-
- if (filename == NULL) {
- croak("sendfile(): NULL filename");
- }
-
- offset = items < 3 ? -1 : SvIV(ST(2));
- bytes = items < 4 ? 0 : SvIV(ST(3));
-
- b = ngx_calloc_buf(r->pool);
- if (b == NULL) {
- XSRETURN_EMPTY;
- }
-
- b->file = ngx_pcalloc(r->pool, sizeof(ngx_file_t));
- if (b->file == NULL) {
- XSRETURN_EMPTY;
- }
-
- path.len = ngx_strlen(filename);
-
- path.data = ngx_pnalloc(r->pool, path.len + 1);
- if (path.data == NULL) {
- XSRETURN_EMPTY;
- }
-
- (void) ngx_cpystrn(path.data, (u_char *) filename, path.len + 1);
-
- clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
-
- ngx_memzero(&of, sizeof(ngx_open_file_info_t));
-
- of.read_ahead = clcf->read_ahead;
- of.directio = clcf->directio;
- of.valid = clcf->open_file_cache_valid;
- of.min_uses = clcf->open_file_cache_min_uses;
- of.errors = clcf->open_file_cache_errors;
- of.events = clcf->open_file_cache_events;
-
- if (ngx_http_set_disable_symlinks(r, clcf, &path, &of) != NGX_OK) {
- XSRETURN_EMPTY;
- }
-
- if (ngx_open_cached_file(clcf->open_file_cache, &path, &of, r->pool)
- != NGX_OK)
- {
- if (of.err == 0) {
- XSRETURN_EMPTY;
- }
-
- ngx_log_error(NGX_LOG_CRIT, r->connection->log, ngx_errno,
- "%s \"%s\" failed", of.failed, filename);
- XSRETURN_EMPTY;
- }
-
- if (offset == -1) {
- offset = 0;
- }
-
- if (bytes == 0) {
- bytes = of.size - offset;
- }
-
- b->in_file = 1;
-
- b->file_pos = offset;
- b->file_last = offset + bytes;
-
- b->file->fd = of.fd;
- b->file->log = r->connection->log;
- b->file->directio = of.is_directio;
-
- (void) ngx_http_perl_output(r, b);
-
-
-void
-flush(r)
- CODE:
-
- ngx_http_request_t *r;
- ngx_buf_t *b;
-
- ngx_http_perl_set_request(r);
-
- b = ngx_calloc_buf(r->pool);
- if (b == NULL) {
- XSRETURN_EMPTY;
- }
-
- b->flush = 1;
-
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "$r->flush");
-
- (void) ngx_http_perl_output(r, b);
-
- XSRETURN_EMPTY;
-
-
-void
-internal_redirect(r, uri)
- CODE:
-
- ngx_http_request_t *r;
- SV *uri;
- ngx_uint_t i;
- ngx_http_perl_ctx_t *ctx;
-
- ngx_http_perl_set_request(r);
-
- uri = ST(1);
-
- ctx = ngx_http_get_module_ctx(r, ngx_http_perl_module);
-
- if (ngx_http_perl_sv2str(aTHX_ r, &ctx->redirect_uri, uri) != NGX_OK) {
- XSRETURN_EMPTY;
- }
-
- for (i = 0; i < ctx->redirect_uri.len; i++) {
- if (ctx->redirect_uri.data[i] == '?') {
-
- ctx->redirect_args.len = ctx->redirect_uri.len - (i + 1);
- ctx->redirect_args.data = &ctx->redirect_uri.data[i + 1];
- ctx->redirect_uri.len = i;
-
- XSRETURN_EMPTY;
- }
- }
-
-
-void
-allow_ranges(r)
- CODE:
-
- ngx_http_request_t *r;
-
- ngx_http_perl_set_request(r);
-
- r->allow_ranges = 1;
-
-
-void
-unescape(r, text, type = 0)
- CODE:
-
- dXSTARG;
- ngx_http_request_t *r;
- SV *text;
- int type;
- u_char *p, *dst, *src;
- STRLEN len;
-
- ngx_http_perl_set_request(r);
-
- text = ST(1);
-
- src = (u_char *) SvPV(text, len);
-
- p = ngx_pnalloc(r->pool, len + 1);
- if (p == NULL) {
- XSRETURN_UNDEF;
- }
-
- dst = p;
-
- type = items < 3 ? 0 : SvIV(ST(2));
-
- ngx_unescape_uri(&dst, &src, len, (ngx_uint_t) type);
- *dst = '\0';
-
- ngx_http_perl_set_targ(p, dst - p);
-
- ST(0) = TARG;
-
-
-void
-variable(r, name, value = NULL)
- CODE:
-
- dXSTARG;
- ngx_http_request_t *r;
- SV *name, *value;
- u_char *p, *lowcase;
- STRLEN len;
- ngx_str_t var, val;
- ngx_uint_t i, hash;
- ngx_http_perl_var_t *v;
- ngx_http_perl_ctx_t *ctx;
- ngx_http_variable_value_t *vv;
-
- ngx_http_perl_set_request(r);
-
- name = ST(1);
-
- if (SvROK(name) && SvTYPE(SvRV(name)) == SVt_PV) {
- name = SvRV(name);
- }
-
- if (items == 2) {
- value = NULL;
-
- } else {
- value = ST(2);
-
- if (SvROK(value) && SvTYPE(SvRV(value)) == SVt_PV) {
- value = SvRV(value);
- }
-
- if (ngx_http_perl_sv2str(aTHX_ r, &val, value) != NGX_OK) {
- XSRETURN_UNDEF;
- }
- }
-
- p = (u_char *) SvPV(name, len);
-
- lowcase = ngx_pnalloc(r->pool, len);
- if (lowcase == NULL) {
- XSRETURN_UNDEF;
- }
-
- hash = ngx_hash_strlow(lowcase, p, len);
-
- var.len = len;
- var.data = lowcase;
-#if (NGX_DEBUG)
-
- if (value) {
- ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "perl variable: \"%V\"=\"%V\"", &var, &val);
- } else {
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "perl variable: \"%V\"", &var);
- }
-#endif
-
- vv = ngx_http_get_variable(r, &var, hash);
- if (vv == NULL) {
- XSRETURN_UNDEF;
- }
-
- if (vv->not_found) {
-
- ctx = ngx_http_get_module_ctx(r, ngx_http_perl_module);
-
- if (ctx->variables) {
-
- v = ctx->variables->elts;
- for (i = 0; i < ctx->variables->nelts; i++) {
-
- if (hash != v[i].hash
- || len != v[i].name.len
- || ngx_strncmp(lowcase, v[i].name.data, len) != 0)
- {
- continue;
- }
-
- if (value) {
- v[i].value = val;
- XSRETURN_UNDEF;
- }
-
- ngx_http_perl_set_targ(v[i].value.data, v[i].value.len);
-
- goto done;
- }
- }
-
- if (value) {
- if (ctx->variables == NULL) {
- ctx->variables = ngx_array_create(r->pool, 1,
- sizeof(ngx_http_perl_var_t));
- if (ctx->variables == NULL) {
- XSRETURN_UNDEF;
- }
- }
-
- v = ngx_array_push(ctx->variables);
- if (v == NULL) {
- XSRETURN_UNDEF;
- }
-
- v->hash = hash;
- v->name.len = len;
- v->name.data = lowcase;
- v->value = val;
-
- XSRETURN_UNDEF;
- }
-
- XSRETURN_UNDEF;
- }
-
- if (value) {
- vv->len = val.len;
- vv->valid = 1;
- vv->no_cacheable = 0;
- vv->not_found = 0;
- vv->data = val.data;
-
- XSRETURN_UNDEF;
- }
-
- ngx_http_perl_set_targ(vv->data, vv->len);
-
- done:
-
- ST(0) = TARG;
-
-
-void
-sleep(r, sleep, next)
- CODE:
-
- ngx_http_request_t *r;
- ngx_msec_t sleep;
- ngx_http_perl_ctx_t *ctx;
-
- ngx_http_perl_set_request(r);
-
- sleep = (ngx_msec_t) SvIV(ST(1));
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "perl sleep: %M", sleep);
-
- ctx = ngx_http_get_module_ctx(r, ngx_http_perl_module);
-
- ctx->next = SvRV(ST(2));
-
- r->connection->write->delayed = 1;
- ngx_add_timer(r->connection->write, sleep);
-
- r->write_event_handler = ngx_http_perl_sleep_handler;
- r->main->count++;
-
-
-void
-log_error(r, err, msg)
- CODE:
-
- ngx_http_request_t *r;
- SV *err, *msg;
- u_char *p;
- STRLEN len;
- ngx_err_t e;
-
- ngx_http_perl_set_request(r);
-
- err = ST(1);
-
- if (SvROK(err) && SvTYPE(SvRV(err)) == SVt_PV) {
- err = SvRV(err);
- }
-
- e = SvIV(err);
-
- msg = ST(2);
-
- if (SvROK(msg) && SvTYPE(SvRV(msg)) == SVt_PV) {
- msg = SvRV(msg);
- }
-
- p = (u_char *) SvPV(msg, len);
-
- ngx_log_error(NGX_LOG_ERR, r->connection->log, e, "perl: %s", p);
diff --git a/nginx/src/http/modules/perl/ngx_http_perl_module.c b/nginx/src/http/modules/perl/ngx_http_perl_module.c
deleted file mode 100644
index 6d3be91..0000000
--- a/nginx/src/http/modules/perl/ngx_http_perl_module.c
+++ /dev/null
@@ -1,1086 +0,0 @@
-
-/*
- * Copyright (C) Igor Sysoev
- * Copyright (C) Nginx, Inc.
- */
-
-
-#include <ngx_config.h>
-#include <ngx_core.h>
-#include <ngx_http.h>
-#include <ngx_http_perl_module.h>
-
-
-typedef struct {
- PerlInterpreter *perl;
- HV *nginx;
- ngx_array_t *modules;
- ngx_array_t *requires;
-} ngx_http_perl_main_conf_t;
-
-
-typedef struct {
- SV *sub;
- ngx_str_t handler;
-} ngx_http_perl_loc_conf_t;
-
-
-typedef struct {
- SV *sub;
- ngx_str_t handler;
-} ngx_http_perl_variable_t;
-
-
-#if (NGX_HTTP_SSI)
-static ngx_int_t ngx_http_perl_ssi(ngx_http_request_t *r,
- ngx_http_ssi_ctx_t *ssi_ctx, ngx_str_t **params);
-#endif
-
-static char *ngx_http_perl_init_interpreter(ngx_conf_t *cf,
- ngx_http_perl_main_conf_t *pmcf);
-static PerlInterpreter *ngx_http_perl_create_interpreter(ngx_conf_t *cf,
- ngx_http_perl_main_conf_t *pmcf);
-static ngx_int_t ngx_http_perl_run_requires(pTHX_ ngx_array_t *requires,
- ngx_log_t *log);
-static ngx_int_t ngx_http_perl_call_handler(pTHX_ ngx_http_request_t *r,
- HV *nginx, SV *sub, SV **args, ngx_str_t *handler, ngx_str_t *rv);
-static void ngx_http_perl_eval_anon_sub(pTHX_ ngx_str_t *handler, SV **sv);
-
-static ngx_int_t ngx_http_perl_preconfiguration(ngx_conf_t *cf);
-static void *ngx_http_perl_create_main_conf(ngx_conf_t *cf);
-static char *ngx_http_perl_init_main_conf(ngx_conf_t *cf, void *conf);
-static void *ngx_http_perl_create_loc_conf(ngx_conf_t *cf);
-static char *ngx_http_perl_merge_loc_conf(ngx_conf_t *cf, void *parent,
- void *child);
-static char *ngx_http_perl(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
-static char *ngx_http_perl_set(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
-
-#if (NGX_HAVE_PERL_MULTIPLICITY)
-static void ngx_http_perl_cleanup_perl(void *data);
-#endif
-
-static ngx_int_t ngx_http_perl_init_worker(ngx_cycle_t *cycle);
-static void ngx_http_perl_exit(ngx_cycle_t *cycle);
-
-
-static ngx_command_t ngx_http_perl_commands[] = {
-
- { ngx_string("perl_modules"),
- NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_str_array_slot,
- NGX_HTTP_MAIN_CONF_OFFSET,
- offsetof(ngx_http_perl_main_conf_t, modules),
- NULL },
-
- { ngx_string("perl_require"),
- NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1,
- ngx_conf_set_str_array_slot,
- NGX_HTTP_MAIN_CONF_OFFSET,
- offsetof(ngx_http_perl_main_conf_t, requires),
- NULL },
-
- { ngx_string("perl"),
- NGX_HTTP_LOC_CONF|NGX_HTTP_LMT_CONF|NGX_CONF_TAKE1,
- ngx_http_perl,
- NGX_HTTP_LOC_CONF_OFFSET,
- 0,
- NULL },
-
- { ngx_string("perl_set"),
- NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE2,
- ngx_http_perl_set,
- NGX_HTTP_LOC_CONF_OFFSET,
- 0,
- NULL },
-
- ngx_null_command
-};
-
-
-static ngx_http_module_t ngx_http_perl_module_ctx = {
- ngx_http_perl_preconfiguration, /* preconfiguration */
- NULL, /* postconfiguration */
-
- ngx_http_perl_create_main_conf, /* create main configuration */
- ngx_http_perl_init_main_conf, /* init main configuration */
-
- NULL, /* create server configuration */
- NULL, /* merge server configuration */
-
- ngx_http_perl_create_loc_conf, /* create location configuration */
- ngx_http_perl_merge_loc_conf /* merge location configuration */
-};
-
-
-ngx_module_t ngx_http_perl_module = {
- NGX_MODULE_V1,
- &ngx_http_perl_module_ctx, /* module context */
- ngx_http_perl_commands, /* module directives */
- NGX_HTTP_MODULE, /* module type */
- NULL, /* init master */
- NULL, /* init module */
- ngx_http_perl_init_worker, /* init process */
- NULL, /* init thread */
- NULL, /* exit thread */
- NULL, /* exit process */
- ngx_http_perl_exit, /* exit master */
- NGX_MODULE_V1_PADDING
-};
-
-
-#if (NGX_HTTP_SSI)
-
-#define NGX_HTTP_PERL_SSI_SUB 0
-#define NGX_HTTP_PERL_SSI_ARG 1
-
-
-static ngx_http_ssi_param_t ngx_http_perl_ssi_params[] = {
- { ngx_string("sub"), NGX_HTTP_PERL_SSI_SUB, 1, 0 },
- { ngx_string("arg"), NGX_HTTP_PERL_SSI_ARG, 0, 1 },
- { ngx_null_string, 0, 0, 0 }
-};
-
-static ngx_http_ssi_command_t ngx_http_perl_ssi_command = {
- ngx_string("perl"), ngx_http_perl_ssi, ngx_http_perl_ssi_params, 0, 0, 1
-};
-
-#endif
-
-
-static ngx_str_t ngx_null_name = ngx_null_string;
-static HV *nginx_stash;
-
-#if (NGX_HAVE_PERL_MULTIPLICITY)
-static ngx_uint_t ngx_perl_term;
-#else
-static PerlInterpreter *perl;
-#endif
-
-
-static void
-ngx_http_perl_xs_init(pTHX)
-{
- newXS("DynaLoader::boot_DynaLoader", boot_DynaLoader, __FILE__);
-
- nginx_stash = gv_stashpv("nginx", TRUE);
-}
-
-
-static ngx_int_t
-ngx_http_perl_handler(ngx_http_request_t *r)
-{
- r->main->count++;
-
- ngx_http_perl_handle_request(r);
-
- return NGX_DONE;
-}
-
-
-void
-ngx_http_perl_handle_request(ngx_http_request_t *r)
-{
- SV *sub;
- ngx_int_t rc;
- ngx_str_t uri, args, *handler;
- ngx_http_perl_ctx_t *ctx;
- ngx_http_perl_loc_conf_t *plcf;
- ngx_http_perl_main_conf_t *pmcf;
-
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "perl handler");
-
- ctx = ngx_http_get_module_ctx(r, ngx_http_perl_module);
-
- if (ctx == NULL) {
- ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_perl_ctx_t));
- if (ctx == NULL) {
- ngx_http_finalize_request(r, NGX_ERROR);
- return;
- }
-
- ngx_http_set_ctx(r, ctx, ngx_http_perl_module);
- }
-
- pmcf = ngx_http_get_module_main_conf(r, ngx_http_perl_module);
-
- {
-
- dTHXa(pmcf->perl);
- PERL_SET_CONTEXT(pmcf->perl);
- PERL_SET_INTERP(pmcf->perl);
-
- if (ctx->next == NULL) {
- plcf = ngx_http_get_module_loc_conf(r, ngx_http_perl_module);
- sub = plcf->sub;
- handler = &plcf->handler;
-
- } else {
- sub = ctx->next;
- handler = &ngx_null_name;
- ctx->next = NULL;
- }
-
- rc = ngx_http_perl_call_handler(aTHX_ r, pmcf->nginx, sub, NULL, handler,
- NULL);
-
- }
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "perl handler done: %i", rc);
-
- if (rc == NGX_DONE) {
- ngx_http_finalize_request(r, rc);
- return;
- }
-
- if (rc > 600) {
- rc = NGX_OK;
- }
-
- if (ctx->redirect_uri.len) {
- uri = ctx->redirect_uri;
- args = ctx->redirect_args;
-
- } else {
- uri.len = 0;
- }
-
- ctx->filename.data = NULL;
- ctx->redirect_uri.len = 0;
-
- if (ctx->done || ctx->next) {
- ngx_http_finalize_request(r, NGX_DONE);
- return;
- }
-
- if (uri.len) {
- ngx_http_internal_redirect(r, &uri, &args);
- ngx_http_finalize_request(r, NGX_DONE);
- return;
- }
-
- if (rc == NGX_OK || rc == NGX_HTTP_OK) {
- ngx_http_send_special(r, NGX_HTTP_LAST);
- ctx->done = 1;
- }
-
- ngx_http_finalize_request(r, rc);
-}
-
-
-void
-ngx_http_perl_sleep_handler(ngx_http_request_t *r)
-{
- ngx_event_t *wev;
-
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "perl sleep handler");
-
- wev = r->connection->write;
-
- if (wev->delayed) {
-
- if (ngx_handle_write_event(wev, 0) != NGX_OK) {
- ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
- }
-
- return;
- }
-
- ngx_http_perl_handle_request(r);
-}
-
-
-static ngx_int_t
-ngx_http_perl_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v,
- uintptr_t data)
-{
- ngx_http_perl_variable_t *pv = (ngx_http_perl_variable_t *) data;
-
- ngx_int_t rc;
- ngx_str_t value;
- ngx_http_perl_ctx_t *ctx;
- ngx_http_perl_main_conf_t *pmcf;
-
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "perl variable handler");
-
- ctx = ngx_http_get_module_ctx(r, ngx_http_perl_module);
-
- if (ctx == NULL) {
- ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_perl_ctx_t));
- if (ctx == NULL) {
- return NGX_ERROR;
- }
-
- ngx_http_set_ctx(r, ctx, ngx_http_perl_module);
- }
-
- pmcf = ngx_http_get_module_main_conf(r, ngx_http_perl_module);
-
- value.data = NULL;
-
- {
-
- dTHXa(pmcf->perl);
- PERL_SET_CONTEXT(pmcf->perl);
- PERL_SET_INTERP(pmcf->perl);
-
- rc = ngx_http_perl_call_handler(aTHX_ r, pmcf->nginx, pv->sub, NULL,
- &pv->handler, &value);
-
- }
-
- if (value.data) {
- v->len = value.len;
- v->valid = 1;
- v->no_cacheable = 0;
- v->not_found = 0;
- v->data = value.data;
-
- } else {
- v->not_found = 1;
- }
-
- ctx->filename.data = NULL;
- ctx->redirect_uri.len = 0;
-
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "perl variable done");
-
- return rc;
-}
-
-
-#if (NGX_HTTP_SSI)
-
-static ngx_int_t
-ngx_http_perl_ssi(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ssi_ctx,
- ngx_str_t **params)
-{
- SV *sv, **asv;
- ngx_int_t rc;
- ngx_str_t *handler, **args;
- ngx_uint_t i;
- ngx_http_perl_ctx_t *ctx;
- ngx_http_perl_main_conf_t *pmcf;
-
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "perl ssi handler");
-
- ctx = ngx_http_get_module_ctx(r, ngx_http_perl_module);
-
- if (ctx == NULL) {
- ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_perl_ctx_t));
- if (ctx == NULL) {
- return NGX_ERROR;
- }
-
- ngx_http_set_ctx(r, ctx, ngx_http_perl_module);
- }
-
- pmcf = ngx_http_get_module_main_conf(r, ngx_http_perl_module);
-
- ctx->ssi = ssi_ctx;
-
- handler = params[NGX_HTTP_PERL_SSI_SUB];
- handler->data[handler->len] = '\0';
-
- {
-
- dTHXa(pmcf->perl);
- PERL_SET_CONTEXT(pmcf->perl);
- PERL_SET_INTERP(pmcf->perl);
-
-#if 0
-
- /* the code is disabled to force the precompiled perl code using only */
-
- ngx_http_perl_eval_anon_sub(aTHX_ handler, &sv);
-
- if (sv == &PL_sv_undef) {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "eval_pv(\"%V\") failed", handler);
- return NGX_ERROR;
- }
-
- if (sv == NULL) {
- sv = newSVpvn((char *) handler->data, handler->len);
- }
-
-#endif
-
- sv = newSVpvn((char *) handler->data, handler->len);
-
- args = &params[NGX_HTTP_PERL_SSI_ARG];
-
- if (args[0]) {
-
- for (i = 0; args[i]; i++) { /* void */ }
-
- asv = ngx_pcalloc(r->pool, (i + 1) * sizeof(SV *));
-
- if (asv == NULL) {
- SvREFCNT_dec(sv);
- return NGX_ERROR;
- }
-
- asv[0] = (SV *) (uintptr_t) i;
-
- for (i = 0; args[i]; i++) {
- asv[i + 1] = newSVpvn((char *) args[i]->data, args[i]->len);
- }
-
- } else {
- asv = NULL;
- }
-
- rc = ngx_http_perl_call_handler(aTHX_ r, pmcf->nginx, sv, asv, handler,
- NULL);
-
- SvREFCNT_dec(sv);
-
- }
-
- ctx->filename.data = NULL;
- ctx->redirect_uri.len = 0;
- ctx->ssi = NULL;
-
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "perl ssi done");
-
- return rc;
-}
-
-#endif
-
-
-static char *
-ngx_http_perl_init_interpreter(ngx_conf_t *cf, ngx_http_perl_main_conf_t *pmcf)
-{
- ngx_str_t *m;
- ngx_uint_t i;
-#if (NGX_HAVE_PERL_MULTIPLICITY)
- ngx_pool_cleanup_t *cln;
-
- cln = ngx_pool_cleanup_add(cf->pool, 0);
- if (cln == NULL) {
- return NGX_CONF_ERROR;
- }
-
-#endif
-
-#ifdef NGX_PERL_MODULES
- if (pmcf->modules == NGX_CONF_UNSET_PTR) {
-
- pmcf->modules = ngx_array_create(cf->pool, 1, sizeof(ngx_str_t));
- if (pmcf->modules == NULL) {
- return NGX_CONF_ERROR;
- }
-
- m = ngx_array_push(pmcf->modules);
- if (m == NULL) {
- return NGX_CONF_ERROR;
- }
-
- ngx_str_set(m, NGX_PERL_MODULES);
- }
-#endif
-
- if (pmcf->modules != NGX_CONF_UNSET_PTR) {
- m = pmcf->modules->elts;
- for (i = 0; i < pmcf->modules->nelts; i++) {
- if (ngx_conf_full_name(cf->cycle, &m[i], 0) != NGX_OK) {
- return NGX_CONF_ERROR;
- }
- }
- }
-
-#if !(NGX_HAVE_PERL_MULTIPLICITY)
-
- if (perl) {
-
- if (ngx_set_environment(cf->cycle, NULL) == NULL) {
- return NGX_CONF_ERROR;
- }
-
- if (ngx_http_perl_run_requires(aTHX_ pmcf->requires, cf->log)
- != NGX_OK)
- {
- return NGX_CONF_ERROR;
- }
-
- pmcf->perl = perl;
- pmcf->nginx = nginx_stash;
-
- return NGX_CONF_OK;
- }
-
-#endif
-
- if (nginx_stash == NULL) {
- PERL_SYS_INIT(&ngx_argc, &ngx_argv);
- }
-
- pmcf->perl = ngx_http_perl_create_interpreter(cf, pmcf);
-
- if (pmcf->perl == NULL) {
- return NGX_CONF_ERROR;
- }
-
- pmcf->nginx = nginx_stash;
-
-#if (NGX_HAVE_PERL_MULTIPLICITY)
-
- cln->handler = ngx_http_perl_cleanup_perl;
- cln->data = pmcf->perl;
-
-#else
-
- perl = pmcf->perl;
-
-#endif
-
- return NGX_CONF_OK;
-}
-
-
-static PerlInterpreter *
-ngx_http_perl_create_interpreter(ngx_conf_t *cf,
- ngx_http_perl_main_conf_t *pmcf)
-{
- int n;
- STRLEN len;
- SV *sv;
- char *ver, **embedding;
- ngx_str_t *m;
- ngx_uint_t i;
- PerlInterpreter *perl;
-
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, cf->log, 0, "create perl interpreter");
-
- if (ngx_set_environment(cf->cycle, NULL) == NULL) {
- return NULL;
- }
-
- perl = perl_alloc();
- if (perl == NULL) {
- ngx_log_error(NGX_LOG_ALERT, cf->log, 0, "perl_alloc() failed");
- return NULL;
- }
-
- {
-
- dTHXa(perl);
- PERL_SET_CONTEXT(perl);
- PERL_SET_INTERP(perl);
-
- perl_construct(perl);
-
-#ifdef PERL_EXIT_DESTRUCT_END
- PL_exit_flags |= PERL_EXIT_DESTRUCT_END;
-#endif
-
- n = (pmcf->modules != NGX_CONF_UNSET_PTR) ? pmcf->modules->nelts * 2 : 0;
-
- embedding = ngx_palloc(cf->pool, (5 + n) * sizeof(char *));
- if (embedding == NULL) {
- goto fail;
- }
-
- embedding[0] = "";
-
- if (n++) {
- m = pmcf->modules->elts;
- for (i = 0; i < pmcf->modules->nelts; i++) {
- embedding[2 * i + 1] = "-I";
- embedding[2 * i + 2] = (char *) m[i].data;
- }
- }
-
- embedding[n++] = "-Mnginx";
- embedding[n++] = "-e";
- embedding[n++] = "0";
- embedding[n] = NULL;
-
- n = perl_parse(perl, ngx_http_perl_xs_init, n, embedding, NULL);
-
- if (n != 0) {
- ngx_log_error(NGX_LOG_ALERT, cf->log, 0, "perl_parse() failed: %d", n);
- goto fail;
- }
-
- sv = get_sv("nginx::VERSION", FALSE);
- ver = SvPV(sv, len);
-
- if (ngx_strcmp(ver, NGINX_VERSION) != 0) {
- ngx_log_error(NGX_LOG_ALERT, cf->log, 0,
- "version " NGINX_VERSION " of nginx.pm is required, "
- "but %s was found", ver);
- goto fail;
- }
-
- if (ngx_http_perl_run_requires(aTHX_ pmcf->requires, cf->log) != NGX_OK) {
- goto fail;
- }
-
- }
-
- return perl;
-
-fail:
-
- (void) perl_destruct(perl);
-
- perl_free(perl);
-
- return NULL;
-}
-
-
-static ngx_int_t
-ngx_http_perl_run_requires(pTHX_ ngx_array_t *requires, ngx_log_t *log)
-{
- u_char *err;
- STRLEN len;
- ngx_str_t *script;
- ngx_uint_t i;
-
- if (requires == NGX_CONF_UNSET_PTR) {
- return NGX_OK;
- }
-
- script = requires->elts;
- for (i = 0; i < requires->nelts; i++) {
-
- require_pv((char *) script[i].data);
-
- if (SvTRUE(ERRSV)) {
-
- err = (u_char *) SvPV(ERRSV, len);
- while (--len && (err[len] == CR || err[len] == LF)) { /* void */ }
-
- ngx_log_error(NGX_LOG_EMERG, log, 0,
- "require_pv(\"%s\") failed: \"%*s\"",
- script[i].data, len + 1, err);
-
- return NGX_ERROR;
- }
- }
-
- return NGX_OK;
-}
-
-
-static ngx_int_t
-ngx_http_perl_call_handler(pTHX_ ngx_http_request_t *r, HV *nginx, SV *sub,
- SV **args, ngx_str_t *handler, ngx_str_t *rv)
-{
- SV *sv;
- int n, status;
- char *line;
- u_char *err;
- STRLEN len, n_a;
- ngx_uint_t i;
- ngx_connection_t *c;
-
- dSP;
-
- status = 0;
-
- ENTER;
- SAVETMPS;
-
- PUSHMARK(sp);
-
- sv = sv_2mortal(sv_bless(newRV_noinc(newSViv(PTR2IV(r))), nginx));
- XPUSHs(sv);
-
- if (args) {
- EXTEND(sp, (intptr_t) args[0]);
-
- for (i = 1; i <= (uintptr_t) args[0]; i++) {
- PUSHs(sv_2mortal(args[i]));
- }
- }
-
- PUTBACK;
-
- c = r->connection;
-
- n = call_sv(sub, G_EVAL);
-
- SPAGAIN;
-
- if (n) {
- if (rv == NULL) {
- status = POPi;
-
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
- "call_sv: %d", status);
-
- } else {
- line = SvPVx(POPs, n_a);
- rv->len = n_a;
-
- rv->data = ngx_pnalloc(r->pool, n_a);
- if (rv->data == NULL) {
- return NGX_ERROR;
- }
-
- ngx_memcpy(rv->data, line, n_a);
- }
- }
-
- PUTBACK;
-
- FREETMPS;
- LEAVE;
-
- /* check $@ */
-
- if (SvTRUE(ERRSV)) {
-
- err = (u_char *) SvPV(ERRSV, len);
- while (--len && (err[len] == CR || err[len] == LF)) { /* void */ }
-
- ngx_log_error(NGX_LOG_ERR, c->log, 0,
- "call_sv(\"%V\") failed: \"%*s\"", handler, len + 1, err);
-
- if (rv) {
- return NGX_ERROR;
- }
-
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
-
- if (n != 1) {
- ngx_log_error(NGX_LOG_ALERT, c->log, 0,
- "call_sv(\"%V\") returned %d results", handler, n);
- status = NGX_OK;
- }
-
- if (rv) {
- return NGX_OK;
- }
-
- return (ngx_int_t) status;
-}
-
-
-static void
-ngx_http_perl_eval_anon_sub(pTHX_ ngx_str_t *handler, SV **sv)
-{
- u_char *p;
-
- for (p = handler->data; *p; p++) {
- if (*p != ' ' && *p != '\t' && *p != CR && *p != LF) {
- break;
- }
- }
-
- if (ngx_strncmp(p, "sub ", 4) == 0
- || ngx_strncmp(p, "sub{", 4) == 0
- || ngx_strncmp(p, "use ", 4) == 0)
- {
- *sv = eval_pv((char *) p, FALSE);
-
- /* eval_pv() does not set ERRSV on failure */
-
- return;
- }
-
- *sv = NULL;
-}
-
-
-static void *
-ngx_http_perl_create_main_conf(ngx_conf_t *cf)
-{
- ngx_http_perl_main_conf_t *pmcf;
-
- pmcf = ngx_pcalloc(cf->pool, sizeof(ngx_http_perl_main_conf_t));
- if (pmcf == NULL) {
- return NULL;
- }
-
- pmcf->modules = NGX_CONF_UNSET_PTR;
- pmcf->requires = NGX_CONF_UNSET_PTR;
-
- return pmcf;
-}
-
-
-static char *
-ngx_http_perl_init_main_conf(ngx_conf_t *cf, void *conf)
-{
- ngx_http_perl_main_conf_t *pmcf = conf;
-
- if (pmcf->perl == NULL) {
- if (ngx_http_perl_init_interpreter(cf, pmcf) != NGX_CONF_OK) {
- return NGX_CONF_ERROR;
- }
- }
-
- return NGX_CONF_OK;
-}
-
-
-#if (NGX_HAVE_PERL_MULTIPLICITY)
-
-static void
-ngx_http_perl_cleanup_perl(void *data)
-{
- PerlInterpreter *perl = data;
-
- PERL_SET_CONTEXT(perl);
- PERL_SET_INTERP(perl);
-
- (void) perl_destruct(perl);
-
- perl_free(perl);
-
- if (ngx_perl_term) {
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, ngx_cycle->log, 0, "perl term");
-
- PERL_SYS_TERM();
- }
-}
-
-#endif
-
-
-static ngx_int_t
-ngx_http_perl_preconfiguration(ngx_conf_t *cf)
-{
-#if (NGX_HTTP_SSI)
- ngx_int_t rc;
- ngx_http_ssi_main_conf_t *smcf;
-
- smcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_ssi_filter_module);
-
- rc = ngx_hash_add_key(&smcf->commands, &ngx_http_perl_ssi_command.name,
- &ngx_http_perl_ssi_command, NGX_HASH_READONLY_KEY);
-
- if (rc != NGX_OK) {
- if (rc == NGX_BUSY) {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "conflicting SSI command \"%V\"",
- &ngx_http_perl_ssi_command.name);
- }
-
- return NGX_ERROR;
- }
-#endif
-
- return NGX_OK;
-}
-
-
-static void *
-ngx_http_perl_create_loc_conf(ngx_conf_t *cf)
-{
- ngx_http_perl_loc_conf_t *plcf;
-
- plcf = ngx_pcalloc(cf->pool, sizeof(ngx_http_perl_loc_conf_t));
- if (plcf == NULL) {
- return NULL;
- }
-
- /*
- * set by ngx_pcalloc():
- *
- * plcf->handler = { 0, NULL };
- */
-
- return plcf;
-}
-
-
-static char *
-ngx_http_perl_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
-{
- ngx_http_perl_loc_conf_t *prev = parent;
- ngx_http_perl_loc_conf_t *conf = child;
-
- if (conf->sub == NULL) {
- conf->sub = prev->sub;
- conf->handler = prev->handler;
- }
-
- return NGX_CONF_OK;
-}
-
-
-static char *
-ngx_http_perl(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
-{
- ngx_http_perl_loc_conf_t *plcf = conf;
-
- ngx_str_t *value;
- ngx_http_core_loc_conf_t *clcf;
- ngx_http_perl_main_conf_t *pmcf;
-
- value = cf->args->elts;
-
- if (plcf->handler.data) {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "duplicate perl handler \"%V\"", &value[1]);
- return NGX_CONF_ERROR;
- }
-
- pmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_perl_module);
-
- if (pmcf->perl == NULL) {
- if (ngx_http_perl_init_interpreter(cf, pmcf) != NGX_CONF_OK) {
- return NGX_CONF_ERROR;
- }
- }
-
- plcf->handler = value[1];
-
- {
-
- dTHXa(pmcf->perl);
- PERL_SET_CONTEXT(pmcf->perl);
- PERL_SET_INTERP(pmcf->perl);
-
- ngx_http_perl_eval_anon_sub(aTHX_ &value[1], &plcf->sub);
-
- if (plcf->sub == &PL_sv_undef) {
- ngx_conf_log_error(NGX_LOG_ERR, cf, 0,
- "eval_pv(\"%V\") failed", &value[1]);
- return NGX_CONF_ERROR;
- }
-
- if (plcf->sub == NULL) {
- plcf->sub = newSVpvn((char *) value[1].data, value[1].len);
- }
-
- }
-
- clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);
- clcf->handler = ngx_http_perl_handler;
-
- return NGX_CONF_OK;
-}
-
-
-static char *
-ngx_http_perl_set(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
-{
- ngx_int_t index;
- ngx_str_t *value;
- ngx_http_variable_t *v;
- ngx_http_perl_variable_t *pv;
- ngx_http_perl_main_conf_t *pmcf;
-
- value = cf->args->elts;
-
- if (value[1].data[0] != '$') {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "invalid variable name \"%V\"", &value[1]);
- return NGX_CONF_ERROR;
- }
-
- value[1].len--;
- value[1].data++;
-
- v = ngx_http_add_variable(cf, &value[1], NGX_HTTP_VAR_CHANGEABLE);
- if (v == NULL) {
- return NGX_CONF_ERROR;
- }
-
- pv = ngx_palloc(cf->pool, sizeof(ngx_http_perl_variable_t));
- if (pv == NULL) {
- return NGX_CONF_ERROR;
- }
-
- index = ngx_http_get_variable_index(cf, &value[1]);
- if (index == NGX_ERROR) {
- return NGX_CONF_ERROR;
- }
-
- pmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_perl_module);
-
- if (pmcf->perl == NULL) {
- if (ngx_http_perl_init_interpreter(cf, pmcf) != NGX_CONF_OK) {
- return NGX_CONF_ERROR;
- }
- }
-
- pv->handler = value[2];
-
- {
-
- dTHXa(pmcf->perl);
- PERL_SET_CONTEXT(pmcf->perl);
- PERL_SET_INTERP(pmcf->perl);
-
- ngx_http_perl_eval_anon_sub(aTHX_ &value[2], &pv->sub);
-
- if (pv->sub == &PL_sv_undef) {
- ngx_conf_log_error(NGX_LOG_ERR, cf, 0,
- "eval_pv(\"%V\") failed", &value[2]);
- return NGX_CONF_ERROR;
- }
-
- if (pv->sub == NULL) {
- pv->sub = newSVpvn((char *) value[2].data, value[2].len);
- }
-
- }
-
- v->get_handler = ngx_http_perl_variable;
- v->data = (uintptr_t) pv;
-
- return NGX_CONF_OK;
-}
-
-
-static ngx_int_t
-ngx_http_perl_init_worker(ngx_cycle_t *cycle)
-{
- ngx_http_perl_main_conf_t *pmcf;
-
- pmcf = ngx_http_cycle_get_module_main_conf(cycle, ngx_http_perl_module);
-
- if (pmcf) {
- dTHXa(pmcf->perl);
- PERL_SET_CONTEXT(pmcf->perl);
- PERL_SET_INTERP(pmcf->perl);
-
- /* set worker's $$ */
-
- sv_setiv(GvSV(gv_fetchpv("$", TRUE, SVt_PV)), (I32) ngx_pid);
- }
-
- return NGX_OK;
-}
-
-
-static void
-ngx_http_perl_exit(ngx_cycle_t *cycle)
-{
-#if (NGX_HAVE_PERL_MULTIPLICITY)
-
- /*
- * the master exit hook is run before global pool cleanup,
- * therefore just set flag here
- */
-
- ngx_perl_term = 1;
-
-#else
-
- if (nginx_stash) {
- ngx_log_debug0(NGX_LOG_DEBUG_HTTP, cycle->log, 0, "perl term");
-
- (void) perl_destruct(perl);
-
- perl_free(perl);
-
- PERL_SYS_TERM();
- }
-
-#endif
-}
diff --git a/nginx/src/http/modules/perl/ngx_http_perl_module.h b/nginx/src/http/modules/perl/ngx_http_perl_module.h
deleted file mode 100644
index 5e60b03..0000000
--- a/nginx/src/http/modules/perl/ngx_http_perl_module.h
+++ /dev/null
@@ -1,67 +0,0 @@
-
-/*
- * Copyright (C) Igor Sysoev
- * Copyright (C) Nginx, Inc.
- */
-
-
-#ifndef _NGX_HTTP_PERL_MODULE_H_INCLUDED_
-#define _NGX_HTTP_PERL_MODULE_H_INCLUDED_
-
-
-#include <ngx_config.h>
-#include <ngx_core.h>
-#include <ngx_http.h>
-#include <nginx.h>
-
-#include <EXTERN.h>
-#include <perl.h>
-
-
-typedef ngx_http_request_t *nginx;
-
-typedef struct {
- ngx_str_t filename;
- ngx_str_t redirect_uri;
- ngx_str_t redirect_args;
-
- SV *next;
-
- ngx_uint_t done; /* unsigned done:1; */
-
- ngx_array_t *variables; /* array of ngx_http_perl_var_t */
-
-#if (NGX_HTTP_SSI)
- ngx_http_ssi_ctx_t *ssi;
-#endif
-} ngx_http_perl_ctx_t;
-
-
-typedef struct {
- ngx_uint_t hash;
- ngx_str_t name;
- ngx_str_t value;
-} ngx_http_perl_var_t;
-
-
-extern ngx_module_t ngx_http_perl_module;
-
-
-/*
- * workaround for "unused variable `Perl___notused'" warning
- * when building with perl 5.6.1
- */
-#ifndef PERL_IMPLICIT_CONTEXT
-#undef dTHXa
-#define dTHXa(a)
-#endif
-
-
-extern void boot_DynaLoader(pTHX_ CV* cv);
-
-
-void ngx_http_perl_handle_request(ngx_http_request_t *r);
-void ngx_http_perl_sleep_handler(ngx_http_request_t *r);
-
-
-#endif /* _NGX_HTTP_PERL_MODULE_H_INCLUDED_ */
diff --git a/nginx/src/http/modules/perl/typemap b/nginx/src/http/modules/perl/typemap
deleted file mode 100644
index e2f1a4c..0000000
--- a/nginx/src/http/modules/perl/typemap
+++ /dev/null
@@ -1,3 +0,0 @@
-TYPEMAP
-
-nginx T_PTROBJ