⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 alias.c

📁 boa 一个简小的web服务器 资源占用极少
💻 C
📖 第 1 页 / 共 2 页
字号:
/*
 *  Boa, an http server
 *  Copyright (C) 1995 Paul Phillips <paulp@go2net.com>
 *  Some changes Copyright (C) 1996 Larry Doolittle <ldoolitt@boa.org>
 *  Some changes Copyright (C) 1996 Russ Nelson <nelson@crynwr.com>
 *  Some changes Copyright (C) 1996-2002 Jon Nelson <jnelson@boa.org>
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 1, or (at your option)
 *  any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 */

/* $Id: alias.c,v 1.70.2.4 2002/07/28 02:46:52 jnelson Exp $ */

#include "boa.h"

static alias *alias_hashtable[ALIAS_HASHTABLE_SIZE];

int get_alias_hash_value(char *file);

/*
 * Name: get_alias_hash_value
 *
 * Description: adds the ASCII values of the file letters
 * and mods by the hashtable size to get the hash value
 * Note: stops at first '/' (or '\0')
 */

int get_alias_hash_value(char *file)
{
    unsigned int hash = 0;
    unsigned int index = 0;
    unsigned char c;

    hash = file[index++];
    while ((c = file[index++]) && c != '/')
        hash += (unsigned int) c;

    return hash % ALIAS_HASHTABLE_SIZE;
}

/*
 * Name: add_alias
 *
 * Description: add an Alias, Redirect, or ScriptAlias to the
 * alias hash table.
 */

void add_alias(char *fakename, char *realname, int type)
{
    int hash;
    alias *old, *new;
    int fakelen, reallen;

    /* sanity checking */
    if (fakename == NULL || realname == NULL) {
        DIE("NULL values sent to add_alias");
    }

    fakelen = strlen(fakename);
    reallen = strlen(realname);
    if (fakelen == 0 || reallen == 0) {
        DIE("empty values sent to add_alias");
    }

    hash = get_alias_hash_value(fakename);

    old = alias_hashtable[hash];

    if (old) {
        while (old->next) {
            if (!strcmp(fakename, old->fakename)) /* don't add twice */
                return;
            old = old->next;
        }
    }

    new = (alias *) malloc(sizeof (alias));
    if (!new) {
        DIE("out of memory adding alias to hash");
    }

    if (old)
        old->next = new;
    else
        alias_hashtable[hash] = new;

    new->fakename = strdup(fakename);
    if (!new->fakename) {
        DIE("failed strdup");
    }
    new->fake_len = fakelen;
    /* check for "here" */
    if (realname[0] == '.' && realname[1] == '/') {
        new->realname = normalize_path(realname+2);
        if (!new->realname) {
            /* superfluous - normalize_path checks for NULL return values. */
            DIE("normalize_path returned NULL");
        }
        reallen = strlen(new->realname);
    } else {
        new->realname = strdup(realname);
        if (!new->realname) {
            DIE("strdup of realname failed");
        }
    }
    new->real_len = reallen;

    new->type = type;
    new->next = NULL;
}

/*
 * Name: find_alias
 *
 * Description: Locates uri in the alias hashtable if it exists.
 *
 * Returns:
 *
 * alias structure or NULL if not found
 */

alias *find_alias(char *uri, int urilen)
{
    alias *current;
    int hash;

    /* Find ScriptAlias, Alias, or Redirect */

    if (urilen == 0)
        urilen = strlen(uri);
    hash = get_alias_hash_value(uri);

    current = alias_hashtable[hash];
    while (current) {
#ifdef FASCIST_LOGGING
        fprintf(stderr,
                "%s:%d - comparing \"%s\" (request) to \"%s\" (alias): ",
                __FILE__, __LINE__, uri, current->fakename);
#endif
        /* current->fake_len must always be:
         *  shorter or equal to the uri
         */
        /*
         * when performing matches:
         * If the virtual part of the url ends in '/', and
         * we get a match, stop there.
         * Otherwise, we require '/' or '\0' at the end of the url.
         * We only check if the virtual path does *not* end in '/'
         */
        if (current->fake_len <= urilen &&
            !memcmp(uri, current->fakename, current->fake_len) &&
            (current->fakename[current->fake_len - 1] == '/' ||
             (current->fakename[current->fake_len - 1] != '/' &&
              (uri[current->fake_len] == '\0' ||
               uri[current->fake_len] == '/')))) {
#ifdef FASCIST_LOGGING
                fprintf(stderr, "Got it!\n");
#endif
                return current;
        }
#ifdef FASCIST_LOGGING
        else
            fprintf(stderr, "Don't Got it!\n");
#endif
        current = current->next;
    }
    return current;
}

/*
 * Name: translate_uri
 *
 * Description: Parse a request's virtual path.
 * Sets query_string, pathname directly.
 * Also sets path_info, path_translated, and script_name via
 *  init_script_alias
 *
 * Note: NPH in user dir is currently broken
 *
 * Note -- this should be broken up.
 *
 * Return values:
 *   0: failure, close it down
 *   1: success, continue
 */

int translate_uri(request * req)
{
    static char buffer[MAX_HEADER_LENGTH + 1];
    char *req_urip;
    alias *current;
    char *p;
    int uri_len;

    req_urip = req->request_uri;
    if (req_urip[0] != '/') {
        send_r_bad_request(req);
        return 0;
    }

    uri_len = strlen(req->request_uri);

    current = find_alias(req->request_uri, uri_len);
    if (current) {

        if (current->type == SCRIPTALIAS) /* Script */
            return init_script_alias(req, current, uri_len);

        /* not a script alias, therefore begin filling in data */

        {
            int len;
            len = current->real_len;
            len += uri_len - current->fake_len;
            if (len > MAX_HEADER_LENGTH) {
                log_error_doc(req);
                fputs("uri too long!\n", stderr);
                send_r_bad_request(req);
                return 0;
            }
            memcpy(buffer, current->realname, current->real_len);
            memcpy(buffer + current->real_len,
                   req->request_uri + current->fake_len,
                   uri_len - current->fake_len + 1);
        }

        if (current->type == REDIRECT) { /* Redirect */
            if (req->method == M_POST) { /* POST to non-script */
                /* it's not a cgi, but we try to POST??? */
                send_r_bad_request(req);
                return 0;       /* not a script alias, therefore begin filling in data */
            }
            send_r_moved_temp(req, buffer, "");
            return 0;
        } else {                /* Alias */
            req->pathname = strdup(buffer);
            if (!req->pathname) {
                send_r_error(req);
                WARN("unable to strdup buffer onto req->pathname");
                return 0;
            }
            return 1;
        }
    }

    /*
       The reason why this is *not* an 'else if' is that,
       after aliasing, we still have to check for '~' expansion
     */

    if (user_dir && req->request_uri[1] == '~') {
        char *user_homedir;

        req_urip = req->request_uri + 2;

        /* since we have uri_len which is from strlen(req->request_uri) */
        p = memchr(req_urip, '/', uri_len - 2);
        if (p)
            *p = '\0';

        user_homedir = get_home_dir(req_urip);
        if (p)                  /* have to restore request_uri in case of error */
            *p = '/';

        if (!user_homedir) {    /*no such user */
            send_r_not_found(req);
            return 0;
        }
        {
            int l1 = strlen(user_homedir);
            int l2 = strlen(user_dir);
            int l3 = (p ? strlen(p) : 0);

            if (l1 + l2 + l3 + 1 > MAX_HEADER_LENGTH) {
                log_error_doc(req);
                fputs("uri too long!\n", stderr);
                send_r_bad_request(req);
                return 0;
            }

            memcpy(buffer, user_homedir, l1);
            buffer[l1] = '/';
            memcpy(buffer + l1 + 1, user_dir, l2 + 1);
            if (p)
                memcpy(buffer + l1 + 1 + l2, p, l3 + 1);
        }
    } else if (document_root) {
        /* no aliasing, no userdir... */
        int l1, l2, l3;

        l1 = strlen(document_root);
        l2 = strlen(req->request_uri);
        if (virtualhost)
            l3 = strlen(req->local_ip_addr);
        else
            l3 = 0;

        if (l1 + l2 + l3 + 1 > MAX_HEADER_LENGTH) {
            log_error_doc(req);
            fputs("uri too long!\n", stderr);
            send_r_bad_request(req);
            return 0;
        }

        /* the 'l2 + 1' is there so we copy the '\0' as well */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -