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