Return to mod_cml.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / lighttpd / src |
1.1 misho 1: #include "buffer.h"
2: #include "server.h"
3: #include "log.h"
4: #include "plugin.h"
5: #include "response.h"
6:
7: #include "stream.h"
8:
9: #include "mod_cml.h"
10:
11: #include <sys/stat.h>
12: #include <time.h>
13:
14: #include <stdlib.h>
15: #include <string.h>
16: #include <errno.h>
17: #include <unistd.h>
18: #include <stdio.h>
19:
20: /* init the plugin data */
21: INIT_FUNC(mod_cml_init) {
22: plugin_data *p;
23:
24: p = calloc(1, sizeof(*p));
25:
26: p->basedir = buffer_init();
27: p->baseurl = buffer_init();
28: p->trigger_handler = buffer_init();
29:
30: return p;
31: }
32:
33: /* detroy the plugin data */
34: FREE_FUNC(mod_cml_free) {
35: plugin_data *p = p_d;
36:
37: UNUSED(srv);
38:
39: if (!p) return HANDLER_GO_ON;
40:
41: if (p->config_storage) {
42: size_t i;
43: for (i = 0; i < srv->config_context->used; i++) {
44: plugin_config *s = p->config_storage[i];
45:
46: buffer_free(s->ext);
47:
48: buffer_free(s->mc_namespace);
49: buffer_free(s->power_magnet);
50: array_free(s->mc_hosts);
51:
52: #if defined(HAVE_MEMCACHE_H)
53: if (s->mc) mc_free(s->mc);
54: #endif
55:
56: free(s);
57: }
58: free(p->config_storage);
59: }
60:
61: buffer_free(p->trigger_handler);
62: buffer_free(p->basedir);
63: buffer_free(p->baseurl);
64:
65: free(p);
66:
67: return HANDLER_GO_ON;
68: }
69:
70: /* handle plugin config and check values */
71:
72: SETDEFAULTS_FUNC(mod_cml_set_defaults) {
73: plugin_data *p = p_d;
74: size_t i = 0;
75:
76: config_values_t cv[] = {
77: { "cml.extension", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
78: { "cml.memcache-hosts", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
79: { "cml.memcache-namespace", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 2 */
80: { "cml.power-magnet", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 3 */
81: { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
82: };
83:
84: if (!p) return HANDLER_ERROR;
85:
1.1.1.2 ! misho 86: p->config_storage = calloc(1, srv->config_context->used * sizeof(plugin_config *));
1.1 misho 87:
88: for (i = 0; i < srv->config_context->used; i++) {
89: plugin_config *s;
90:
91: s = malloc(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(HAVE_MEMCACHE_H)
97: s->mc = NULL;
98: #endif
99:
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;
104:
105: p->config_storage[i] = s;
106:
107: if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
108: return HANDLER_ERROR;
109: }
110:
111: if (s->mc_hosts->used) {
112: #if defined(HAVE_MEMCACHE_H)
113: size_t k;
114: s->mc = mc_new();
115:
116: for (k = 0; k < s->mc_hosts->used; k++) {
117: data_string *ds = (data_string *)s->mc_hosts->data[k];
118:
119: if (0 != mc_server_add4(s->mc, ds->value->ptr)) {
120: log_error_write(srv, __FILE__, __LINE__, "sb",
121: "connection to host failed:",
122: ds->value);
123:
124: return HANDLER_ERROR;
125: }
126: }
127: #else
128: log_error_write(srv, __FILE__, __LINE__, "s",
129: "memcache support is not compiled in but cml.memcache-hosts is set, aborting");
130: return HANDLER_ERROR;
131: #endif
132: }
133: }
134:
135: return HANDLER_GO_ON;
136: }
137:
138: #define PATCH(x) \
139: p->conf.x = s->x;
140: static int mod_cml_patch_connection(server *srv, connection *con, plugin_data *p) {
141: size_t i, j;
142: plugin_config *s = p->config_storage[0];
143:
144: PATCH(ext);
145: #if defined(HAVE_MEMCACHE_H)
146: PATCH(mc);
147: #endif
148: PATCH(mc_namespace);
149: PATCH(power_magnet);
150:
151: /* skip the first, the global context */
152: for (i = 1; i < srv->config_context->used; i++) {
153: data_config *dc = (data_config *)srv->config_context->data[i];
154: s = p->config_storage[i];
155:
156: /* condition didn't match */
157: if (!config_check_cond(srv, con, dc)) continue;
158:
159: /* merge config */
160: for (j = 0; j < dc->value->used; j++) {
161: data_unset *du = dc->value->data[j];
162:
163: if (buffer_is_equal_string(du->key, CONST_STR_LEN("cml.extension"))) {
164: PATCH(ext);
165: } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("cml.memcache-hosts"))) {
166: #if defined(HAVE_MEMCACHE_H)
167: PATCH(mc);
168: #endif
169: } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("cml.memcache-namespace"))) {
170: PATCH(mc_namespace);
171: } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("cml.power-magnet"))) {
172: PATCH(power_magnet);
173: }
174: }
175: }
176:
177: return 0;
178: }
179: #undef PATCH
180:
181: static int cache_call_lua(server *srv, connection *con, plugin_data *p, buffer *cml_file) {
182: buffer *b;
183: char *c;
184:
185: /* cleanup basedir */
186: b = p->baseurl;
187: buffer_copy_string_buffer(b, con->uri.path);
188: for (c = b->ptr + b->used - 1; c > b->ptr && *c != '/'; c--);
189:
190: if (*c == '/') {
191: b->used = c - b->ptr + 2;
192: *(c+1) = '\0';
193: }
194:
195: b = p->basedir;
196: buffer_copy_string_buffer(b, con->physical.path);
197: for (c = b->ptr + b->used - 1; c > b->ptr && *c != '/'; c--);
198:
199: if (*c == '/') {
200: b->used = c - b->ptr + 2;
201: *(c+1) = '\0';
202: }
203:
204:
205: /* prepare variables
206: * - cookie-based
207: * - get-param-based
208: */
209: return cache_parse_lua(srv, con, p, cml_file);
210: }
211:
212: URIHANDLER_FUNC(mod_cml_power_magnet) {
213: plugin_data *p = p_d;
214:
215: mod_cml_patch_connection(srv, con, p);
216:
217: buffer_reset(p->basedir);
218: buffer_reset(p->baseurl);
219: buffer_reset(p->trigger_handler);
220:
221: if (buffer_is_empty(p->conf.power_magnet)) return HANDLER_GO_ON;
222:
223: /*
224: * power-magnet:
225: * cml.power-magnet = server.docroot + "/rewrite.cml"
226: *
227: * is called on EACH request, take the original REQUEST_URI and modifies the
228: * request header as neccesary.
229: *
230: * First use:
231: * if file_exists("/maintainance.html") {
232: * output_include = ( "/maintainance.html" )
233: * return CACHE_HIT
234: * }
235: *
236: * as we only want to rewrite HTML like requests we should cover it in a conditional
237: *
238: * */
239:
240: switch(cache_call_lua(srv, con, p, p->conf.power_magnet)) {
241: case -1:
242: /* error */
243: if (con->conf.log_request_handling) {
244: log_error_write(srv, __FILE__, __LINE__, "s", "cache-error");
245: }
246: con->http_status = 500;
247: return HANDLER_COMEBACK;
248: case 0:
249: if (con->conf.log_request_handling) {
250: log_error_write(srv, __FILE__, __LINE__, "s", "cache-hit");
251: }
252: /* cache-hit */
253: buffer_reset(con->physical.path);
254: return HANDLER_FINISHED;
255: case 1:
256: /* cache miss */
257: return HANDLER_GO_ON;
258: default:
259: con->http_status = 500;
260: return HANDLER_COMEBACK;
261: }
262: }
263:
264: URIHANDLER_FUNC(mod_cml_is_handled) {
265: plugin_data *p = p_d;
266:
267: if (buffer_is_empty(con->physical.path)) return HANDLER_ERROR;
268:
269: mod_cml_patch_connection(srv, con, p);
270:
271: buffer_reset(p->basedir);
272: buffer_reset(p->baseurl);
273: buffer_reset(p->trigger_handler);
274:
275: if (buffer_is_empty(p->conf.ext)) return HANDLER_GO_ON;
276:
277: if (!buffer_is_equal_right_len(con->physical.path, p->conf.ext, p->conf.ext->used - 1)) {
278: return HANDLER_GO_ON;
279: }
280:
281: switch(cache_call_lua(srv, con, p, con->physical.path)) {
282: case -1:
283: /* error */
284: if (con->conf.log_request_handling) {
285: log_error_write(srv, __FILE__, __LINE__, "s", "cache-error");
286: }
287: con->http_status = 500;
288: return HANDLER_COMEBACK;
289: case 0:
290: if (con->conf.log_request_handling) {
291: log_error_write(srv, __FILE__, __LINE__, "s", "cache-hit");
292: }
293: /* cache-hit */
294: buffer_reset(con->physical.path);
295: return HANDLER_FINISHED;
296: case 1:
297: if (con->conf.log_request_handling) {
298: log_error_write(srv, __FILE__, __LINE__, "s", "cache-miss");
299: }
300: /* cache miss */
301: return HANDLER_COMEBACK;
302: default:
303: con->http_status = 500;
304: return HANDLER_COMEBACK;
305: }
306: }
307:
308: int mod_cml_plugin_init(plugin *p);
309: int mod_cml_plugin_init(plugin *p) {
310: p->version = LIGHTTPD_VERSION_ID;
311: p->name = buffer_init_string("cache");
312:
313: p->init = mod_cml_init;
314: p->cleanup = mod_cml_free;
315: p->set_defaults = mod_cml_set_defaults;
316:
317: p->handle_subrequest_start = mod_cml_is_handled;
318: p->handle_physical = mod_cml_power_magnet;
319:
320: p->data = NULL;
321:
322: return 0;
323: }