📄 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 + -