20
/* init the plugin data */
21
INIT_FUNC(mod_cml_init) {
24
p = calloc(1, sizeof(*p));
26
p->basedir = buffer_init();
27
p->baseurl = buffer_init();
28
p->session_id = buffer_init();
29
p->trigger_handler = buffer_init();
34
/* detroy the plugin data */
35
FREE_FUNC(mod_cml_free) {
40
if (!p) return HANDLER_GO_ON;
42
if (p->config_storage) {
44
for (i = 0; i < srv->config_context->used; i++) {
45
plugin_config *s = p->config_storage[i];
49
buffer_free(s->mc_namespace);
50
array_free(s->mc_hosts);
52
#if defined(HAVE_MEMCACHE_H)
53
if (s->mc) mc_free(s->mc);
58
free(p->config_storage);
61
buffer_free(p->trigger_handler);
62
buffer_free(p->session_id);
63
buffer_free(p->basedir);
64
buffer_free(p->baseurl);
71
/* handle plugin config and check values */
73
SETDEFAULTS_FUNC(mod_cml_set_defaults) {
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 }
84
if (!p) return HANDLER_ERROR;
86
p->config_storage = malloc(srv->config_context->used * sizeof(specific_config *));
88
for (i = 0; i < srv->config_context->used; i++) {
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)
99
cv[0].destination = s->ext;
100
cv[1].destination = s->mc_hosts;
101
cv[2].destination = s->mc_namespace;
103
p->config_storage[i] = s;
105
if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
106
return HANDLER_ERROR;
109
if (s->mc_hosts->used) {
110
#if defined(HAVE_MEMCACHE_H)
114
for (k = 0; k < s->mc_hosts->used; k++) {
115
data_string *ds = (data_string *)s->mc_hosts->data[k];
117
if (0 != mc_server_add4(s->mc, ds->value->ptr)) {
118
log_error_write(srv, __FILE__, __LINE__, "sb",
119
"connection to host failed:",
122
return HANDLER_ERROR;
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;
133
return HANDLER_GO_ON;
138
static int mod_cml_patch_connection(server *srv, connection *con, plugin_data *p) {
140
plugin_config *s = p->config_storage[0];
143
#if defined(HAVE_MEMCACHE_H)
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];
153
/* condition didn't match */
154
if (!config_check_cond(srv, con, dc)) continue;
157
for (j = 0; j < dc->value->used; j++) {
158
data_unset *du = dc->value->data[j];
160
if (buffer_is_equal_string(du->key, CONST_STR_LEN("cml.extension"))) {
162
} else if (buffer_is_equal_string(du->key, CONST_STR_LEN("cml.memcache-hosts"))) {
163
#if defined(HAVE_MEMCACHE_H)
166
} else if (buffer_is_equal_string(du->key, CONST_STR_LEN("cml.memcache-namespace"))) {
177
int cache_get_cookie_session_id(server *srv, connection *con, plugin_data *p) {
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;
189
if (!DATA_IS_STRING(d)) return -1;
190
if (ds->value->used == 0) return -1;
192
if (ds->value->ptr[0] == '\0' ||
193
ds->value->ptr[0] == '=' ||
194
ds->value->ptr[0] == ';') return -1;
196
buffer_reset(p->session_id);
197
for (i = 0; i < ds->value->used; i++) {
198
switch(ds->value->ptr[i]) {
201
if (0 == strncmp(ds->value->ptr + key, "PHPSESSID", i - key)) {
202
/* found PHP-session-id-key */
213
buffer_copy_string_len(p->session_id, ds->value->ptr + value, i - value);
222
if (is_key == 1 && key == i) key = i + 1;
223
if (is_key == 0 && value == i) value = i + 1;
227
buffer_copy_string_len(p->session_id, ds->value->ptr + value, i - value);
235
return !buffer_is_empty(p->session_id);
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;
244
buffer_reset(p->session_id);
245
for (i = 0; i < con->uri.query->used; i++) {
246
switch(con->uri.query->ptr[i]) {
249
if (0 == strncmp(con->uri.query->ptr + key, "PHPSESSID", i - key)) {
250
/* found PHP-session-id-key */
261
buffer_copy_string_len(p->session_id, con->uri.query->ptr + value, i - value);
270
if (is_key == 1 && key == i) key = i + 1;
271
if (is_key == 0 && value == i) value = i + 1;
275
buffer_copy_string_len(p->session_id, con->uri.query->ptr + value, i - value);
282
return !buffer_is_empty(p->session_id);
285
int cache_get_session_id(server *srv, connection *con, plugin_data *p) {
287
return cache_get_cookie_session_id(srv, con, p) ||
288
cache_get_url_session_id(srv, con, p);
293
URIHANDLER_FUNC(mod_cml_is_handled) {
297
buffer *fn = con->physical.path;
298
plugin_data *p = p_d;
301
if (fn->used == 0) return HANDLER_ERROR;
303
mod_cml_patch_connection(srv, con, p);
305
buffer_reset(p->basedir);
306
buffer_reset(p->baseurl);
307
buffer_reset(p->session_id);
308
buffer_reset(p->trigger_handler);
310
if (buffer_is_empty(p->conf.ext)) return HANDLER_GO_ON;
312
ct_len = p->conf.ext->used - 1;
313
s_len = fn->used - 1;
315
if (s_len < ct_len) return HANDLER_GO_ON;
317
if (0 != strncmp(fn->ptr + s_len - ct_len, p->conf.ext->ptr, ct_len)) {
319
return HANDLER_GO_ON;
322
/* cleanup basedir */
324
buffer_copy_string_buffer(b, con->uri.path);
325
for (c = b->ptr + b->used - 1; c > b->ptr && *c != '/'; c--);
328
b->used = c - b->ptr + 2;
333
buffer_copy_string_buffer(b, fn);
334
for (c = b->ptr + b->used - 1; c > b->ptr && *c != '/'; c--);
337
b->used = c - b->ptr + 2;
347
cache_get_session_id(srv, con, p);
349
ret = cache_parse_lua(srv, con, p, fn);
354
if (con->conf.log_request_handling) {
355
log_error_write(srv, __FILE__, __LINE__, "s", "cache-error");
357
con->http_status = 500;
358
return HANDLER_COMEBACK;
360
if (con->conf.log_request_handling) {
361
log_error_write(srv, __FILE__, __LINE__, "s", "cache-hit");
364
buffer_reset(con->physical.path);
365
return HANDLER_FINISHED;
367
if (con->conf.log_request_handling) {
368
log_error_write(srv, __FILE__, __LINE__, "s", "cache-miss");
371
return HANDLER_COMEBACK;
377
int mod_cml_plugin_init(plugin *p) {
378
p->version = LIGHTTPD_VERSION_ID;
379
p->name = buffer_init_string("cache");
381
p->init = mod_cml_init;
382
p->cleanup = mod_cml_free;
383
p->set_defaults = mod_cml_set_defaults;
385
p->handle_subrequest_start = mod_cml_is_handled;