Annotation of embedaddon/lighttpd/src/mod_cml.c, revision 1.1.1.1

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: 
                     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:                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: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>