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;
}
|