#ifndef DDEBUG #define DDEBUG 0 #endif #include "ddebug.h" #include "ngx_http_echo_foreach.h" #include "ngx_http_echo_util.h" #include ngx_int_t ngx_http_echo_it_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data) { ngx_http_echo_ctx_t *ctx; ngx_uint_t i; ngx_array_t *choices; ngx_str_t *choice_elts, *choice; ctx = ngx_http_get_module_ctx(r, ngx_http_echo_module); if (ctx && ctx->foreach != NULL) { choices = ctx->foreach->choices; i = ctx->foreach->next_choice; if (i < choices->nelts) { choice_elts = choices->elts; choice = &choice_elts[i]; v->len = choice->len; v->data = choice->data; v->valid = 1; v->no_cacheable = 1; v->not_found = 0; return NGX_OK; } } v->not_found = 1; return NGX_OK; } ngx_int_t ngx_http_echo_exec_echo_foreach_split(ngx_http_request_t *r, ngx_http_echo_ctx_t *ctx, ngx_array_t *computed_args) { ngx_http_echo_loc_conf_t *elcf; ngx_str_t *delimiter, *compound; u_char *pos, *last, *end; ngx_str_t *choice; ngx_str_t *computed_arg_elts; ngx_array_t *cmds; ngx_http_echo_cmd_t *cmd; ngx_http_echo_cmd_t *cmd_elts; if (ctx->foreach != NULL) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "Nested echo_foreach not supported yet."); return NGX_HTTP_INTERNAL_SERVER_ERROR; } if (computed_args->nelts < 2) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "echo_foreach should take at least two arguments. " "(if your delimiter starts with \"-\", preceding it " "with a \"--\".)"); return NGX_HTTP_INTERNAL_SERVER_ERROR; } computed_arg_elts = computed_args->elts; compound = &computed_arg_elts[1]; dd("HEY coumpound len: %u", (int) compound->len); ctx->foreach = ngx_palloc(r->pool, sizeof(ngx_http_echo_foreach_ctx_t)); if (ctx->foreach == NULL) { return NGX_ERROR; } ctx->foreach->cmd_index = ctx->next_handler_cmd; ctx->foreach->next_choice = 0; ctx->foreach->choices = ngx_array_create(r->pool, 10, sizeof(ngx_str_t)); if (ctx->foreach->choices == NULL) { return NGX_ERROR; } delimiter = &computed_arg_elts[0]; pos = compound->data; end = compound->data + compound->len; while ((last = ngx_http_echo_strlstrn(pos, end, delimiter->data, delimiter->len - 1)) != NULL) { dd("entered the loop"); if (last == pos) { dd("!!! len == 0"); pos = last + delimiter->len; continue; } choice = ngx_array_push(ctx->foreach->choices); if (choice == NULL) { return NGX_ERROR; } choice->data = pos; choice->len = last - pos; pos = last + delimiter->len; } if (pos < end) { choice = ngx_array_push(ctx->foreach->choices); if (choice == NULL) { return NGX_ERROR; } choice->data = pos; choice->len = end - pos; } if (ctx->foreach->choices->nelts == 0) { /* skip the foreach body entirely */ elcf = ngx_http_get_module_loc_conf(r, ngx_http_echo_module); cmds = elcf->handler_cmds; cmd_elts = cmds->elts; for (/* void */; ctx->next_handler_cmd < cmds->nelts; ctx->next_handler_cmd++) { cmd = &cmd_elts[ctx->next_handler_cmd + 1]; if (cmd->opcode == echo_opcode_echo_end) { return NGX_OK; } } } return NGX_OK; } ngx_int_t ngx_http_echo_exec_echo_end(ngx_http_request_t *r, ngx_http_echo_ctx_t *ctx) { if (ctx->foreach == NULL) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "Found a echo_end that has no corresponding echo_foreach " "before it."); return NGX_ERROR; } ctx->foreach->next_choice++; if (ctx->foreach->next_choice >= ctx->foreach->choices->nelts) { /* TODO We need to explicitly free the foreach ctx from * the pool */ ctx->foreach = NULL; return NGX_OK; } dd("echo_end: ++ next_choice (total: %u): %u", (unsigned) ctx->foreach->choices->nelts, (unsigned) ctx->foreach->next_choice); /* the main handler dispatcher loop will increment * ctx->next_handler_cmd for us anyway. */ ctx->next_handler_cmd = ctx->foreach->cmd_index; return NGX_OK; }