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

1.1.1.3 ! misho       1: #include "first.h"
        !             2: 
1.1       misho       3: #include "base.h"
                      4: #include "log.h"
                      5: #include "buffer.h"
1.1.1.3 ! misho       6: #include "http_chunk.h"
1.1       misho       7: 
                      8: #include "plugin.h"
                      9: 
                     10: #include "mod_magnet_cache.h"
                     11: #include "response.h"
                     12: #include "stat_cache.h"
                     13: #include "status_counter.h"
                     14: #include "etag.h"
                     15: 
                     16: #include <ctype.h>
                     17: #include <stdlib.h>
                     18: #include <string.h>
                     19: #include <assert.h>
                     20: #include <setjmp.h>
                     21: 
                     22: #ifdef HAVE_LUA_H
                     23: #include <lua.h>
                     24: #include <lauxlib.h>
                     25: 
1.1.1.3 ! misho      26: #define LUA_RIDX_LIGHTTPD_SERVER     "lighty.srv"
        !            27: #define LUA_RIDX_LIGHTTPD_CONNECTION "lighty.con"
        !            28: 
1.1       misho      29: #define MAGNET_CONFIG_RAW_URL       "magnet.attract-raw-url-to"
                     30: #define MAGNET_CONFIG_PHYSICAL_PATH "magnet.attract-physical-path-to"
                     31: #define MAGNET_RESTART_REQUEST      99
                     32: 
                     33: /* plugin config for all request/connections */
                     34: 
                     35: static jmp_buf exceptionjmp;
                     36: 
                     37: typedef struct {
                     38:        array *url_raw;
                     39:        array *physical_path;
                     40: } plugin_config;
                     41: 
                     42: typedef struct {
                     43:        PLUGIN_DATA;
                     44: 
                     45:        script_cache *cache;
                     46: 
                     47:        buffer *encode_buf;
                     48: 
                     49:        plugin_config **config_storage;
                     50: 
                     51:        plugin_config conf;
                     52: } plugin_data;
                     53: 
                     54: /* init the plugin data */
                     55: INIT_FUNC(mod_magnet_init) {
                     56:        plugin_data *p;
                     57: 
                     58:        p = calloc(1, sizeof(*p));
                     59: 
                     60:        p->cache = script_cache_init();
                     61:        p->encode_buf = buffer_init();
                     62: 
                     63:        return p;
                     64: }
                     65: 
                     66: /* detroy the plugin data */
                     67: FREE_FUNC(mod_magnet_free) {
                     68:        plugin_data *p = p_d;
                     69: 
                     70:        UNUSED(srv);
                     71: 
                     72:        if (!p) return HANDLER_GO_ON;
                     73: 
                     74:        if (p->config_storage) {
                     75:                size_t i;
                     76: 
                     77:                for (i = 0; i < srv->config_context->used; i++) {
                     78:                        plugin_config *s = p->config_storage[i];
                     79: 
1.1.1.3 ! misho      80:                        if (NULL == s) continue;
1.1       misho      81: 
                     82:                        array_free(s->url_raw);
                     83:                        array_free(s->physical_path);
                     84: 
                     85:                        free(s);
                     86:                }
                     87:                free(p->config_storage);
                     88:        }
                     89: 
                     90:        script_cache_free(p->cache);
                     91:        buffer_free(p->encode_buf);
                     92: 
                     93:        free(p);
                     94: 
                     95:        return HANDLER_GO_ON;
                     96: }
                     97: 
                     98: /* handle plugin config and check values */
                     99: 
                    100: SETDEFAULTS_FUNC(mod_magnet_set_defaults) {
                    101:        plugin_data *p = p_d;
                    102:        size_t i = 0;
                    103: 
                    104:        config_values_t cv[] = {
                    105:                { MAGNET_CONFIG_RAW_URL,       NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION },       /* 0 */
                    106:                { MAGNET_CONFIG_PHYSICAL_PATH, NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION },       /* 1 */
                    107:                { NULL,                           NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
                    108:        };
                    109: 
                    110:        if (!p) return HANDLER_ERROR;
                    111: 
1.1.1.2   misho     112:        p->config_storage = calloc(1, srv->config_context->used * sizeof(plugin_config *));
1.1       misho     113: 
                    114:        for (i = 0; i < srv->config_context->used; i++) {
1.1.1.3 ! misho     115:                data_config const* config = (data_config const*)srv->config_context->data[i];
1.1       misho     116:                plugin_config *s;
                    117: 
                    118:                s = calloc(1, sizeof(plugin_config));
                    119:                s->url_raw  = array_init();
                    120:                s->physical_path = array_init();
                    121: 
                    122:                cv[0].destination = s->url_raw;
                    123:                cv[1].destination = s->physical_path;
                    124: 
                    125:                p->config_storage[i] = s;
                    126: 
1.1.1.3 ! misho     127:                if (0 != config_insert_values_global(srv, config->value, cv, i == 0 ? T_CONFIG_SCOPE_SERVER : T_CONFIG_SCOPE_CONNECTION)) {
1.1       misho     128:                        return HANDLER_ERROR;
                    129:                }
                    130:        }
                    131: 
                    132:        return HANDLER_GO_ON;
                    133: }
                    134: 
                    135: #define PATCH(x) \
                    136:        p->conf.x = s->x;
                    137: static int mod_magnet_patch_connection(server *srv, connection *con, plugin_data *p) {
                    138:        size_t i, j;
                    139:        plugin_config *s = p->config_storage[0];
                    140: 
                    141:        PATCH(url_raw);
                    142:        PATCH(physical_path);
                    143: 
                    144:        /* skip the first, the global context */
                    145:        for (i = 1; i < srv->config_context->used; i++) {
                    146:                data_config *dc = (data_config *)srv->config_context->data[i];
                    147:                s = p->config_storage[i];
                    148: 
                    149:                /* condition didn't match */
                    150:                if (!config_check_cond(srv, con, dc)) continue;
                    151: 
                    152:                /* merge config */
                    153:                for (j = 0; j < dc->value->used; j++) {
                    154:                        data_unset *du = dc->value->data[j];
                    155: 
                    156:                        if (buffer_is_equal_string(du->key, CONST_STR_LEN(MAGNET_CONFIG_RAW_URL))) {
                    157:                                PATCH(url_raw);
                    158:                        } else if (buffer_is_equal_string(du->key, CONST_STR_LEN(MAGNET_CONFIG_PHYSICAL_PATH))) {
                    159:                                PATCH(physical_path);
                    160:                        }
                    161:                }
                    162:        }
                    163: 
                    164:        return 0;
                    165: }
                    166: #undef PATCH
                    167: 
1.1.1.3 ! misho     168: #if !defined(LUA_VERSION_NUM) || LUA_VERSION_NUM < 502
        !           169: /* lua5.1 backward compat definition */
        !           170: static void lua_pushglobaltable(lua_State *L) { /* (-0, +1, -) */
        !           171:        lua_pushvalue(L, LUA_GLOBALSINDEX);
        !           172: }
        !           173: #endif
        !           174: 
        !           175: static void magnet_setfenv_mainfn(lua_State *L, int funcIndex) { /* (-1, 0, -) */
        !           176: #if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM >= 502
        !           177:        /* set "_ENV" upvalue, which should be the first upvalue of a "main" lua
        !           178:         * function if it uses any global names
        !           179:         */
        !           180: 
        !           181:        const char* first_upvalue_name = lua_getupvalue(L, funcIndex, 1);
        !           182:        if (NULL == first_upvalue_name) return; /* doesn't have any upvalues */
        !           183:        lua_pop(L, 1); /* only need the name of the upvalue, not the value */
        !           184: 
        !           185:        if (0 != strcmp(first_upvalue_name, "_ENV")) return;
        !           186: 
        !           187:        if (NULL == lua_setupvalue(L, funcIndex, 1)) {
        !           188:                /* pop value if lua_setupvalue didn't set the (not existing) upvalue */
        !           189:                lua_pop(L, 1);
        !           190:        }
        !           191: #else
        !           192:        lua_setfenv(L, funcIndex);
        !           193: #endif
        !           194: }
        !           195: 
        !           196: #if !defined(LUA_VERSION_NUM) || LUA_VERSION_NUM < 502
        !           197: /* lua 5.2 already supports __pairs */
1.1       misho     198: 
1.1.1.3 ! misho     199: /* See http://lua-users.org/wiki/GeneralizedPairsAndIpairs for implementation details.
        !           200:  * Override the default pairs() function to allow us to use a __pairs metakey
        !           201:  */
1.1       misho     202: static int magnet_pairs(lua_State *L) {
1.1.1.3 ! misho     203:        luaL_checkany(L, 1); /* "self" */
1.1       misho     204: 
                    205:        if (luaL_getmetafield(L, 1, "__pairs")) {
1.1.1.3 ! misho     206:                /* call __pairs(self) */
        !           207:                lua_pushvalue(L, 1);
        !           208:                lua_call(L, 1, 3);
1.1       misho     209:        } else {
1.1.1.3 ! misho     210:                /* call <original-pairs-method>(self) */
1.1       misho     211:                lua_pushvalue(L, lua_upvalueindex(1));
1.1.1.3 ! misho     212:                lua_pushvalue(L, 1);
        !           213:                lua_call(L, 1, 3);
1.1       misho     214:        }
1.1.1.3 ! misho     215:        return 3;
1.1       misho     216: }
1.1.1.3 ! misho     217: #endif
1.1       misho     218: 
                    219: /* Define a function that will iterate over an array* (in upval 1) using current position (upval 2) */
                    220: static int magnet_array_next(lua_State *L) {
                    221:        data_unset *du;
                    222:        data_string *ds;
                    223:        data_integer *di;
                    224: 
                    225:        size_t pos = lua_tointeger(L, lua_upvalueindex(1));
                    226:        array *a = lua_touserdata(L, lua_upvalueindex(2));
                    227: 
                    228:        lua_settop(L, 0);
                    229: 
                    230:        if (pos >= a->used) return 0;
                    231:        if (NULL != (du = a->data[pos])) {
1.1.1.3 ! misho     232:                lua_pushlstring(L, CONST_BUF_LEN(du->key));
1.1       misho     233:                switch (du->type) {
                    234:                        case TYPE_STRING:
                    235:                                ds = (data_string *)du;
1.1.1.3 ! misho     236:                                if (!buffer_is_empty(ds->value)) {
        !           237:                                        lua_pushlstring(L, CONST_BUF_LEN(ds->value));
1.1       misho     238:                                } else {
                    239:                                        lua_pushnil(L);
                    240:                                }
                    241:                                break;
                    242:                        case TYPE_COUNT:
                    243:                        case TYPE_INTEGER:
                    244:                                di = (data_integer *)du;
                    245:                                lua_pushinteger(L, di->value);
                    246:                                break;
                    247:                        default:
                    248:                                lua_pushnil(L);
                    249:                                break;
                    250:                }
                    251: 
                    252:                /* Update our positional upval to reflect our new current position */
                    253:                pos++;
                    254:                lua_pushinteger(L, pos);
                    255:                lua_replace(L, lua_upvalueindex(1));
                    256: 
                    257:                /* Returning 2 items on the stack (key, value) */
                    258:                return 2;
                    259:        }
                    260:        return 0;
                    261: }
                    262: 
                    263: /* Create the closure necessary to iterate over the array *a with the above function */
                    264: static int magnet_array_pairs(lua_State *L, array *a) {
                    265:        lua_pushinteger(L, 0); /* Push our current pos (the start) into upval 1 */
                    266:        lua_pushlightuserdata(L, a); /* Push our array *a into upval 2 */
                    267:        lua_pushcclosure(L, magnet_array_next, 2); /* Push our new closure with 2 upvals */
                    268:        return 1;
                    269: }
                    270: 
1.1.1.3 ! misho     271: static server* magnet_get_server(lua_State *L) {
1.1       misho     272:        server *srv;
                    273: 
1.1.1.3 ! misho     274:        lua_getfield(L, LUA_REGISTRYINDEX, LUA_RIDX_LIGHTTPD_SERVER);
1.1       misho     275:        srv = lua_touserdata(L, -1);
                    276:        lua_pop(L, 1);
                    277: 
1.1.1.3 ! misho     278:        return srv;
        !           279: }
        !           280: 
        !           281: static connection* magnet_get_connection(lua_State *L) {
        !           282:        connection *con;
        !           283: 
        !           284:        lua_getfield(L, LUA_REGISTRYINDEX, LUA_RIDX_LIGHTTPD_CONNECTION);
        !           285:        con = lua_touserdata(L, -1);
        !           286:        lua_pop(L, 1);
        !           287: 
        !           288:        return con;
        !           289: }
        !           290: 
        !           291: typedef struct {
        !           292:        const char *ptr;
        !           293:        size_t len;
        !           294: } const_buffer;
        !           295: 
        !           296: static const_buffer magnet_checkconstbuffer(lua_State *L, int index) {
        !           297:        const_buffer cb;
        !           298:        cb.ptr = luaL_checklstring(L, index, &cb.len);
        !           299:        return cb;
        !           300: }
        !           301: 
        !           302: static buffer* magnet_checkbuffer(lua_State *L, int index) {
        !           303:        const_buffer cb = magnet_checkconstbuffer(L, index);
        !           304:        buffer *b = buffer_init();
        !           305:        buffer_copy_string_len(b, cb.ptr, cb.len);
        !           306:        return b;
        !           307: }
        !           308: 
        !           309: static int magnet_print(lua_State *L) {
        !           310:        buffer *b = magnet_checkbuffer(L, 1);
        !           311: 
        !           312:        log_error_write(magnet_get_server(L), __FILE__, __LINE__, "sB",
        !           313:                "(lua-print)",
        !           314:                b);
        !           315: 
        !           316:        buffer_free(b);
1.1       misho     317: 
                    318:        return 0;
                    319: }
                    320: 
                    321: static int magnet_stat(lua_State *L) {
1.1.1.3 ! misho     322:        buffer *sb = magnet_checkbuffer(L, 1);
        !           323:        server *srv = magnet_get_server(L);
        !           324:        connection *con = magnet_get_connection(L);
1.1       misho     325:        stat_cache_entry *sce = NULL;
1.1.1.3 ! misho     326:        handler_t res;
1.1       misho     327: 
1.1.1.3 ! misho     328:        res = stat_cache_get_entry(srv, con, sb, &sce);
        !           329:        buffer_free(sb);
1.1       misho     330: 
1.1.1.3 ! misho     331:        if (HANDLER_GO_ON != res) {
1.1       misho     332:                lua_pushnil(L);
                    333:                return 1;
                    334:        }
                    335: 
1.1.1.3 ! misho     336:        lua_newtable(L); // return value
1.1       misho     337: 
                    338:        lua_pushboolean(L, S_ISREG(sce->st.st_mode));
                    339:        lua_setfield(L, -2, "is_file");
1.1.1.3 ! misho     340: 
1.1       misho     341:        lua_pushboolean(L, S_ISDIR(sce->st.st_mode));
                    342:        lua_setfield(L, -2, "is_dir");
                    343: 
                    344:        lua_pushboolean(L, S_ISCHR(sce->st.st_mode));
                    345:        lua_setfield(L, -2, "is_char");
                    346: 
                    347:        lua_pushboolean(L, S_ISBLK(sce->st.st_mode));
                    348:        lua_setfield(L, -2, "is_block");
                    349: 
                    350:        lua_pushboolean(L, S_ISSOCK(sce->st.st_mode));
                    351:        lua_setfield(L, -2, "is_socket");
                    352: 
                    353:        lua_pushboolean(L, S_ISLNK(sce->st.st_mode));
                    354:        lua_setfield(L, -2, "is_link");
                    355: 
                    356:        lua_pushboolean(L, S_ISFIFO(sce->st.st_mode));
                    357:        lua_setfield(L, -2, "is_fifo");
                    358: 
                    359:        lua_pushinteger(L, sce->st.st_mtime);
                    360:        lua_setfield(L, -2, "st_mtime");
                    361: 
                    362:        lua_pushinteger(L, sce->st.st_ctime);
                    363:        lua_setfield(L, -2, "st_ctime");
                    364: 
                    365:        lua_pushinteger(L, sce->st.st_atime);
                    366:        lua_setfield(L, -2, "st_atime");
                    367: 
                    368:        lua_pushinteger(L, sce->st.st_uid);
                    369:        lua_setfield(L, -2, "st_uid");
                    370: 
                    371:        lua_pushinteger(L, sce->st.st_gid);
                    372:        lua_setfield(L, -2, "st_gid");
                    373: 
                    374:        lua_pushinteger(L, sce->st.st_size);
                    375:        lua_setfield(L, -2, "st_size");
                    376: 
                    377:        lua_pushinteger(L, sce->st.st_ino);
                    378:        lua_setfield(L, -2, "st_ino");
                    379: 
1.1.1.3 ! misho     380:        if (!buffer_string_is_empty(sce->etag)) {
1.1       misho     381:                /* we have to mutate the etag */
                    382:                buffer *b = buffer_init();
                    383:                etag_mutate(b, sce->etag);
                    384: 
1.1.1.3 ! misho     385:                lua_pushlstring(L, CONST_BUF_LEN(b));
1.1       misho     386:                buffer_free(b);
                    387:        } else {
                    388:                lua_pushnil(L);
                    389:        }
                    390:        lua_setfield(L, -2, "etag");
                    391: 
1.1.1.3 ! misho     392:        if (!buffer_string_is_empty(sce->content_type)) {
        !           393:                lua_pushlstring(L, CONST_BUF_LEN(sce->content_type));
1.1       misho     394:        } else {
                    395:                lua_pushnil(L);
                    396:        }
                    397:        lua_setfield(L, -2, "content-type");
                    398: 
                    399:        return 1;
                    400: }
                    401: 
                    402: 
                    403: static int magnet_atpanic(lua_State *L) {
1.1.1.3 ! misho     404:        buffer *b = magnet_checkbuffer(L, 1);
1.1       misho     405: 
1.1.1.3 ! misho     406:        log_error_write(magnet_get_server(L), __FILE__, __LINE__, "sB",
        !           407:                "(lua-atpanic)",
        !           408:                b);
1.1       misho     409: 
1.1.1.3 ! misho     410:        buffer_free(b);
1.1       misho     411: 
                    412:        longjmp(exceptionjmp, 1);
                    413: }
                    414: 
                    415: static int magnet_reqhdr_get(lua_State *L) {
1.1.1.3 ! misho     416:        connection *con = magnet_get_connection(L);
1.1       misho     417:        data_string *ds;
                    418: 
1.1.1.3 ! misho     419:        /* __index: param 1 is the (empty) table the value was not found in */
1.1       misho     420:        const char *key = luaL_checkstring(L, 2);
                    421: 
                    422:        if (NULL != (ds = (data_string *)array_get_element(con->request.headers, key))) {
1.1.1.3 ! misho     423:                if (!buffer_is_empty(ds->value)) {
        !           424:                        lua_pushlstring(L, CONST_BUF_LEN(ds->value));
1.1       misho     425:                } else {
                    426:                        lua_pushnil(L);
                    427:                }
                    428:        } else {
                    429:                lua_pushnil(L);
                    430:        }
                    431:        return 1;
                    432: }
                    433: 
                    434: static int magnet_reqhdr_pairs(lua_State *L) {
1.1.1.3 ! misho     435:        connection *con = magnet_get_connection(L);
1.1       misho     436: 
                    437:        return magnet_array_pairs(L, con->request.headers);
                    438: }
                    439: 
                    440: static int magnet_status_get(lua_State *L) {
                    441:        data_integer *di;
1.1.1.3 ! misho     442:        server *srv = magnet_get_server(L);
1.1       misho     443: 
1.1.1.3 ! misho     444:        /* __index: param 1 is the (empty) table the value was not found in */
        !           445:        const_buffer key = magnet_checkconstbuffer(L, 2);
1.1       misho     446: 
1.1.1.3 ! misho     447:        di = status_counter_get_counter(srv, key.ptr, key.len);
1.1       misho     448: 
1.1.1.3 ! misho     449:        lua_pushinteger(L, (lua_Integer)di->value);
1.1       misho     450: 
                    451:        return 1;
                    452: }
                    453: 
                    454: static int magnet_status_set(lua_State *L) {
1.1.1.3 ! misho     455:        server *srv = magnet_get_server(L);
1.1       misho     456: 
1.1.1.3 ! misho     457:        /* __newindex: param 1 is the (empty) table the value is supposed to be set in */
        !           458:        const_buffer key = magnet_checkconstbuffer(L, 2);
        !           459:        int counter = (int) luaL_checkinteger(L, 3);
1.1       misho     460: 
1.1.1.3 ! misho     461:        status_counter_set(srv, key.ptr, key.len, counter);
1.1       misho     462: 
                    463:        return 0;
                    464: }
                    465: 
                    466: static int magnet_status_pairs(lua_State *L) {
1.1.1.3 ! misho     467:        server *srv = magnet_get_server(L);
1.1       misho     468: 
                    469:        return magnet_array_pairs(L, srv->status);
                    470: }
                    471: 
                    472: typedef struct {
                    473:        const char *name;
                    474:        enum {
                    475:                MAGNET_ENV_UNSET,
                    476: 
                    477:                MAGNET_ENV_PHYICAL_PATH,
                    478:                MAGNET_ENV_PHYICAL_REL_PATH,
                    479:                MAGNET_ENV_PHYICAL_DOC_ROOT,
1.1.1.2   misho     480:                MAGNET_ENV_PHYICAL_BASEDIR,
1.1       misho     481: 
                    482:                MAGNET_ENV_URI_PATH,
                    483:                MAGNET_ENV_URI_PATH_RAW,
                    484:                MAGNET_ENV_URI_SCHEME,
                    485:                MAGNET_ENV_URI_AUTHORITY,
                    486:                MAGNET_ENV_URI_QUERY,
                    487: 
                    488:                MAGNET_ENV_REQUEST_METHOD,
                    489:                MAGNET_ENV_REQUEST_URI,
                    490:                MAGNET_ENV_REQUEST_ORIG_URI,
                    491:                MAGNET_ENV_REQUEST_PATH_INFO,
                    492:                MAGNET_ENV_REQUEST_REMOTE_IP,
                    493:                MAGNET_ENV_REQUEST_PROTOCOL
                    494:        } type;
                    495: } magnet_env_t;
                    496: 
                    497: static const magnet_env_t magnet_env[] = {
                    498:        { "physical.path", MAGNET_ENV_PHYICAL_PATH },
                    499:        { "physical.rel-path", MAGNET_ENV_PHYICAL_REL_PATH },
                    500:        { "physical.doc-root", MAGNET_ENV_PHYICAL_DOC_ROOT },
1.1.1.2   misho     501:        { "physical.basedir", MAGNET_ENV_PHYICAL_BASEDIR },
1.1       misho     502: 
                    503:        { "uri.path", MAGNET_ENV_URI_PATH },
                    504:        { "uri.path-raw", MAGNET_ENV_URI_PATH_RAW },
                    505:        { "uri.scheme", MAGNET_ENV_URI_SCHEME },
                    506:        { "uri.authority", MAGNET_ENV_URI_AUTHORITY },
                    507:        { "uri.query", MAGNET_ENV_URI_QUERY },
                    508: 
                    509:        { "request.method", MAGNET_ENV_REQUEST_METHOD },
                    510:        { "request.uri", MAGNET_ENV_REQUEST_URI },
                    511:        { "request.orig-uri", MAGNET_ENV_REQUEST_ORIG_URI },
                    512:        { "request.path-info", MAGNET_ENV_REQUEST_PATH_INFO },
                    513:        { "request.remote-ip", MAGNET_ENV_REQUEST_REMOTE_IP },
                    514:        { "request.protocol", MAGNET_ENV_REQUEST_PROTOCOL },
                    515: 
                    516:        { NULL, MAGNET_ENV_UNSET }
                    517: };
                    518: 
                    519: static buffer *magnet_env_get_buffer_by_id(server *srv, connection *con, int id) {
                    520:        buffer *dest = NULL;
                    521: 
                    522:        UNUSED(srv);
                    523: 
                    524:        /**
                    525:         * map all internal variables to lua
                    526:         *
                    527:         */
                    528: 
                    529:        switch (id) {
                    530:        case MAGNET_ENV_PHYICAL_PATH: dest = con->physical.path; break;
                    531:        case MAGNET_ENV_PHYICAL_REL_PATH: dest = con->physical.rel_path; break;
                    532:        case MAGNET_ENV_PHYICAL_DOC_ROOT: dest = con->physical.doc_root; break;
1.1.1.2   misho     533:        case MAGNET_ENV_PHYICAL_BASEDIR: dest = con->physical.basedir; break;
1.1       misho     534: 
                    535:        case MAGNET_ENV_URI_PATH: dest = con->uri.path; break;
                    536:        case MAGNET_ENV_URI_PATH_RAW: dest = con->uri.path_raw; break;
                    537:        case MAGNET_ENV_URI_SCHEME: dest = con->uri.scheme; break;
                    538:        case MAGNET_ENV_URI_AUTHORITY: dest = con->uri.authority; break;
                    539:        case MAGNET_ENV_URI_QUERY: dest = con->uri.query; break;
                    540: 
                    541:        case MAGNET_ENV_REQUEST_METHOD:
                    542:                buffer_copy_string(srv->tmp_buf, get_http_method_name(con->request.http_method));
                    543:                dest = srv->tmp_buf;
                    544:                break;
                    545:        case MAGNET_ENV_REQUEST_URI:      dest = con->request.uri; break;
                    546:        case MAGNET_ENV_REQUEST_ORIG_URI: dest = con->request.orig_uri; break;
                    547:        case MAGNET_ENV_REQUEST_PATH_INFO: dest = con->request.pathinfo; break;
                    548:        case MAGNET_ENV_REQUEST_REMOTE_IP: dest = con->dst_addr_buf; break;
                    549:        case MAGNET_ENV_REQUEST_PROTOCOL:
                    550:                buffer_copy_string(srv->tmp_buf, get_http_version_name(con->request.http_version));
                    551:                dest = srv->tmp_buf;
                    552:                break;
                    553: 
                    554:        case MAGNET_ENV_UNSET: break;
                    555:        }
                    556: 
                    557:        return dest;
                    558: }
                    559: 
                    560: static buffer *magnet_env_get_buffer(server *srv, connection *con, const char *key) {
                    561:        size_t i;
                    562: 
                    563:        for (i = 0; magnet_env[i].name; i++) {
                    564:                if (0 == strcmp(key, magnet_env[i].name)) break;
                    565:        }
                    566: 
                    567:        return magnet_env_get_buffer_by_id(srv, con, magnet_env[i].type);
                    568: }
                    569: 
                    570: static int magnet_env_get(lua_State *L) {
1.1.1.3 ! misho     571:        server *srv = magnet_get_server(L);
        !           572:        connection *con = magnet_get_connection(L);
1.1       misho     573: 
1.1.1.3 ! misho     574:        /* __index: param 1 is the (empty) table the value was not found in */
1.1       misho     575:        const char *key = luaL_checkstring(L, 2);
                    576:        buffer *dest = NULL;
                    577: 
                    578:        dest = magnet_env_get_buffer(srv, con, key);
                    579: 
1.1.1.3 ! misho     580:        if (!buffer_is_empty(dest)) {
        !           581:                lua_pushlstring(L, CONST_BUF_LEN(dest));
1.1       misho     582:        } else {
                    583:                lua_pushnil(L);
                    584:        }
                    585: 
                    586:        return 1;
                    587: }
                    588: 
                    589: static int magnet_env_set(lua_State *L) {
1.1.1.3 ! misho     590:        server *srv = magnet_get_server(L);
        !           591:        connection *con = magnet_get_connection(L);
1.1       misho     592: 
1.1.1.3 ! misho     593:        /* __newindex: param 1 is the (empty) table the value is supposed to be set in */
1.1       misho     594:        const char *key = luaL_checkstring(L, 2);
                    595:        buffer *dest = NULL;
                    596: 
1.1.1.3 ! misho     597:        luaL_checkany(L, 3); /* nil or a string */
1.1       misho     598: 
                    599:        if (NULL != (dest = magnet_env_get_buffer(srv, con, key))) {
1.1.1.3 ! misho     600:                if (lua_isnil(L, 3)) {
        !           601:                        buffer_reset(dest);
        !           602:                } else {
        !           603:                        const_buffer val = magnet_checkconstbuffer(L, 3);
        !           604:                        buffer_copy_string_len(dest, val.ptr, val.len);
        !           605:                }
1.1       misho     606:        } else {
                    607:                /* couldn't save */
                    608: 
                    609:                return luaL_error(L, "couldn't store '%s' in lighty.env[]", key);
                    610:        }
                    611: 
                    612:        return 0;
                    613: }
                    614: 
                    615: static int magnet_env_next(lua_State *L) {
1.1.1.3 ! misho     616:        server *srv = magnet_get_server(L);
        !           617:        connection *con = magnet_get_connection(L);
        !           618:        const int pos = lua_tointeger(L, lua_upvalueindex(1));
1.1       misho     619: 
                    620:        buffer *dest;
                    621: 
1.1.1.3 ! misho     622:        /* ignore previous key: use upvalue for current pos */
1.1       misho     623:        lua_settop(L, 0);
                    624: 
                    625:        if (NULL == magnet_env[pos].name) return 0; /* end of list */
1.1.1.3 ! misho     626:        /* Update our positional upval to reflect our new current position */
        !           627:        lua_pushinteger(L, pos + 1);
        !           628:        lua_replace(L, lua_upvalueindex(1));
1.1       misho     629: 
1.1.1.3 ! misho     630:        /* key to return */
1.1       misho     631:        lua_pushstring(L, magnet_env[pos].name);
                    632: 
1.1.1.3 ! misho     633:        /* get value */
1.1       misho     634:        dest = magnet_env_get_buffer_by_id(srv, con, magnet_env[pos].type);
1.1.1.3 ! misho     635:        if (!buffer_is_empty(dest)) {
        !           636:                lua_pushlstring(L, CONST_BUF_LEN(dest));
1.1       misho     637:        } else {
                    638:                lua_pushnil(L);
                    639:        }
                    640: 
1.1.1.3 ! misho     641:        /* return 2 items on the stack (key, value) */
1.1       misho     642:        return 2;
                    643: }
                    644: 
                    645: static int magnet_env_pairs(lua_State *L) {
                    646:        lua_pushinteger(L, 0); /* Push our current pos (the start) into upval 1 */
                    647:        lua_pushcclosure(L, magnet_env_next, 1); /* Push our new closure with 1 upvals */
                    648:        return 1;
                    649: }
                    650: 
                    651: static int magnet_cgi_get(lua_State *L) {
1.1.1.3 ! misho     652:        connection *con = magnet_get_connection(L);
1.1       misho     653:        data_string *ds;
                    654: 
1.1.1.3 ! misho     655:        /* __index: param 1 is the (empty) table the value was not found in */
1.1       misho     656:        const char *key = luaL_checkstring(L, 2);
                    657: 
1.1.1.3 ! misho     658:        ds = (data_string *)array_get_element(con->environment, key);
        !           659:        if (NULL != ds && !buffer_is_empty(ds->value))
1.1       misho     660:                lua_pushlstring(L, CONST_BUF_LEN(ds->value));
                    661:        else
                    662:                lua_pushnil(L);
                    663: 
                    664:        return 1;
                    665: }
                    666: 
                    667: static int magnet_cgi_set(lua_State *L) {
1.1.1.3 ! misho     668:        connection *con = magnet_get_connection(L);
1.1       misho     669: 
1.1.1.3 ! misho     670:        /* __newindex: param 1 is the (empty) table the value is supposed to be set in */
        !           671:        const_buffer key = magnet_checkconstbuffer(L, 2);
        !           672:        const_buffer val = magnet_checkconstbuffer(L, 2);
1.1       misho     673: 
1.1.1.3 ! misho     674:        array_set_key_value(con->environment, key.ptr, key.len, val.ptr, val.len);
1.1       misho     675: 
                    676:        return 0;
                    677: }
                    678: 
                    679: static int magnet_cgi_pairs(lua_State *L) {
1.1.1.3 ! misho     680:        connection *con = magnet_get_connection(L);
1.1       misho     681: 
                    682:        return magnet_array_pairs(L, con->environment);
                    683: }
                    684: 
                    685: 
1.1.1.3 ! misho     686: static int magnet_copy_response_header(server *srv, connection *con, lua_State *L, int lighty_table_ndx) {
        !           687:        force_assert(lua_istable(L, lighty_table_ndx));
1.1       misho     688: 
1.1.1.3 ! misho     689:        lua_getfield(L, lighty_table_ndx, "header"); /* lighty.header */
1.1       misho     690:        if (lua_istable(L, -1)) {
                    691:                /* header is found, and is a table */
                    692: 
                    693:                lua_pushnil(L);
                    694:                while (lua_next(L, -2) != 0) {
                    695:                        if (lua_isstring(L, -1) && lua_isstring(L, -2)) {
1.1.1.3 ! misho     696:                                const_buffer key = magnet_checkconstbuffer(L, -2);
        !           697:                                const_buffer val = magnet_checkconstbuffer(L, -1);
1.1       misho     698: 
1.1.1.3 ! misho     699:                                response_header_overwrite(srv, con, key.ptr, key.len, val.ptr, val.len);
1.1       misho     700:                        }
                    701: 
                    702:                        lua_pop(L, 1);
                    703:                }
                    704:        }
1.1.1.3 ! misho     705:        lua_pop(L, 1); /* pop lighty.header */
1.1       misho     706: 
                    707:        return 0;
                    708: }
                    709: 
                    710: /**
                    711:  * walk through the content array
                    712:  *
                    713:  * content = { "<pre>", { file = "/content" } , "</pre>" }
                    714:  *
                    715:  * header["Content-Type"] = "text/html"
                    716:  *
                    717:  * return 200
                    718:  */
1.1.1.3 ! misho     719: static int magnet_attach_content(server *srv, connection *con, lua_State *L, int lighty_table_ndx) {
        !           720:        force_assert(lua_istable(L, lighty_table_ndx));
1.1       misho     721: 
1.1.1.3 ! misho     722:        lua_getfield(L, lighty_table_ndx, "content"); /* lighty.content */
1.1       misho     723:        if (lua_istable(L, -1)) {
                    724:                int i;
1.1.1.3 ! misho     725:                /* content is found, and is a table */
1.1       misho     726: 
                    727:                for (i = 1; ; i++) {
                    728:                        lua_rawgeti(L, -1, i);
                    729: 
                    730:                        /* -1 is the value and should be the value ... aka a table */
                    731:                        if (lua_isstring(L, -1)) {
1.1.1.3 ! misho     732:                                const_buffer data = magnet_checkconstbuffer(L, -1);
1.1       misho     733: 
1.1.1.3 ! misho     734:                                chunkqueue_append_mem(con->write_queue, data.ptr, data.len);
1.1       misho     735:                        } else if (lua_istable(L, -1)) {
                    736:                                lua_getfield(L, -1, "filename");
1.1.1.3 ! misho     737:                                lua_getfield(L, -2, "length"); /* (0-based) end of range (not actually "length") */
        !           738:                                lua_getfield(L, -3, "offset"); /* (0-based) start of range */
1.1       misho     739: 
                    740:                                if (lua_isstring(L, -3)) { /* filename has to be a string */
1.1.1.3 ! misho     741:                                        buffer *fn = magnet_checkbuffer(L, -3);
        !           742:                                        off_t off = (off_t) luaL_optinteger(L, -1, 0);
        !           743:                                        off_t len = (off_t) luaL_optinteger(L, -2, -1); /*(-1 to http_chunk_append_file_range() uses file size minus offset)*/
        !           744:                                        if (off < 0) {
        !           745:                                                buffer_free(fn);
        !           746:                                                return luaL_error(L, "offset for '%s' is negative", lua_tostring(L, -3));
        !           747:                                        }
        !           748: 
        !           749:                                        if (len >= off) {
        !           750:                                                len -= off;
        !           751:                                        } else if (-1 != len) {
        !           752:                                                buffer_free(fn);
        !           753:                                                return luaL_error(L, "offset > length for '%s'", lua_tostring(L, -3));
        !           754:                                        }
1.1       misho     755: 
1.1.1.3 ! misho     756:                                        if (0 != len && 0 != http_chunk_append_file_range(srv, con, fn, off, len)) {
        !           757:                                                buffer_free(fn);
        !           758:                                                return luaL_error(L, "error opening file content '%s' at offset %lld", lua_tostring(L, -3), (long long)off);
1.1       misho     759:                                        }
                    760: 
                    761:                                        buffer_free(fn);
                    762:                                } else {
                    763:                                        return luaL_error(L, "content[%d] is a table and requires the field \"filename\"", i);
                    764:                                }
                    765: 
                    766:                                lua_pop(L, 3);
                    767:                        } else if (lua_isnil(L, -1)) {
1.1.1.3 ! misho     768:                                /* end of list */
1.1       misho     769: 
                    770:                                lua_pop(L, 1);
                    771: 
                    772:                                break;
                    773:                        } else {
                    774:                                return luaL_error(L, "content[%d] is neither a string nor a table: ", i);
                    775:                        }
                    776: 
1.1.1.3 ! misho     777:                        lua_pop(L, 1); /* pop the content[...] entry value */
1.1       misho     778:                }
                    779:        } else {
                    780:                return luaL_error(L, "lighty.content has to be a table");
                    781:        }
1.1.1.3 ! misho     782:        lua_pop(L, 1); /* pop lighty.content */
1.1       misho     783: 
                    784:        return 0;
                    785: }
                    786: 
1.1.1.3 ! misho     787: static int traceback(lua_State *L) {
1.1       misho     788:        if (!lua_isstring(L, 1))  /* 'message' not a string? */
                    789:                return 1;  /* keep it intact */
1.1.1.3 ! misho     790:        lua_getglobal(L, "debug");
1.1       misho     791:        if (!lua_istable(L, -1)) {
                    792:                lua_pop(L, 1);
                    793:                return 1;
                    794:        }
                    795:        lua_getfield(L, -1, "traceback");
                    796:        if (!lua_isfunction(L, -1)) {
                    797:                lua_pop(L, 2);
                    798:                return 1;
                    799:        }
                    800:        lua_pushvalue(L, 1);  /* pass error message */
                    801:        lua_pushinteger(L, 2);  /* skip this function and traceback */
                    802:        lua_call(L, 2, 1);  /* call debug.traceback */
                    803:        return 1;
                    804: }
                    805: 
1.1.1.3 ! misho     806: /* push traceback function before calling lua_pcall after narg arguments
        !           807:  * have been pushed (inserts it before the arguments). returns index for
        !           808:  * traceback function ("msgh" in lua_pcall)
        !           809:  */
1.1       misho     810: static int push_traceback(lua_State *L, int narg) {
                    811:        int base = lua_gettop(L) - narg;  /* function index */
                    812:        lua_pushcfunction(L, traceback);
                    813:        lua_insert(L, base);
                    814:        return base;
                    815: }
                    816: 
                    817: static handler_t magnet_attract(server *srv, connection *con, plugin_data *p, buffer *name) {
                    818:        lua_State *L;
1.1.1.3 ! misho     819:        int lua_return_value;
        !           820:        const int func_ndx = 1;
        !           821:        const int lighty_table_ndx = 2;
1.1       misho     822: 
1.1.1.3 ! misho     823:        /* get the script-context */
1.1       misho     824:        L = script_cache_get_script(srv, con, p->cache, name);
                    825: 
                    826:        if (lua_isstring(L, -1)) {
                    827:                log_error_write(srv, __FILE__, __LINE__,
                    828:                                "sbss",
                    829:                                "loading script",
                    830:                                name,
                    831:                                "failed:",
                    832:                                lua_tostring(L, -1));
                    833: 
                    834:                lua_pop(L, 1);
                    835: 
1.1.1.3 ! misho     836:                force_assert(lua_gettop(L) == 0); /* only the error should have been on the stack */
1.1       misho     837: 
                    838:                con->http_status = 500;
                    839:                con->mode = DIRECT;
                    840: 
                    841:                return HANDLER_FINISHED;
                    842:        }
                    843: 
1.1.1.3 ! misho     844:        force_assert(lua_gettop(L) == 1);
        !           845:        force_assert(lua_isfunction(L, func_ndx));
        !           846: 
1.1       misho     847:        lua_pushlightuserdata(L, srv);
1.1.1.3 ! misho     848:        lua_setfield(L, LUA_REGISTRYINDEX, LUA_RIDX_LIGHTTPD_SERVER);
1.1       misho     849: 
                    850:        lua_pushlightuserdata(L, con);
1.1.1.3 ! misho     851:        lua_setfield(L, LUA_REGISTRYINDEX, LUA_RIDX_LIGHTTPD_CONNECTION);
1.1       misho     852: 
                    853:        lua_atpanic(L, magnet_atpanic);
                    854: 
                    855:        /**
                    856:         * we want to create empty environment for our script
                    857:         *
                    858:         * setmetatable({}, {__index = _G})
                    859:         *
1.1.1.3 ! misho     860:         * if a function symbol is not defined in our env, __index will lookup
1.1       misho     861:         * in the global env.
                    862:         *
                    863:         * all variables created in the script-env will be thrown
                    864:         * away at the end of the script run.
                    865:         */
                    866:        lua_newtable(L); /* my empty environment aka {}              (sp += 1) */
                    867: 
                    868:        /* we have to overwrite the print function */
                    869:        lua_pushcfunction(L, magnet_print);                       /* (sp += 1) */
                    870:        lua_setfield(L, -2, "print"); /* -1 is the env we want to set(sp -= 1) */
                    871: 
                    872:        /**
1.1.1.3 ! misho     873:         * lighty.request[] (ro) has the HTTP-request headers
        !           874:         * lighty.env[] (rw) has various url/physical file paths and
        !           875:         *                   request meta data; might contain nil values
        !           876:         * lighty.req_env[] (ro) has the cgi environment
        !           877:         * lighty.status[] (ro) has the status counters
        !           878:         * lighty.content[] (rw) is a table of string/file
        !           879:         * lighty.header[] (rw) is a array to set response headers
1.1       misho     880:         */
                    881: 
                    882:        lua_newtable(L); /* lighty.*                                 (sp += 1) */
                    883: 
                    884:        lua_newtable(L); /*  {}                                      (sp += 1) */
                    885:        lua_newtable(L); /* the meta-table for the request-table     (sp += 1) */
                    886:        lua_pushcfunction(L, magnet_reqhdr_get);                  /* (sp += 1) */
                    887:        lua_setfield(L, -2, "__index");                           /* (sp -= 1) */
                    888:        lua_pushcfunction(L, magnet_reqhdr_pairs);                /* (sp += 1) */
                    889:        lua_setfield(L, -2, "__pairs");                           /* (sp -= 1) */
                    890:        lua_setmetatable(L, -2); /* tie the metatable to request     (sp -= 1) */
                    891:        lua_setfield(L, -2, "request"); /* content = {}              (sp -= 1) */
                    892: 
                    893:        lua_newtable(L); /*  {}                                      (sp += 1) */
1.1.1.3 ! misho     894:        lua_newtable(L); /* the meta-table for the env-table         (sp += 1) */
1.1       misho     895:        lua_pushcfunction(L, magnet_env_get);                     /* (sp += 1) */
                    896:        lua_setfield(L, -2, "__index");                           /* (sp -= 1) */
                    897:        lua_pushcfunction(L, magnet_env_set);                     /* (sp += 1) */
                    898:        lua_setfield(L, -2, "__newindex");                        /* (sp -= 1) */
                    899:        lua_pushcfunction(L, magnet_env_pairs);                   /* (sp += 1) */
                    900:        lua_setfield(L, -2, "__pairs");                           /* (sp -= 1) */
1.1.1.3 ! misho     901:        lua_setmetatable(L, -2); /* tie the metatable to env         (sp -= 1) */
1.1       misho     902:        lua_setfield(L, -2, "env"); /* content = {}                  (sp -= 1) */
                    903: 
                    904:        lua_newtable(L); /*  {}                                      (sp += 1) */
1.1.1.3 ! misho     905:        lua_newtable(L); /* the meta-table for the req_env-table     (sp += 1) */
1.1       misho     906:        lua_pushcfunction(L, magnet_cgi_get);                     /* (sp += 1) */
                    907:        lua_setfield(L, -2, "__index");                           /* (sp -= 1) */
                    908:        lua_pushcfunction(L, magnet_cgi_set);                     /* (sp += 1) */
                    909:        lua_setfield(L, -2, "__newindex");                        /* (sp -= 1) */
                    910:        lua_pushcfunction(L, magnet_cgi_pairs);                   /* (sp += 1) */
                    911:        lua_setfield(L, -2, "__pairs");                           /* (sp -= 1) */
                    912:        lua_setmetatable(L, -2); /* tie the metatable to req_env     (sp -= 1) */
                    913:        lua_setfield(L, -2, "req_env"); /* content = {}              (sp -= 1) */
                    914: 
                    915:        lua_newtable(L); /*  {}                                      (sp += 1) */
1.1.1.3 ! misho     916:        lua_newtable(L); /* the meta-table for the status-table      (sp += 1) */
1.1       misho     917:        lua_pushcfunction(L, magnet_status_get);                  /* (sp += 1) */
                    918:        lua_setfield(L, -2, "__index");                           /* (sp -= 1) */
                    919:        lua_pushcfunction(L, magnet_status_set);                  /* (sp += 1) */
                    920:        lua_setfield(L, -2, "__newindex");                        /* (sp -= 1) */
                    921:        lua_pushcfunction(L, magnet_status_pairs);                /* (sp += 1) */
                    922:        lua_setfield(L, -2, "__pairs");                           /* (sp -= 1) */
1.1.1.3 ! misho     923:        lua_setmetatable(L, -2); /* tie the metatable to statzs      (sp -= 1) */
1.1       misho     924:        lua_setfield(L, -2, "status"); /* content = {}               (sp -= 1) */
                    925: 
                    926:        /* add empty 'content' and 'header' tables */
                    927:        lua_newtable(L); /*  {}                                      (sp += 1) */
                    928:        lua_setfield(L, -2, "content"); /* content = {}              (sp -= 1) */
                    929: 
                    930:        lua_newtable(L); /*  {}                                      (sp += 1) */
                    931:        lua_setfield(L, -2, "header"); /* header = {}                (sp -= 1) */
                    932: 
                    933:        lua_pushinteger(L, MAGNET_RESTART_REQUEST);
                    934:        lua_setfield(L, -2, "RESTART_REQUEST");
                    935: 
                    936:        lua_pushcfunction(L, magnet_stat);                        /* (sp += 1) */
                    937:        lua_setfield(L, -2, "stat"); /* -1 is the env we want to set (sp -= 1) */
                    938: 
1.1.1.3 ! misho     939:        /* insert lighty table at index 2 */
        !           940:        lua_pushvalue(L, -1);
        !           941:        lua_insert(L, lighty_table_ndx);
        !           942: 
1.1       misho     943:        lua_setfield(L, -2, "lighty"); /* lighty.*                   (sp -= 1) */
                    944: 
1.1.1.3 ! misho     945: #if !defined(LUA_VERSION_NUM) || LUA_VERSION_NUM < 502
        !           946:        /* override the default pairs() function to our __pairs capable version;
        !           947:         * not needed for lua 5.2+
        !           948:         */
1.1       misho     949:        lua_getglobal(L, "pairs"); /* push original pairs()          (sp += 1) */
                    950:        lua_pushcclosure(L, magnet_pairs, 1);
                    951:        lua_setfield(L, -2, "pairs");                             /* (sp -= 1) */
1.1.1.3 ! misho     952: #endif
1.1       misho     953: 
                    954:        lua_newtable(L); /* the meta-table for the new env           (sp += 1) */
1.1.1.3 ! misho     955:        lua_pushglobaltable(L);                                   /* (sp += 1) */
1.1       misho     956:        lua_setfield(L, -2, "__index"); /* { __index = _G }          (sp -= 1) */
                    957:        lua_setmetatable(L, -2); /* setmetatable({}, {__index = _G}) (sp -= 1) */
                    958: 
1.1.1.3 ! misho     959:        magnet_setfenv_mainfn(L, 1);                              /* (sp -= 1) */
1.1       misho     960: 
1.1.1.3 ! misho     961:        /* pcall will destroy the func value, duplicate it */     /* (sp += 1) */
        !           962:        lua_pushvalue(L, func_ndx);
        !           963:        {
        !           964:                int errfunc = push_traceback(L, 0);
        !           965:                int ret = lua_pcall(L, 0, 1, errfunc);
1.1       misho     966:                lua_remove(L, errfunc);
                    967: 
1.1.1.3 ! misho     968:                /* reset environment */
        !           969:                lua_pushglobaltable(L);                               /* (sp += 1) */
        !           970:                magnet_setfenv_mainfn(L, 1);                          /* (sp -= 1) */
        !           971: 
        !           972:                if (0 != ret) {
        !           973:                        log_error_write(srv, __FILE__, __LINE__,
        !           974:                                "ss",
        !           975:                                "lua_pcall():",
        !           976:                                lua_tostring(L, -1));
        !           977:                        lua_pop(L, 2); /* remove the error-msg and the lighty table at index 2 */
1.1       misho     978: 
1.1.1.3 ! misho     979:                        force_assert(lua_gettop(L) == 1); /* only the function should be on the stack */
1.1       misho     980: 
1.1.1.3 ! misho     981:                        con->http_status = 500;
        !           982:                        con->mode = DIRECT;
1.1       misho     983: 
1.1.1.3 ! misho     984:                        return HANDLER_FINISHED;
        !           985:                }
1.1       misho     986:        }
                    987: 
1.1.1.3 ! misho     988:        /* we should have the function, the lighty table and the return value on the stack */
        !           989:        force_assert(lua_gettop(L) == 3);
1.1       misho     990: 
1.1.1.3 ! misho     991:        lua_return_value = (int) luaL_optinteger(L, -1, -1);
        !           992:        lua_pop(L, 1); /* pop return value */
1.1       misho     993: 
1.1.1.3 ! misho     994:        magnet_copy_response_header(srv, con, L, lighty_table_ndx);
1.1       misho     995: 
1.1.1.3 ! misho     996:        {
        !           997:                handler_t result = HANDLER_GO_ON;
        !           998: 
        !           999:                if (lua_return_value > 99) {
        !          1000:                        con->http_status = lua_return_value;
        !          1001:                        con->file_finished = 1;
        !          1002: 
        !          1003:                        /* try { ...*/
        !          1004:                        if (0 == setjmp(exceptionjmp)) {
        !          1005:                                magnet_attach_content(srv, con, L, lighty_table_ndx);
        !          1006:                                if (!chunkqueue_is_empty(con->write_queue)) {
        !          1007:                                        con->mode = p->id;
        !          1008:                                }
        !          1009:                        } else {
        !          1010:                                lua_settop(L, 2); /* remove all but function and lighty table */
        !          1011:                                /* } catch () { */
        !          1012:                                con->http_status = 500;
        !          1013:                                con->mode = DIRECT;
        !          1014:                        }
1.1       misho    1015: 
1.1.1.3 ! misho    1016:                        result = HANDLER_FINISHED;
        !          1017:                } else if (MAGNET_RESTART_REQUEST == lua_return_value) {
        !          1018:                        result = HANDLER_COMEBACK;
        !          1019:                }
1.1       misho    1020: 
1.1.1.3 ! misho    1021:                lua_pop(L, 1); /* pop the lighty table */
        !          1022:                force_assert(lua_gettop(L) == 1); /* only the function should remain on the stack */
1.1       misho    1023: 
1.1.1.3 ! misho    1024:                return result;
1.1       misho    1025:        }
                   1026: }
                   1027: 
                   1028: static handler_t magnet_attract_array(server *srv, connection *con, plugin_data *p, array *files) {
                   1029:        size_t i;
1.1.1.3 ! misho    1030:        handler_t ret = HANDLER_GO_ON;
1.1       misho    1031: 
                   1032:        /* no filename set */
                   1033:        if (files->used == 0) return HANDLER_GO_ON;
                   1034: 
                   1035:        /**
                   1036:         * execute all files and jump out on the first !HANDLER_GO_ON
                   1037:         */
1.1.1.3 ! misho    1038:        for (i = 0; i < files->used && ret == HANDLER_GO_ON; i++) {
1.1       misho    1039:                data_string *ds = (data_string *)files->data[i];
                   1040: 
1.1.1.3 ! misho    1041:                if (buffer_string_is_empty(ds->value)) continue;
1.1       misho    1042: 
                   1043:                ret = magnet_attract(srv, con, p, ds->value);
1.1.1.3 ! misho    1044:        }
1.1       misho    1045: 
1.1.1.3 ! misho    1046:        if (con->error_handler_saved_status) {
        !          1047:                /* retrieve (possibly modified) REDIRECT_STATUS and store as number */
        !          1048:                unsigned long x;
        !          1049:                data_string * const ds = (data_string *)array_get_element(con->environment, "REDIRECT_STATUS");
        !          1050:                if (ds && (x = strtoul(ds->value->ptr, NULL, 10)) < 1000)
        !          1051:                        /*(simplified validity check x < 1000)*/
        !          1052:                        con->error_handler_saved_status =
        !          1053:                          con->error_handler_saved_status > 0 ? (int)x : -(int)x;
1.1       misho    1054:        }
                   1055: 
1.1.1.3 ! misho    1056:        return ret;
1.1       misho    1057: }
                   1058: 
                   1059: URIHANDLER_FUNC(mod_magnet_uri_handler) {
                   1060:        plugin_data *p = p_d;
                   1061: 
                   1062:        mod_magnet_patch_connection(srv, con, p);
                   1063: 
                   1064:        return magnet_attract_array(srv, con, p, p->conf.url_raw);
                   1065: }
                   1066: 
                   1067: URIHANDLER_FUNC(mod_magnet_physical) {
                   1068:        plugin_data *p = p_d;
                   1069: 
                   1070:        mod_magnet_patch_connection(srv, con, p);
                   1071: 
                   1072:        return magnet_attract_array(srv, con, p, p->conf.physical_path);
                   1073: }
                   1074: 
                   1075: 
                   1076: /* this function is called at dlopen() time and inits the callbacks */
                   1077: 
                   1078: int mod_magnet_plugin_init(plugin *p);
                   1079: int mod_magnet_plugin_init(plugin *p) {
                   1080:        p->version     = LIGHTTPD_VERSION_ID;
                   1081:        p->name        = buffer_init_string("magnet");
                   1082: 
                   1083:        p->init        = mod_magnet_init;
                   1084:        p->handle_uri_clean  = mod_magnet_uri_handler;
                   1085:        p->handle_physical   = mod_magnet_physical;
                   1086:        p->set_defaults  = mod_magnet_set_defaults;
                   1087:        p->cleanup     = mod_magnet_free;
                   1088: 
                   1089:        p->data        = NULL;
                   1090: 
                   1091:        return 0;
                   1092: }
                   1093: 
                   1094: #else
1.1.1.3 ! misho    1095: 
        !          1096: #pragma message("lua is required, but was not found")
        !          1097: 
1.1       misho    1098: int mod_magnet_plugin_init(plugin *p);
                   1099: int mod_magnet_plugin_init(plugin *p) {
                   1100:        UNUSED(p);
                   1101:        return -1;
                   1102: }
                   1103: #endif

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