1*76404edcSAsim Jamshed #include "base.h"
2*76404edcSAsim Jamshed #include "log.h"
3*76404edcSAsim Jamshed #include "buffer.h"
4*76404edcSAsim Jamshed
5*76404edcSAsim Jamshed #include "plugin.h"
6*76404edcSAsim Jamshed
7*76404edcSAsim Jamshed #include "response.h"
8*76404edcSAsim Jamshed
9*76404edcSAsim Jamshed #include <stdlib.h>
10*76404edcSAsim Jamshed #include <string.h>
11*76404edcSAsim Jamshed
12*76404edcSAsim Jamshed /* plugin config for all request/connections */
13*76404edcSAsim Jamshed
14*76404edcSAsim Jamshed typedef struct {
15*76404edcSAsim Jamshed int handled; /* make sure that we only apply the headers once */
16*76404edcSAsim Jamshed } handler_ctx;
17*76404edcSAsim Jamshed
18*76404edcSAsim Jamshed typedef struct {
19*76404edcSAsim Jamshed array *request_header;
20*76404edcSAsim Jamshed array *response_header;
21*76404edcSAsim Jamshed
22*76404edcSAsim Jamshed array *environment;
23*76404edcSAsim Jamshed } plugin_config;
24*76404edcSAsim Jamshed
25*76404edcSAsim Jamshed typedef struct {
26*76404edcSAsim Jamshed PLUGIN_DATA;
27*76404edcSAsim Jamshed
28*76404edcSAsim Jamshed plugin_config **config_storage;
29*76404edcSAsim Jamshed
30*76404edcSAsim Jamshed plugin_config conf;
31*76404edcSAsim Jamshed } plugin_data;
32*76404edcSAsim Jamshed
handler_ctx_init(void)33*76404edcSAsim Jamshed static handler_ctx * handler_ctx_init(void) {
34*76404edcSAsim Jamshed handler_ctx * hctx;
35*76404edcSAsim Jamshed
36*76404edcSAsim Jamshed hctx = calloc(1, sizeof(*hctx));
37*76404edcSAsim Jamshed
38*76404edcSAsim Jamshed hctx->handled = 0;
39*76404edcSAsim Jamshed
40*76404edcSAsim Jamshed return hctx;
41*76404edcSAsim Jamshed }
42*76404edcSAsim Jamshed
handler_ctx_free(handler_ctx * hctx)43*76404edcSAsim Jamshed static void handler_ctx_free(handler_ctx *hctx) {
44*76404edcSAsim Jamshed free(hctx);
45*76404edcSAsim Jamshed }
46*76404edcSAsim Jamshed
47*76404edcSAsim Jamshed
48*76404edcSAsim Jamshed /* init the plugin data */
INIT_FUNC(mod_setenv_init)49*76404edcSAsim Jamshed INIT_FUNC(mod_setenv_init) {
50*76404edcSAsim Jamshed plugin_data *p;
51*76404edcSAsim Jamshed
52*76404edcSAsim Jamshed p = calloc(1, sizeof(*p));
53*76404edcSAsim Jamshed
54*76404edcSAsim Jamshed return p;
55*76404edcSAsim Jamshed }
56*76404edcSAsim Jamshed
57*76404edcSAsim Jamshed /* detroy the plugin data */
FREE_FUNC(mod_setenv_free)58*76404edcSAsim Jamshed FREE_FUNC(mod_setenv_free) {
59*76404edcSAsim Jamshed plugin_data *p = p_d;
60*76404edcSAsim Jamshed
61*76404edcSAsim Jamshed UNUSED(srv);
62*76404edcSAsim Jamshed
63*76404edcSAsim Jamshed if (!p) return HANDLER_GO_ON;
64*76404edcSAsim Jamshed
65*76404edcSAsim Jamshed if (p->config_storage) {
66*76404edcSAsim Jamshed size_t i;
67*76404edcSAsim Jamshed for (i = 0; i < srv->config_context->used; i++) {
68*76404edcSAsim Jamshed plugin_config *s = p->config_storage[i];
69*76404edcSAsim Jamshed
70*76404edcSAsim Jamshed array_free(s->request_header);
71*76404edcSAsim Jamshed array_free(s->response_header);
72*76404edcSAsim Jamshed array_free(s->environment);
73*76404edcSAsim Jamshed
74*76404edcSAsim Jamshed free(s);
75*76404edcSAsim Jamshed }
76*76404edcSAsim Jamshed free(p->config_storage);
77*76404edcSAsim Jamshed }
78*76404edcSAsim Jamshed
79*76404edcSAsim Jamshed free(p);
80*76404edcSAsim Jamshed
81*76404edcSAsim Jamshed return HANDLER_GO_ON;
82*76404edcSAsim Jamshed }
83*76404edcSAsim Jamshed
84*76404edcSAsim Jamshed /* handle plugin config and check values */
85*76404edcSAsim Jamshed
SETDEFAULTS_FUNC(mod_setenv_set_defaults)86*76404edcSAsim Jamshed SETDEFAULTS_FUNC(mod_setenv_set_defaults) {
87*76404edcSAsim Jamshed plugin_data *p = p_d;
88*76404edcSAsim Jamshed size_t i = 0;
89*76404edcSAsim Jamshed
90*76404edcSAsim Jamshed config_values_t cv[] = {
91*76404edcSAsim Jamshed { "setenv.add-request-header", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
92*76404edcSAsim Jamshed { "setenv.add-response-header", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
93*76404edcSAsim Jamshed { "setenv.add-environment", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 2 */
94*76404edcSAsim Jamshed { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
95*76404edcSAsim Jamshed };
96*76404edcSAsim Jamshed
97*76404edcSAsim Jamshed if (!p) return HANDLER_ERROR;
98*76404edcSAsim Jamshed
99*76404edcSAsim Jamshed p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
100*76404edcSAsim Jamshed
101*76404edcSAsim Jamshed for (i = 0; i < srv->config_context->used; i++) {
102*76404edcSAsim Jamshed plugin_config *s;
103*76404edcSAsim Jamshed
104*76404edcSAsim Jamshed s = calloc(1, sizeof(plugin_config));
105*76404edcSAsim Jamshed s->request_header = array_init();
106*76404edcSAsim Jamshed s->response_header = array_init();
107*76404edcSAsim Jamshed s->environment = array_init();
108*76404edcSAsim Jamshed
109*76404edcSAsim Jamshed cv[0].destination = s->request_header;
110*76404edcSAsim Jamshed cv[1].destination = s->response_header;
111*76404edcSAsim Jamshed cv[2].destination = s->environment;
112*76404edcSAsim Jamshed
113*76404edcSAsim Jamshed p->config_storage[i] = s;
114*76404edcSAsim Jamshed
115*76404edcSAsim Jamshed if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
116*76404edcSAsim Jamshed return HANDLER_ERROR;
117*76404edcSAsim Jamshed }
118*76404edcSAsim Jamshed }
119*76404edcSAsim Jamshed
120*76404edcSAsim Jamshed return HANDLER_GO_ON;
121*76404edcSAsim Jamshed }
122*76404edcSAsim Jamshed
123*76404edcSAsim Jamshed #define PATCH(x) \
124*76404edcSAsim Jamshed p->conf.x = s->x;
mod_setenv_patch_connection(server * srv,connection * con,plugin_data * p)125*76404edcSAsim Jamshed static int mod_setenv_patch_connection(server *srv, connection *con, plugin_data *p) {
126*76404edcSAsim Jamshed size_t i, j;
127*76404edcSAsim Jamshed plugin_config *s = p->config_storage[0];
128*76404edcSAsim Jamshed
129*76404edcSAsim Jamshed PATCH(request_header);
130*76404edcSAsim Jamshed PATCH(response_header);
131*76404edcSAsim Jamshed PATCH(environment);
132*76404edcSAsim Jamshed
133*76404edcSAsim Jamshed /* skip the first, the global context */
134*76404edcSAsim Jamshed for (i = 1; i < srv->config_context->used; i++) {
135*76404edcSAsim Jamshed data_config *dc = (data_config *)srv->config_context->data[i];
136*76404edcSAsim Jamshed s = p->config_storage[i];
137*76404edcSAsim Jamshed
138*76404edcSAsim Jamshed /* condition didn't match */
139*76404edcSAsim Jamshed if (!config_check_cond(srv, con, dc)) continue;
140*76404edcSAsim Jamshed
141*76404edcSAsim Jamshed /* merge config */
142*76404edcSAsim Jamshed for (j = 0; j < dc->value->used; j++) {
143*76404edcSAsim Jamshed data_unset *du = dc->value->data[j];
144*76404edcSAsim Jamshed
145*76404edcSAsim Jamshed if (buffer_is_equal_string(du->key, CONST_STR_LEN("setenv.add-request-header"))) {
146*76404edcSAsim Jamshed PATCH(request_header);
147*76404edcSAsim Jamshed } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("setenv.add-response-header"))) {
148*76404edcSAsim Jamshed PATCH(response_header);
149*76404edcSAsim Jamshed } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("setenv.add-environment"))) {
150*76404edcSAsim Jamshed PATCH(environment);
151*76404edcSAsim Jamshed }
152*76404edcSAsim Jamshed }
153*76404edcSAsim Jamshed }
154*76404edcSAsim Jamshed
155*76404edcSAsim Jamshed return 0;
156*76404edcSAsim Jamshed }
157*76404edcSAsim Jamshed #undef PATCH
158*76404edcSAsim Jamshed
URIHANDLER_FUNC(mod_setenv_uri_handler)159*76404edcSAsim Jamshed URIHANDLER_FUNC(mod_setenv_uri_handler) {
160*76404edcSAsim Jamshed plugin_data *p = p_d;
161*76404edcSAsim Jamshed size_t k;
162*76404edcSAsim Jamshed handler_ctx *hctx;
163*76404edcSAsim Jamshed
164*76404edcSAsim Jamshed if (con->plugin_ctx[p->id]) {
165*76404edcSAsim Jamshed hctx = con->plugin_ctx[p->id];
166*76404edcSAsim Jamshed } else {
167*76404edcSAsim Jamshed hctx = handler_ctx_init();
168*76404edcSAsim Jamshed
169*76404edcSAsim Jamshed con->plugin_ctx[p->id] = hctx;
170*76404edcSAsim Jamshed }
171*76404edcSAsim Jamshed
172*76404edcSAsim Jamshed if (hctx->handled) {
173*76404edcSAsim Jamshed return HANDLER_GO_ON;
174*76404edcSAsim Jamshed }
175*76404edcSAsim Jamshed
176*76404edcSAsim Jamshed hctx->handled = 1;
177*76404edcSAsim Jamshed
178*76404edcSAsim Jamshed mod_setenv_patch_connection(srv, con, p);
179*76404edcSAsim Jamshed
180*76404edcSAsim Jamshed for (k = 0; k < p->conf.request_header->used; k++) {
181*76404edcSAsim Jamshed data_string *ds = (data_string *)p->conf.request_header->data[k];
182*76404edcSAsim Jamshed data_string *ds_dst;
183*76404edcSAsim Jamshed
184*76404edcSAsim Jamshed if (NULL == (ds_dst = (data_string *)array_get_unused_element(con->request.headers, TYPE_STRING))) {
185*76404edcSAsim Jamshed ds_dst = data_string_init();
186*76404edcSAsim Jamshed }
187*76404edcSAsim Jamshed
188*76404edcSAsim Jamshed buffer_copy_string_buffer(ds_dst->key, ds->key);
189*76404edcSAsim Jamshed buffer_copy_string_buffer(ds_dst->value, ds->value);
190*76404edcSAsim Jamshed
191*76404edcSAsim Jamshed array_insert_unique(con->request.headers, (data_unset *)ds_dst);
192*76404edcSAsim Jamshed }
193*76404edcSAsim Jamshed
194*76404edcSAsim Jamshed for (k = 0; k < p->conf.environment->used; k++) {
195*76404edcSAsim Jamshed data_string *ds = (data_string *)p->conf.environment->data[k];
196*76404edcSAsim Jamshed data_string *ds_dst;
197*76404edcSAsim Jamshed
198*76404edcSAsim Jamshed if (NULL == (ds_dst = (data_string *)array_get_unused_element(con->environment, TYPE_STRING))) {
199*76404edcSAsim Jamshed ds_dst = data_string_init();
200*76404edcSAsim Jamshed }
201*76404edcSAsim Jamshed
202*76404edcSAsim Jamshed buffer_copy_string_buffer(ds_dst->key, ds->key);
203*76404edcSAsim Jamshed buffer_copy_string_buffer(ds_dst->value, ds->value);
204*76404edcSAsim Jamshed
205*76404edcSAsim Jamshed array_insert_unique(con->environment, (data_unset *)ds_dst);
206*76404edcSAsim Jamshed }
207*76404edcSAsim Jamshed
208*76404edcSAsim Jamshed for (k = 0; k < p->conf.response_header->used; k++) {
209*76404edcSAsim Jamshed data_string *ds = (data_string *)p->conf.response_header->data[k];
210*76404edcSAsim Jamshed
211*76404edcSAsim Jamshed response_header_insert(srv, con, CONST_BUF_LEN(ds->key), CONST_BUF_LEN(ds->value));
212*76404edcSAsim Jamshed }
213*76404edcSAsim Jamshed
214*76404edcSAsim Jamshed /* not found */
215*76404edcSAsim Jamshed return HANDLER_GO_ON;
216*76404edcSAsim Jamshed }
217*76404edcSAsim Jamshed
CONNECTION_FUNC(mod_setenv_reset)218*76404edcSAsim Jamshed CONNECTION_FUNC(mod_setenv_reset) {
219*76404edcSAsim Jamshed plugin_data *p = p_d;
220*76404edcSAsim Jamshed
221*76404edcSAsim Jamshed UNUSED(srv);
222*76404edcSAsim Jamshed
223*76404edcSAsim Jamshed if (con->plugin_ctx[p->id]) {
224*76404edcSAsim Jamshed handler_ctx_free(con->plugin_ctx[p->id]);
225*76404edcSAsim Jamshed con->plugin_ctx[p->id] = NULL;
226*76404edcSAsim Jamshed }
227*76404edcSAsim Jamshed
228*76404edcSAsim Jamshed return HANDLER_GO_ON;
229*76404edcSAsim Jamshed }
230*76404edcSAsim Jamshed
231*76404edcSAsim Jamshed /* this function is called at dlopen() time and inits the callbacks */
232*76404edcSAsim Jamshed
233*76404edcSAsim Jamshed int mod_setenv_plugin_init(plugin *p);
mod_setenv_plugin_init(plugin * p)234*76404edcSAsim Jamshed int mod_setenv_plugin_init(plugin *p) {
235*76404edcSAsim Jamshed p->version = LIGHTTPD_VERSION_ID;
236*76404edcSAsim Jamshed p->name = buffer_init_string("setenv");
237*76404edcSAsim Jamshed
238*76404edcSAsim Jamshed p->init = mod_setenv_init;
239*76404edcSAsim Jamshed p->handle_uri_clean = mod_setenv_uri_handler;
240*76404edcSAsim Jamshed p->set_defaults = mod_setenv_set_defaults;
241*76404edcSAsim Jamshed p->cleanup = mod_setenv_free;
242*76404edcSAsim Jamshed
243*76404edcSAsim Jamshed p->connection_reset = mod_setenv_reset;
244*76404edcSAsim Jamshed
245*76404edcSAsim Jamshed p->data = NULL;
246*76404edcSAsim Jamshed
247*76404edcSAsim Jamshed return 0;
248*76404edcSAsim Jamshed }
249