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

1.1       misho       1: #include "base.h"
                      2: #include "log.h"
                      3: #include "buffer.h"
                      4: #include "stat_cache.h"
                      5: 
                      6: #include "plugin.h"
                      7: 
                      8: #include <assert.h>
                      9: #include <ctype.h>
                     10: #include <stdlib.h>
                     11: #include <string.h>
                     12: #include <errno.h>
                     13: 
                     14: typedef struct {
                     15:        buffer *server_root;
                     16:        buffer *default_host;
                     17:        buffer *document_root;
                     18: 
                     19:        buffer *docroot_cache_key;
                     20:        buffer *docroot_cache_value;
                     21:        buffer *docroot_cache_servername;
                     22: 
                     23:        unsigned short debug;
                     24: } plugin_config;
                     25: 
                     26: typedef struct {
                     27:        PLUGIN_DATA;
                     28: 
                     29:        buffer *doc_root;
                     30: 
                     31:        plugin_config **config_storage;
                     32:        plugin_config conf;
                     33: } plugin_data;
                     34: 
                     35: INIT_FUNC(mod_simple_vhost_init) {
                     36:        plugin_data *p;
                     37: 
                     38:        p = calloc(1, sizeof(*p));
                     39: 
                     40:        p->doc_root = buffer_init();
                     41: 
                     42:        return p;
                     43: }
                     44: 
                     45: FREE_FUNC(mod_simple_vhost_free) {
                     46:        plugin_data *p = p_d;
                     47: 
                     48:        UNUSED(srv);
                     49: 
                     50:        if (!p) return HANDLER_GO_ON;
                     51: 
                     52:        if (p->config_storage) {
                     53:                size_t i;
                     54:                for (i = 0; i < srv->config_context->used; i++) {
                     55:                        plugin_config *s = p->config_storage[i];
                     56: 
                     57:                        buffer_free(s->document_root);
                     58:                        buffer_free(s->default_host);
                     59:                        buffer_free(s->server_root);
                     60: 
                     61:                        buffer_free(s->docroot_cache_key);
                     62:                        buffer_free(s->docroot_cache_value);
                     63:                        buffer_free(s->docroot_cache_servername);
                     64: 
                     65:                        free(s);
                     66:                }
                     67: 
                     68:                free(p->config_storage);
                     69:        }
                     70: 
                     71:        buffer_free(p->doc_root);
                     72: 
                     73:        free(p);
                     74: 
                     75:        return HANDLER_GO_ON;
                     76: }
                     77: 
                     78: SETDEFAULTS_FUNC(mod_simple_vhost_set_defaults) {
                     79:        plugin_data *p = p_d;
                     80:        size_t i;
                     81: 
                     82:        config_values_t cv[] = {
                     83:                { "simple-vhost.server-root",       NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
                     84:                { "simple-vhost.default-host",      NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
                     85:                { "simple-vhost.document-root",     NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
                     86:                { "simple-vhost.debug",             NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION },
                     87:                { NULL,                             NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
                     88:        };
                     89: 
                     90:        if (!p) return HANDLER_ERROR;
                     91: 
                     92:        p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
                     93: 
                     94:        for (i = 0; i < srv->config_context->used; i++) {
                     95:                plugin_config *s;
                     96: 
                     97:                s = calloc(1, sizeof(plugin_config));
                     98: 
                     99:                s->server_root = buffer_init();
                    100:                s->default_host = buffer_init();
                    101:                s->document_root = buffer_init();
                    102: 
                    103:                s->docroot_cache_key = buffer_init();
                    104:                s->docroot_cache_value = buffer_init();
                    105:                s->docroot_cache_servername = buffer_init();
                    106: 
                    107:                s->debug = 0;
                    108: 
                    109:                cv[0].destination = s->server_root;
                    110:                cv[1].destination = s->default_host;
                    111:                cv[2].destination = s->document_root;
                    112:                cv[3].destination = &(s->debug);
                    113: 
                    114: 
                    115:                p->config_storage[i] = s;
                    116: 
                    117:                if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
                    118:                        return HANDLER_ERROR;
                    119:                }
                    120:        }
                    121: 
                    122:        return HANDLER_GO_ON;
                    123: }
                    124: 
                    125: static int build_doc_root(server *srv, connection *con, plugin_data *p, buffer *out, buffer *host) {
                    126:        stat_cache_entry *sce = NULL;
                    127:        assert(p->conf.server_root->used > 1);
                    128: 
                    129:        buffer_prepare_copy(out, 128);
                    130:        buffer_copy_string_buffer(out, p->conf.server_root);
                    131: 
                    132:        if (host->used) {
                    133:                /* a hostname has to start with a alpha-numerical character
                    134:                 * and must not contain a slash "/"
                    135:                 */
                    136:                char *dp;
                    137: 
                    138:                BUFFER_APPEND_SLASH(out);
                    139: 
                    140:                if (NULL == (dp = strchr(host->ptr, ':'))) {
                    141:                        buffer_append_string_buffer(out, host);
                    142:                } else {
                    143:                        buffer_append_string_len(out, host->ptr, dp - host->ptr);
                    144:                }
                    145:        }
                    146:        BUFFER_APPEND_SLASH(out);
                    147: 
                    148:        if (p->conf.document_root->used > 2 && p->conf.document_root->ptr[0] == '/') {
                    149:                buffer_append_string_len(out, p->conf.document_root->ptr + 1, p->conf.document_root->used - 2);
                    150:        } else {
                    151:                buffer_append_string_buffer(out, p->conf.document_root);
                    152:                BUFFER_APPEND_SLASH(out);
                    153:        }
                    154: 
                    155:        if (HANDLER_ERROR == stat_cache_get_entry(srv, con, out, &sce)) {
                    156:                if (p->conf.debug) {
                    157:                        log_error_write(srv, __FILE__, __LINE__, "sb",
                    158:                                        strerror(errno), out);
                    159:                }
                    160:                return -1;
                    161:        } else if (!S_ISDIR(sce->st.st_mode)) {
                    162:                return -1;
                    163:        }
                    164: 
                    165:        return 0;
                    166: }
                    167: 
                    168: 
                    169: #define PATCH(x) \
                    170:        p->conf.x = s->x;
                    171: static int mod_simple_vhost_patch_connection(server *srv, connection *con, plugin_data *p) {
                    172:        size_t i, j;
                    173:        plugin_config *s = p->config_storage[0];
                    174: 
                    175:        PATCH(server_root);
                    176:        PATCH(default_host);
                    177:        PATCH(document_root);
                    178: 
                    179:        PATCH(docroot_cache_key);
                    180:        PATCH(docroot_cache_value);
                    181:        PATCH(docroot_cache_servername);
                    182: 
                    183:        PATCH(debug);
                    184: 
                    185:        /* skip the first, the global context */
                    186:        for (i = 1; i < srv->config_context->used; i++) {
                    187:                data_config *dc = (data_config *)srv->config_context->data[i];
                    188:                s = p->config_storage[i];
                    189: 
                    190:                /* condition didn't match */
                    191:                if (!config_check_cond(srv, con, dc)) continue;
                    192: 
                    193:                /* merge config */
                    194:                for (j = 0; j < dc->value->used; j++) {
                    195:                        data_unset *du = dc->value->data[j];
                    196: 
                    197:                        if (buffer_is_equal_string(du->key, CONST_STR_LEN("simple-vhost.server-root"))) {
                    198:                                PATCH(server_root);
                    199:                                PATCH(docroot_cache_key);
                    200:                                PATCH(docroot_cache_value);
                    201:                                PATCH(docroot_cache_servername);
                    202:                        } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("simple-vhost.default-host"))) {
                    203:                                PATCH(default_host);
                    204:                        } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("simple-vhost.document-root"))) {
                    205:                                PATCH(document_root);
                    206:                        } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("simple-vhost.debug"))) {
                    207:                                PATCH(debug);
                    208:                        }
                    209:                }
                    210:        }
                    211: 
                    212:        return 0;
                    213: }
                    214: #undef PATCH
                    215: 
                    216: static handler_t mod_simple_vhost_docroot(server *srv, connection *con, void *p_data) {
                    217:        plugin_data *p = p_data;
                    218: 
                    219:        /*
                    220:         * cache the last successfull translation from hostname (authority) to docroot
                    221:         * - this saves us a stat() call
                    222:         *
                    223:         */
                    224: 
                    225:        mod_simple_vhost_patch_connection(srv, con, p);
                    226: 
                    227:        /* build_doc_root() requires a server_root; skip module if simple-vhost.server-root is not set
                    228:         * or set to an empty string (especially don't cache any results!)
                    229:         */
                    230:        if (p->conf.server_root->used < 2) return HANDLER_GO_ON;
                    231: 
                    232:        if (p->conf.docroot_cache_key->used &&
                    233:            con->uri.authority->used &&
                    234:            buffer_is_equal(p->conf.docroot_cache_key, con->uri.authority)) {
                    235:                /* cache hit */
                    236:                buffer_copy_string_buffer(con->server_name,       p->conf.docroot_cache_servername);
                    237:                buffer_copy_string_buffer(con->physical.doc_root, p->conf.docroot_cache_value);
                    238:        } else {
                    239:                /* build document-root */
                    240:                if ((con->uri.authority->used == 0) ||
                    241:                    build_doc_root(srv, con, p, p->doc_root, con->uri.authority)) {
                    242:                        /* not found, fallback the default-host */
                    243:                        if (0 == build_doc_root(srv, con, p,
                    244:                                           p->doc_root,
                    245:                                           p->conf.default_host)) {
                    246:                                /* default host worked */
                    247:                                buffer_copy_string_buffer(con->server_name, p->conf.default_host);
                    248:                                buffer_copy_string_buffer(con->physical.doc_root, p->doc_root);
                    249:                                /* do not cache default host */
                    250:                        }
                    251:                        return HANDLER_GO_ON;
                    252:                }
                    253: 
                    254:                /* found host */
                    255:                buffer_copy_string_buffer(con->server_name, con->uri.authority);
                    256:                buffer_copy_string_buffer(con->physical.doc_root, p->doc_root);
                    257: 
                    258:                /* copy to cache */
                    259:                buffer_copy_string_buffer(p->conf.docroot_cache_key,        con->uri.authority);
                    260:                buffer_copy_string_buffer(p->conf.docroot_cache_value,      p->doc_root);
                    261:                buffer_copy_string_buffer(p->conf.docroot_cache_servername, con->server_name);
                    262:        }
                    263: 
                    264:        return HANDLER_GO_ON;
                    265: }
                    266: 
                    267: 
                    268: int mod_simple_vhost_plugin_init(plugin *p);
                    269: int mod_simple_vhost_plugin_init(plugin *p) {
                    270:        p->version     = LIGHTTPD_VERSION_ID;
                    271:        p->name        = buffer_init_string("simple_vhost");
                    272: 
                    273:        p->init        = mod_simple_vhost_init;
                    274:        p->set_defaults = mod_simple_vhost_set_defaults;
                    275:        p->handle_docroot  = mod_simple_vhost_docroot;
                    276:        p->cleanup     = mod_simple_vhost_free;
                    277: 
                    278:        p->data        = NULL;
                    279: 
                    280:        return 0;
                    281: }

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