view src/http/ngx_http_config.c @ 140:55a211e5eeb7 NGINX_0_3_17

nginx 0.3.17 *) Change: now on Linux configure checks the presence of epoll and sendfile64() in kernel. *) Feature: the "map" directive supports domain names in the ".domain.tld" form. *) Bugfix: the timeouts were not used in SSL handshake; bug appeared in 0.2.4. *) Bugfix: in the HTTPS protocol in the "proxy_pass" directive. *) Bugfix: when the HTTPS protocol was used in the "proxy_pass" directive the port 80 was used by default.
author Igor Sysoev <http://sysoev.ru>
date Sun, 18 Dec 2005 00:00:00 +0300
parents
children
line wrap: on
line source


/*
 * Copyright (C) Igor Sysoev
 */


#include <ngx_config.h>
#include <ngx_core.h>
#include <ngx_event.h>
#include <ngx_http.h>


ngx_int_t
ngx_http_config_add_hash(ngx_http_hash_conf_t *h, ngx_str_t *key, void *value,
    ngx_uint_t flags)
{
    size_t           len;
    ngx_str_t       *name;
    ngx_uint_t       i, k, n, skip;
    ngx_hash_key_t  *hk;
    u_char           buf[2048];

    if (!(flags & NGX_HTTP_WILDCARD_HASH)) {

        /* exact hash */

        k = 0;

        for (i = 0; i < key->len; i++) {
            key->data[i] = ngx_tolower(key->data[i]);
            k = ngx_hash(k, key->data[i]);
        }

        k %= NGX_HTTP_CONFIG_HASH;

        /* check conflicts in exact hash */

        name = h->keys_hash[k].elts;

        if (name) {
            for (i = 0; i < h->keys_hash[k].nelts; i++) {
                if (key->len != name[i].len) {
                    continue;
                }

                if (ngx_strncmp(key->data, name[i].data, key->len) == 0) {
                    return NGX_BUSY;
                }
            }

        } else {
            if (ngx_array_init(&h->keys_hash[k], h->temp_pool, 4,
                               sizeof(ngx_str_t))
                != NGX_OK)
            {
                return NGX_ERROR;
            }
        }

        name = ngx_array_push(&h->keys_hash[k]);
        if (name == NULL) {
            return NGX_ERROR;
        }

        *name = *key;

        hk = ngx_array_push(&h->keys);
        if (hk == NULL) {
            return NGX_ERROR;
        }

        hk->key = *key;
        hk->key_hash = ngx_hash_key(key->data, key->len);
        hk->value = value;

    } else {

        /* wildcard hash */

        skip = (key->data[0] == '*') ? 2 : 1;
        k = 0;

        for (i = skip; i < key->len; i++) {
            key->data[i] = ngx_tolower(key->data[i]);
            k = ngx_hash(k, key->data[i]);
        }

        k %= NGX_HTTP_CONFIG_HASH;

        if (skip == 1) {

            /* check conflicts in exact hash for ".example.com" */

            name = h->keys_hash[k].elts;

            if (name) {
                len = key->len - skip;

                for (i = 0; i < h->keys_hash[k].nelts; i++) {
                    if (len != name[i].len) {
                        continue;
                    }

                    if (ngx_strncmp(&key->data[1], name[i].data, len) == 0) {
                        return NGX_BUSY;
                    }
                }

            } else {
                if (ngx_array_init(&h->keys_hash[k], h->temp_pool, 4,
                                   sizeof(ngx_str_t))
                    != NGX_OK)
                {
                    return NGX_ERROR;
                }
            }

            name = ngx_array_push(&h->keys_hash[k]);
            if (name == NULL) {
                return NGX_ERROR;
            }

            name->len = key->len - 1;
            name->data = ngx_palloc(h->temp_pool, name->len);
            if (name->data == NULL) {
                return NGX_ERROR;
            }

            ngx_memcpy(name->data, &key->data[1], name->len);
        }


        /*
         * convert "*.example.com" to "com.example.\0"
         *      and ".example.com" to "com.example\0"
         */

        len = 0;
        n = 0;

        for (i = key->len - 1; i; i--) {
            if (key->data[i] == '.') {
                ngx_memcpy(&buf[n], &key->data[i + 1], len);
                n += len;
                buf[n++] = '.';
                len = 0;
                continue;
            }

            len++;
        }

        if (len) {
            ngx_memcpy(&buf[n], &key->data[1], len);
            n += len;
        }

        buf[n] = '\0';


        /* check conflicts in wildcard hash */

        name = h->dns_hash[k].elts;

        if (name) {
            len = key->len - skip;

            for (i = 0; i < h->dns_hash[k].nelts; i++) {
                if (len != name[i].len) {
                    continue;
                }

                if (ngx_strncmp(key->data + skip, name[i].data, len) == 0) {
                    return NGX_BUSY;
                }
            }

        } else {
            if (ngx_array_init(&h->dns_hash[k], h->temp_pool, 4,
                               sizeof(ngx_str_t))
                != NGX_OK)
            {
                return NGX_ERROR;
            }
        }

        name = ngx_array_push(&h->dns_hash[k]);
        if (name == NULL) {
            return NGX_ERROR;
        }

        name->len = key->len - skip;
        name->data = ngx_palloc(h->temp_pool, name->len);
        if (name->data == NULL) {
            return NGX_ERROR;
        }
        ngx_memcpy(name->data, key->data + skip, name->len);


        ngx_memcpy(key->data, buf, key->len);
        key->len--;

        hk = ngx_array_push(&h->dns_wildcards);
        if (hk == NULL) {
            return NGX_ERROR;
        }

        hk->key = *key;
        hk->key_hash = 0;
        hk->value = value;
    }

    return NGX_OK;
}