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

1.1.1.3 ! misho       1: #include "first.h"
        !             2: 
1.1       misho       3: #include "plugin.h"
                      4: #include "log.h"
                      5: #include "response.h"
                      6: #include "stat_cache.h"
                      7: 
                      8: #include <string.h>
                      9: #include <errno.h>
                     10: #include <ctype.h>
                     11: 
                     12: typedef struct {
                     13:        /* unparsed pieces */
                     14:        buffer *path_pieces_raw;
                     15: 
                     16:        /* pieces for path creation */
                     17:        size_t len;
                     18:        buffer **path_pieces;
                     19: } plugin_config;
                     20: 
                     21: typedef struct {
                     22:        PLUGIN_DATA;
                     23:        buffer *tmp_buf;
                     24: 
                     25:        plugin_config **config_storage;
                     26:        plugin_config conf;
                     27: } plugin_data;
                     28: 
                     29: INIT_FUNC(mod_evhost_init) {
                     30:        plugin_data *p;
                     31: 
                     32:        p = calloc(1, sizeof(*p));
                     33: 
                     34:        p->tmp_buf = buffer_init();
                     35: 
                     36:        return p;
                     37: }
                     38: 
                     39: FREE_FUNC(mod_evhost_free) {
                     40:        plugin_data *p = p_d;
                     41: 
                     42:        UNUSED(srv);
                     43: 
                     44:        if (!p) return HANDLER_GO_ON;
                     45: 
                     46:        if (p->config_storage) {
                     47:                size_t i;
                     48:                for (i = 0; i < srv->config_context->used; i++) {
                     49:                        plugin_config *s = p->config_storage[i];
                     50: 
1.1.1.3 ! misho      51:                        if (NULL == s) continue;
1.1       misho      52: 
                     53:                        if(s->path_pieces) {
                     54:                                size_t j;
                     55:                                for (j = 0; j < s->len; j++) {
                     56:                                        buffer_free(s->path_pieces[j]);
                     57:                                }
                     58: 
                     59:                                free(s->path_pieces);
                     60:                        }
                     61: 
                     62:                        buffer_free(s->path_pieces_raw);
                     63: 
                     64:                        free(s);
                     65:                }
                     66:                free(p->config_storage);
                     67:        }
                     68: 
                     69:        buffer_free(p->tmp_buf);
                     70: 
                     71:        free(p);
                     72: 
                     73:        return HANDLER_GO_ON;
                     74: }
                     75: 
                     76: static void mod_evhost_parse_pattern(plugin_config *s) {
                     77:        char *ptr = s->path_pieces_raw->ptr,*pos;
                     78: 
                     79:        s->path_pieces = NULL;
                     80: 
                     81:        for(pos=ptr;*ptr;ptr++) {
                     82:                if(*ptr == '%') {
                     83:                        s->path_pieces = realloc(s->path_pieces,(s->len+2) * sizeof(*s->path_pieces));
                     84:                        s->path_pieces[s->len] = buffer_init();
                     85:                        s->path_pieces[s->len+1] = buffer_init();
                     86: 
                     87:                        buffer_copy_string_len(s->path_pieces[s->len],pos,ptr-pos);
                     88:                        pos = ptr + 2;
                     89: 
                     90:                        buffer_copy_string_len(s->path_pieces[s->len+1],ptr++,2);
                     91: 
                     92:                        s->len += 2;
                     93:                }
                     94:        }
                     95: 
                     96:        if(*pos != '\0') {
                     97:                s->path_pieces = realloc(s->path_pieces,(s->len+1) * sizeof(*s->path_pieces));
                     98:                s->path_pieces[s->len] = buffer_init();
                     99: 
                    100:                buffer_copy_string_len(s->path_pieces[s->len],pos,ptr-pos);
                    101: 
                    102:                s->len += 1;
                    103:        }
                    104: }
                    105: 
                    106: SETDEFAULTS_FUNC(mod_evhost_set_defaults) {
                    107:        plugin_data *p = p_d;
                    108:        size_t i;
                    109: 
                    110:        /**
                    111:         *
                    112:         * #
                    113:         * # define a pattern for the host url finding
                    114:         * # %% => % sign
                    115:         * # %0 => domain name + tld
                    116:         * # %1 => tld
                    117:         * # %2 => domain name without tld
                    118:         * # %3 => subdomain 1 name
                    119:         * # %4 => subdomain 2 name
                    120:         * # %_ => fqdn (without port info)
                    121:         * #
                    122:         * evhost.path-pattern = "/home/ckruse/dev/www/%3/htdocs/"
                    123:         *
                    124:         */
                    125: 
                    126:        config_values_t cv[] = {
                    127:                { "evhost.path-pattern",            NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
                    128:                { NULL,                             NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
                    129:        };
                    130: 
                    131:        if (!p) return HANDLER_ERROR;
                    132: 
1.1.1.2   misho     133:        p->config_storage = calloc(1, srv->config_context->used * sizeof(plugin_config *));
1.1       misho     134: 
                    135:        for (i = 0; i < srv->config_context->used; i++) {
1.1.1.3 ! misho     136:                data_config const* config = (data_config const*)srv->config_context->data[i];
1.1       misho     137:                plugin_config *s;
                    138: 
                    139:                s = calloc(1, sizeof(plugin_config));
                    140:                s->path_pieces_raw = buffer_init();
                    141:                s->path_pieces     = NULL;
                    142:                s->len             = 0;
                    143: 
                    144:                cv[0].destination = s->path_pieces_raw;
                    145: 
                    146:                p->config_storage[i] = s;
                    147: 
1.1.1.3 ! misho     148:                if (0 != config_insert_values_global(srv, config->value, cv, i == 0 ? T_CONFIG_SCOPE_SERVER : T_CONFIG_SCOPE_CONNECTION)) {
1.1       misho     149:                        return HANDLER_ERROR;
                    150:                }
                    151: 
1.1.1.3 ! misho     152:                if (!buffer_string_is_empty(s->path_pieces_raw)) {
1.1       misho     153:                        mod_evhost_parse_pattern(s);
                    154:                }
                    155:        }
                    156: 
                    157:        return HANDLER_GO_ON;
                    158: }
                    159: 
                    160: /**
                    161:  * assign the different parts of the domain to array-indezes (sub2.sub1.domain.tld)
                    162:  * - %0 - domain.tld
                    163:  * - %1 - tld
                    164:  * - %2 - domain
                    165:  * - %3 - sub1
                    166:  * - ...
                    167:  */
                    168: 
                    169: static int mod_evhost_parse_host(connection *con,array *host) {
1.1.1.3 ! misho     170:        register char *ptr = con->uri.authority->ptr + buffer_string_length(con->uri.authority);
1.1       misho     171:        char *colon = ptr; /* needed to filter out the colon (if exists) */
                    172:        int first = 1;
                    173:        data_string *ds;
                    174:        int i;
                    175: 
                    176:        /* first, find the domain + tld */
                    177:        for(;ptr > con->uri.authority->ptr;ptr--) {
                    178:                if(*ptr == '.') {
                    179:                        if(first) first = 0;
                    180:                        else      break;
                    181:                } else if(*ptr == ':') {
                    182:                        colon = ptr;
                    183:                        first = 1;
                    184:                }
                    185:        }
                    186: 
                    187:        ds = data_string_init();
                    188:        buffer_copy_string_len(ds->key,CONST_STR_LEN("%0"));
                    189: 
                    190:        /* if we stopped at a dot, skip the dot */
                    191:        if (*ptr == '.') ptr++;
                    192:        buffer_copy_string_len(ds->value, ptr, colon-ptr);
                    193: 
                    194:        array_insert_unique(host,(data_unset *)ds);
                    195: 
                    196:        /* if the : is not the start of the authority, go on parsing the hostname */
                    197: 
                    198:        if (colon != con->uri.authority->ptr) {
                    199:                for(ptr = colon - 1, i = 1; ptr > con->uri.authority->ptr; ptr--) {
                    200:                        if(*ptr == '.') {
                    201:                                if (ptr != colon - 1) {
                    202:                                        /* is something between the dots */
                    203:                                        ds = data_string_init();
                    204:                                        buffer_copy_string_len(ds->key,CONST_STR_LEN("%"));
1.1.1.3 ! misho     205:                                        buffer_append_int(ds->key, i++);
1.1       misho     206:                                        buffer_copy_string_len(ds->value,ptr+1,colon-ptr-1);
                    207: 
                    208:                                        array_insert_unique(host,(data_unset *)ds);
                    209:                                }
                    210:                                colon = ptr;
                    211:                        }
                    212:                }
                    213: 
                    214:                /* if the . is not the first charactor of the hostname */
                    215:                if (colon != ptr) {
                    216:                        ds = data_string_init();
                    217:                        buffer_copy_string_len(ds->key,CONST_STR_LEN("%"));
1.1.1.3 ! misho     218:                        buffer_append_int(ds->key, i /* ++ */);
1.1       misho     219:                        buffer_copy_string_len(ds->value,ptr,colon-ptr);
                    220: 
                    221:                        array_insert_unique(host,(data_unset *)ds);
                    222:                }
                    223:        }
                    224: 
                    225:        return 0;
                    226: }
                    227: 
                    228: #define PATCH(x) \
                    229:        p->conf.x = s->x;
                    230: static int mod_evhost_patch_connection(server *srv, connection *con, plugin_data *p) {
                    231:        size_t i, j;
                    232:        plugin_config *s = p->config_storage[0];
                    233: 
                    234:        PATCH(path_pieces);
                    235:        PATCH(len);
                    236: 
                    237:        /* skip the first, the global context */
                    238:        for (i = 1; i < srv->config_context->used; i++) {
                    239:                data_config *dc = (data_config *)srv->config_context->data[i];
                    240:                s = p->config_storage[i];
                    241: 
                    242:                /* condition didn't match */
                    243:                if (!config_check_cond(srv, con, dc)) continue;
                    244: 
                    245:                /* merge config */
                    246:                for (j = 0; j < dc->value->used; j++) {
                    247:                        data_unset *du = dc->value->data[j];
                    248: 
                    249:                        if (buffer_is_equal_string(du->key, CONST_STR_LEN("evhost.path-pattern"))) {
                    250:                                PATCH(path_pieces);
                    251:                                PATCH(len);
                    252:                        }
                    253:                }
                    254:        }
                    255: 
                    256:        return 0;
                    257: }
                    258: #undef PATCH
                    259: 
                    260: 
                    261: static handler_t mod_evhost_uri_handler(server *srv, connection *con, void *p_d) {
                    262:        plugin_data *p = p_d;
                    263:        size_t i;
                    264:        array *parsed_host;
                    265:        register char *ptr;
                    266:        int not_good = 0;
                    267:        stat_cache_entry *sce = NULL;
                    268: 
                    269:        /* not authority set */
1.1.1.3 ! misho     270:        if (buffer_string_is_empty(con->uri.authority)) return HANDLER_GO_ON;
1.1       misho     271: 
                    272:        mod_evhost_patch_connection(srv, con, p);
                    273: 
                    274:        /* missing even default(global) conf */
                    275:        if (0 == p->conf.len) {
                    276:                return HANDLER_GO_ON;
                    277:        }
                    278: 
                    279:        parsed_host = array_init();
                    280: 
                    281:        mod_evhost_parse_host(con, parsed_host);
                    282: 
                    283:        /* build document-root */
                    284:        buffer_reset(p->tmp_buf);
                    285: 
                    286:        for (i = 0; i < p->conf.len; i++) {
                    287:                ptr = p->conf.path_pieces[i]->ptr;
                    288:                if (*ptr == '%') {
                    289:                        data_string *ds;
                    290: 
                    291:                        if (*(ptr+1) == '%') {
                    292:                                /* %% */
                    293:                                buffer_append_string_len(p->tmp_buf,CONST_STR_LEN("%"));
                    294:                        } else if (*(ptr+1) == '_' ) {
                    295:                                /* %_ == full hostname */
                    296:                                char *colon = strchr(con->uri.authority->ptr, ':');
                    297: 
                    298:                                if(colon == NULL) {
                    299:                                        buffer_append_string_buffer(p->tmp_buf, con->uri.authority); /* adds fqdn */
                    300:                                } else {
                    301:                                        /* strip the port out of the authority-part of the URI scheme */
                    302:                                        buffer_append_string_len(p->tmp_buf, con->uri.authority->ptr, colon - con->uri.authority->ptr); /* adds fqdn */
                    303:                                }
                    304:                        } else if (NULL != (ds = (data_string *)array_get_element(parsed_host,p->conf.path_pieces[i]->ptr))) {
1.1.1.3 ! misho     305:                                buffer_append_string_buffer(p->tmp_buf,ds->value);
1.1       misho     306:                        } else {
                    307:                                /* unhandled %-sequence */
                    308:                        }
                    309:                } else {
                    310:                        buffer_append_string_buffer(p->tmp_buf,p->conf.path_pieces[i]);
                    311:                }
                    312:        }
                    313: 
1.1.1.3 ! misho     314:        buffer_append_slash(p->tmp_buf);
1.1       misho     315: 
                    316:        array_free(parsed_host);
                    317: 
                    318:        if (HANDLER_ERROR == stat_cache_get_entry(srv, con, p->tmp_buf, &sce)) {
                    319:                log_error_write(srv, __FILE__, __LINE__, "sb", strerror(errno), p->tmp_buf);
                    320:                not_good = 1;
                    321:        } else if(!S_ISDIR(sce->st.st_mode)) {
                    322:                log_error_write(srv, __FILE__, __LINE__, "sb", "not a directory:", p->tmp_buf);
                    323:                not_good = 1;
                    324:        }
                    325: 
                    326:        if (!not_good) {
1.1.1.3 ! misho     327:                buffer_copy_buffer(con->physical.doc_root, p->tmp_buf);
1.1       misho     328:        }
                    329: 
                    330:        return HANDLER_GO_ON;
                    331: }
                    332: 
                    333: int mod_evhost_plugin_init(plugin *p);
                    334: int mod_evhost_plugin_init(plugin *p) {
                    335:        p->version     = LIGHTTPD_VERSION_ID;
                    336:        p->name                    = buffer_init_string("evhost");
                    337:        p->init                    = mod_evhost_init;
                    338:        p->set_defaults            = mod_evhost_set_defaults;
                    339:        p->handle_docroot          = mod_evhost_uri_handler;
                    340:        p->cleanup                 = mod_evhost_free;
                    341: 
                    342:        p->data                    = NULL;
                    343: 
                    344:        return 0;
                    345: }
                    346: 
                    347: /* eof */

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