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

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

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