1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114
|
#include "h2o.h"
static h2o_header_t *find_header(h2o_headers_t *headers, h2o_headers_command_t *cmd)
{
size_t index;
if (h2o_iovec_is_token(cmd->name)) {
index = h2o_find_header(headers, (void *)cmd->name, SIZE_MAX);
} else {
index = h2o_find_header_by_str(headers, cmd->name->base, cmd->name->len, SIZE_MAX);
}
if (index == SIZE_MAX)
return NULL;
return headers->entries + index;
}
static void remove_header(h2o_headers_t *headers, h2o_headers_command_t *cmd)
{
size_t src, dst = 0;
for (src = 0; src != headers->size; ++src) {
if (h2o_iovec_is_token(cmd->name)) {
if (headers->entries[src].name == cmd->name)
continue;
} else {
if (h2o_memis(headers->entries[src].name->base, headers->entries[src].name->len, cmd->name->base, cmd->name->len))
continue;
}
/* not matched */
if (dst != src)
headers->entries[dst] = headers->entries[src];
++dst;
}
headers->size = dst;
}
void h2o_headers_append_command(h2o_headers_command_t **cmds, int cmd, h2o_iovec_t *name, h2o_iovec_t value)
{
h2o_headers_command_t *new_cmds;
size_t cnt;
if (*cmds != NULL) {
for (cnt = 0; (*cmds)[cnt].cmd != H2O_HEADERS_CMD_NULL; ++cnt)
;
} else {
cnt = 0;
}
new_cmds = h2o_mem_alloc_shared(NULL, (cnt + 2) * sizeof(*new_cmds), NULL);
if (*cmds != NULL)
memcpy(new_cmds, *cmds, cnt * sizeof(*new_cmds));
new_cmds[cnt] = (h2o_headers_command_t){cmd, name, value};
new_cmds[cnt + 1] = (h2o_headers_command_t){H2O_HEADERS_CMD_NULL};
if (*cmds != NULL)
h2o_mem_release_shared(*cmds);
*cmds = new_cmds;
}
void h2o_rewrite_headers(h2o_mem_pool_t *pool, h2o_headers_t *headers, h2o_headers_command_t *cmd)
{
h2o_header_t *target;
switch (cmd->cmd) {
case H2O_HEADERS_CMD_ADD:
goto AddHeader;
case H2O_HEADERS_CMD_APPEND:
if ((target = find_header(headers, cmd)) == NULL)
goto AddHeader;
goto AppendToken;
case H2O_HEADERS_CMD_MERGE:
if ((target = find_header(headers, cmd)) == NULL)
goto AddHeader;
if (h2o_contains_token(target->value.base, target->value.len, cmd->value.base, cmd->value.len, ','))
return;
goto AppendToken;
case H2O_HEADERS_CMD_SET:
remove_header(headers, cmd);
goto AddHeader;
case H2O_HEADERS_CMD_SETIFEMPTY:
if (find_header(headers, cmd) != NULL)
return;
goto AddHeader;
case H2O_HEADERS_CMD_UNSET:
remove_header(headers, cmd);
return;
}
assert(!"FIXME");
return;
AddHeader:
if (h2o_iovec_is_token(cmd->name)) {
h2o_add_header(pool, headers, (void *)cmd->name, NULL, cmd->value.base, cmd->value.len);
} else {
h2o_add_header_by_str(pool, headers, cmd->name->base, cmd->name->len, 0, NULL, cmd->value.base, cmd->value.len);
}
return;
AppendToken:
if (target->value.len != 0) {
h2o_iovec_t v;
v.len = target->value.len + 2 + cmd->value.len;
v.base = h2o_mem_alloc_pool(pool, v.len);
memcpy(v.base, target->value.base, target->value.len);
v.base[target->value.len] = ',';
v.base[target->value.len + 1] = ' ';
memcpy(v.base + target->value.len + 2, cmd->value.base, cmd->value.len);
target->value = v;
} else {
target->value = cmd->value;
}
return;
}
|