[tests] skip mod-secdownload HMAC-SHA1,HMAC-SHA256
[lighttpd.git] / src / mod_cml.c
blob16ecdfd5cbf1b97e8abdb0bdc4a9843ab058943f
1 #include "first.h"
3 #include "mod_cml.h"
5 #include "base.h"
6 #include "buffer.h"
7 #include "log.h"
8 #include "plugin.h"
10 #include <sys/stat.h>
11 #include <time.h>
13 #include <stdlib.h>
14 #include <string.h>
15 #include <errno.h>
17 /* init the plugin data */
18 INIT_FUNC(mod_cml_init) {
19 plugin_data *p;
21 p = calloc(1, sizeof(*p));
23 p->basedir = buffer_init();
24 p->baseurl = buffer_init();
25 p->trigger_handler = buffer_init();
27 return p;
30 /* detroy the plugin data */
31 FREE_FUNC(mod_cml_free) {
32 plugin_data *p = p_d;
34 UNUSED(srv);
36 if (!p) return HANDLER_GO_ON;
38 if (p->config_storage) {
39 size_t i;
40 for (i = 0; i < srv->config_context->used; i++) {
41 plugin_config *s = p->config_storage[i];
43 if (NULL == s) continue;
45 buffer_free(s->ext);
47 buffer_free(s->mc_namespace);
48 buffer_free(s->power_magnet);
49 array_free(s->mc_hosts);
51 #if defined(USE_MEMCACHED)
52 if (s->memc) memcached_free(s->memc);
53 #endif
55 free(s);
57 free(p->config_storage);
60 buffer_free(p->trigger_handler);
61 buffer_free(p->basedir);
62 buffer_free(p->baseurl);
64 free(p);
66 return HANDLER_GO_ON;
69 /* handle plugin config and check values */
71 SETDEFAULTS_FUNC(mod_cml_set_defaults) {
72 plugin_data *p = p_d;
73 size_t i = 0;
75 config_values_t cv[] = {
76 { "cml.extension", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
77 { "cml.memcache-hosts", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
78 { "cml.memcache-namespace", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 2 */
79 { "cml.power-magnet", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 3 */
80 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
83 if (!p) return HANDLER_ERROR;
85 p->config_storage = calloc(srv->config_context->used, sizeof(plugin_config *));
87 for (i = 0; i < srv->config_context->used; i++) {
88 data_config const* config = (data_config const*)srv->config_context->data[i];
89 plugin_config *s;
91 s = calloc(1, sizeof(plugin_config));
92 s->ext = buffer_init();
93 s->mc_hosts = array_init();
94 s->mc_namespace = buffer_init();
95 s->power_magnet = buffer_init();
96 #if defined(USE_MEMCACHED)
97 s->memc = NULL;
98 #endif
100 cv[0].destination = s->ext;
101 cv[1].destination = s->mc_hosts;
102 cv[2].destination = s->mc_namespace;
103 cv[3].destination = s->power_magnet;
105 p->config_storage[i] = s;
107 if (0 != config_insert_values_global(srv, config->value, cv, i == 0 ? T_CONFIG_SCOPE_SERVER : T_CONFIG_SCOPE_CONNECTION)) {
108 return HANDLER_ERROR;
111 if (!array_is_vlist(s->mc_hosts)) {
112 log_error_write(srv, __FILE__, __LINE__, "s",
113 "unexpected value for cml.memcache-hosts; expected list of \"host\"");
114 return HANDLER_ERROR;
117 if (s->mc_hosts->used) {
118 #if defined(USE_MEMCACHED)
119 buffer *option_string = buffer_init();
120 size_t k;
123 data_string *ds = (data_string *)s->mc_hosts->data[0];
125 buffer_append_string_len(option_string, CONST_STR_LEN("--SERVER="));
126 buffer_append_string_buffer(option_string, ds->value);
129 for (k = 1; k < s->mc_hosts->used; k++) {
130 data_string *ds = (data_string *)s->mc_hosts->data[k];
132 buffer_append_string_len(option_string, CONST_STR_LEN(" --SERVER="));
133 buffer_append_string_buffer(option_string, ds->value);
136 s->memc = memcached(CONST_BUF_LEN(option_string));
138 if (NULL == s->memc) {
139 log_error_write(srv, __FILE__, __LINE__, "sb",
140 "configuring memcached failed for option string:",
141 option_string);
143 buffer_free(option_string);
145 if (NULL == s->memc) return HANDLER_ERROR;
146 #else
147 log_error_write(srv, __FILE__, __LINE__, "s",
148 "memcache support is not compiled in but cml.memcache-hosts is set, aborting");
149 return HANDLER_ERROR;
150 #endif
154 return HANDLER_GO_ON;
157 #define PATCH(x) \
158 p->conf.x = s->x;
159 static int mod_cml_patch_connection(server *srv, connection *con, plugin_data *p) {
160 size_t i, j;
161 plugin_config *s = p->config_storage[0];
163 PATCH(ext);
164 #if defined(USE_MEMCACHED)
165 PATCH(memc);
166 #endif
167 PATCH(mc_namespace);
168 PATCH(power_magnet);
170 /* skip the first, the global context */
171 for (i = 1; i < srv->config_context->used; i++) {
172 data_config *dc = (data_config *)srv->config_context->data[i];
173 s = p->config_storage[i];
175 /* condition didn't match */
176 if (!config_check_cond(srv, con, dc)) continue;
178 /* merge config */
179 for (j = 0; j < dc->value->used; j++) {
180 data_unset *du = dc->value->data[j];
182 if (buffer_is_equal_string(du->key, CONST_STR_LEN("cml.extension"))) {
183 PATCH(ext);
184 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("cml.memcache-hosts"))) {
185 #if defined(USE_MEMCACHED)
186 PATCH(memc);
187 #endif
188 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("cml.memcache-namespace"))) {
189 PATCH(mc_namespace);
190 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("cml.power-magnet"))) {
191 PATCH(power_magnet);
196 return 0;
198 #undef PATCH
200 static int cache_call_lua(server *srv, connection *con, plugin_data *p, buffer *cml_file) {
201 buffer *b;
202 char *c;
204 /* cleanup basedir */
205 b = p->baseurl;
206 buffer_copy_buffer(b, con->uri.path);
207 for (c = b->ptr + buffer_string_length(b); c > b->ptr && *c != '/'; c--);
209 if (*c == '/') {
210 buffer_string_set_length(b, c - b->ptr + 1);
213 b = p->basedir;
214 buffer_copy_buffer(b, con->physical.path);
215 for (c = b->ptr + buffer_string_length(b); c > b->ptr && *c != '/'; c--);
217 if (*c == '/') {
218 buffer_string_set_length(b, c - b->ptr + 1);
222 /* prepare variables
223 * - cookie-based
224 * - get-param-based
226 return cache_parse_lua(srv, con, p, cml_file);
229 URIHANDLER_FUNC(mod_cml_power_magnet) {
230 plugin_data *p = p_d;
232 mod_cml_patch_connection(srv, con, p);
234 buffer_clear(p->basedir);
235 buffer_clear(p->baseurl);
236 buffer_clear(p->trigger_handler);
238 if (buffer_string_is_empty(p->conf.power_magnet)) return HANDLER_GO_ON;
241 * power-magnet:
242 * cml.power-magnet = server.docroot + "/rewrite.cml"
244 * is called on EACH request, take the original REQUEST_URI and modifies the
245 * request header as neccesary.
247 * First use:
248 * if file_exists("/maintainance.html") {
249 * output_include = ( "/maintainance.html" )
250 * return CACHE_HIT
253 * as we only want to rewrite HTML like requests we should cover it in a conditional
255 * */
257 switch(cache_call_lua(srv, con, p, p->conf.power_magnet)) {
258 case -1:
259 /* error */
260 if (con->conf.log_request_handling) {
261 log_error_write(srv, __FILE__, __LINE__, "s", "cache-error");
263 con->http_status = 500;
264 return HANDLER_COMEBACK;
265 case 0:
266 if (con->conf.log_request_handling) {
267 log_error_write(srv, __FILE__, __LINE__, "s", "cache-hit");
269 /* cache-hit */
270 buffer_reset(con->physical.path);
271 return HANDLER_FINISHED;
272 case 1:
273 /* cache miss */
274 return HANDLER_GO_ON;
275 default:
276 con->http_status = 500;
277 return HANDLER_COMEBACK;
281 URIHANDLER_FUNC(mod_cml_is_handled) {
282 plugin_data *p = p_d;
284 if (buffer_string_is_empty(con->physical.path)) return HANDLER_ERROR;
286 mod_cml_patch_connection(srv, con, p);
288 buffer_clear(p->basedir);
289 buffer_clear(p->baseurl);
290 buffer_clear(p->trigger_handler);
292 if (buffer_string_is_empty(p->conf.ext)) return HANDLER_GO_ON;
294 if (!buffer_is_equal_right_len(con->physical.path, p->conf.ext, buffer_string_length(p->conf.ext))) {
295 return HANDLER_GO_ON;
298 switch(cache_call_lua(srv, con, p, con->physical.path)) {
299 case -1:
300 /* error */
301 if (con->conf.log_request_handling) {
302 log_error_write(srv, __FILE__, __LINE__, "s", "cache-error");
304 con->http_status = 500;
305 return HANDLER_COMEBACK;
306 case 0:
307 if (con->conf.log_request_handling) {
308 log_error_write(srv, __FILE__, __LINE__, "s", "cache-hit");
310 /* cache-hit */
311 buffer_reset(con->physical.path);
312 return HANDLER_FINISHED;
313 case 1:
314 if (con->conf.log_request_handling) {
315 log_error_write(srv, __FILE__, __LINE__, "s", "cache-miss");
317 /* cache miss */
318 return HANDLER_COMEBACK;
319 default:
320 con->http_status = 500;
321 return HANDLER_COMEBACK;
325 int mod_cml_plugin_init(plugin *p);
326 int mod_cml_plugin_init(plugin *p) {
327 p->version = LIGHTTPD_VERSION_ID;
328 p->name = buffer_init_string("cache");
330 p->init = mod_cml_init;
331 p->cleanup = mod_cml_free;
332 p->set_defaults = mod_cml_set_defaults;
334 p->handle_subrequest_start = mod_cml_is_handled;
335 p->handle_physical = mod_cml_power_magnet;
337 p->data = NULL;
339 return 0;