summaryrefslogtreecommitdiff
path: root/src/mod_cml.c
diff options
context:
space:
mode:
authorJan Kneschke <jan@kneschke.de>2005-07-06 11:58:19 +0000
committerJan Kneschke <jan@kneschke.de>2005-07-06 11:58:19 +0000
commit81368ccd4e7c2cf535254d793d7e99d22d97df46 (patch)
tree89ec82d2f97d1fcef84ae128357ff9e5f56cd748 /src/mod_cml.c
parent288b0b51e7cb9f68d3c20605b2a05978fe42dee2 (diff)
downloadlighttpd-git-81368ccd4e7c2cf535254d793d7e99d22d97df46.tar.gz
added mod_cml (Cache Meta Language)
git-svn-id: svn://svn.lighttpd.net/lighttpd/branches/lighttpd-1.3.x@421 152afb58-edef-0310-8abb-c4023f1b3aa9
Diffstat (limited to 'src/mod_cml.c')
-rw-r--r--src/mod_cml.c329
1 files changed, 329 insertions, 0 deletions
diff --git a/src/mod_cml.c b/src/mod_cml.c
new file mode 100644
index 00000000..1ebf6b50
--- /dev/null
+++ b/src/mod_cml.c
@@ -0,0 +1,329 @@
+#include <sys/stat.h>
+#include <time.h>
+
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stdio.h>
+
+#include "buffer.h"
+#include "server.h"
+#include "log.h"
+#include "plugin.h"
+#include "response.h"
+
+#include "stream.h"
+
+#include "mod_cml.h"
+
+/* init the plugin data */
+INIT_FUNC(mod_cache_init) {
+ plugin_data *p;
+
+ p = calloc(1, sizeof(*p));
+
+ p->basedir = buffer_init();
+
+ return p;
+}
+
+/* detroy the plugin data */
+FREE_FUNC(mod_cache_free) {
+ plugin_data *p = p_d;
+
+ UNUSED(srv);
+
+ if (!p) return HANDLER_GO_ON;
+
+ if (p->config_storage) {
+ size_t i;
+ for (i = 0; i < srv->config_context->used; i++) {
+ plugin_config *s = p->config_storage[i];
+
+ buffer_free(s->ext);
+
+ free(s);
+ }
+ free(p->config_storage);
+ }
+
+ buffer_free(p->basedir);
+
+ free(p);
+
+ return HANDLER_GO_ON;
+}
+
+/* handle plugin config and check values */
+
+SETDEFAULTS_FUNC(mod_cache_set_defaults) {
+ plugin_data *p = p_d;
+ size_t i = 0;
+
+ config_values_t cv[] = {
+ { "cache.extension", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
+ { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
+ };
+
+ if (!p) return HANDLER_ERROR;
+
+ p->config_storage = malloc(srv->config_context->used * sizeof(specific_config *));
+
+ for (i = 0; i < srv->config_context->used; i++) {
+ plugin_config *s;
+
+ s = malloc(sizeof(plugin_config));
+ s->ext = buffer_init();
+
+ cv[0].destination = s->ext;
+
+ p->config_storage[i] = s;
+
+ if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
+ return HANDLER_ERROR;
+ }
+ }
+
+ return HANDLER_GO_ON;
+}
+
+#define PATCH(x) \
+ p->conf.x = s->x;
+static int mod_cache_patch_connection(server *srv, connection *con, plugin_data *p, const char *stage, size_t stage_len) {
+ size_t i, j;
+
+ /* skip the first, the global context */
+ for (i = 1; i < srv->config_context->used; i++) {
+ data_config *dc = (data_config *)srv->config_context->data[i];
+ plugin_config *s = p->config_storage[i];
+
+ /* not our stage */
+ if (!buffer_is_equal_string(dc->comp_key, stage, stage_len)) continue;
+
+ /* condition didn't match */
+ if (!config_check_cond(srv, con, dc)) continue;
+
+ /* merge config */
+ for (j = 0; j < dc->value->used; j++) {
+ data_unset *du = dc->value->data[j];
+
+ if (buffer_is_equal_string(du->key, CONST_STR_LEN("cache.extension"))) {
+ PATCH(ext);
+ }
+ }
+ }
+
+ return 0;
+}
+
+static int mod_cache_setup_connection(server *srv, connection *con, plugin_data *p) {
+ plugin_config *s = p->config_storage[0];
+ UNUSED(srv);
+ UNUSED(con);
+
+ PATCH(ext);
+
+ return 0;
+}
+#undef PATCH
+
+
+int cache_get_cookie_session_id(server *srv, connection *con, plugin_data *p) {
+ data_unset *d;
+
+ if (NULL != (d = array_get_element(con->request.headers, "Cookie"))) {
+ data_string *ds = (data_string *)d;
+ size_t key = 0, value = 0;
+ size_t is_key = 1, is_sid = 0;
+ size_t i;
+
+ /* found COOKIE */
+ if (!DATA_IS_STRING(d)) return -1;
+ if (ds->value->used == 0) return -1;
+
+ if (ds->value->ptr[0] == '\0' ||
+ ds->value->ptr[0] == '=' ||
+ ds->value->ptr[0] == ';') return -1;
+
+ buffer_reset(p->session_id);
+ for (i = 0; i < ds->value->used; i++) {
+ switch(ds->value->ptr[i]) {
+ case '=':
+ if (is_key) {
+ if (0 == strncmp(ds->value->ptr + key, "PHPSESSID", i - key)) {
+ /* found PHP-session-id-key */
+ is_sid = 1;
+ }
+ value = i + 1;
+
+ is_key = 0;
+ }
+
+ break;
+ case ';':
+ if (is_sid) {
+ buffer_copy_string_len(p->session_id, ds->value->ptr + value, i - value);
+ }
+
+ is_sid = 0;
+ key = i + 1;
+ value = 0;
+ is_key = 1;
+ break;
+ case ' ':
+ if (is_key == 1 && key == i) key = i + 1;
+ if (is_key == 0 && value == i) value = i + 1;
+ break;
+ case '\0':
+ if (is_sid) {
+ buffer_copy_string_len(p->session_id, ds->value->ptr + value, i - value);
+ }
+ /* fin */
+ break;
+ }
+ }
+
+ if (!buffer_is_empty(p->session_id)) {
+ log_error_write(srv, __FILE__, __LINE__, "sb",
+ "Session-ID", p->session_id);
+ }
+ }
+
+ return !buffer_is_empty(p->session_id);
+}
+
+int cache_get_url_session_id(server *srv, connection *con, plugin_data *p) {
+ size_t key = 0, value = 0;
+ size_t is_key = 1, is_sid = 0;
+ size_t i;
+
+ buffer_reset(p->session_id);
+ for (i = 0; i < con->uri.query->used; i++) {
+ switch(con->uri.query->ptr[i]) {
+ case '=':
+ if (is_key) {
+ if (0 == strncmp(con->uri.query->ptr + key, "PHPSESSID", i - key)) {
+ /* found PHP-session-id-key */
+ is_sid = 1;
+ }
+ value = i + 1;
+
+ is_key = 0;
+ }
+
+ break;
+ case '&':
+ if (is_sid) {
+ buffer_copy_string_len(p->session_id, con->uri.query->ptr + value, i - value);
+ }
+
+ is_sid = 0;
+ key = i + 1;
+ value = 0;
+ is_key = 1;
+ break;
+ case ' ':
+ if (is_key == 1 && key == i) key = i + 1;
+ if (is_key == 0 && value == i) value = i + 1;
+ break;
+ case '\0':
+ if (is_sid) {
+ buffer_copy_string_len(p->session_id, con->uri.query->ptr + value, i - value);
+ }
+ /* fin */
+ break;
+ }
+ }
+
+ if (!buffer_is_empty(p->session_id)) {
+ log_error_write(srv, __FILE__, __LINE__, "sb",
+ "Session-ID", p->session_id);
+ }
+
+ return !buffer_is_empty(p->session_id);
+}
+
+int cache_get_session_id(server *srv, connection *con, plugin_data *p) {
+
+ return cache_get_cookie_session_id(srv, con, p) ||
+ cache_get_url_session_id(srv, con, p);
+
+}
+
+
+URIHANDLER_FUNC(mod_cache_is_handled) {
+ int ct_len, s_len;
+ buffer *b;
+ char *c;
+ buffer *fn = con->physical.path;
+ plugin_data *p = p_d;
+ size_t i;
+
+ if (fn->used == 0) return HANDLER_ERROR;
+
+ mod_cache_setup_connection(srv, con, p);
+ for (i = 0; i < srv->config_patches->used; i++) {
+ buffer *patch = srv->config_patches->ptr[i];
+
+ mod_cache_patch_connection(srv, con, p, CONST_BUF_LEN(patch));
+ }
+
+ if (buffer_is_empty(p->conf.ext)) return HANDLER_GO_ON;
+
+ ct_len = p->conf.ext->used - 1;
+ s_len = fn->used - 1;
+
+ if (s_len < ct_len) return HANDLER_GO_ON;
+
+ if (0 != strncmp(fn->ptr + s_len - ct_len, p->conf.ext->ptr, ct_len)) {
+ /* not my job */
+ return HANDLER_GO_ON;
+ }
+
+ /* cleanup basedir */
+ b = p->basedir;
+ buffer_copy_string_buffer(b, fn);
+ for (c = b->ptr + b->used - 1; c > b->ptr && *c != '/'; c--);
+
+ if (*c == '/') {
+ b->used = c - b->ptr + 2;
+ *(c+1) = '\0';
+ }
+
+ /* prepare variables
+ * - session-id
+ * - cookie-based
+ * - get-param-based
+ */
+
+ cache_get_session_id(srv, con, p);
+
+ switch(cache_parse(srv, con, p, fn)) {
+ case -1:
+ con->http_status = 500;
+ return HANDLER_COMEBACK;
+ case 0:
+ buffer_reset(con->physical.path);
+ return HANDLER_FINISHED;
+ case 1:
+ return HANDLER_COMEBACK;
+ }
+
+ return 0;
+}
+
+int mod_cache_plugin_init(plugin *p) {
+ p->version = LIGHTTPD_VERSION_ID;
+ p->name = buffer_init_string("cache");
+
+ p->init = mod_cache_init;
+ p->cleanup = mod_cache_free;
+ p->set_defaults = mod_cache_set_defaults;
+
+ p->handle_subrequest_start = mod_cache_is_handled;
+
+ p->data = NULL;
+
+ return 0;
+}