static char * ngx_http_access_rule(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) {//将参数里面的IP地址等,放入对应的location的rules中 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 ngx_memzero(&cidr, sizeof(ngx_cidr_t)); value = cf->args->elts; all = (value[1].len == 3 && ngx_strcmp(value[1].data, "all") == 0); if (!all) {//deny all;遇到这种 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]); } } switch (cidr.family) { #if (NGX_HAVE_INET6) case AF_INET6: case 0: /* 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; if (!all) { break; } /* "all" passes through */ #endif default: /* AF_INET */ 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; } return NGX_CONF_OK; }
static char * ngx_event_debug_connection(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { #if (NGX_DEBUG) ngx_event_conf_t *ecf = 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 (NGX_HAVE_UNIX_DOMAIN) if (ngx_strcmp(value[1].data, "unix:") == 0) { cidr = ngx_array_push(&ecf->debug_connection); 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(&ecf->debug_connection); 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 debug_connection \"%V\"", u.err, &u.host); } return NGX_CONF_ERROR; } cidr = ngx_array_push_n(&ecf->debug_connection, 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; } } #else ngx_conf_log_error(NGX_LOG_WARN, cf, 0, "\"debug_connection\" is ignored, you need to rebuild " "nginx using --with-debug option to enable it"); #endif return NGX_CONF_OK; }
static char* ngx_http_fancyindex_ignore(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { ngx_http_fancyindex_loc_conf_t *alcf = conf; ngx_str_t *value; #if (NGX_PCRE) ngx_uint_t i; ngx_regex_elt_t *re; ngx_regex_compile_t rc; u_char errstr[NGX_MAX_CONF_ERRSTR]; if (alcf->ignore == NGX_CONF_UNSET_PTR) { alcf->ignore = ngx_array_create(cf->pool, 2, sizeof(ngx_regex_elt_t)); if (alcf->ignore == NULL) { return NGX_CONF_ERROR; } } value = cf->args->elts; ngx_memzero(&rc, sizeof(ngx_regex_compile_t)); rc.err.data = errstr; rc.err.len = NGX_MAX_CONF_ERRSTR; rc.pool = cf->pool; for (i = 1; i < cf->args->nelts; i++) { re = ngx_array_push(alcf->ignore); if (re == NULL) { return NGX_CONF_ERROR; } rc.pattern = value[i]; rc.options = NGX_REGEX_CASELESS; if (ngx_regex_compile(&rc) != NGX_OK) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%V", &rc.err); return NGX_CONF_ERROR; } re->name = value[i].data; re->regex = rc.regex; } return NGX_CONF_OK; #else /* !NGX_PCRE */ ngx_uint_t i; ngx_str_t *str; if (alcf->ignore == NGX_CONF_UNSET_PTR) { alcf->ignore = ngx_array_create(cf->pool, 2, sizeof(ngx_str_t)); if (alcf->ignore == NULL) { return NGX_CONF_ERROR; } } value = cf->args->elts; for (i = 1; i < cf->args->nelts; i++) { str = ngx_array_push(alcf->ignore); if (str == NULL) { return NGX_CONF_ERROR; } str->data = value[i].data; str->len = value[i].len; } return NGX_CONF_OK; #endif /* NGX_PCRE */ }
static char * ngx_rtmp_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { size_t len, off; in_port_t port; ngx_str_t *value; ngx_url_t u; ngx_uint_t i, m; ngx_module_t **modules; struct sockaddr *sa; ngx_rtmp_listen_t *ls; struct sockaddr_in *sin; ngx_rtmp_core_main_conf_t *cmcf; #if (NGX_HAVE_INET6) struct sockaddr_in6 *sin6; #endif value = cf->args->elts; ngx_memzero(&u, sizeof(ngx_url_t)); u.url = value[1]; u.listen = 1; if (ngx_parse_url(cf->pool, &u) != NGX_OK) { if (u.err) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%s in \"%V\" of the \"listen\" directive", u.err, &u.url); } return NGX_CONF_ERROR; } cmcf = ngx_rtmp_conf_get_module_main_conf(cf, ngx_rtmp_core_module); ls = cmcf->listen.elts; for (i = 0; i < cmcf->listen.nelts; i++) { sa = (struct sockaddr *) ls[i].sockaddr; if (sa->sa_family != u.family) { continue; } switch (sa->sa_family) { #if (NGX_HAVE_INET6) case AF_INET6: off = offsetof(struct sockaddr_in6, sin6_addr); len = 16; sin6 = (struct sockaddr_in6 *) sa; port = sin6->sin6_port; break; #endif default: /* AF_INET */ off = offsetof(struct sockaddr_in, sin_addr); len = 4; sin = (struct sockaddr_in *) sa; port = sin->sin_port; break; } if (ngx_memcmp(ls[i].sockaddr + off, u.sockaddr + off, len) != 0) { continue; } if (port != u.port) { continue; } ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "duplicate \"%V\" address and port pair", &u.url); return NGX_CONF_ERROR; } ls = ngx_array_push(&cmcf->listen); if (ls == NULL) { return NGX_CONF_ERROR; } ngx_memzero(ls, sizeof(ngx_rtmp_listen_t)); ngx_memcpy(ls->sockaddr, u.sockaddr, u.socklen); ls->socklen = u.socklen; ls->wildcard = u.wildcard; ls->ctx = cf->ctx; #if defined(nginx_version) && nginx_version >= 1009011 modules = cf->cycle->modules; #else modules = ngx_modules; #endif for (m = 0; modules[m]; m++) { if (modules[m]->type != NGX_RTMP_MODULE) { continue; } } for (i = 2; i < cf->args->nelts; i++) { if (ngx_strcmp(value[i].data, "bind") == 0) { ls->bind = 1; continue; } if (ngx_strncmp(value[i].data, "ipv6only=o", 10) == 0) { #if (NGX_HAVE_INET6 && defined IPV6_V6ONLY) struct sockaddr *sa; u_char buf[NGX_SOCKADDR_STRLEN]; sa = (struct sockaddr *) ls->sockaddr; if (sa->sa_family == AF_INET6) { if (ngx_strcmp(&value[i].data[10], "n") == 0) { ls->ipv6only = 1; } else if (ngx_strcmp(&value[i].data[10], "ff") == 0) { ls->ipv6only = 0; } else { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid ipv6only flags \"%s\"", &value[i].data[9]); return NGX_CONF_ERROR; } ls->bind = 1; } else { len = ngx_sock_ntop(sa, #if (nginx_version >= 1005003) ls->socklen, #endif buf, NGX_SOCKADDR_STRLEN, 1); ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "ipv6only is not supported " "on addr \"%*s\", ignored", len, buf); } continue; #else ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "bind ipv6only is not supported " "on this platform"); return NGX_CONF_ERROR; #endif } if (ngx_strncmp(value[i].data, "so_keepalive=", 13) == 0) { if (ngx_strcmp(&value[i].data[13], "on") == 0) { ls->so_keepalive = 1; } else if (ngx_strcmp(&value[i].data[13], "off") == 0) { ls->so_keepalive = 2; } else { #if (NGX_HAVE_KEEPALIVE_TUNABLE) u_char *p, *end; ngx_str_t s; end = value[i].data + value[i].len; s.data = value[i].data + 13; p = ngx_strlchr(s.data, end, ':'); if (p == NULL) { p = end; } if (p > s.data) { s.len = p - s.data; ls->tcp_keepidle = ngx_parse_time(&s, 1); if (ls->tcp_keepidle == (time_t) NGX_ERROR) { goto invalid_so_keepalive; } } s.data = (p < end) ? (p + 1) : end; p = ngx_strlchr(s.data, end, ':'); if (p == NULL) { p = end; } if (p > s.data) { s.len = p - s.data; ls->tcp_keepintvl = ngx_parse_time(&s, 1); if (ls->tcp_keepintvl == (time_t) NGX_ERROR) { goto invalid_so_keepalive; } } s.data = (p < end) ? (p + 1) : end; if (s.data < end) { s.len = end - s.data; ls->tcp_keepcnt = ngx_atoi(s.data, s.len); if (ls->tcp_keepcnt == NGX_ERROR) { goto invalid_so_keepalive; } } if (ls->tcp_keepidle == 0 && ls->tcp_keepintvl == 0 && ls->tcp_keepcnt == 0) { goto invalid_so_keepalive; } ls->so_keepalive = 1; #else ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "the \"so_keepalive\" parameter accepts " "only \"on\" or \"off\" on this platform"); return NGX_CONF_ERROR; #endif } ls->bind = 1; continue; #if (NGX_HAVE_KEEPALIVE_TUNABLE) invalid_so_keepalive: ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid so_keepalive value: \"%s\"", &value[i].data[13]); return NGX_CONF_ERROR; #endif } if (ngx_strcmp(value[i].data, "proxy_protocol") == 0) { ls->proxy_protocol = 1; continue; } ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "the invalid \"%V\" parameter", &value[i]); return NGX_CONF_ERROR; } return NGX_CONF_OK; }
static ngx_int_t ngx_http_set_expires(ngx_http_request_t *r, ngx_http_headers_conf_t *conf) { syslog(LOG_INFO, "[%s:%s:%d]", __FILE__, __func__, __LINE__); size_t len; time_t now, expires_time, max_age; ngx_uint_t i; ngx_table_elt_t *expires, *cc, **ccp; expires = r->headers_out.expires; if (expires == NULL) { expires = ngx_list_push(&r->headers_out.headers); if (expires == NULL) { return NGX_ERROR; } r->headers_out.expires = expires; expires->hash = 1; ngx_str_set(&expires->key, "Expires"); } len = sizeof("Mon, 28 Sep 1970 06:00:00 GMT"); expires->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; } ccp = ngx_array_push(&r->headers_out.cache_control); if (ccp == NULL) { 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 = cc; } else { for (i = 1; i < r->headers_out.cache_control.nelts; i++) { ccp[i]->hash = 0; } cc = ccp[0]; } if (conf->expires == NGX_HTTP_EXPIRES_EPOCH) { expires->value.data = (u_char *) "Thu, 01 Jan 1970 00:00:01 GMT"; ngx_str_set(&cc->value, "no-cache"); return NGX_OK; } if (conf->expires == NGX_HTTP_EXPIRES_MAX) { expires->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; } expires->value.data = ngx_pnalloc(r->pool, len); if (expires->value.data == NULL) { return NGX_ERROR; } if (conf->expires_time == 0 && conf->expires != NGX_HTTP_EXPIRES_DAILY) { ngx_memcpy(expires->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 (conf->expires == NGX_HTTP_EXPIRES_DAILY) { expires_time = ngx_next_time(conf->expires_time); max_age = expires_time - now; } else if (conf->expires == NGX_HTTP_EXPIRES_ACCESS || r->headers_out.last_modified_time == -1) { expires_time = now + conf->expires_time; max_age = conf->expires_time; } else { expires_time = r->headers_out.last_modified_time + conf->expires_time; max_age = expires_time - now; } ngx_http_time(expires->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 char * ngx_stream_upstream_server(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { ngx_stream_upstream_srv_conf_t *uscf = conf; time_t fail_timeout; ngx_str_t *value, s; ngx_url_t u; ngx_int_t weight, max_fails; ngx_uint_t i; ngx_stream_upstream_server_t *us; us = ngx_array_push(uscf->servers); if (us == NULL) { return NGX_CONF_ERROR; } ngx_memzero(us, sizeof(ngx_stream_upstream_server_t)); value = cf->args->elts; weight = 1; max_fails = 1; fail_timeout = 10; for (i = 2; i < cf->args->nelts; i++) { if (ngx_strncmp(value[i].data, "weight=", 7) == 0) { if (!(uscf->flags & NGX_STREAM_UPSTREAM_WEIGHT)) { goto not_supported; } weight = ngx_atoi(&value[i].data[7], value[i].len - 7); if (weight == NGX_ERROR || weight == 0) { goto invalid; } continue; } if (ngx_strncmp(value[i].data, "max_fails=", 10) == 0) { if (!(uscf->flags & NGX_STREAM_UPSTREAM_MAX_FAILS)) { goto not_supported; } max_fails = ngx_atoi(&value[i].data[10], value[i].len - 10); if (max_fails == NGX_ERROR) { goto invalid; } continue; } if (ngx_strncmp(value[i].data, "fail_timeout=", 13) == 0) { if (!(uscf->flags & NGX_STREAM_UPSTREAM_FAIL_TIMEOUT)) { goto not_supported; } s.len = value[i].len - 13; s.data = &value[i].data[13]; fail_timeout = ngx_parse_time(&s, 1); if (fail_timeout == (time_t) NGX_ERROR) { goto invalid; } continue; } if (ngx_strcmp(value[i].data, "backup") == 0) { if (!(uscf->flags & NGX_STREAM_UPSTREAM_BACKUP)) { goto not_supported; } us->backup = 1; continue; } if (ngx_strcmp(value[i].data, "down") == 0) { if (!(uscf->flags & NGX_STREAM_UPSTREAM_DOWN)) { goto not_supported; } us->down = 1; continue; } goto invalid; } ngx_memzero(&u, sizeof(ngx_url_t)); u.url = value[1]; if (ngx_parse_url(cf->pool, &u) != NGX_OK) { if (u.err) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%s in upstream \"%V\"", u.err, &u.url); } return NGX_CONF_ERROR; } if (u.no_port) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "no port in upstream \"%V\"", &u.url); return NGX_CONF_ERROR; } us->name = u.url; us->addrs = u.addrs; us->naddrs = u.naddrs; us->weight = weight; us->max_fails = max_fails; us->fail_timeout = fail_timeout; return NGX_CONF_OK; invalid: ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid parameter \"%V\"", &value[i]); return NGX_CONF_ERROR; not_supported: ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "balancing method does not support parameter \"%V\"", &value[i]); return NGX_CONF_ERROR; }
static char * ngx_rtmp_core_server(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { char *rv; void *mconf; ngx_uint_t m; ngx_conf_t pcf; ngx_module_t **modules; ngx_rtmp_module_t *module; ngx_rtmp_conf_ctx_t *ctx, *rtmp_ctx; ngx_rtmp_core_srv_conf_t *cscf, **cscfp; ngx_rtmp_core_main_conf_t *cmcf; ctx = ngx_pcalloc(cf->pool, sizeof(ngx_rtmp_conf_ctx_t)); if (ctx == NULL) { return NGX_CONF_ERROR; } rtmp_ctx = cf->ctx; ctx->main_conf = rtmp_ctx->main_conf; /* the server{}'s srv_conf */ ctx->srv_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_rtmp_max_module); if (ctx->srv_conf == NULL) { return NGX_CONF_ERROR; } ctx->app_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_rtmp_max_module); if (ctx->app_conf == NULL) { return NGX_CONF_ERROR; } #if defined(nginx_version) && nginx_version >= 1009011 modules = cf->cycle->modules; #else modules = ngx_modules; #endif for (m = 0; modules[m]; m++) { if (modules[m]->type != NGX_RTMP_MODULE) { continue; } module = modules[m]->ctx; if (module->create_srv_conf) { mconf = module->create_srv_conf(cf); if (mconf == NULL) { return NGX_CONF_ERROR; } ctx->srv_conf[modules[m]->ctx_index] = mconf; } if (module->create_app_conf) { mconf = module->create_app_conf(cf); if (mconf == NULL) { return NGX_CONF_ERROR; } ctx->app_conf[modules[m]->ctx_index] = mconf; } } /* the server configuration context */ cscf = ctx->srv_conf[ngx_rtmp_core_module.ctx_index]; cscf->ctx = ctx; cmcf = ctx->main_conf[ngx_rtmp_core_module.ctx_index]; cscfp = ngx_array_push(&cmcf->servers); if (cscfp == NULL) { return NGX_CONF_ERROR; } *cscfp = cscf; /* parse inside server{} */ pcf = *cf; cf->ctx = ctx; cf->cmd_type = NGX_RTMP_SRV_CONF; rv = ngx_conf_parse(cf, NULL); *cf = pcf; return rv; }
static char * ngx_proc_process(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { char *rv; void *mconf; ngx_int_t i; ngx_str_t *value; ngx_flag_t flag; ngx_conf_t pcf; ngx_uint_t m; ngx_proc_conf_t *cpcf, **cpcfp; ngx_proc_module_t *module; ngx_proc_conf_ctx_t *ctx, *procs_ctx; ngx_proc_main_conf_t *cmcf; value = cf->args->elts; flag = 0; for (m = 0; ngx_modules[m]; m++) { if (ngx_modules[m]->type != NGX_PROC_MODULE) { continue; } module = ngx_modules[m]->ctx; if (ngx_strcmp(module->name.data, value[1].data) == 0) { flag = 1; break; } } if (flag == 0) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "no %V process module", &value[1]); return NGX_CONF_ERROR; } /* new conf ctx */ ctx = ngx_pcalloc(cf->pool, sizeof(ngx_proc_conf_ctx_t)); if (ctx == NULL) { return NGX_CONF_ERROR; } procs_ctx = cf->ctx; ctx->main_conf = procs_ctx->main_conf; /* old main conf */ /* the processes{}'s proc_conf */ ctx->proc_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_procs_max_module); if (ctx->proc_conf == NULL) { return NGX_CONF_ERROR; } for (m = 0; ngx_modules[m]; m++) { if (ngx_modules[m]->type != NGX_PROC_MODULE) { continue; } module = ngx_modules[m]->ctx; if (module->create_proc_conf) { mconf = module->create_proc_conf(cf); if (mconf == NULL) { return NGX_CONF_ERROR; } /* new proc conf */ ctx->proc_conf[ngx_modules[m]->ctx_index] = mconf; } } /* the proc configuration context */ cpcf = ctx->proc_conf[ngx_proc_core_module.ctx_index]; cpcf->ctx = ctx; cpcf->name = value[1]; cmcf = ctx->main_conf[ngx_proc_core_module.ctx_index]; cpcfp = ngx_array_push(&cmcf->processes); if (cpcfp == NULL) { return NGX_CONF_ERROR; } *cpcfp = cpcf; /* check process conf repeat */ cpcfp = cmcf->processes.elts; for (i = cmcf->processes.nelts - 2; i >= 0 ; i--) { if (ngx_strcmp(cpcfp[i]->name.data, cpcf->name.data) == 0) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "process repeat"); return NGX_CONF_ERROR; } } /* parse inside process{} */ pcf = *cf; cf->ctx = ctx; cf->cmd_type = NGX_PROC_CONF; rv = ngx_conf_parse(cf, NULL); *cf = pcf; return rv; }
char * ngx_http_file_cache_valid_set_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { char *p = conf; time_t valid; ngx_str_t *value; ngx_uint_t i, n, status; ngx_array_t **a; ngx_http_cache_valid_t *v; static ngx_uint_t statuses[] = { 200, 301, 302 }; a = (ngx_array_t **) (p + cmd->offset); if (*a == NGX_CONF_UNSET_PTR) { *a = ngx_array_create(cf->pool, 1, sizeof(ngx_http_cache_valid_t)); if (*a == NULL) { return NGX_CONF_ERROR; } } value = cf->args->elts; n = cf->args->nelts - 1; valid = ngx_parse_time(&value[n], 1); if (valid < 0) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid time value \"%V\"", &value[n]); return NGX_CONF_ERROR; } if (n == 1) { for (i = 0; i < 3; i++) { v = ngx_array_push(*a); if (v == NULL) { return NGX_CONF_ERROR; } v->status = statuses[i]; v->valid = valid; } return NGX_CONF_OK; } for (i = 1; i < n; i++) { if (ngx_strcmp(value[i].data, "any") == 0) { status = 0; } else { status = ngx_atoi(value[i].data, value[i].len); if (status < 100) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid status \"%V\"", &value[i]); return NGX_CONF_ERROR; } } v = ngx_array_push(*a); if (v == NULL) { return NGX_CONF_ERROR; } v->status = status; v->valid = valid; } return NGX_CONF_OK; }
static char * ngx_http_data_dome_auth_set(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { ngx_http_data_dome_auth_conf_t *acf = conf; ngx_str_t *value; ngx_http_variable_t *v; ngx_http_data_dome_auth_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 (acf->vars == NGX_CONF_UNSET_PTR) { acf->vars = ngx_array_create(cf->pool, 1, sizeof(ngx_http_data_dome_auth_variable_t)); if (acf->vars == NULL) { return NGX_CONF_ERROR; } } av = ngx_array_push(acf->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_data_dome_auth_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; }
ngx_listening_t * ngx_create_listening(ngx_conf_t *cf, void *sockaddr, socklen_t socklen) { size_t len; ngx_listening_t *ls; struct sockaddr *sa; u_char text[NGX_SOCKADDR_STRLEN]; ls = ngx_array_push(&cf->cycle->listening); if (ls == NULL) { return NULL; } ngx_memzero(ls, sizeof(ngx_listening_t)); sa = ngx_palloc(cf->pool, socklen); if (sa == NULL) { return NULL; } ngx_memcpy(sa, sockaddr, socklen); ls->sockaddr = sa; ls->socklen = socklen; len = ngx_sock_ntop(sa, text, NGX_SOCKADDR_STRLEN, 1); ls->addr_text.len = len; switch (ls->sockaddr->sa_family) { #if (NGX_HAVE_INET6) case AF_INET6: ls->addr_text_max_len = NGX_INET6_ADDRSTRLEN; break; #endif #if (NGX_HAVE_UNIX_DOMAIN) case AF_UNIX: ls->addr_text_max_len = NGX_UNIX_ADDRSTRLEN; len++; break; #endif case AF_INET: ls->addr_text_max_len = NGX_INET_ADDRSTRLEN; break; default: ls->addr_text_max_len = NGX_SOCKADDR_STRLEN; break; } ls->addr_text.data = ngx_pnalloc(cf->pool, len); if (ls->addr_text.data == NULL) { return NULL; } ngx_memcpy(ls->addr_text.data, text, len); ls->fd = (ngx_socket_t) -1; ls->type = SOCK_STREAM; ls->backlog = NGX_LISTEN_BACKLOG; ls->rcvbuf = -1; ls->sndbuf = -1; #if (NGX_HAVE_SETFIB) ls->setfib = -1; #endif return ls; }
static char * ngx_mail_core_server(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { char *rv; void *mconf; ngx_uint_t m; ngx_conf_t pcf; ngx_mail_module_t *module; ngx_mail_conf_ctx_t *ctx, *mail_ctx; ngx_mail_core_srv_conf_t *cscf, **cscfp; ngx_mail_core_main_conf_t *cmcf; ctx = ngx_pcalloc(cf->pool, sizeof(ngx_mail_conf_ctx_t)); if (ctx == NULL) { return NGX_CONF_ERROR; } mail_ctx = cf->ctx; ctx->main_conf = mail_ctx->main_conf; /* the server{}'s srv_conf */ ctx->srv_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_mail_max_module); if (ctx->srv_conf == NULL) { return NGX_CONF_ERROR; } for (m = 0; ngx_modules[m]; m++) { if (ngx_modules[m]->type != NGX_MAIL_MODULE) { continue; } module = ngx_modules[m]->ctx; if (module->create_srv_conf) { mconf = module->create_srv_conf(cf); if (mconf == NULL) { return NGX_CONF_ERROR; } ctx->srv_conf[ngx_modules[m]->ctx_index] = mconf; } } /* the server configuration context */ cscf = ctx->srv_conf[ngx_mail_core_module.ctx_index]; cscf->ctx = ctx; cmcf = ctx->main_conf[ngx_mail_core_module.ctx_index]; cscfp = ngx_array_push(&cmcf->servers); if (cscfp == NULL) { return NGX_CONF_ERROR; } *cscfp = cscf; /* parse inside server{} */ pcf = *cf; cf->ctx = ctx; cf->cmd_type = NGX_MAIL_SRV_CONF; rv = ngx_conf_parse(cf, NULL); *cf = pcf; return rv; }
static char * ngx_http_headers_expires_by_types(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { ngx_http_headers_conf_t *hcf = conf; ngx_http_headers_expires_time_t *et; char *rs; ngx_str_t *value; ngx_uint_t i, hash; ngx_uint_t n; ngx_hash_key_t *type; value = cf->args->elts; if (hcf->types_keys == NULL) { hcf->types_keys = ngx_array_create(cf->pool, 1, sizeof(ngx_hash_key_t)); if (hcf->types_keys == NULL) { return NGX_CONF_ERROR; } } et = ngx_pcalloc(cf->pool, sizeof(ngx_http_headers_expires_time_t)); if (et == NULL) { return NGX_CONF_ERROR; } if (ngx_strcmp(value[1].data, "modified") == 0) { et->expires = NGX_HTTP_EXPIRES_MODIFIED; if (cf->args->nelts == 3) { return NGX_CONF_ERROR; } n = 3; } else { et->expires = NGX_HTTP_EXPIRES_ACCESS; if (cf->args->nelts == 2) { return NGX_CONF_ERROR; } n = 2; } rs = ngx_http_headers_parse_expires(cf, &et->expires, &et->expires_time); if (rs != NGX_CONF_OK) { return rs; } for (; n < cf->args->nelts; n++) { hash = ngx_hash_strlow(value[n].data, value[n].data, value[n].len); value[n].data[value[n].len] = '\0'; type = hcf->types_keys->elts; for (i = 0; i < hcf->types_keys->nelts; i++) { if (ngx_strcmp(value[n].data, type[i].key.data) == 0) { ngx_conf_log_error(NGX_LOG_WARN, cf, 0, "duplicate MIME type \"%V\"", &value[n]); continue; } } type = ngx_array_push(hcf->types_keys); if (type == NULL) { return NGX_CONF_ERROR; } type->key = value[n]; type->key_hash = hash; type->value = (void *) et; } return NGX_CONF_OK; }
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; }
static char * ngx_rtmp_play_url(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { ngx_rtmp_play_app_conf_t *pacf = conf; ngx_rtmp_play_entry_t *pe, **ppe; ngx_str_t url; ngx_url_t *u; size_t add, n; ngx_str_t *value; if (pacf->entries.nalloc == 0 && ngx_array_init(&pacf->entries, cf->pool, 1, sizeof(void *)) != NGX_OK) { return NGX_CONF_ERROR; } value = cf->args->elts; for (n = 1; n < cf->args->nelts; ++n) { ppe = ngx_array_push(&pacf->entries); if (ppe == NULL) { return NGX_CONF_ERROR; } pe = ngx_pcalloc(cf->pool, sizeof(ngx_rtmp_play_entry_t)); if (pe == NULL) { return NGX_CONF_ERROR; } *ppe = pe; if (ngx_strncasecmp(value[n].data, (u_char *) "http://", 7)) { /* local file */ pe->root = ngx_palloc(cf->pool, sizeof(ngx_str_t)); if (pe->root == NULL) { return NGX_CONF_ERROR; } *pe->root = value[n]; continue; } /* http case */ url = value[n]; add = sizeof("http://") - 1; url.data += add; url.len -= add; u = ngx_pcalloc(cf->pool, sizeof(ngx_url_t)); if (u == NULL) { return NGX_CONF_ERROR; } u->url.len = url.len; u->url.data = url.data; u->default_port = 80; u->uri_part = 1; if (ngx_parse_url(cf->pool, u) != NGX_OK) { if (u->err) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%s in url \"%V\"", u->err, &u->url); } return NGX_CONF_ERROR; } pe->url = u; } return NGX_CONF_OK; }
char * ngx_http_drizzle_query(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { ngx_str_t *value = cf->args->elts; ngx_str_t sql = value[cf->args->nelts - 1]; ngx_http_drizzle_loc_conf_t *dlcf = conf; ngx_http_compile_complex_value_t ccv; ngx_drizzle_mixed_t *query; ngx_drizzle_http_method_t *method; ngx_uint_t methods, i; if (sql.len == 0) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "drizzle: empty value in \"%V\" directive", &cmd->name); return NGX_CONF_ERROR; } if (cf->args->nelts == 2) { /* default query */ dd("default query"); if (dlcf->default_query != NULL) { return "is duplicate"; } dlcf->default_query = ngx_pcalloc(cf->pool, sizeof(ngx_drizzle_mixed_t)); if (dlcf->default_query == NULL) { return NGX_CONF_ERROR; } methods = 0xFFFF; query = dlcf->default_query; } else { /* method-specific query */ dd("method-specific query"); methods = 0; for (i = 1; i < cf->args->nelts - 1; i++) { for (method = ngx_drizzle_http_methods; method->name; method++) { if (ngx_strcasecmp(value[i].data, method->name) == 0) { /* correct method name */ if (dlcf->methods_set & method->key) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "drizzle: \"%V\" directive" " for method \"%V\" is duplicate", &cmd->name, &value[i]); return NGX_CONF_ERROR; } methods |= method->key; goto next; } } ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "drizzle: invalid method \"%V\"", &value[i]); return NGX_CONF_ERROR; next: continue; } if (dlcf->queries == NULL) { dlcf->queries = ngx_array_create(cf->pool, 4, sizeof(ngx_drizzle_mixed_t)); if (dlcf->queries == NULL) { return NGX_CONF_ERROR; } } query = ngx_array_push(dlcf->queries); if (query == NULL) { return NGX_CONF_ERROR; } ngx_memzero(query, sizeof(ngx_drizzle_mixed_t)); dlcf->methods_set |= methods; } if (ngx_http_script_variables_count(&sql)) { /* complex value */ dd("complex value"); query->key = methods; query->cv = ngx_palloc(cf->pool, sizeof(ngx_http_complex_value_t)); if (query->cv == NULL) { return NGX_CONF_ERROR; } ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t)); ccv.cf = cf; ccv.value = &sql; ccv.complex_value = query->cv; if (ngx_http_compile_complex_value(&ccv) != NGX_OK) { return NGX_CONF_ERROR; } } else { /* simple value */ dd("simple value"); query->key = methods; query->sv = sql; } return NGX_CONF_OK; }
ngx_cycle_t * ngx_init_cycle(ngx_cycle_t *old_cycle) { void *rv; char **senv, **env; u_char *temppath; ngx_err_t err; ngx_uint_t i, n; ngx_log_t *log; ngx_time_t *tp; ngx_conf_t conf; ngx_pool_t *pool; ngx_cycle_t *cycle, **old; ngx_command_t *cmd; ngx_shm_zone_t *shm_zone, *oshm_zone; ngx_list_part_t *part, *opart; ngx_open_file_t *file; ngx_listening_t *ls, *nls; ngx_core_conf_t *ccf, *old_ccf; ngx_core_module_t *module; char hostname[NGX_MAXHOSTNAMELEN]; ngx_timezone_update(); /* force localtime update with a new timezone */ tp = ngx_timeofday(); tp->sec = 0; ngx_time_update(); ngx_increase_pipe_generation(); log = old_cycle->log; pool = ngx_create_pool(NGX_CYCLE_POOL_SIZE, log); if (pool == NULL) { return NULL; } pool->log = log; cycle = ngx_pcalloc(pool, sizeof(ngx_cycle_t)); if (cycle == NULL) { ngx_destroy_pool(pool); return NULL; } cycle->pool = pool; cycle->log = log; cycle->new_log.log_level = NGX_LOG_ERR; cycle->old_cycle = old_cycle; cycle->conf_prefix.len = old_cycle->conf_prefix.len; cycle->conf_prefix.data = ngx_pstrdup(pool, &old_cycle->conf_prefix); if (cycle->conf_prefix.data == NULL) { ngx_destroy_pool(pool); return NULL; } cycle->prefix.len = old_cycle->prefix.len; cycle->prefix.data = ngx_pstrdup(pool, &old_cycle->prefix); if (cycle->prefix.data == NULL) { ngx_destroy_pool(pool); return NULL; } cycle->conf_file.len = old_cycle->conf_file.len; cycle->conf_file.data = ngx_pnalloc(pool, old_cycle->conf_file.len + 1); if (cycle->conf_file.data == NULL) { ngx_destroy_pool(pool); return NULL; } ngx_cpystrn(cycle->conf_file.data, old_cycle->conf_file.data, old_cycle->conf_file.len + 1); cycle->conf_param.len = old_cycle->conf_param.len; cycle->conf_param.data = ngx_pstrdup(pool, &old_cycle->conf_param); if (cycle->conf_param.data == NULL) { ngx_destroy_pool(pool); return NULL; } n = old_cycle->paths.nelts ? old_cycle->paths.nelts : 10; cycle->paths.elts = ngx_pcalloc(pool, n * sizeof(ngx_path_t *)); if (cycle->paths.elts == NULL) { ngx_destroy_pool(pool); return NULL; } cycle->paths.nelts = 0; cycle->paths.size = sizeof(ngx_path_t *); cycle->paths.nalloc = n; cycle->paths.pool = pool; if (old_cycle->open_files.part.nelts) { n = old_cycle->open_files.part.nelts; for (part = old_cycle->open_files.part.next; part; part = part->next) { n += part->nelts; } } else { n = 20; } if (ngx_list_init(&cycle->open_files, pool, n, sizeof(ngx_open_file_t)) != NGX_OK) { ngx_destroy_pool(pool); return NULL; } if (old_cycle->shared_memory.part.nelts) { n = old_cycle->shared_memory.part.nelts; for (part = old_cycle->shared_memory.part.next; part; part = part->next) { n += part->nelts; } } else { n = 1; } if (ngx_list_init(&cycle->shared_memory, pool, n, sizeof(ngx_shm_zone_t)) != NGX_OK) { ngx_destroy_pool(pool); return NULL; } n = old_cycle->listening.nelts ? old_cycle->listening.nelts : 10; cycle->listening.elts = ngx_pcalloc(pool, n * sizeof(ngx_listening_t)); if (cycle->listening.elts == NULL) { ngx_destroy_pool(pool); return NULL; } cycle->listening.nelts = 0; cycle->listening.size = sizeof(ngx_listening_t); cycle->listening.nalloc = n; cycle->listening.pool = pool; ngx_queue_init(&cycle->reusable_connections_queue); cycle->conf_ctx = ngx_pcalloc(pool, ngx_max_module * sizeof(void *)); if (cycle->conf_ctx == NULL) { ngx_destroy_pool(pool); return NULL; } if (gethostname(hostname, NGX_MAXHOSTNAMELEN) == -1) { ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "gethostname() failed"); ngx_destroy_pool(pool); return NULL; } /* on Linux gethostname() silently truncates name that does not fit */ hostname[NGX_MAXHOSTNAMELEN - 1] = '\0'; cycle->hostname.len = ngx_strlen(hostname); cycle->hostname.data = ngx_pnalloc(pool, cycle->hostname.len); if (cycle->hostname.data == NULL) { ngx_destroy_pool(pool); return NULL; } ngx_strlow(cycle->hostname.data, (u_char *) hostname, cycle->hostname.len); for (i = 0; ngx_modules[i]; i++) { if (ngx_modules[i]->type != NGX_CORE_MODULE) { continue; } module = ngx_modules[i]->ctx; if (module->create_conf) { rv = module->create_conf(cycle); if (rv == NULL) { ngx_destroy_pool(pool); return NULL; } cycle->conf_ctx[ngx_modules[i]->index] = rv; } } senv = environ; ngx_memzero(&conf, sizeof(ngx_conf_t)); /* STUB: init array ? */ conf.args = ngx_array_create(pool, 10, sizeof(ngx_str_t)); if (conf.args == NULL) { ngx_destroy_pool(pool); return NULL; } conf.temp_pool = ngx_create_pool(NGX_CYCLE_POOL_SIZE, log); if (conf.temp_pool == NULL) { ngx_destroy_pool(pool); return NULL; } conf.ctx = cycle->conf_ctx; conf.cycle = cycle; conf.pool = pool; conf.log = log; conf.module_type = NGX_CORE_MODULE; conf.cmd_type = NGX_MAIN_CONF; #if 0 log->log_level = NGX_LOG_DEBUG_ALL; #endif if (ngx_conf_param(&conf) != NGX_CONF_OK) { environ = senv; ngx_destroy_cycle_pools(&conf); return NULL; } if (ngx_conf_parse(&conf, &cycle->conf_file) != NGX_CONF_OK) { environ = senv; ngx_destroy_cycle_pools(&conf); return NULL; } if (ngx_show_directives) { ngx_log_stderr(0, "all available directives:"); for (i = 0; ngx_module_names[i]; i++) { ngx_log_stderr(0, "%s:", ngx_module_names[i]); cmd = ngx_modules[i]->commands; if(cmd == NULL) { continue; } for ( /* void */ ; cmd->name.len; cmd++) { ngx_log_stderr(0, " %V", &cmd->name); } } #if (NGX_DSO) ngx_show_dso_directives(&conf); #endif return cycle; } if (ngx_show_modules) { ngx_log_stderr(0, "loaded modules:"); for (i = 0; ngx_module_names[i]; i++) { #if (NGX_DSO) ngx_uint_t major, minor; if (ngx_is_dynamic_module(&conf, ngx_module_names[i], &major, &minor) == NGX_OK) { ngx_log_stderr(0, " %s (shared, %ui.%ui)", ngx_module_names[i], major, minor); } else { #endif ngx_log_stderr(0, " %s (static)", ngx_module_names[i]); #if (NGX_DSO) } #endif } ngx_destroy_cycle_pools(&conf); return cycle; } if (ngx_test_config && !ngx_quiet_mode) { ngx_log_stderr(0, "the configuration file %s syntax is ok", cycle->conf_file.data); } for (i = 0; ngx_modules[i]; i++) { if (ngx_modules[i]->type != NGX_CORE_MODULE) { continue; } module = ngx_modules[i]->ctx; if (module->init_conf) { if (module->init_conf(cycle, cycle->conf_ctx[ngx_modules[i]->index]) == NGX_CONF_ERROR) { environ = senv; ngx_destroy_cycle_pools(&conf); return NULL; } } } if (ngx_process == NGX_PROCESS_SIGNALLER) { return cycle; } ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module); if (ngx_test_config) { if (ngx_create_pidfile(&ccf->pid, log) != NGX_OK) { goto failed; } } else if (!ngx_is_init_cycle(old_cycle)) { /* * we do not create the pid file in the first ngx_init_cycle() call * because we need to write the demonized process pid */ old_ccf = (ngx_core_conf_t *) ngx_get_conf(old_cycle->conf_ctx, ngx_core_module); if (ccf->pid.len != old_ccf->pid.len || ngx_strcmp(ccf->pid.data, old_ccf->pid.data) != 0) { /* new pid file name */ if (ngx_create_pidfile(&ccf->pid, log) != NGX_OK) { goto failed; } ngx_delete_pidfile(old_cycle); } } if (ngx_test_lockfile(cycle->lock_file.data, log) != NGX_OK) { goto failed; } if (ngx_create_paths(cycle, ccf->user) != NGX_OK) { goto failed; } if (cycle->new_log.file == NULL) { cycle->new_log.file = ngx_conf_open_file(cycle, &error_log); if (cycle->new_log.file == NULL) { goto failed; } } /* open pipes */ if (!ngx_is_init_cycle(old_cycle)) { if (ngx_open_pipes(cycle) == NGX_ERROR) { ngx_log_error(NGX_LOG_EMERG, cycle->log, 0, "can not open pipes"); goto failed; } } /* open the new files */ part = &cycle->open_files.part; file = part->elts; temppath = ngx_palloc(conf.temp_pool, NGX_MAX_PATH); for (i = 0; /* void */ ; i++) { if (i >= part->nelts) { if (part->next == NULL) { break; } part = part->next; file = part->elts; i = 0; } if (file[i].name.len == 0) { continue; } if (file[i].name.len >= NGX_MAX_PATH) { ngx_log_error(NGX_LOG_EMERG, log, 0, "path \"%s\" is too long", file[i].name.data); goto failed; } ngx_cpystrn(temppath, file[i].name.data, file[i].name.len + 1); err = ngx_create_full_path(temppath, 0755); if (err != 0) { ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, ngx_create_dir_n " \"%s\" failed", file[i].name.data); goto failed; } file[i].fd = ngx_open_file(file[i].name.data, NGX_FILE_APPEND, NGX_FILE_CREATE_OR_OPEN, NGX_FILE_DEFAULT_ACCESS); ngx_log_debug3(NGX_LOG_DEBUG_CORE, log, 0, "log: %p %d \"%s\"", &file[i], file[i].fd, file[i].name.data); if (file[i].fd == NGX_INVALID_FILE) { ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, ngx_open_file_n " \"%s\" failed", file[i].name.data); goto failed; } #if !(NGX_WIN32) if (fcntl(file[i].fd, F_SETFD, FD_CLOEXEC) == -1) { ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "fcntl(FD_CLOEXEC) \"%s\" failed", file[i].name.data); goto failed; } #endif } #if (NGX_SYSLOG) if (cycle->log->syslog != NULL && cycle->log->syslog->fd != NGX_INVALID_FILE) { ngx_close_socket(cycle->log->syslog->fd); } #endif cycle->log = &cycle->new_log; pool->log = &cycle->new_log; /* create shared memory */ part = &cycle->shared_memory.part; shm_zone = part->elts; for (i = 0; /* void */ ; i++) { if (i >= part->nelts) { if (part->next == NULL) { break; } part = part->next; shm_zone = part->elts; i = 0; } if (shm_zone[i].shm.size == 0) { ngx_log_error(NGX_LOG_EMERG, log, 0, "zero size shared memory zone \"%V\"", &shm_zone[i].shm.name); goto failed; } shm_zone[i].shm.log = cycle->log; opart = &old_cycle->shared_memory.part; oshm_zone = opart->elts; for (n = 0; /* void */ ; n++) { if (n >= opart->nelts) { if (opart->next == NULL) { break; } opart = opart->next; oshm_zone = opart->elts; n = 0; } if (shm_zone[i].shm.name.len != oshm_zone[n].shm.name.len) { continue; } if (ngx_strncmp(shm_zone[i].shm.name.data, oshm_zone[n].shm.name.data, shm_zone[i].shm.name.len) != 0) { continue; } if (shm_zone[i].tag == oshm_zone[n].tag && shm_zone[i].shm.size == oshm_zone[n].shm.size) { shm_zone[i].shm.addr = oshm_zone[n].shm.addr; if (shm_zone[i].init(&shm_zone[i], oshm_zone[n].data) != NGX_OK) { goto failed; } goto shm_zone_found; } ngx_shm_free(&oshm_zone[n].shm); break; } if (ngx_shm_alloc(&shm_zone[i].shm) != NGX_OK) { goto failed; } if (ngx_init_zone_pool(cycle, &shm_zone[i]) != NGX_OK) { goto failed; } if (shm_zone[i].init(&shm_zone[i], NULL) != NGX_OK) { goto failed; } shm_zone_found: continue; } /* handle the listening sockets */ if (old_cycle->listening.nelts) { ls = old_cycle->listening.elts; for (i = 0; i < old_cycle->listening.nelts; i++) { ls[i].remain = 0; } nls = cycle->listening.elts; for (n = 0; n < cycle->listening.nelts; n++) { for (i = 0; i < old_cycle->listening.nelts; i++) { if (ls[i].ignore) { continue; } if (ngx_cmp_sockaddr(nls[n].sockaddr, ls[i].sockaddr) == NGX_OK) { nls[n].fd = ls[i].fd; nls[n].previous = &ls[i]; ls[i].remain = 1; if (ls[n].backlog != nls[i].backlog) { nls[n].listen = 1; } #if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER) /* * FreeBSD, except the most recent versions, * could not remove accept filter */ nls[n].deferred_accept = ls[i].deferred_accept; if (ls[i].accept_filter && nls[n].accept_filter) { if (ngx_strcmp(ls[i].accept_filter, nls[n].accept_filter) != 0) { nls[n].delete_deferred = 1; nls[n].add_deferred = 1; } } else if (ls[i].accept_filter) { nls[n].delete_deferred = 1; } else if (nls[n].accept_filter) { nls[n].add_deferred = 1; } #endif #if (NGX_HAVE_DEFERRED_ACCEPT && defined TCP_DEFER_ACCEPT) if (ls[n].deferred_accept && !nls[n].deferred_accept) { nls[n].delete_deferred = 1; } else if (ls[i].deferred_accept != nls[n].deferred_accept) { nls[n].add_deferred = 1; } #endif break; } } if (nls[n].fd == -1) { nls[n].open = 1; } } } else { ls = cycle->listening.elts; for (i = 0; i < cycle->listening.nelts; i++) { ls[i].open = 1; #if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER) if (ls[i].accept_filter) { ls[i].add_deferred = 1; } #endif #if (NGX_HAVE_DEFERRED_ACCEPT && defined TCP_DEFER_ACCEPT) if (ls[i].deferred_accept) { ls[i].add_deferred = 1; } #endif } } if (ngx_open_listening_sockets(cycle) != NGX_OK) { goto failed; } if (!ngx_test_config) { ngx_configure_listening_sockets(cycle); } /* commit the new cycle configuration */ if (!ngx_use_stderr && cycle->log->file->fd != ngx_stderr) { if (ngx_set_stderr(cycle->log->file->fd) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, ngx_set_stderr_n " failed"); } } pool->log = cycle->log; for (i = 0; ngx_modules[i]; i++) { if (ngx_modules[i]->init_module) { if (ngx_modules[i]->init_module(cycle) != NGX_OK) { /* fatal */ exit(1); } } } /* close and delete stuff that lefts from an old cycle */ /* free the unnecessary shared memory */ opart = &old_cycle->shared_memory.part; oshm_zone = opart->elts; for (i = 0; /* void */ ; i++) { if (i >= opart->nelts) { if (opart->next == NULL) { goto old_shm_zone_done; } opart = opart->next; oshm_zone = opart->elts; i = 0; } part = &cycle->shared_memory.part; shm_zone = part->elts; for (n = 0; /* void */ ; n++) { if (n >= part->nelts) { if (part->next == NULL) { break; } part = part->next; shm_zone = part->elts; n = 0; } if (oshm_zone[i].shm.name.len == shm_zone[n].shm.name.len && ngx_strncmp(oshm_zone[i].shm.name.data, shm_zone[n].shm.name.data, oshm_zone[i].shm.name.len) == 0) { goto live_shm_zone; } } ngx_shm_free(&oshm_zone[i].shm); live_shm_zone: continue; } old_shm_zone_done: /* close the unnecessary listening sockets */ ls = old_cycle->listening.elts; for (i = 0; i < old_cycle->listening.nelts; i++) { if (ls[i].remain || ls[i].fd == -1) { continue; } if (ngx_close_socket(ls[i].fd) == -1) { ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno, ngx_close_socket_n " listening socket on %V failed", &ls[i].addr_text); } #if (NGX_HAVE_UNIX_DOMAIN) if (ls[i].sockaddr->sa_family == AF_UNIX) { u_char *name; name = ls[i].addr_text.data + sizeof("unix:") - 1; ngx_log_error(NGX_LOG_WARN, cycle->log, 0, "deleting socket %s", name); if (ngx_delete_file(name) == -1) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_socket_errno, ngx_delete_file_n " %s failed", name); } } #endif } /* close the unnecessary open files */ part = &old_cycle->open_files.part; file = part->elts; for (i = 0; /* void */ ; i++) { if (i >= part->nelts) { if (part->next == NULL) { break; } part = part->next; file = part->elts; i = 0; } if (file[i].fd == NGX_INVALID_FILE || file[i].fd == ngx_stderr) { continue; } if (ngx_close_file(file[i].fd) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, ngx_close_file_n " \"%s\" failed", file[i].name.data); } } ngx_destroy_pool(conf.temp_pool); if (ngx_process == NGX_PROCESS_MASTER || ngx_is_init_cycle(old_cycle)) { /* * perl_destruct() frees environ, if it is not the same as it was at * perl_construct() time, therefore we save the previous cycle * environment before ngx_conf_parse() where it will be changed. */ env = environ; environ = senv; ngx_destroy_pool(old_cycle->pool); cycle->old_cycle = NULL; environ = env; return cycle; } if (ngx_temp_pool == NULL) { ngx_temp_pool = ngx_create_pool(128, cycle->log); if (ngx_temp_pool == NULL) { ngx_log_error(NGX_LOG_EMERG, cycle->log, 0, "could not create ngx_temp_pool"); exit(1); } n = 10; ngx_old_cycles.elts = ngx_pcalloc(ngx_temp_pool, n * sizeof(ngx_cycle_t *)); if (ngx_old_cycles.elts == NULL) { exit(1); } ngx_old_cycles.nelts = 0; ngx_old_cycles.size = sizeof(ngx_cycle_t *); ngx_old_cycles.nalloc = n; ngx_old_cycles.pool = ngx_temp_pool; ngx_cleaner_event.handler = ngx_clean_old_cycles; ngx_cleaner_event.log = cycle->log; ngx_cleaner_event.data = &dumb; dumb.fd = (ngx_socket_t) -1; } ngx_temp_pool->log = cycle->log; old = ngx_array_push(&ngx_old_cycles); if (old == NULL) { exit(1); } *old = old_cycle; if (!ngx_cleaner_event.timer_set) { ngx_add_timer(&ngx_cleaner_event, 30000); ngx_cleaner_event.timer_set = 1; } return cycle; failed: if (!ngx_is_init_cycle(old_cycle)) { old_ccf = (ngx_core_conf_t *) ngx_get_conf(old_cycle->conf_ctx, ngx_core_module); if (old_ccf->environment) { environ = old_ccf->environment; } } /* rollback the new cycle configuration */ part = &cycle->open_files.part; file = part->elts; for (i = 0; /* void */ ; i++) { if (i >= part->nelts) { if (part->next == NULL) { break; } part = part->next; file = part->elts; i = 0; } if (file[i].fd == NGX_INVALID_FILE || file[i].fd == ngx_stderr) { continue; } if (ngx_close_file(file[i].fd) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, ngx_close_file_n " \"%s\" failed", file[i].name.data); } } ngx_close_pipes(); if (ngx_test_config) { ngx_destroy_cycle_pools(&conf); return NULL; } ls = cycle->listening.elts; for (i = 0; i < cycle->listening.nelts; i++) { if (ls[i].fd == -1 || !ls[i].open) { continue; } if (ngx_close_socket(ls[i].fd) == -1) { ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno, ngx_close_socket_n " %V failed", &ls[i].addr_text); } } ngx_destroy_cycle_pools(&conf); return NULL; }
static char * ngx_rtmp_relay_push_pull(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { ngx_str_t *value, v, n; ngx_rtmp_relay_app_conf_t *racf; ngx_rtmp_relay_target_t *target, **t; ngx_url_t *u; ngx_uint_t i; ngx_int_t is_pull, is_static; ngx_event_t **ee, *e; ngx_rtmp_relay_static_t *rs; u_char *p; value = cf->args->elts; racf = ngx_rtmp_conf_get_module_app_conf(cf, ngx_rtmp_relay_module); is_pull = (value[0].data[3] == 'l'); is_static = 0; target = ngx_pcalloc(cf->pool, sizeof(*target)); if (target == NULL) { return NGX_CONF_ERROR; } target->tag = &ngx_rtmp_relay_module; target->data = target; u = &target->url; u->default_port = 1935; u->uri_part = 1; u->url = value[1]; if (ngx_strncasecmp(u->url.data, (u_char *) "rtmp://", 7) == 0) { u->url.data += 7; u->url.len -= 7; } if (ngx_parse_url(cf->pool, u) != NGX_OK) { if (u->err) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%s in url \"%V\"", u->err, &u->url); } return NGX_CONF_ERROR; } value += 2; for (i = 2; i < cf->args->nelts; ++i, ++value) { p = ngx_strlchr(value->data, value->data + value->len, '='); if (p == NULL) { n = *value; ngx_str_set(&v, "1"); } else { n.data = value->data; n.len = p - value->data; v.data = p + 1; v.len = value->data + value->len - p - 1; } #define NGX_RTMP_RELAY_STR_PAR(name, var) \ if (n.len == sizeof(name) - 1 \ && ngx_strncasecmp(n.data, (u_char *) name, n.len) == 0) \ { \ target->var = v; \ continue; \ } #define NGX_RTMP_RELAY_NUM_PAR(name, var) \ if (n.len == sizeof(name) - 1 \ && ngx_strncasecmp(n.data, (u_char *) name, n.len) == 0) \ { \ target->var = ngx_atoi(v.data, v.len); \ continue; \ } NGX_RTMP_RELAY_STR_PAR("app", app); NGX_RTMP_RELAY_STR_PAR("name", name); NGX_RTMP_RELAY_STR_PAR("tcUrl", tc_url); NGX_RTMP_RELAY_STR_PAR("pageUrl", page_url); NGX_RTMP_RELAY_STR_PAR("swfUrl", swf_url); NGX_RTMP_RELAY_STR_PAR("flashVer", flash_ver); NGX_RTMP_RELAY_STR_PAR("playPath", play_path); NGX_RTMP_RELAY_NUM_PAR("live", live); NGX_RTMP_RELAY_NUM_PAR("start", start); NGX_RTMP_RELAY_NUM_PAR("stop", stop); #undef NGX_RTMP_RELAY_STR_PAR #undef NGX_RTMP_RELAY_NUM_PAR if (n.len == sizeof("static") - 1 && ngx_strncasecmp(n.data, (u_char *) "static", n.len) == 0 && ngx_atoi(v.data, v.len)) { is_static = 1; continue; } return "unsuppored parameter"; } if (is_static) { if (!is_pull) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "static push is not allowed"); return NGX_CONF_ERROR; } if (target->name.len == 0) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "stream name missing in static pull " "declaration"); return NGX_CONF_ERROR; } ee = ngx_array_push(&racf->static_events); if (ee == NULL) { return NGX_CONF_ERROR; } e = ngx_pcalloc(cf->pool, sizeof(ngx_event_t)); if (e == NULL) { return NGX_CONF_ERROR; } *ee = e; rs = ngx_pcalloc(cf->pool, sizeof(ngx_rtmp_relay_static_t)); if (rs == NULL) { return NGX_CONF_ERROR; } rs->target = target; e->data = rs; e->log = &cf->cycle->new_log; e->handler = ngx_rtmp_relay_static_pull_reconnect; t = ngx_array_push(&racf->static_pulls); } else if (is_pull) { t = ngx_array_push(&racf->pulls); } else { t = ngx_array_push(&racf->pushes); } if (t == NULL) { return NGX_CONF_ERROR; } *t = target; return NGX_CONF_OK; }
ngx_stream_upstream_srv_conf_t * ngx_stream_upstream_add(ngx_conf_t *cf, ngx_url_t *u, ngx_uint_t flags) { ngx_uint_t i; ngx_stream_upstream_server_t *us; ngx_stream_upstream_srv_conf_t *uscf, **uscfp; ngx_stream_upstream_main_conf_t *umcf; if (!(flags & NGX_STREAM_UPSTREAM_CREATE)) { if (ngx_parse_url(cf->pool, u) != NGX_OK) { if (u->err) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%s in upstream \"%V\"", u->err, &u->url); } return NULL; } } umcf = ngx_stream_conf_get_module_main_conf(cf, ngx_stream_upstream_module); uscfp = umcf->upstreams.elts; for (i = 0; i < umcf->upstreams.nelts; i++) { if (uscfp[i]->host.len != u->host.len || ngx_strncasecmp(uscfp[i]->host.data, u->host.data, u->host.len) != 0) { continue; } if ((flags & NGX_STREAM_UPSTREAM_CREATE) && (uscfp[i]->flags & NGX_STREAM_UPSTREAM_CREATE)) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "duplicate upstream \"%V\"", &u->host); return NULL; } if ((uscfp[i]->flags & NGX_STREAM_UPSTREAM_CREATE) && !u->no_port) { ngx_conf_log_error(NGX_LOG_WARN, cf, 0, "upstream \"%V\" may not have port %d", &u->host, u->port); return NULL; } if ((flags & NGX_STREAM_UPSTREAM_CREATE) && !uscfp[i]->no_port) { ngx_log_error(NGX_LOG_WARN, cf->log, 0, "upstream \"%V\" may not have port %d in %s:%ui", &u->host, uscfp[i]->port, uscfp[i]->file_name, uscfp[i]->line); return NULL; } if (uscfp[i]->port != u->port) { continue; } if (flags & NGX_STREAM_UPSTREAM_CREATE) { uscfp[i]->flags = flags; } return uscfp[i]; } uscf = ngx_pcalloc(cf->pool, sizeof(ngx_stream_upstream_srv_conf_t)); if (uscf == NULL) { return NULL; } uscf->flags = flags; uscf->host = u->host; uscf->file_name = cf->conf_file->file.name.data; uscf->line = cf->conf_file->line; uscf->port = u->port; uscf->no_port = u->no_port; if (u->naddrs == 1) { uscf->servers = ngx_array_create(cf->pool, 1, sizeof(ngx_stream_upstream_server_t)); if (uscf->servers == NULL) { return NULL; } us = ngx_array_push(uscf->servers); if (us == NULL) { return NULL; } ngx_memzero(us, sizeof(ngx_stream_upstream_server_t)); us->addrs = u->addrs; us->naddrs = 1; } uscfp = ngx_array_push(&umcf->upstreams); if (uscfp == NULL) { return NULL; } *uscfp = uscf; return uscf; }
//#define readconf_debug static char * ngx_http_dummy_read_conf(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { ngx_http_dummy_loc_conf_t *alcf = conf, **bar; ngx_http_dummy_main_conf_t *main_cf; ngx_str_t *value; ngx_http_rule_t rule, *rule_r; ngx_http_custom_rule_location_t *location; unsigned int i; #ifdef readconf_debug if (cf) { value = cf->args->elts; ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "TOP READ CONF %V %V", &(value[0]), &(value[1])); } #endif if (!alcf || !cf) return (NGX_CONF_ERROR); value = cf->args->elts; main_cf = ngx_http_conf_get_module_main_conf(cf, ngx_http_naxsi_module); if (!alcf->pushed) { bar = ngx_array_push(main_cf->locations); if (!bar) return (NGX_CONF_ERROR); *bar = alcf; alcf->pushed = 1; } if (!ngx_strcmp(value[0].data, TOP_BASIC_RULE_T)) { #ifdef readconf_debug ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "XX-TOP READ CONF %s", value[0].data); #endif memset(&rule, 0, sizeof(ngx_http_rule_t)); if (ngx_http_dummy_cfg_parse_one_rule(cf, value, &rule, cf->args->nelts) != NGX_CONF_OK) { ngx_http_dummy_line_conf_error(cf, value); return (NGX_CONF_ERROR); } /* push in whitelist rules, as it have a whitelist ID array */ if (rule.wl_id) { #ifdef readconf_debug ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "pushing rule %d in whitelist rules", rule.rule_id); #endif if (alcf->whitelist_rules == NULL) { alcf->whitelist_rules = ngx_array_create(cf->pool, 2, sizeof(ngx_http_rule_t)); if (alcf->whitelist_rules == NULL) { return NGX_CONF_ERROR; } } rule_r = ngx_array_push(alcf->whitelist_rules); if (!rule_r) { return (NGX_CONF_ERROR); } memcpy(rule_r, &rule, sizeof(ngx_http_rule_t)); } /* else push in appropriate ruleset */ else { if (rule.br->headers) { #ifdef readconf_debug ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "pushing rule %d in header rules", rule.rule_id); #endif if (alcf->header_rules == NULL) { alcf->header_rules = ngx_array_create(cf->pool, 2, sizeof(ngx_http_rule_t)); if (alcf->header_rules == NULL) return NGX_CONF_ERROR; } rule_r = ngx_array_push(alcf->header_rules); if (!rule_r) return (NGX_CONF_ERROR); memcpy(rule_r, &rule, sizeof(ngx_http_rule_t)); } /* push in body match rules (POST/PUT) */ if (rule.br->body || rule.br->body_var) { #ifdef readconf_debug ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "pushing rule %d in body rules", rule.rule_id); #endif if (alcf->body_rules == NULL) { alcf->body_rules = ngx_array_create(cf->pool, 2, sizeof(ngx_http_rule_t)); if (alcf->body_rules == NULL) return NGX_CONF_ERROR; } rule_r = ngx_array_push(alcf->body_rules); if (!rule_r) return (NGX_CONF_ERROR); memcpy(rule_r, &rule, sizeof(ngx_http_rule_t)); } /* push in generic rules, as it's matching the URI */ if (rule.br->url) { #ifdef readconf_debug ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "pushing rule %d in generic rules", rule.rule_id); #endif if (alcf->generic_rules == NULL) { alcf->generic_rules = ngx_array_create(cf->pool, 2, sizeof(ngx_http_rule_t)); if (alcf->generic_rules == NULL) return NGX_CONF_ERROR; } rule_r = ngx_array_push(alcf->generic_rules); if (!rule_r) return (NGX_CONF_ERROR); memcpy(rule_r, &rule, sizeof(ngx_http_rule_t)); } /* push in GET arg rules, but we should push in POST rules too */ if (rule.br->args_var || rule.br->args) { #ifdef readconf_debug ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "pushing rule %d in GET rules", rule.rule_id); #endif if (alcf->get_rules == NULL) { alcf->get_rules = ngx_array_create(cf->pool, 2, sizeof(ngx_http_rule_t)); if (alcf->get_rules == NULL) return NGX_CONF_ERROR; } rule_r = ngx_array_push(alcf->get_rules); if (!rule_r) return (NGX_CONF_ERROR); memcpy(rule_r, &rule, sizeof(ngx_http_rule_t)); } /* push in custom locations. It's a rule matching a VAR_NAME or an EXACT_URI : - GET_VAR, POST_VAR, URI */ if (rule.br->custom_location) { #ifdef readconf_debug ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "pushing rule %d in custom_location rules", rule.rule_id); #endif location = rule.br->custom_locations->elts; for (i = 0; i < rule.br->custom_locations->nelts; i++) { if (location[i].args_var) { if (alcf->get_rules == NULL) { alcf->get_rules = ngx_array_create(cf->pool, 2, sizeof(ngx_http_rule_t)); if (alcf->get_rules == NULL) return NGX_CONF_ERROR; } rule_r = ngx_array_push(alcf->get_rules); if (!rule_r) return (NGX_CONF_ERROR); memcpy(rule_r, &rule, sizeof(ngx_http_rule_t)); } if (location[i].body_var) { if (alcf->body_rules == NULL) { alcf->body_rules = ngx_array_create(cf->pool, 2, sizeof(ngx_http_rule_t)); if (alcf->body_rules == NULL) return NGX_CONF_ERROR; } rule_r = ngx_array_push(alcf->body_rules); if (!rule_r) return (NGX_CONF_ERROR); memcpy(rule_r, &rule, sizeof(ngx_http_rule_t)); } if (location[i].headers_var) { if (alcf->header_rules == NULL) { alcf->header_rules = ngx_array_create(cf->pool, 2, sizeof(ngx_http_rule_t)); if (alcf->header_rules == NULL) return NGX_CONF_ERROR; } rule_r = ngx_array_push(alcf->header_rules); if (!rule_r) return (NGX_CONF_ERROR); memcpy(rule_r, &rule, sizeof(ngx_http_rule_t)); } } } } return (NGX_CONF_OK); } ngx_http_dummy_line_conf_error(cf, value); return (NGX_CONF_ERROR); }
static char * ngx_rtmp_core_application(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { char *rv; ngx_int_t i; ngx_str_t *value; ngx_conf_t save; ngx_module_t **modules; ngx_rtmp_module_t *module; ngx_rtmp_conf_ctx_t *ctx, *pctx; ngx_rtmp_core_srv_conf_t *cscf; ngx_rtmp_core_app_conf_t *cacf, **cacfp; ctx = ngx_pcalloc(cf->pool, sizeof(ngx_rtmp_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->app_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_rtmp_max_module); if (ctx->app_conf == NULL) { return NGX_CONF_ERROR; } #if defined(nginx_version) && nginx_version >= 1009011 modules = cf->cycle->modules; #else modules = ngx_modules; #endif for (i = 0; modules[i]; i++) { if (modules[i]->type != NGX_RTMP_MODULE) { continue; } module = modules[i]->ctx; if (module->create_app_conf) { ctx->app_conf[modules[i]->ctx_index] = module->create_app_conf(cf); if (ctx->app_conf[modules[i]->ctx_index] == NULL) { return NGX_CONF_ERROR; } } } cacf = ctx->app_conf[ngx_rtmp_core_module.ctx_index]; cacf->app_conf = ctx->app_conf; value = cf->args->elts; cacf->name = value[1]; cscf = pctx->srv_conf[ngx_rtmp_core_module.ctx_index]; cacfp = ngx_array_push(&cscf->applications); if (cacfp == NULL) { return NGX_CONF_ERROR; } *cacfp = cacf; save = *cf; cf->ctx = ctx; cf->cmd_type = NGX_RTMP_APP_CONF; rv = ngx_conf_parse(cf, NULL); *cf= save; return rv; }
static char * ngx_http_naxsi_cr_loc_conf(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { ngx_http_dummy_loc_conf_t *alcf = conf, **bar; ngx_http_dummy_main_conf_t *main_cf; ngx_str_t *value; ngx_http_check_rule_t *rule_c; unsigned int i; u_char *var_end; if (!alcf || !cf) return (NGX_CONF_ERROR); value = cf->args->elts; main_cf = ngx_http_conf_get_module_main_conf(cf, ngx_http_naxsi_module); if (!alcf->pushed) { bar = ngx_array_push(main_cf->locations); if (!bar) return (NGX_CONF_ERROR); *bar = alcf; alcf->pushed = 1; } if (ngx_strcmp(value[0].data, TOP_CHECK_RULE_T) && ngx_strcmp(value[0].data, TOP_CHECK_RULE_N)) return (NGX_CONF_ERROR); #ifdef readconf_debug ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "pushing rule %d in check rules", rule.rule_id); #endif i = 0; if (!alcf->check_rules) alcf->check_rules = ngx_array_create(cf->pool, 2, sizeof(ngx_http_check_rule_t)); if (!alcf->check_rules) return (NGX_CONF_ERROR); rule_c = ngx_array_push(alcf->check_rules); if (!rule_c) return (NGX_CONF_ERROR); memset(rule_c, 0, sizeof(ngx_http_check_rule_t)); /* process the first word : score rule */ if (value[1].data[i] == '$') { #ifdef MDBG ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "XX-special score rule !"); #endif var_end = (u_char *) ngx_strchr((value[1].data)+i, ' '); if (!var_end) { ngx_http_dummy_line_conf_error(cf, value); return (NGX_CONF_ERROR); } rule_c->sc_tag.data = ngx_pcalloc(cf->pool, var_end - value[1].data +1); if (!rule_c->sc_tag.data) return (NGX_CONF_ERROR); memcpy(rule_c->sc_tag.data, value[1].data, (var_end - value[1].data)); i += (var_end - value[1].data) + 1; rule_c->sc_tag.len = (var_end - value[1].data); } else { ngx_http_dummy_line_conf_error(cf, value); return (NGX_CONF_ERROR); } // move to next word while (value[1].data[i] && value[1].data[i] == ' ') i++; // get the comparison type if (value[1].data[i] == '>' && value[1].data[i+1] == '=') rule_c->cmp = SUP_OR_EQUAL; else if (value[1].data[i] == '>' && value[1].data[i+1] != '=') rule_c->cmp = SUP; else if (value[1].data[i] == '<' && value[1].data[i+1] == '=') rule_c->cmp = INF_OR_EQUAL; else if (value[1].data[i] == '<' && value[1].data[i+1] != '=') rule_c->cmp = INF; else { ngx_http_dummy_line_conf_error(cf, value); return (NGX_CONF_ERROR); } // move to next word while (value[1].data[i] && !(value[1].data[i] >= '0' && value[1].data[i] <= '9') && (value[1].data[i] != '-')) i++; #ifdef readconf_debug ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "XX-special score in checkrule:%s from (%d)", value[1].data, atoi((const char *)value[1].data+i)); #endif // get the score rule_c->sc_score = atoi((const char *)(value[1].data+i)); /* process the second word : Action rule */ if (ngx_strstr(value[2].data, "BLOCK")) rule_c->block = 1; else if (ngx_strstr(value[2].data,"ALLOW")) rule_c->allow = 1; else if (ngx_strstr(value[2].data, "LOG")) rule_c->log = 1; else { ngx_http_dummy_line_conf_error(cf, value); return (NGX_CONF_ERROR); } return (NGX_CONF_OK); }
ngx_chain_t * ngx_darwin_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit) { int rc; u_char *prev; off_t size, send, prev_send, aligned, sent, fprev; off_t header_size, file_size; ngx_uint_t eintr, complete; ngx_err_t err; ngx_buf_t *file; ngx_array_t header, trailer; ngx_event_t *wev; ngx_chain_t *cl; struct sf_hdtr hdtr; struct iovec *iov, headers[NGX_HEADERS], trailers[NGX_TRAILERS]; wev = c->write; if (!wev->ready) { return in; } #if (NGX_HAVE_KQUEUE) if ((ngx_event_flags & NGX_USE_KQUEUE_EVENT) && wev->pending_eof) { (void) ngx_connection_error(c, wev->kq_errno, "kevent() reported about an closed connection"); wev->error = 1; return NGX_CHAIN_ERROR; } #endif /* the maximum limit size is the maximum size_t value - the page size */ if (limit == 0 || limit > (off_t) (NGX_MAX_SIZE_T_VALUE - ngx_pagesize)) { limit = NGX_MAX_SIZE_T_VALUE - ngx_pagesize; } send = 0; header.elts = headers; header.size = sizeof(struct iovec); header.nalloc = NGX_HEADERS; header.pool = c->pool; trailer.elts = trailers; trailer.size = sizeof(struct iovec); trailer.nalloc = NGX_TRAILERS; trailer.pool = c->pool; for ( ;; ) { file = NULL; file_size = 0; header_size = 0; eintr = 0; complete = 0; prev_send = send; header.nelts = 0; trailer.nelts = 0; /* create the header iovec and coalesce the neighbouring bufs */ prev = NULL; iov = NULL; for (cl = in; cl && header.nelts < IOV_MAX && send < limit; cl = cl->next) { if (ngx_buf_special(cl->buf)) { continue; } if (!ngx_buf_in_memory_only(cl->buf)) { break; } size = cl->buf->last - cl->buf->pos; if (send + size > limit) { size = limit - send; } if (prev == cl->buf->pos) { iov->iov_len += (size_t) size; } else { iov = ngx_array_push(&header); if (iov == NULL) { return NGX_CHAIN_ERROR; } iov->iov_base = (void *) cl->buf->pos; iov->iov_len = (size_t) size; } prev = cl->buf->pos + (size_t) size; header_size += size; send += size; } if (cl && cl->buf->in_file && send < limit) { file = cl->buf; /* coalesce the neighbouring file bufs */ do { size = cl->buf->file_last - cl->buf->file_pos; if (send + size > limit) { size = limit - send; aligned = (cl->buf->file_pos + size + ngx_pagesize - 1) & ~((off_t) ngx_pagesize - 1); if (aligned <= cl->buf->file_last) { size = aligned - cl->buf->file_pos; } } file_size += size; send += size; fprev = cl->buf->file_pos + size; cl = cl->next; } while (cl && cl->buf->in_file && send < limit && file->file->fd == cl->buf->file->fd && fprev == cl->buf->file_pos); } if (file && header.nelts == 0) { /* create the trailer iovec and coalesce the neighbouring bufs */ prev = NULL; iov = NULL; while (cl && header.nelts < IOV_MAX && send < limit) { if (ngx_buf_special(cl->buf)) { cl = cl->next; continue; } if (!ngx_buf_in_memory_only(cl->buf)) { break; } size = cl->buf->last - cl->buf->pos; if (send + size > limit) { size = limit - send; } if (prev == cl->buf->pos) { iov->iov_len += (size_t) size; } else { iov = ngx_array_push(&trailer); if (iov == NULL) { return NGX_CHAIN_ERROR; } iov->iov_base = (void *) cl->buf->pos; iov->iov_len = (size_t) size; } prev = cl->buf->pos + (size_t) size; send += size; cl = cl->next; } } if (file) { /* * sendfile() returns EINVAL if sf_hdtr's count is 0, * but corresponding pointer is not NULL */ hdtr.headers = header.nelts ? (struct iovec *) header.elts: NULL; hdtr.hdr_cnt = header.nelts; hdtr.trailers = trailer.nelts ? (struct iovec *) trailer.elts: NULL; hdtr.trl_cnt = trailer.nelts; sent = header_size + file_size; ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0, "sendfile: @%O %O h:%O", file->file_pos, sent, header_size); rc = sendfile(file->file->fd, c->fd, file->file_pos, &sent, &hdtr, 0); if (rc == -1) { err = ngx_errno; switch (err) { case NGX_EAGAIN: break; case NGX_EINTR: eintr = 1; break; default: wev->error = 1; (void) ngx_connection_error(c, err, "sendfile() failed"); return NGX_CHAIN_ERROR; } ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, err, "sendfile() sent only %O bytes", sent); } if (rc == 0 && sent == 0) { /* * if rc and sent equal to zero, then someone * has truncated the file, so the offset became beyond * the end of the file */ ngx_log_error(NGX_LOG_ALERT, c->log, 0, "sendfile() reported that \"%s\" was truncated", file->file->name.data); return NGX_CHAIN_ERROR; } ngx_log_debug4(NGX_LOG_DEBUG_EVENT, c->log, 0, "sendfile: %d, @%O %O:%O", rc, file->file_pos, sent, file_size + header_size); } else { rc = writev(c->fd, header.elts, header.nelts); ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, "writev: %d of %uz", rc, send); if (rc == -1) { err = ngx_errno; switch (err) { case NGX_EAGAIN: break; case NGX_EINTR: eintr = 1; break; default: wev->error = 1; ngx_connection_error(c, err, "writev() failed"); return NGX_CHAIN_ERROR; } ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, err, "writev() not ready"); } sent = rc > 0 ? rc : 0; } if (send - prev_send == sent) { complete = 1; } c->sent += sent; for (cl = in; cl; cl = cl->next) { if (ngx_buf_special(cl->buf)) { continue; } if (sent == 0) { break; } size = ngx_buf_size(cl->buf); if (sent >= size) { sent -= size; if (ngx_buf_in_memory(cl->buf)) { cl->buf->pos = cl->buf->last; } if (cl->buf->in_file) { cl->buf->file_pos = cl->buf->file_last; } continue; } if (ngx_buf_in_memory(cl->buf)) { cl->buf->pos += (size_t) sent; } if (cl->buf->in_file) { cl->buf->file_pos += sent; } break; } if (eintr) { continue; } if (!complete) { wev->ready = 0; return cl; } if (send >= limit || cl == NULL) { return cl; } in = cl; } }
//#define main_conf_debug static char * ngx_http_dummy_read_main_conf(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { ngx_http_dummy_main_conf_t *alcf = conf; ngx_str_t *value; ngx_http_rule_t rule, *rule_r; ngx_http_custom_rule_location_t *location; unsigned int i; if (!alcf || !cf) return (NGX_CONF_ERROR); /* alloc a new rule */ value = cf->args->elts; /* parse the line, fill rule struct */ #ifdef main_conf_debug ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "XX-TOP READ CONF %s", value[0].data); #endif if (ngx_strcmp(value[0].data, TOP_MAIN_BASIC_RULE_T) && ngx_strcmp(value[0].data, TOP_MAIN_BASIC_RULE_N)) { ngx_http_dummy_line_conf_error(cf, value); return (NGX_CONF_ERROR); } memset(&rule, 0, sizeof(ngx_http_rule_t)); if (ngx_http_dummy_cfg_parse_one_rule(cf/*, alcf*/, value, &rule, cf->args->nelts) != NGX_CONF_OK) { ngx_http_dummy_line_conf_error(cf, value); return (NGX_CONF_ERROR); } if (rule.br->headers) { #ifdef main_conf_debug ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "pushing rule %d in header rules", rule.rule_id); #endif if (alcf->header_rules == NULL) { alcf->header_rules = ngx_array_create(cf->pool, 2, sizeof(ngx_http_rule_t)); if (alcf->header_rules == NULL) return NGX_CONF_ERROR; } rule_r = ngx_array_push(alcf->header_rules); if (!rule_r) return (NGX_CONF_ERROR); memcpy(rule_r, &rule, sizeof(ngx_http_rule_t)); } /* push in body match rules (POST/PUT) */ if (rule.br->body || rule.br->body_var) { #ifdef main_conf_debug ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "pushing rule %d in body rules", rule.rule_id); #endif if (alcf->body_rules == NULL) { alcf->body_rules = ngx_array_create(cf->pool, 2, sizeof(ngx_http_rule_t)); if (alcf->body_rules == NULL) return NGX_CONF_ERROR; } rule_r = ngx_array_push(alcf->body_rules); if (!rule_r) return (NGX_CONF_ERROR); memcpy(rule_r, &rule, sizeof(ngx_http_rule_t)); } /* push in generic rules, as it's matching the URI */ if (rule.br->url) { #ifdef main_conf_debug ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "pushing rule %d in generic rules", rule.rule_id); #endif if (alcf->generic_rules == NULL) { alcf->generic_rules = ngx_array_create(cf->pool, 2, sizeof(ngx_http_rule_t)); if (alcf->generic_rules == NULL) return NGX_CONF_ERROR; } rule_r = ngx_array_push(alcf->generic_rules); if (!rule_r) return (NGX_CONF_ERROR); memcpy(rule_r, &rule, sizeof(ngx_http_rule_t)); } /* push in GET arg rules, but we should push in POST rules too */ if (rule.br->args_var || rule.br->args) { #ifdef main_conf_debug ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "pushing rule %d in GET rules", rule.rule_id); #endif if (alcf->get_rules == NULL) { alcf->get_rules = ngx_array_create(cf->pool, 2, sizeof(ngx_http_rule_t)); if (alcf->get_rules == NULL) return NGX_CONF_ERROR; } rule_r = ngx_array_push(alcf->get_rules); if (!rule_r) return (NGX_CONF_ERROR); memcpy(rule_r, &rule, sizeof(ngx_http_rule_t)); } /* push in custom locations. It's a rule matching a VAR_NAME or an EXACT_URI : - GET_VAR, POST_VAR, URI */ if (rule.br->custom_location) { #ifdef main_conf_debug ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "pushing rule %d in custom_location rules", rule.rule_id); #endif location = rule.br->custom_locations->elts; for (i = 0; i < rule.br->custom_locations->nelts; i++) { if (location[i].args_var) { if (alcf->get_rules == NULL) { alcf->get_rules = ngx_array_create(cf->pool, 2, sizeof(ngx_http_rule_t)); if (alcf->get_rules == NULL) return NGX_CONF_ERROR; } rule_r = ngx_array_push(alcf->get_rules); if (!rule_r) return (NGX_CONF_ERROR); memcpy(rule_r, &rule, sizeof(ngx_http_rule_t)); } if (location[i].body_var) { if (alcf->body_rules == NULL) { alcf->body_rules = ngx_array_create(cf->pool, 2, sizeof(ngx_http_rule_t)); if (alcf->body_rules == NULL) return NGX_CONF_ERROR; } rule_r = ngx_array_push(alcf->body_rules); if (!rule_r) return (NGX_CONF_ERROR); memcpy(rule_r, &rule, sizeof(ngx_http_rule_t)); } if (location[i].headers_var) { if (alcf->header_rules == NULL) { alcf->header_rules = ngx_array_create(cf->pool, 2, sizeof(ngx_http_rule_t)); if (alcf->header_rules == NULL) return NGX_CONF_ERROR; } rule_r = ngx_array_push(alcf->header_rules); if (!rule_r) return (NGX_CONF_ERROR); memcpy(rule_r, &rule, sizeof(ngx_http_rule_t)); } } } return (NGX_CONF_OK); }
static char * ngx_dso_save(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { u_char *p; ngx_int_t rc; ngx_str_t *value, path, name; ngx_dso_module_t *dm; ngx_dso_conf_ctx_t *ctx; ctx = cf->ctx; value = cf->args->elts; if (ctx->modules->nelts >= NGX_DSO_MAX) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "module \"%V\" can not be loaded, " "because the dso module limit (%ui) is reached.", &value[1], NGX_DSO_MAX); return NGX_CONF_ERROR; } if (cf->args->nelts == 3) { name = value[1]; path = value[2]; } else { /* cf->args->nelts == 2 */ if (value[1].len > 3 && value[1].data[value[1].len - 3] == '.' && value[1].data[value[1].len - 2] == 's' && value[1].data[value[1].len - 1] == 'o') { path = value[1]; name.data = ngx_pcalloc(cf->pool, value[1].len - 2); if (path.data == NULL) { return NGX_CONF_ERROR; } name.len = value[1].len - 3; ngx_memcpy(name.data, path.data, name.len); } else { path.len = value[1].len + sizeof(NGX_SOEXT); path.data = ngx_pcalloc(cf->pool, path.len); if (path.data == NULL) { return NGX_CONF_ERROR; } p = ngx_cpymem(path.data, value[1].data, value[1].len); ngx_memcpy(p, NGX_SOEXT, sizeof(NGX_SOEXT) - 1); name = value[1]; } } rc = ngx_dso_check_duplicated(cf, ctx->modules, &name, &path); if (rc == NGX_DECLINED) { return NGX_CONF_OK; } dm = ngx_array_push(ctx->modules); if (dm == NULL) { return NGX_CONF_ERROR; } dm->name = name; dm->path = path; dm->handle = NULL; 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, forbid_action; ngx_uint_t i, nodelay; ngx_shm_zone_t *shm_zone; ngx_http_limit_req_limit_t *limit, *limits; ngx_http_limit_req_variable_t condition; value = cf->args->elts; shm_zone = NULL; burst = 0; nodelay = 0; condition.index = -1; ngx_str_null(&condition.var); ngx_str_null(&forbid_action); 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; } if (ngx_strncmp(value[i].data, "forbid_action=", 14) == 0) { s.len = value[i].len - 14; s.data = value[i].data + 14; if (s.len < 2 || (s.data[0] != '@' && s.data[0] != '/')) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid forbid_action \"%V\"", &value[i]); return NGX_CONF_ERROR; } forbid_action = s; continue; } if (ngx_strncmp(value[i].data, "condition=", 10) == 0) { s.len = value[i].len - 10; s.data = value[i].data + 10; if (s.len < 2 || s.data[0] != '$') { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid condition \"%V\"", &value[i]); return NGX_CONF_ERROR; } s.len--; s.data++; condition.index = ngx_http_get_variable_index(cf, &s); if (condition.index == NGX_ERROR) { return NGX_CONF_ERROR; } condition.var = s; 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; } if (shm_zone->data == NULL) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "unknown limit_req_zone \"%V\"", &shm_zone->shm.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; limit->forbid_action = forbid_action; limit->condition = condition; return NGX_CONF_OK; }
static ngx_int_t ngx_conf_read_token(ngx_conf_t *cf) { u_char *start, ch, *src, *dst; off_t file_size; size_t len; ssize_t n, size; ngx_uint_t found, need_space, last_space, sharp_comment, variable; ngx_uint_t quoted, s_quoted, d_quoted, start_line; ngx_str_t *word; ngx_buf_t *b; found = 0; need_space = 0; last_space = 1; sharp_comment = 0; variable = 0; quoted = 0; s_quoted = 0; d_quoted = 0; cf->args->nelts = 0; b = cf->conf_file->buffer; start = b->pos; start_line = cf->conf_file->line; file_size = ngx_file_size(&cf->conf_file->file.info); for ( ;; ) { if (b->pos >= b->last) { if (cf->conf_file->file.offset >= file_size) { if (cf->args->nelts > 0 || !last_space) { if (cf->conf_file->file.fd == NGX_INVALID_FILE) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "unexpected end of parameter, " "expecting \";\""); return NGX_ERROR; } ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "unexpected end of file, " "expecting \";\" or \"}\""); return NGX_ERROR; } return NGX_CONF_FILE_DONE; } len = b->pos - start; if (len == NGX_CONF_BUFFER) { cf->conf_file->line = start_line; if (d_quoted) { ch = '"'; } else if (s_quoted) { ch = '\''; } else { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "too long parameter \"%*s...\" started", 10, start); return NGX_ERROR; } ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "too long parameter, probably " "missing terminating \"%c\" character", ch); return NGX_ERROR; } if (len) { ngx_memmove(b->start, start, len); } size = (ssize_t) (file_size - cf->conf_file->file.offset); if (size > b->end - (b->start + len)) { size = b->end - (b->start + len); } n = ngx_read_file(&cf->conf_file->file, b->start + len, size, cf->conf_file->file.offset); if (n == NGX_ERROR) { return NGX_ERROR; } if (n != size) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, ngx_read_file_n " returned " "only %z bytes instead of %z", n, size); return NGX_ERROR; } b->pos = b->start + len; b->last = b->pos + n; start = b->start; if (ngx_dump_config) { (void) ngx_write_console(ngx_stderr, b->pos, n); } } ch = *b->pos++; if (ch == LF) { cf->conf_file->line++; if (sharp_comment) { sharp_comment = 0; } } if (sharp_comment) { continue; } if (quoted) { quoted = 0; continue; } if (need_space) { if (ch == ' ' || ch == '\t' || ch == CR || ch == LF) { last_space = 1; need_space = 0; continue; } if (ch == ';') { return NGX_OK; } if (ch == '{') { return NGX_CONF_BLOCK_START; } if (ch == ')') { last_space = 1; need_space = 0; } else { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "unexpected \"%c\"", ch); return NGX_ERROR; } } if (last_space) { if (ch == ' ' || ch == '\t' || ch == CR || ch == LF) { continue; } start = b->pos - 1; start_line = cf->conf_file->line; switch (ch) { case ';': case '{': if (cf->args->nelts == 0) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "unexpected \"%c\"", ch); return NGX_ERROR; } if (ch == '{') { return NGX_CONF_BLOCK_START; } return NGX_OK; case '}': if (cf->args->nelts != 0) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "unexpected \"}\""); return NGX_ERROR; } return NGX_CONF_BLOCK_DONE; case '#': sharp_comment = 1; continue; case '\\': quoted = 1; last_space = 0; continue; case '"': start++; d_quoted = 1; last_space = 0; continue; case '\'': start++; s_quoted = 1; last_space = 0; continue; default: last_space = 0; } } else { if (ch == '{' && variable) { continue; } variable = 0; if (ch == '\\') { quoted = 1; continue; } if (ch == '$') { variable = 1; continue; } if (d_quoted) { if (ch == '"') { d_quoted = 0; need_space = 1; found = 1; } } else if (s_quoted) { if (ch == '\'') { s_quoted = 0; need_space = 1; found = 1; } } else if (ch == ' ' || ch == '\t' || ch == CR || ch == LF || ch == ';' || ch == '{') { last_space = 1; found = 1; } if (found) { word = ngx_array_push(cf->args); if (word == NULL) { return NGX_ERROR; } word->data = ngx_pnalloc(cf->pool, b->pos - start); if (word->data == NULL) { return NGX_ERROR; } for (dst = word->data, src = start, len = 0; src < b->pos - 1; len++) { if (*src == '\\') { switch (src[1]) { case '"': case '\'': case '\\': src++; break; case 't': *dst++ = '\t'; src += 2; continue; case 'r': *dst++ = '\r'; src += 2; continue; case 'n': *dst++ = '\n'; src += 2; continue; } } *dst++ = *src++; } *dst = '\0'; word->len = len; if (ch == ';') { return NGX_OK; } if (ch == '{') { return NGX_CONF_BLOCK_START; } found = 0; } } } }
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_array_t *variables; ngx_http_limit_req_variable_t *v; value = cf->args->elts; ctx = NULL; size = 0; rate = 1; scale = 1; name.len = 0; v = NULL; variables = ngx_array_create(cf->pool, 5, sizeof(ngx_http_limit_req_variable_t)); if (variables == NULL) { return NGX_CONF_ERROR; } for (i = 1; 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; } if (value[i].data[0] == '$') { value[i].len--; value[i].data++; v = ngx_array_push(variables); if (v == NULL) { return NGX_CONF_ERROR; } v->index = ngx_http_get_variable_index(cf, &value[i]); if (v->index == NGX_ERROR) { return NGX_CONF_ERROR; } v->var = value[i]; 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; } if (variables->nelts == 0) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "no variable is defined for %V \"%V\"", &cmd->name, &name); return NGX_CONF_ERROR; } ctx = ngx_pcalloc(cf->pool, sizeof(ngx_http_limit_req_ctx_t)); if (ctx == NULL) { return NGX_CONF_ERROR; } ctx->rate = rate * 1000 / scale; ctx->limit_vars = variables; 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 variable \"%V\"", &cmd->name, &name, &v->var); return NGX_CONF_ERROR; } shm_zone->init = ngx_http_limit_req_init_zone; shm_zone->data = ctx; return NGX_CONF_OK; }
static ngx_inline ngx_int_t make_content_buf( ngx_http_request_t *r, ngx_buf_t **pb, ngx_http_fancyindex_loc_conf_t *alcf) { ngx_http_fancyindex_entry_t *entry; int (*sort_cmp_func) (const void*, const void*); const char *sort_url_args = ""; off_t length; size_t len, root, copy, allocated; u_char *filename, *last, scale; ngx_tm_t tm; ngx_array_t entries; ngx_time_t *tp; ngx_uint_t i; ngx_int_t size; ngx_str_t path; ngx_dir_t dir; ngx_buf_t *b; static char *months[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", }; /* * NGX_DIR_MASK_LEN is lesser than NGX_HTTP_FANCYINDEX_PREALLOCATE */ if ((last = ngx_http_map_uri_to_path(r, &path, &root, NGX_HTTP_FANCYINDEX_PREALLOCATE)) == 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 fancyindex: \"%s\"", path.data); if (ngx_open_dir(&path, &dir) == NGX_ERROR) { ngx_int_t rc, err = ngx_errno; ngx_uint_t level; 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 /* NGX_SUPPRESS_WARN */ if (ngx_array_init(&entries, r->pool, 40, sizeof(ngx_http_fancyindex_entry_t)) != NGX_OK) return ngx_http_fancyindex_error(r, &dir, &path); filename = path.data; filename[path.len] = '/'; /* Read directory entries and their associated information. */ for (;;) { ngx_set_errno(0); if (ngx_read_dir(&dir) == NGX_ERROR) { ngx_int_t 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_fancyindex_error(r, &dir, &path); } break; } ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "http fancyindex file: \"%s\"", ngx_de_name(&dir)); len = ngx_de_namelen(&dir); if (ngx_de_name(&dir)[0] == '.') continue; #if NGX_PCRE { ngx_str_t str = { len, ngx_de_name(&dir) }; if (alcf->ignore && ngx_regex_exec_array(alcf->ignore, &str, r->connection->log) != NGX_DECLINED) { continue; } } #else /* !NGX_PCRE */ if (alcf->ignore) { u_int match_found = 0; ngx_str_t *s = alcf->ignore->elts; for (i = 0; i < alcf->ignore->nelts; i++, s++) { if (ngx_strcmp(ngx_de_name(&dir), s->data) == 0) { match_found = 1; break; } } if (match_found) { continue; } } #endif /* NGX_PCRE */ 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_FANCYINDEX_PREALLOCATE; if ((filename = ngx_palloc(r->pool, allocated)) == NULL) return ngx_http_fancyindex_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) { ngx_int_t err = ngx_errno; if (err != NGX_ENOENT) { ngx_log_error(NGX_LOG_ERR, r->connection->log, err, ngx_de_info_n " \"%s\" failed", filename); continue; } 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_fancyindex_error(r, &dir, &path); } } } if ((entry = ngx_array_push(&entries)) == NULL) return ngx_http_fancyindex_error(r, &dir, &path); entry->name.len = len; entry->name.data = ngx_palloc(r->pool, len + 1); if (entry->name.data == NULL) return ngx_http_fancyindex_error(r, &dir, &path); ngx_cpystrn(entry->name.data, ngx_de_name(&dir), len + 1); entry->escape = 2 * ngx_fancyindex_escape_uri(NULL, ngx_de_name(&dir), len); entry->dir = ngx_de_is_dir(&dir); entry->mtime = ngx_de_mtime(&dir); entry->size = ngx_de_size(&dir); entry->utf_len = (r->headers_out.charset.len == 5 && ngx_strncasecmp(r->headers_out.charset.data, (u_char*) "utf-8", 5) == 0) ? ngx_utf8_length(entry->name.data, entry->name.len) : len; } if (ngx_close_dir(&dir) == NGX_ERROR) { ngx_log_error(NGX_LOG_ALERT, r->connection->log, ngx_errno, ngx_close_dir_n " \"%s\" failed", &path); } /* * Calculate needed buffer length. */ len = r->uri.len + ngx_sizeof_ssz(t05_body2) + ngx_sizeof_ssz(t06_list1) + ngx_sizeof_ssz(t_parentdir_entry) + ngx_sizeof_ssz(t07_list2) ; entry = entries.elts; for (i = 0; i < entries.nelts; i++) { /* * Genearated table rows are as follows, unneeded whitespace * is stripped out: * * <tr class="X"> * <td><a href="U[?sort]">fname</a></td> * <td>size</td><td>date</td> * </tr> */ len += ngx_sizeof_ssz("<tr class=\"X\"><td><a href=\"") + entry[i].name.len + entry[i].escape /* Escaped URL */ + ngx_sizeof_ssz("?C=x&O=y") /* URL sorting arguments */ + ngx_sizeof_ssz("\">") + entry[i].name.len + entry[i].utf_len + NGX_HTTP_FANCYINDEX_NAME_LEN + ngx_sizeof_ssz(">") + ngx_sizeof_ssz("</a></td><td>") + 20 /* File size */ + ngx_sizeof_ssz("</td><td>") + ngx_sizeof_ssz(" 28-Sep-1970 12:00 ") + ngx_sizeof_ssz("</td></tr>\n") + 2 /* CR LF */ ; } if ((b = ngx_create_temp_buf(r->pool, len)) == NULL) return NGX_HTTP_INTERNAL_SERVER_ERROR; /* * Determine the sorting criteria. URL arguments look like: * * C=x[&O=y] * * Where x={M,S,N} and y={A,D} */ if ((r->args.len == 3 || (r->args.len == 7 && r->args.data[3] == '&')) && r->args.data[0] == 'C' && r->args.data[1] == '=') { /* Determine whether the direction of the sorting */ ngx_int_t sort_descending = r->args.len == 7 && r->args.data[4] == 'O' && r->args.data[5] == '=' && r->args.data[6] == 'D'; /* Pick the sorting criteria */ switch (r->args.data[2]) { case 'M': /* Sort by mtime */ if (sort_descending) { sort_cmp_func = ngx_http_fancyindex_cmp_entries_mtime_desc; sort_url_args = "?C=M&O=D"; } else { sort_cmp_func = ngx_http_fancyindex_cmp_entries_mtime_asc; sort_url_args = "?C=M&O=A"; } break; case 'S': /* Sort by size */ if (sort_descending) { sort_cmp_func = ngx_http_fancyindex_cmp_entries_size_desc; sort_url_args = "?C=S&O=D"; } else { sort_cmp_func = ngx_http_fancyindex_cmp_entries_size_asc; sort_url_args = "?C=S&O=A"; } break; case 'N': /* Sort by name */ default: if (sort_descending) { sort_cmp_func = ngx_http_fancyindex_cmp_entries_name_desc; sort_url_args = "?C=N&O=D"; } else { sort_cmp_func = ngx_http_fancyindex_cmp_entries_name_asc; } break; } } else { sort_cmp_func = ngx_http_fancyindex_cmp_entries_name_asc; } /* Sort entries, if needed */ if (entries.nelts > 1) { ngx_qsort(entry, (size_t) entries.nelts, sizeof(ngx_http_fancyindex_entry_t), sort_cmp_func); } b->last = ngx_cpymem_str(b->last, r->uri); b->last = ngx_cpymem_ssz(b->last, t05_body2); b->last = ngx_cpymem_ssz(b->last, t06_list1); tp = ngx_timeofday(); /* "Parent dir" entry, always first */ b->last = ngx_cpymem_ssz(b->last, "<tr class=\"o\">" "<td><a href=\"../"); if (*sort_url_args) { b->last = ngx_cpymem(b->last, sort_url_args, ngx_sizeof_ssz("?C=N&O=A")); } b->last = ngx_cpymem_ssz(b->last, "\">Parent directory/</a></td>" "<td>-</td>" "<td>-</td>" "</tr>"); /* Entries for directories and files */ for (i = 0; i < entries.nelts; i++) { static const char _evenodd[] = { 'e', 'o' }; b->last = ngx_cpymem_ssz(b->last, "<tr class=\""); *b->last++ = _evenodd[i & 0x01]; /* * Alternative implementation: * *b->last++ = (i & 0x01) ? 'e' : 'o'; */ b->last = ngx_cpymem_ssz(b->last, "\"><td><a href=\""); if (entry[i].escape) { ngx_fancyindex_escape_uri(b->last, entry[i].name.data, entry[i].name.len); b->last += entry[i].name.len + entry[i].escape; } else { b->last = ngx_cpymem_str(b->last, entry[i].name); } if (entry[i].dir) { *b->last++ = '/'; if (*sort_url_args) { b->last = ngx_cpymem(b->last, sort_url_args, ngx_sizeof_ssz("?C=x&O=y")); } } *b->last++ = '"'; *b->last++ = '>'; len = entry[i].utf_len; if (entry[i].name.len - len) { if (len > NGX_HTTP_FANCYINDEX_NAME_LEN) { copy = NGX_HTTP_FANCYINDEX_NAME_LEN - 3 + 1; } else { copy = NGX_HTTP_FANCYINDEX_NAME_LEN + 1; } b->last = ngx_utf8_cpystrn(b->last, entry[i].name.data, copy, entry[i].name.len); last = b->last; } else { b->last = ngx_cpystrn(b->last, entry[i].name.data, NGX_HTTP_FANCYINDEX_NAME_LEN + 1); last = b->last - 3; } if (len > NGX_HTTP_FANCYINDEX_NAME_LEN) { b->last = ngx_cpymem_ssz(last, "..></a></td><td>"); } else { if (entry[i].dir && NGX_HTTP_FANCYINDEX_NAME_LEN - len > 0) { *b->last++ = '/'; len++; } b->last = ngx_cpymem_ssz(b->last, "</a></td><td>"); } if (alcf->exact_size) { if (entry[i].dir) { *b->last++ = '-'; } else { b->last = ngx_sprintf(b->last, "%19O", entry[i].size); } } else { if (entry[i].dir) { *b->last++ = '-'; } 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); } } } ngx_gmtime(entry[i].mtime + tp->gmtoff * 60 * alcf->localtime, &tm); b->last = ngx_sprintf(b->last, "</td><td>%02d-%s-%d %02d:%02d</td></tr>", tm.ngx_tm_mday, months[tm.ngx_tm_mon - 1], tm.ngx_tm_year, tm.ngx_tm_hour, tm.ngx_tm_min); *b->last++ = CR; *b->last++ = LF; } /* Output table bottom */ b->last = ngx_cpymem_ssz(b->last, t07_list2); *pb = b; return NGX_OK; }
static ngx_int_t ngx_http_autoindex_handler(ngx_http_request_t *r) { u_char *last, *filename, scale; off_t length; size_t len, char_len, escape_html, allocated, root; ngx_tm_t tm; ngx_err_t err; ngx_buf_t *b; ngx_int_t rc, size; ngx_str_t path; ngx_dir_t dir; ngx_uint_t i, level, utf8; ngx_pool_t *pool; ngx_time_t *tp; ngx_chain_t out; ngx_array_t entries; ngx_http_autoindex_entry_t *entry; ngx_http_autoindex_loc_conf_t *alcf; static char *months[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; 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; } /* 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); 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; r->headers_out.content_type_len = sizeof("text/html") - 1; ngx_str_set(&r->headers_out.content_type, "text/html"); 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] = '/'; 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; } 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) { 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->escape = 2 * ngx_escape_uri(NULL, ngx_de_name(&dir), len, NGX_ESCAPE_URI_COMPONENT); entry->escape_html = ngx_escape_html(NULL, entry->name.data, entry->name.len); if (utf8) { entry->utf_len = ngx_utf8_length(entry->name.data, entry->name.len); } else { entry->utf_len = len; } entry->dir = ngx_de_is_dir(&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 " \"%s\" failed", &path); } 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++) { 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(">") - 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 NGX_HTTP_INTERNAL_SERVER_ERROR; } if (entries.nelts > 1) { ngx_qsort(entry, (size_t) entries.nelts, sizeof(ngx_http_autoindex_entry_t), ngx_http_autoindex_cmp_entries); } 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); 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, "..></a>", sizeof("..></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; } /* TODO: free temporary pool */ b->last = ngx_cpymem(b->last, "</pre><hr>", sizeof("</pre><hr>") - 1); b->last = ngx_cpymem(b->last, tail, sizeof(tail) - 1); 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); }