📄 alias.c
字号:
/* * 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 + -