| |
| |
| #include <ndk.h> |
| |
| |
| typedef struct { |
| ngx_http_script_code_pt code; |
| void *func; |
| } ndk_set_var_code_t; |
| |
| typedef struct { |
| ngx_http_script_code_pt code; |
| void *func; |
| size_t size; |
| } ndk_set_var_size_code_t; |
| |
| typedef struct { |
| ngx_http_script_code_pt code; |
| void *func; |
| void *data; |
| } ndk_set_var_data_code_t; |
| |
| typedef struct { |
| ngx_http_script_code_pt code; |
| void *func; |
| size_t size; |
| void *data; |
| } ndk_set_var_size_data_code_t; |
| |
| |
| typedef struct { |
| ngx_int_t index; |
| ngx_str_t *value; |
| ngx_http_variable_t *v; |
| ngx_conf_t *cf; |
| ndk_http_rewrite_loc_conf_t *rlcf; |
| } ndk_set_var_info_t; |
| |
| |
| static void ndk_set_var_code (ngx_http_script_engine_t *e); |
| static void ndk_set_var_hash_code (ngx_http_script_engine_t *e); |
| static void ndk_set_var_value_code (ngx_http_script_engine_t *e); |
| |
| |
| static inline void |
| ndk_set_var_code_finalize (ngx_http_script_engine_t *e, ngx_int_t rc, |
| ngx_http_variable_value_t *v, ngx_str_t *str) |
| { |
| switch (rc) { |
| |
| case NGX_OK : |
| |
| v->data = str->data; |
| v->len = str->len; |
| v->valid = 1; |
| v->no_cacheable = 0; |
| v->not_found = 0; |
| |
| ngx_log_debug1 (NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0, |
| "http script value (post filter): \"%v\"", v); |
| break; |
| |
| case NGX_DECLINED : |
| |
| v->valid = 0; |
| v->not_found = 1; |
| v->no_cacheable = 1; |
| break; |
| |
| case NGX_ERROR : |
| |
| e->ip = ndk_http_script_exit; |
| e->status = NGX_HTTP_INTERNAL_SERVER_ERROR; |
| break; |
| } |
| } |
| |
| |
| |
| static void |
| ndk_set_var_code (ngx_http_script_engine_t *e) |
| { |
| ngx_int_t rc; |
| ngx_str_t str; |
| ngx_http_variable_value_t *v; |
| ndk_set_var_code_t *sv; |
| ndk_set_var_pt func; |
| |
| sv = (ndk_set_var_code_t *) e->ip; |
| |
| e->ip += sizeof (ndk_set_var_code_t); |
| |
| v = e->sp++; |
| |
| func = sv->func; |
| |
| rc = func (e->request, &str); |
| |
| ndk_set_var_code_finalize (e, rc, v, &str); |
| } |
| |
| |
| static void |
| ndk_set_var_data_code (ngx_http_script_engine_t *e) |
| { |
| ngx_int_t rc; |
| ngx_str_t str; |
| ngx_http_variable_value_t *v; |
| ndk_set_var_data_code_t *svd; |
| ndk_set_var_data_pt func; |
| |
| svd = (ndk_set_var_data_code_t *) e->ip; |
| |
| e->ip += sizeof (ndk_set_var_data_code_t); |
| |
| v = e->sp++; |
| |
| func = svd->func; |
| |
| rc = func (e->request, &str, svd->data); |
| |
| ndk_set_var_code_finalize (e, rc, v, &str); |
| } |
| |
| |
| static void |
| ndk_set_var_value_code (ngx_http_script_engine_t *e) |
| { |
| ngx_int_t rc; |
| ngx_str_t str; |
| ngx_http_variable_value_t *v; |
| ndk_set_var_code_t *sv; |
| ndk_set_var_value_pt func; |
| |
| sv = (ndk_set_var_code_t *) e->ip; |
| |
| e->ip += sizeof (ndk_set_var_code_t); |
| |
| v = e->sp - 1; |
| |
| func = sv->func; |
| |
| rc = func (e->request, &str, v); |
| |
| ndk_set_var_code_finalize (e, rc, v, &str); |
| } |
| |
| |
| static void |
| ndk_set_var_value_data_code (ngx_http_script_engine_t *e) |
| { |
| ngx_int_t rc; |
| ngx_str_t str; |
| ngx_http_variable_value_t *v; |
| ndk_set_var_data_code_t *svd; |
| ndk_set_var_value_data_pt func; |
| |
| svd = (ndk_set_var_data_code_t *) e->ip; |
| |
| e->ip += sizeof (ndk_set_var_data_code_t); |
| |
| v = e->sp - 1; |
| |
| func = svd->func; |
| |
| rc = func (e->request, &str, v, svd->data); |
| |
| ndk_set_var_code_finalize (e, rc, v, &str); |
| } |
| |
| |
| static void |
| ndk_set_var_multi_value_code (ngx_http_script_engine_t *e) |
| { |
| ngx_int_t rc; |
| ngx_str_t str; |
| ngx_http_variable_value_t *v; |
| ndk_set_var_size_code_t *svs; |
| ndk_set_var_value_pt func; |
| |
| svs = (ndk_set_var_size_code_t *) e->ip; |
| |
| e->ip += sizeof (ndk_set_var_size_code_t); |
| |
| v = e->sp - svs->size; |
| e->sp = v + 1; |
| |
| func = svs->func; |
| |
| rc = func (e->request, &str, v); |
| |
| ndk_set_var_code_finalize (e, rc, v, &str); |
| } |
| |
| |
| static void |
| ndk_set_var_multi_value_data_code (ngx_http_script_engine_t *e) |
| { |
| ngx_int_t rc; |
| ngx_str_t str; |
| ngx_http_variable_value_t *v; |
| ndk_set_var_size_data_code_t *svsd; |
| ndk_set_var_value_data_pt func; |
| |
| svsd = (ndk_set_var_size_data_code_t *) e->ip; |
| |
| e->ip += sizeof (ndk_set_var_size_data_code_t); |
| |
| v = e->sp - svsd->size; |
| e->sp = v + 1; |
| |
| func = svsd->func; |
| |
| rc = func (e->request, &str, v, svsd->data); |
| |
| ndk_set_var_code_finalize (e, rc, v, &str); |
| } |
| |
| |
| static void |
| ndk_set_var_hash_code (ngx_http_script_engine_t *e) |
| { |
| u_char *p; |
| ngx_http_variable_value_t *v; |
| ndk_set_var_size_code_t *svs; |
| ndk_set_var_hash_pt func; |
| |
| svs = (ndk_set_var_size_code_t *) e->ip; |
| |
| e->ip += sizeof (ndk_set_var_size_code_t); |
| |
| p = ngx_palloc (e->request->pool, svs->size); |
| if (p == NULL) { |
| e->ip = ndk_http_script_exit; |
| e->status = NGX_HTTP_INTERNAL_SERVER_ERROR; |
| return; |
| } |
| |
| v = e->sp - 1; |
| |
| func = svs->func; |
| |
| func (p, (char *) v->data, v->len); |
| |
| v->data = (u_char *) p; |
| v->len = svs->size; |
| |
| ngx_log_debug1(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0, |
| "http script hashed value: \"%v\"", v); |
| } |
| |
| |
| |
| static char * |
| ndk_set_var_name (ndk_set_var_info_t *info, ngx_str_t *varname) |
| { |
| ngx_int_t index; |
| ngx_http_variable_t *v; |
| ngx_conf_t *cf; |
| ndk_http_rewrite_loc_conf_t *rlcf; |
| ngx_str_t name; |
| |
| name = *varname; |
| |
| cf = info->cf; |
| rlcf = ngx_http_conf_get_module_loc_conf (cf, ngx_http_rewrite_module); |
| |
| if (name.data[0] != '$') { |
| ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, |
| "invalid variable name \"%V\"", &name); |
| return NGX_CONF_ERROR; |
| } |
| |
| name.len--; |
| name.data++; |
| |
| v = ngx_http_add_variable (cf, &name, NGX_HTTP_VAR_CHANGEABLE); |
| if (v == NULL) { |
| return NGX_CONF_ERROR; |
| } |
| |
| index = ngx_http_get_variable_index (cf, &name); |
| if (index == NGX_ERROR) { |
| return NGX_CONF_ERROR; |
| } |
| |
| if (v->get_handler == NULL |
| && ngx_strncasecmp(name.data, (u_char *) "arg_", 4) != 0 |
| && ngx_strncasecmp(name.data, (u_char *) "cookie_", 7) != 0 |
| && ngx_strncasecmp(name.data, (u_char *) "http_", 5) != 0 |
| && ngx_strncasecmp(name.data, (u_char *) "sent_http_", 10) != 0 |
| && ngx_strncasecmp(name.data, (u_char *) "upstream_http_", 14) != 0) |
| { |
| v->get_handler = ndk_http_rewrite_var; |
| v->data = index; |
| } |
| |
| info->v = v; |
| info->index = index; |
| info->rlcf = rlcf; |
| |
| return NGX_CONF_OK; |
| } |
| |
| |
| |
| static void |
| ndk_set_variable_value_space (ndk_http_rewrite_loc_conf_t *rlcf, ngx_uint_t count) |
| { |
| // if the number of variable values that will be used is greater than 10, |
| // make sure there is enough space allocated on the rewrite value stack |
| |
| if (count <= 10) |
| return; |
| |
| if (rlcf->stack_size == NGX_CONF_UNSET_UINT) { |
| rlcf->stack_size = count; |
| return; |
| } |
| |
| if (rlcf->stack_size < count) |
| rlcf->stack_size = count; |
| } |
| |
| |
| |
| static char * |
| ndk_set_var_filter (ngx_conf_t *cf, ndk_http_rewrite_loc_conf_t *rlcf, |
| ndk_set_var_t *filter) |
| { |
| ndk_set_var_code_t *sv; |
| ndk_set_var_size_code_t *svs; |
| ndk_set_var_data_code_t *svd; |
| ndk_set_var_size_data_code_t *svsd; |
| |
| if (filter == NULL) { |
| return "no filter set"; |
| } |
| |
| switch (filter->type) { |
| |
| case NDK_SET_VAR_BASIC : |
| |
| sv = ngx_http_script_start_code (cf->pool, &rlcf->codes, |
| sizeof(ndk_set_var_code_t)); |
| if (sv == NULL) { |
| return NGX_CONF_ERROR; |
| } |
| |
| sv->code = ndk_set_var_code; |
| sv->func = filter->func; |
| break; |
| |
| |
| case NDK_SET_VAR_DATA : |
| |
| svd = ngx_http_script_start_code (cf->pool, &rlcf->codes, |
| sizeof(ndk_set_var_data_code_t)); |
| if (svd == NULL) { |
| return NGX_CONF_ERROR; |
| } |
| |
| svd->code = ndk_set_var_data_code; |
| svd->func = filter->func; |
| svd->data = filter->data; |
| break; |
| |
| |
| case NDK_SET_VAR_VALUE : |
| |
| sv = ngx_http_script_start_code (cf->pool, &rlcf->codes, |
| sizeof(ndk_set_var_code_t)); |
| if (sv == NULL) { |
| return NGX_CONF_ERROR; |
| } |
| |
| sv->code = ndk_set_var_value_code; |
| sv->func = filter->func; |
| break; |
| |
| |
| case NDK_SET_VAR_VALUE_DATA : |
| |
| svd = ngx_http_script_start_code (cf->pool, &rlcf->codes, |
| sizeof(ndk_set_var_data_code_t)); |
| if (svd == NULL) { |
| return NGX_CONF_ERROR; |
| } |
| |
| svd->code = ndk_set_var_value_data_code; |
| svd->func = filter->func; |
| svd->data = filter->data; |
| break; |
| |
| |
| case NDK_SET_VAR_MULTI_VALUE : |
| |
| svs = ngx_http_script_start_code (cf->pool, &rlcf->codes, |
| sizeof(ndk_set_var_size_code_t)); |
| if (svs == NULL) { |
| return NGX_CONF_ERROR; |
| } |
| |
| svs->code = ndk_set_var_multi_value_code; |
| svs->func = filter->func; |
| svs->size = filter->size; |
| |
| ndk_set_variable_value_space (rlcf, svs->size); |
| break; |
| |
| |
| case NDK_SET_VAR_MULTI_VALUE_DATA : |
| |
| svsd = ngx_http_script_start_code (cf->pool, &rlcf->codes, |
| sizeof(ndk_set_var_size_data_code_t)); |
| if (svsd == NULL) { |
| return NGX_CONF_ERROR; |
| } |
| |
| svsd->code = ndk_set_var_multi_value_data_code; |
| svsd->func = filter->func; |
| svsd->size = filter->size; |
| svsd->data = filter->data; |
| |
| ndk_set_variable_value_space (rlcf, svsd->size); |
| break; |
| |
| |
| case NDK_SET_VAR_HASH : |
| |
| svs = ngx_http_script_start_code (cf->pool, &rlcf->codes, |
| sizeof(ndk_set_var_size_code_t)); |
| if (svs == NULL) { |
| return NGX_CONF_ERROR; |
| } |
| |
| svs->code = ndk_set_var_hash_code; |
| svs->func = filter->func; |
| svs->size = filter->size; |
| break; |
| |
| |
| default : |
| |
| ngx_conf_log_error (NGX_LOG_EMERG, cf, 0, |
| "invalid filter type \"%ul\"", filter->type); |
| return NGX_CONF_ERROR; |
| } |
| |
| return NGX_CONF_OK; |
| } |
| |
| |
| |
| static char * |
| ndk_set_var_filter_value (ndk_set_var_info_t *info, ndk_set_var_t *filter) |
| { |
| ngx_conf_t *cf; |
| ngx_http_variable_t *v; |
| ndk_http_rewrite_loc_conf_t *rlcf; |
| ngx_http_script_var_code_t *vcode; |
| ngx_http_script_var_handler_code_t *vhcode; |
| |
| v = info->v; |
| cf = info->cf; |
| rlcf = info->rlcf; |
| |
| if (ndk_set_var_filter (cf, rlcf, filter) != NGX_CONF_OK) { |
| return NGX_CONF_ERROR; |
| } |
| |
| if (v->set_handler) { |
| vhcode = ngx_http_script_start_code (cf->pool, &rlcf->codes, |
| sizeof(ngx_http_script_var_handler_code_t)); |
| if (vhcode == NULL) { |
| return NGX_CONF_ERROR; |
| } |
| |
| vhcode->code = ngx_http_script_var_set_handler_code; |
| vhcode->handler = v->set_handler; |
| vhcode->data = v->data; |
| |
| return NGX_CONF_OK; |
| } |
| |
| vcode = ngx_http_script_start_code (cf->pool, &rlcf->codes, |
| sizeof(ngx_http_script_var_code_t)); |
| if (vcode == NULL) { |
| return NGX_CONF_ERROR; |
| } |
| |
| vcode->code = ngx_http_script_set_var_code; |
| vcode->index = (uintptr_t) info->index; |
| |
| return NGX_CONF_OK; |
| } |
| |
| |
| |
| |
| char * |
| ndk_set_var_core (ngx_conf_t *cf, ngx_str_t *name, ndk_set_var_t *filter) |
| { |
| char *p; |
| ndk_set_var_info_t info; |
| |
| info.cf = cf; |
| |
| p = ndk_set_var_name (&info, name); |
| if (p != NGX_CONF_OK) |
| return p; |
| |
| return ndk_set_var_filter_value (&info, filter); |
| } |
| |
| |
| char * |
| ndk_set_var_value_core (ngx_conf_t *cf, ngx_str_t *name, ngx_str_t *value, ndk_set_var_t *filter) |
| { |
| char *p; |
| ndk_set_var_info_t info; |
| |
| info.cf = cf; |
| |
| p = ndk_set_var_name (&info, name); |
| if (p != NGX_CONF_OK) |
| return p; |
| |
| p = ndk_http_rewrite_value (cf, info.rlcf, value); |
| if (p != NGX_CONF_OK) { |
| return p; |
| } |
| |
| return ndk_set_var_filter_value (&info, filter); |
| } |
| |
| |
| char * |
| ndk_set_var_multi_value_core (ngx_conf_t *cf, ngx_str_t *name, ngx_str_t *value, ndk_set_var_t *filter) |
| { |
| char *p; |
| ndk_set_var_info_t info; |
| ngx_int_t i; |
| |
| info.cf = cf; |
| |
| p = ndk_set_var_name (&info, name); |
| if (p != NGX_CONF_OK) |
| return p; |
| |
| for (i=filter->size; i; i--, value++) { |
| |
| p = ndk_http_rewrite_value (cf, info.rlcf, value); |
| if (p != NGX_CONF_OK) { |
| return p; |
| } |
| } |
| |
| return ndk_set_var_filter_value (&info, filter); |
| } |
| |
| |
| |
| char * |
| ndk_set_var (ngx_conf_t *cf, ngx_command_t *cmd, void *conf) |
| { |
| ngx_str_t *value; |
| ndk_set_var_t *filter; |
| |
| value = cf->args->elts; |
| value++; |
| |
| filter = (ndk_set_var_t *) cmd->post; |
| |
| return ndk_set_var_core (cf, value, filter); |
| } |
| |
| |
| char * |
| ndk_set_var_value (ngx_conf_t *cf, ngx_command_t *cmd, void *conf) |
| { |
| ngx_str_t *value; |
| ndk_set_var_t *filter; |
| |
| value = cf->args->elts; |
| value++; |
| |
| filter = (ndk_set_var_t *) cmd->post; |
| |
| return ndk_set_var_value_core (cf, value, |
| cf->args->nelts == 1 + 1 ? value : value + 1, filter); |
| } |
| |
| |
| char * |
| ndk_set_var_multi_value (ngx_conf_t *cf, ngx_command_t *cmd, void *conf) |
| { |
| ngx_str_t *value; |
| ndk_set_var_t *filter; |
| |
| value = cf->args->elts; |
| value++; |
| |
| filter = (ndk_set_var_t *) cmd->post; |
| |
| return ndk_set_var_multi_value_core (cf, value, value + 1, filter); |
| } |
| |
| |