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

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

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