~ubuntu-branches/ubuntu/natty/lighttpd/natty

« back to all changes in this revision

Viewing changes to src/mod_cml.c

  • Committer: Bazaar Package Importer
  • Author(s): Torsten Marek
  • Date: 2005-11-26 11:48:51 UTC
  • Revision ID: james.westby@ubuntu.com-20051126114851-76t9q0rrwbzjnt2t
Tags: upstream-1.4.8
ImportĀ upstreamĀ versionĀ 1.4.8

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#include <sys/stat.h>
 
2
#include <time.h>
 
3
 
 
4
#include <stdlib.h>
 
5
#include <string.h>
 
6
#include <errno.h>
 
7
#include <unistd.h>
 
8
#include <stdio.h>
 
9
 
 
10
#include "buffer.h"
 
11
#include "server.h"
 
12
#include "log.h"
 
13
#include "plugin.h"
 
14
#include "response.h"
 
15
 
 
16
#include "stream.h"
 
17
 
 
18
#include "mod_cml.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->session_id      = buffer_init();
 
29
        p->trigger_handler = buffer_init();
 
30
        
 
31
        return p;
 
32
}
 
33
 
 
34
/* detroy the plugin data */
 
35
FREE_FUNC(mod_cml_free) {
 
36
        plugin_data *p = p_d;
 
37
        
 
38
        UNUSED(srv);
 
39
 
 
40
        if (!p) return HANDLER_GO_ON;
 
41
        
 
42
        if (p->config_storage) {
 
43
                size_t i;
 
44
                for (i = 0; i < srv->config_context->used; i++) {
 
45
                        plugin_config *s = p->config_storage[i];
 
46
                        
 
47
                        buffer_free(s->ext);
 
48
                        
 
49
                        buffer_free(s->mc_namespace);
 
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->session_id);
 
63
        buffer_free(p->basedir);
 
64
        buffer_free(p->baseurl);
 
65
        
 
66
        free(p);
 
67
        
 
68
        return HANDLER_GO_ON;
 
69
}
 
70
 
 
71
/* handle plugin config and check values */
 
72
 
 
73
SETDEFAULTS_FUNC(mod_cml_set_defaults) {
 
74
        plugin_data *p = p_d;
 
75
        size_t i = 0;
 
76
        
 
77
        config_values_t cv[] = { 
 
78
                { "cml.extension",              NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },       /* 0 */
 
79
                { "cml.memcache-hosts",         NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION },        /* 1 */
 
80
                { "cml.memcache-namespace",     NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },       /* 2 */
 
81
                { NULL,                         NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
 
82
        };
 
83
        
 
84
        if (!p) return HANDLER_ERROR;
 
85
        
 
86
        p->config_storage = malloc(srv->config_context->used * sizeof(specific_config *));
 
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
#if defined(HAVE_MEMCACHE_H)
 
96
                s->mc = NULL;
 
97
#endif
 
98
                
 
99
                cv[0].destination = s->ext;
 
100
                cv[1].destination = s->mc_hosts;
 
101
                cv[2].destination = s->mc_namespace;
 
102
                
 
103
                p->config_storage[i] = s;
 
104
        
 
105
                if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
 
106
                        return HANDLER_ERROR;
 
107
                }
 
108
                
 
109
                if (s->mc_hosts->used) {
 
110
#if defined(HAVE_MEMCACHE_H)
 
111
                        size_t k;
 
112
                        s->mc = mc_new();
 
113
                
 
114
                        for (k = 0; k < s->mc_hosts->used; k++) {
 
115
                                data_string *ds = (data_string *)s->mc_hosts->data[k];
 
116
                                
 
117
                                if (0 != mc_server_add4(s->mc, ds->value->ptr)) {
 
118
                                        log_error_write(srv, __FILE__, __LINE__, "sb", 
 
119
                                                        "connection to host failed:", 
 
120
                                                        ds->value);
 
121
                                        
 
122
                                        return HANDLER_ERROR;
 
123
                                }
 
124
                        }
 
125
#else
 
126
                        log_error_write(srv, __FILE__, __LINE__, "s", 
 
127
                                        "memcache support is not compiled in but cml.memcache-hosts is set, aborting");
 
128
                        return HANDLER_ERROR;
 
129
#endif
 
130
                }
 
131
        }
 
132
        
 
133
        return HANDLER_GO_ON;
 
134
}
 
135
 
 
136
#define PATCH(x) \
 
137
        p->conf.x = s->x;
 
138
static int mod_cml_patch_connection(server *srv, connection *con, plugin_data *p) {
 
139
        size_t i, j;
 
140
        plugin_config *s = p->config_storage[0];
 
141
        
 
142
        PATCH(ext);
 
143
#if defined(HAVE_MEMCACHE_H)
 
144
        PATCH(mc);
 
145
#endif
 
146
        PATCH(mc_namespace);
 
147
        
 
148
        /* skip the first, the global context */
 
149
        for (i = 1; i < srv->config_context->used; i++) {
 
150
                data_config *dc = (data_config *)srv->config_context->data[i];
 
151
                s = p->config_storage[i];
 
152
                
 
153
                /* condition didn't match */
 
154
                if (!config_check_cond(srv, con, dc)) continue;
 
155
                
 
156
                /* merge config */
 
157
                for (j = 0; j < dc->value->used; j++) {
 
158
                        data_unset *du = dc->value->data[j];
 
159
                        
 
160
                        if (buffer_is_equal_string(du->key, CONST_STR_LEN("cml.extension"))) {
 
161
                                PATCH(ext);
 
162
                        } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("cml.memcache-hosts"))) {
 
163
#if defined(HAVE_MEMCACHE_H)
 
164
                                PATCH(mc);
 
165
#endif
 
166
                        } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("cml.memcache-namespace"))) {
 
167
                                PATCH(mc_namespace);
 
168
                        }
 
169
                }
 
170
        }
 
171
        
 
172
        return 0;
 
173
}
 
174
#undef PATCH
 
175
 
 
176
 
 
177
int cache_get_cookie_session_id(server *srv, connection *con, plugin_data *p) {
 
178
        data_unset *d;
 
179
 
 
180
        UNUSED(srv);
 
181
        
 
182
        if (NULL != (d = array_get_element(con->request.headers, "Cookie"))) {
 
183
                data_string *ds = (data_string *)d;
 
184
                size_t key = 0, value = 0;
 
185
                size_t is_key = 1, is_sid = 0;
 
186
                size_t i;
 
187
                
 
188
                /* found COOKIE */
 
189
                if (!DATA_IS_STRING(d)) return -1;
 
190
                if (ds->value->used == 0) return -1;
 
191
                        
 
192
                if (ds->value->ptr[0] == '\0' ||
 
193
                    ds->value->ptr[0] == '=' ||
 
194
                    ds->value->ptr[0] == ';') return -1;
 
195
                
 
196
                buffer_reset(p->session_id);
 
197
                for (i = 0; i < ds->value->used; i++) {
 
198
                        switch(ds->value->ptr[i]) {
 
199
                        case '=':
 
200
                                if (is_key) {
 
201
                                        if (0 == strncmp(ds->value->ptr + key, "PHPSESSID", i - key)) {
 
202
                                                /* found PHP-session-id-key */
 
203
                                                is_sid = 1;
 
204
                                        }
 
205
                                        value = i + 1;
 
206
                                
 
207
                                        is_key = 0;
 
208
                                }
 
209
                                
 
210
                                break;
 
211
                        case ';':
 
212
                                if (is_sid) {
 
213
                                        buffer_copy_string_len(p->session_id, ds->value->ptr + value, i - value);
 
214
                                }
 
215
                                
 
216
                                is_sid = 0;
 
217
                                key = i + 1;
 
218
                                value = 0;
 
219
                                is_key = 1;
 
220
                                break;
 
221
                        case ' ':
 
222
                                if (is_key == 1 && key == i) key = i + 1;
 
223
                                if (is_key == 0 && value == i) value = i + 1;
 
224
                                break;
 
225
                        case '\0':
 
226
                                if (is_sid) {
 
227
                                        buffer_copy_string_len(p->session_id, ds->value->ptr + value, i - value);
 
228
                                }
 
229
                                /* fin */
 
230
                                break;
 
231
                        }
 
232
                }
 
233
        }
 
234
        
 
235
        return !buffer_is_empty(p->session_id);
 
236
}
 
237
 
 
238
int cache_get_url_session_id(server *srv, connection *con, plugin_data *p) {
 
239
        size_t key = 0, value = 0;
 
240
        size_t is_key = 1, is_sid = 0;
 
241
        size_t i;
 
242
        
 
243
        UNUSED(srv);
 
244
        buffer_reset(p->session_id);
 
245
        for (i = 0; i < con->uri.query->used; i++) {
 
246
                switch(con->uri.query->ptr[i]) {
 
247
                case '=':
 
248
                        if (is_key) {
 
249
                                if (0 == strncmp(con->uri.query->ptr + key, "PHPSESSID", i - key)) {
 
250
                                        /* found PHP-session-id-key */
 
251
                                                is_sid = 1;
 
252
                                }
 
253
                                value = i + 1;
 
254
                                
 
255
                                is_key = 0;
 
256
                        }
 
257
                        
 
258
                        break;
 
259
                case '&':
 
260
                        if (is_sid) {
 
261
                                buffer_copy_string_len(p->session_id, con->uri.query->ptr + value, i - value);
 
262
                        }
 
263
                        
 
264
                        is_sid = 0;
 
265
                        key = i + 1;
 
266
                        value = 0;
 
267
                        is_key = 1;
 
268
                        break;
 
269
                case ' ':
 
270
                        if (is_key == 1 && key == i) key = i + 1;
 
271
                        if (is_key == 0 && value == i) value = i + 1;
 
272
                        break;
 
273
                case '\0':
 
274
                        if (is_sid) {
 
275
                                buffer_copy_string_len(p->session_id, con->uri.query->ptr + value, i - value);
 
276
                        }
 
277
                        /* fin */
 
278
                        break;
 
279
                }
 
280
        }
 
281
 
 
282
        return !buffer_is_empty(p->session_id);
 
283
}
 
284
 
 
285
int cache_get_session_id(server *srv, connection *con, plugin_data *p) {
 
286
        
 
287
        return cache_get_cookie_session_id(srv, con, p) || 
 
288
                cache_get_url_session_id(srv, con, p);
 
289
        
 
290
}
 
291
 
 
292
 
 
293
URIHANDLER_FUNC(mod_cml_is_handled) {
 
294
        int ct_len, s_len;
 
295
        buffer *b;
 
296
        char *c;
 
297
        buffer *fn = con->physical.path;
 
298
        plugin_data *p = p_d;
 
299
        int ret;
 
300
        
 
301
        if (fn->used == 0) return HANDLER_ERROR;
 
302
        
 
303
        mod_cml_patch_connection(srv, con, p);
 
304
        
 
305
        buffer_reset(p->basedir);
 
306
        buffer_reset(p->baseurl);
 
307
        buffer_reset(p->session_id);
 
308
        buffer_reset(p->trigger_handler);
 
309
        
 
310
        if (buffer_is_empty(p->conf.ext)) return HANDLER_GO_ON;
 
311
        
 
312
        ct_len = p->conf.ext->used - 1;
 
313
        s_len = fn->used - 1;
 
314
        
 
315
        if (s_len < ct_len) return HANDLER_GO_ON;
 
316
        
 
317
        if (0 != strncmp(fn->ptr + s_len - ct_len, p->conf.ext->ptr, ct_len)) {
 
318
                /* not my job */
 
319
                return HANDLER_GO_ON;
 
320
        }
 
321
        
 
322
        /* cleanup basedir */
 
323
        b = p->baseurl;
 
324
        buffer_copy_string_buffer(b, con->uri.path);
 
325
        for (c = b->ptr + b->used - 1; c > b->ptr && *c != '/'; c--);
 
326
        
 
327
        if (*c == '/') {
 
328
                b->used = c - b->ptr + 2;
 
329
                *(c+1) = '\0';
 
330
        }
 
331
        
 
332
        b = p->basedir;
 
333
        buffer_copy_string_buffer(b, fn);
 
334
        for (c = b->ptr + b->used - 1; c > b->ptr && *c != '/'; c--);
 
335
        
 
336
        if (*c == '/') {
 
337
                b->used = c - b->ptr + 2;
 
338
                *(c+1) = '\0';
 
339
        }
 
340
        
 
341
        /* prepare variables
 
342
         * - session-id
 
343
         *   - cookie-based
 
344
         *   - get-param-based
 
345
         */
 
346
        
 
347
        cache_get_session_id(srv, con, p);
 
348
        
 
349
        ret = cache_parse_lua(srv, con, p, fn);
 
350
        
 
351
        switch(ret) {
 
352
        case -1:
 
353
                /* error */
 
354
                if (con->conf.log_request_handling) {
 
355
                        log_error_write(srv, __FILE__, __LINE__, "s", "cache-error");
 
356
                }
 
357
                con->http_status = 500;
 
358
                return HANDLER_COMEBACK;
 
359
        case 0:
 
360
                if (con->conf.log_request_handling) {
 
361
                        log_error_write(srv, __FILE__, __LINE__, "s", "cache-hit");
 
362
                }
 
363
                /* cache-hit */
 
364
                buffer_reset(con->physical.path);
 
365
                return HANDLER_FINISHED;
 
366
        case 1:
 
367
                if (con->conf.log_request_handling) {
 
368
                        log_error_write(srv, __FILE__, __LINE__, "s", "cache-miss");
 
369
                }
 
370
                /* cache miss */
 
371
                return HANDLER_COMEBACK;
 
372
        }
 
373
        
 
374
        return 0;
 
375
}
 
376
 
 
377
int mod_cml_plugin_init(plugin *p) {
 
378
        p->version     = LIGHTTPD_VERSION_ID;
 
379
        p->name        = buffer_init_string("cache");
 
380
        
 
381
        p->init        = mod_cml_init;
 
382
        p->cleanup     = mod_cml_free;
 
383
        p->set_defaults  = mod_cml_set_defaults;
 
384
        
 
385
        p->handle_subrequest_start = mod_cml_is_handled;
 
386
        
 
387
        p->data        = NULL;
 
388
        
 
389
        return 0;
 
390
}