From c21c3b0befeb46a51b6bf3758ffa30813bea0ff0 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sat, 9 Mar 2024 14:19:22 +0100 Subject: Adding upstream version 1.44.3. Signed-off-by: Daniel Baumann --- .../libh2o/lib/handler/configurator/headers_util.c | 143 +++++++++++++++++++++ 1 file changed, 143 insertions(+) create mode 100644 web/server/h2o/libh2o/lib/handler/configurator/headers_util.c (limited to 'web/server/h2o/libh2o/lib/handler/configurator/headers_util.c') diff --git a/web/server/h2o/libh2o/lib/handler/configurator/headers_util.c b/web/server/h2o/libh2o/lib/handler/configurator/headers_util.c new file mode 100644 index 000000000..c05b9b7c2 --- /dev/null +++ b/web/server/h2o/libh2o/lib/handler/configurator/headers_util.c @@ -0,0 +1,143 @@ +#include "h2o.h" +#include "h2o/configurator.h" + +struct headers_util_configurator_t { + h2o_configurator_t super; + h2o_configurator_t *child; + h2o_configurator_get_headers_commands_cb get_commands; +}; + +static int extract_name(const char *src, size_t len, h2o_iovec_t **_name) +{ + h2o_iovec_t name; + const h2o_token_t *name_token; + + name = h2o_str_stripws(src, len); + if (name.len == 0) + return -1; + + name = h2o_strdup(NULL, name.base, name.len); + h2o_strtolower(name.base, name.len); + + if ((name_token = h2o_lookup_token(name.base, name.len)) != NULL) { + *_name = (h2o_iovec_t *)&name_token->buf; + free(name.base); + } else { + *_name = h2o_mem_alloc(sizeof(**_name)); + **_name = name; + } + + return 0; +} + +static int extract_name_value(const char *src, h2o_iovec_t **name, h2o_iovec_t *value) +{ + const char *colon = strchr(src, ':'); + + if (colon == NULL) + return -1; + + if (extract_name(src, colon - src, name) != 0) + return -1; + *value = h2o_str_stripws(colon + 1, strlen(colon + 1)); + *value = h2o_strdup(NULL, value->base, value->len); + + return 0; +} + +static int add_cmd(h2o_configurator_command_t *cmd, yoml_t *node, int cmd_id, h2o_iovec_t *name, h2o_iovec_t value, + h2o_headers_command_t **cmds) +{ + if (h2o_iovec_is_token(name)) { + const h2o_token_t *token = (void *)name; + if (h2o_headers_is_prohibited_name(token)) { + h2o_configurator_errprintf(cmd, node, "the named header cannot be rewritten"); + return -1; + } + } + + h2o_headers_append_command(cmds, cmd_id, name, value); + return 0; +} + +static int on_config_header_2arg(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx, int cmd_id, yoml_t *node, + h2o_headers_command_t **headers_cmds) +{ + h2o_iovec_t *name, value; + + if (extract_name_value(node->data.scalar, &name, &value) != 0) { + h2o_configurator_errprintf(cmd, node, "failed to parse the value; should be in form of `name: value`"); + return -1; + } + if (add_cmd(cmd, node, cmd_id, name, value, headers_cmds) != 0) { + if (!h2o_iovec_is_token(name)) + free(name->base); + free(value.base); + return -1; + } + return 0; +} + +static int on_config_header_unset(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx, yoml_t *node) +{ + h2o_iovec_t *name; + struct headers_util_configurator_t *self = (void *)cmd->configurator; + + if (extract_name(node->data.scalar, strlen(node->data.scalar), &name) != 0) { + h2o_configurator_errprintf(cmd, node, "invalid header name"); + return -1; + } + if (add_cmd(cmd, node, H2O_HEADERS_CMD_UNSET, name, (h2o_iovec_t){NULL}, self->get_commands(self->child)) != 0) { + if (!h2o_iovec_is_token(name)) + free(name->base); + return -1; + } + return 0; +} + +#define DEFINE_2ARG(fn, cmd_id) \ + static int fn(h2o_configurator_command_t *cmd, h2o_configurator_context_t *ctx, yoml_t *node) \ + { \ + struct headers_util_configurator_t *self = (void *)cmd->configurator; \ + return on_config_header_2arg(cmd, ctx, cmd_id, node, self->get_commands(self->child)); \ + } + +DEFINE_2ARG(on_config_header_add, H2O_HEADERS_CMD_ADD) +DEFINE_2ARG(on_config_header_append, H2O_HEADERS_CMD_APPEND) +DEFINE_2ARG(on_config_header_merge, H2O_HEADERS_CMD_MERGE) +DEFINE_2ARG(on_config_header_set, H2O_HEADERS_CMD_SET) +DEFINE_2ARG(on_config_header_setifempty, H2O_HEADERS_CMD_SETIFEMPTY) + +#undef DEFINE_2ARG + +void h2o_configurator_define_headers_commands(h2o_globalconf_t *global_conf, h2o_configurator_t *conf, const char *prefix, + h2o_configurator_get_headers_commands_cb get_commands) +{ + struct headers_util_configurator_t *c = (void *)h2o_configurator_create(global_conf, sizeof(*c)); + c->child = conf; + c->get_commands = get_commands; + size_t prefix_len = strlen(prefix); + +#define DEFINE_CMD_NAME(name, suffix) \ + char *name = h2o_mem_alloc(prefix_len + sizeof(suffix)); \ + memcpy(name, prefix, prefix_len); \ + memcpy(name + prefix_len, suffix, sizeof(suffix)) + + DEFINE_CMD_NAME(add_directive, ".add"); + DEFINE_CMD_NAME(append_directive, ".append"); + DEFINE_CMD_NAME(merge_directive, ".merge"); + DEFINE_CMD_NAME(set_directive, ".set"); + DEFINE_CMD_NAME(setifempty_directive, ".setifempty"); + DEFINE_CMD_NAME(unset_directive, ".unset"); +#undef DEFINE_CMD_NAME + +#define DEFINE_CMD(name, cb) \ + h2o_configurator_define_command(&c->super, name, H2O_CONFIGURATOR_FLAG_ALL_LEVELS | H2O_CONFIGURATOR_FLAG_EXPECT_SCALAR, cb) + DEFINE_CMD(add_directive, on_config_header_add); + DEFINE_CMD(append_directive, on_config_header_append); + DEFINE_CMD(merge_directive, on_config_header_merge); + DEFINE_CMD(set_directive, on_config_header_set); + DEFINE_CMD(setifempty_directive, on_config_header_setifempty); + DEFINE_CMD(unset_directive, on_config_header_unset); +#undef DEFINE_CMD +} -- cgit v1.2.3