mirror of
https://github.com/apache/httpd.git
synced 2025-08-06 11:06:17 +00:00

Obtained from: Apache 1.3.9 (minus unused files), tag APACHE_1_3_9 Submitted by: Apache Group git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@83751 13f79535-47bb-0310-9956-ffa450edef68
498 lines
18 KiB
C
498 lines
18 KiB
C
/* ====================================================================
|
|
* Copyright (c) 1996-1999 The Apache Group. All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
*
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
*
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in
|
|
* the documentation and/or other materials provided with the
|
|
* distribution.
|
|
*
|
|
* 3. All advertising materials mentioning features or use of this
|
|
* software must display the following acknowledgment:
|
|
* "This product includes software developed by the Apache Group
|
|
* for use in the Apache HTTP server project (http://www.apache.org/)."
|
|
*
|
|
* 4. The names "Apache Server" and "Apache Group" must not be used to
|
|
* endorse or promote products derived from this software without
|
|
* prior written permission. For written permission, please contact
|
|
* apache@apache.org.
|
|
*
|
|
* 5. Products derived from this software may not be called "Apache"
|
|
* nor may "Apache" appear in their names without prior written
|
|
* permission of the Apache Group.
|
|
*
|
|
* 6. Redistributions of any form whatsoever must retain the following
|
|
* acknowledgment:
|
|
* "This product includes software developed by the Apache Group
|
|
* for use in the Apache HTTP server project (http://www.apache.org/)."
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY
|
|
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE APACHE GROUP OR
|
|
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
|
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
|
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
|
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
* ====================================================================
|
|
*
|
|
* This software consists of voluntary contributions made by many
|
|
* individuals on behalf of the Apache Group and was originally based
|
|
* on public domain software written at the National Center for
|
|
* Supercomputing Applications, University of Illinois, Urbana-Champaign.
|
|
* For more information on the Apache Group and the Apache HTTP server
|
|
* project, please see <http://www.apache.org/>.
|
|
*
|
|
*/
|
|
|
|
|
|
#ifndef _MOD_REWRITE_H
|
|
#define _MOD_REWRITE_H 1
|
|
|
|
/*
|
|
** _ _ _
|
|
** _ __ ___ ___ __| | _ __ _____ ___ __(_) |_ ___
|
|
** | '_ ` _ \ / _ \ / _` | | '__/ _ \ \ /\ / / '__| | __/ _ \
|
|
** | | | | | | (_) | (_| | | | | __/\ V V /| | | | || __/
|
|
** |_| |_| |_|\___/ \__,_|___|_| \___| \_/\_/ |_| |_|\__\___|
|
|
** |_____|
|
|
**
|
|
** URL Rewriting Module
|
|
**
|
|
** This module uses a rule-based rewriting engine (based on a
|
|
** regular-expression parser) to rewrite requested URLs on the fly.
|
|
**
|
|
** It supports an unlimited number of additional rule conditions (which can
|
|
** operate on a lot of variables, even on HTTP headers) for granular
|
|
** matching and even external database lookups (either via plain text
|
|
** tables, DBM hash files or even external processes) for advanced URL
|
|
** substitution.
|
|
**
|
|
** It operates on the full URLs (including the PATH_INFO part) both in
|
|
** per-server context (httpd.conf) and per-dir context (.htaccess) and even
|
|
** can generate QUERY_STRING parts on result. The rewriting result finally
|
|
** can lead to internal subprocessing, external request redirection or even
|
|
** to internal proxy throughput.
|
|
**
|
|
** This module was originally written in April 1996 and
|
|
** gifted exclusively to the The Apache Group in July 1997 by
|
|
**
|
|
** Ralf S. Engelschall
|
|
** rse@engelschall.com
|
|
** www.engelschall.com
|
|
*/
|
|
|
|
|
|
/* Include from the underlaying Unix system ... */
|
|
#include <string.h>
|
|
#include <stdarg.h>
|
|
#include <stdlib.h>
|
|
#include <time.h>
|
|
#include <signal.h>
|
|
#include <errno.h>
|
|
#include <ctype.h>
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
|
|
/* Include from the Apache server ... */
|
|
#define CORE_PRIVATE
|
|
#include "httpd.h"
|
|
#include "http_config.h"
|
|
#include "http_conf_globals.h"
|
|
#include "http_request.h"
|
|
#include "http_core.h"
|
|
#include "http_log.h"
|
|
#include "http_vhost.h"
|
|
|
|
/*
|
|
* The key in the r->notes table wherein we store our accumulated
|
|
* Vary values, and the one used for per-condition checks in a chain.
|
|
*/
|
|
#define VARY_KEY "rewrite-Vary"
|
|
#define VARY_KEY_THIS "rewrite-Vary-this"
|
|
|
|
/* The NDBM support:
|
|
* We support only NDBM files.
|
|
* But we have to stat the file for the mtime,
|
|
* so we also need to know the file extension
|
|
*/
|
|
#ifndef NO_DBM_REWRITEMAP
|
|
#if defined(__GLIBC__) && defined(__GLIBC_MINOR__) \
|
|
&& __GLIBC__ >= 2 && __GLIBC_MINOR__ >= 1
|
|
#include <db1/ndbm.h>
|
|
#else
|
|
#include <ndbm.h>
|
|
#endif
|
|
#if defined(DBM_SUFFIX)
|
|
#define NDBM_FILE_SUFFIX DBM_SUFFIX
|
|
#elif defined(__FreeBSD__) || (defined(DB_LOCK) && defined(DB_SHMEM))
|
|
#define NDBM_FILE_SUFFIX ".db"
|
|
#else
|
|
#define NDBM_FILE_SUFFIX ".pag"
|
|
#endif
|
|
#endif
|
|
|
|
|
|
/* The locking support:
|
|
* Try to determine whether we should use fcntl() or flock().
|
|
* Would be better ap_config.h could provide this... :-(
|
|
*/
|
|
#if defined(USE_FCNTL_SERIALIZED_ACCEPT)
|
|
#define USE_FCNTL 1
|
|
#include <fcntl.h>
|
|
#endif
|
|
#if defined(USE_FLOCK_SERIALIZED_ACCEPT)
|
|
#define USE_FLOCK 1
|
|
#include <sys/file.h>
|
|
#endif
|
|
#if !defined(USE_FCNTL) && !defined(USE_FLOCK)
|
|
#define USE_FLOCK 1
|
|
#if !defined(MPE) && !defined(WIN32) && !defined(__TANDEM)
|
|
#include <sys/file.h>
|
|
#endif
|
|
#ifndef LOCK_UN
|
|
#undef USE_FLOCK
|
|
#define USE_FCNTL 1
|
|
#include <fcntl.h>
|
|
#endif
|
|
#endif
|
|
#ifdef AIX
|
|
#undef USE_FLOCK
|
|
#define USE_FCNTL 1
|
|
#include <fcntl.h>
|
|
#endif
|
|
#ifdef WIN32
|
|
#undef USE_FCNTL
|
|
#define USE_LOCKING
|
|
#include <sys/locking.h>
|
|
#endif
|
|
|
|
|
|
/*
|
|
**
|
|
** Some defines
|
|
**
|
|
*/
|
|
|
|
#define ENVVAR_SCRIPT_URL "SCRIPT_URL"
|
|
#define ENVVAR_SCRIPT_URI "SCRIPT_URI"
|
|
|
|
#ifndef SUPPORT_DBM_REWRITEMAP
|
|
#define SUPPORT_DBM_REWRITEMAP 0
|
|
#endif
|
|
|
|
#define REWRITE_FORCED_MIMETYPE_NOTEVAR "rewrite-forced-mimetype"
|
|
|
|
#define CONDFLAG_NONE 1<<0
|
|
#define CONDFLAG_NOCASE 1<<1
|
|
#define CONDFLAG_NOTMATCH 1<<2
|
|
#define CONDFLAG_ORNEXT 1<<3
|
|
|
|
#define RULEFLAG_NONE 1<<0
|
|
#define RULEFLAG_FORCEREDIRECT 1<<1
|
|
#define RULEFLAG_LASTRULE 1<<2
|
|
#define RULEFLAG_NEWROUND 1<<3
|
|
#define RULEFLAG_CHAIN 1<<4
|
|
#define RULEFLAG_IGNOREONSUBREQ 1<<5
|
|
#define RULEFLAG_NOTMATCH 1<<6
|
|
#define RULEFLAG_PROXY 1<<7
|
|
#define RULEFLAG_PASSTHROUGH 1<<8
|
|
#define RULEFLAG_FORBIDDEN 1<<9
|
|
#define RULEFLAG_GONE 1<<10
|
|
#define RULEFLAG_QSAPPEND 1<<11
|
|
#define RULEFLAG_NOCASE 1<<12
|
|
|
|
#define MAPTYPE_TXT 1<<0
|
|
#define MAPTYPE_DBM 1<<1
|
|
#define MAPTYPE_PRG 1<<2
|
|
#define MAPTYPE_INT 1<<3
|
|
#define MAPTYPE_RND 1<<4
|
|
|
|
#define ENGINE_DISABLED 1<<0
|
|
#define ENGINE_ENABLED 1<<1
|
|
|
|
#define OPTION_NONE 1<<0
|
|
#define OPTION_INHERIT 1<<1
|
|
|
|
#define CACHEMODE_TS 1<<0
|
|
#define CACHEMODE_TTL 1<<1
|
|
|
|
#define CACHE_TLB_ROWS 1024
|
|
#define CACHE_TLB_COLS 4
|
|
|
|
#ifndef FALSE
|
|
#define FALSE 0
|
|
#define TRUE !FALSE
|
|
#endif
|
|
|
|
#ifndef NO
|
|
#define NO FALSE
|
|
#define YES TRUE
|
|
#endif
|
|
|
|
#ifndef RAND_MAX
|
|
#define RAND_MAX 32767
|
|
#endif
|
|
|
|
#ifndef LONG_STRING_LEN
|
|
#define LONG_STRING_LEN 2048
|
|
#endif
|
|
|
|
#define MAX_ENV_FLAGS 15
|
|
|
|
#define MAX_NMATCH 10
|
|
|
|
/*
|
|
**
|
|
** our private data structures we handle with
|
|
**
|
|
*/
|
|
|
|
/* the list structures for holding the mapfile information
|
|
* and the rewrite rules
|
|
*/
|
|
typedef struct {
|
|
char *name; /* the name of the map */
|
|
char *datafile; /* filename for map data files */
|
|
char *checkfile; /* filename to check for map existence */
|
|
int type; /* the type of the map */
|
|
int fpin; /* in file pointer for program maps */
|
|
int fpout; /* out file pointer for program maps */
|
|
int fperr; /* err file pointer for program maps */
|
|
char *(*func)(request_rec *, /* function pointer for internal maps */
|
|
char *);
|
|
} rewritemap_entry;
|
|
|
|
typedef struct {
|
|
char *input; /* Input string of RewriteCond */
|
|
char *pattern; /* the RegExp pattern string */
|
|
regex_t *regexp;
|
|
int flags; /* Flags which control the match */
|
|
} rewritecond_entry;
|
|
|
|
typedef struct {
|
|
array_header *rewriteconds; /* the corresponding RewriteCond entries */
|
|
char *pattern; /* the RegExp pattern string */
|
|
regex_t *regexp; /* the RegExp pattern compilation */
|
|
char *output; /* the Substitution string */
|
|
int flags; /* Flags which control the substitution */
|
|
char *forced_mimetype; /* forced MIME type of substitution */
|
|
int forced_responsecode; /* forced HTTP redirect response status */
|
|
char *env[MAX_ENV_FLAGS+1]; /* added environment variables */
|
|
int skip; /* number of next rules to skip */
|
|
} rewriterule_entry;
|
|
|
|
|
|
/* the per-server or per-virtual-server configuration
|
|
* statically generated once on startup for every server
|
|
*/
|
|
typedef struct {
|
|
int state; /* the RewriteEngine state */
|
|
int options; /* the RewriteOption state */
|
|
char *rewritelogfile; /* the RewriteLog filename */
|
|
int rewritelogfp; /* the RewriteLog open filepointer */
|
|
int rewriteloglevel; /* the RewriteLog level of verbosity */
|
|
array_header *rewritemaps; /* the RewriteMap entries */
|
|
array_header *rewriteconds; /* the RewriteCond entries (temporary) */
|
|
array_header *rewriterules; /* the RewriteRule entries */
|
|
server_rec *server; /* the corresponding server indicator */
|
|
} rewrite_server_conf;
|
|
|
|
|
|
/* the per-directory configuration
|
|
* generated on-the-fly by Apache server for current request
|
|
*/
|
|
typedef struct {
|
|
int state; /* the RewriteEngine state */
|
|
int options; /* the RewriteOption state */
|
|
array_header *rewriteconds; /* the RewriteCond entries (temporary) */
|
|
array_header *rewriterules; /* the RewriteRule entries */
|
|
char *directory; /* the directory where it applies */
|
|
char *baseurl; /* the base-URL where it applies */
|
|
} rewrite_perdir_conf;
|
|
|
|
|
|
/* the cache structures,
|
|
* a 4-way hash table with LRU functionality
|
|
*/
|
|
typedef struct cacheentry {
|
|
time_t time;
|
|
char *key;
|
|
char *value;
|
|
} cacheentry;
|
|
|
|
typedef struct tlbentry {
|
|
int t[CACHE_TLB_COLS];
|
|
} cachetlbentry;
|
|
|
|
typedef struct cachelist {
|
|
char *resource;
|
|
array_header *entries;
|
|
array_header *tlb;
|
|
} cachelist;
|
|
|
|
typedef struct cache {
|
|
pool *pool;
|
|
array_header *lists;
|
|
} cache;
|
|
|
|
|
|
/* the regex structure for the
|
|
* substitution of backreferences
|
|
*/
|
|
typedef struct backrefinfo {
|
|
char *source;
|
|
int nsub;
|
|
regmatch_t regmatch[10];
|
|
} backrefinfo;
|
|
|
|
|
|
/*
|
|
**
|
|
** forward declarations
|
|
**
|
|
*/
|
|
|
|
/* config structure handling */
|
|
static void *config_server_create(pool *p, server_rec *s);
|
|
static void *config_server_merge (pool *p, void *basev, void *overridesv);
|
|
static void *config_perdir_create(pool *p, char *path);
|
|
static void *config_perdir_merge (pool *p, void *basev, void *overridesv);
|
|
|
|
/* config directive handling */
|
|
static const char *cmd_rewriteengine(cmd_parms *cmd,
|
|
rewrite_perdir_conf *dconf, int flag);
|
|
static const char *cmd_rewriteoptions(cmd_parms *cmd,
|
|
rewrite_perdir_conf *dconf,
|
|
char *option);
|
|
static const char *cmd_rewriteoptions_setoption(pool *p, int *options,
|
|
char *name);
|
|
static const char *cmd_rewritelog (cmd_parms *cmd, void *dconf, char *a1);
|
|
static const char *cmd_rewriteloglevel(cmd_parms *cmd, void *dconf, char *a1);
|
|
static const char *cmd_rewritemap (cmd_parms *cmd, void *dconf, char *a1,
|
|
char *a2);
|
|
static const char *cmd_rewritelock(cmd_parms *cmd, void *dconf, char *a1);
|
|
static const char *cmd_rewritebase(cmd_parms *cmd, rewrite_perdir_conf *dconf,
|
|
char *a1);
|
|
static const char *cmd_rewritecond(cmd_parms *cmd, rewrite_perdir_conf *dconf,
|
|
char *str);
|
|
static const char *cmd_rewritecond_parseflagfield(pool *p,
|
|
rewritecond_entry *new,
|
|
char *str);
|
|
static const char *cmd_rewritecond_setflag(pool *p, rewritecond_entry *cfg,
|
|
char *key, char *val);
|
|
static const char *cmd_rewriterule(cmd_parms *cmd, rewrite_perdir_conf *dconf,
|
|
char *str);
|
|
static const char *cmd_rewriterule_parseflagfield(pool *p,
|
|
rewriterule_entry *new,
|
|
char *str);
|
|
static const char *cmd_rewriterule_setflag(pool *p, rewriterule_entry *cfg,
|
|
char *key, char *val);
|
|
|
|
/* initialisation */
|
|
static void init_module(server_rec *s, pool *p);
|
|
static void init_child(server_rec *s, pool *p);
|
|
|
|
/* runtime hooks */
|
|
static int hook_uri2file (request_rec *r);
|
|
static int hook_mimetype (request_rec *r);
|
|
static int hook_fixup (request_rec *r);
|
|
static int handler_redirect(request_rec *r);
|
|
|
|
/* rewriting engine */
|
|
static int apply_rewrite_list(request_rec *r, array_header *rewriterules,
|
|
char *perdir);
|
|
static int apply_rewrite_rule(request_rec *r, rewriterule_entry *p,
|
|
char *perdir);
|
|
static int apply_rewrite_cond(request_rec *r, rewritecond_entry *p,
|
|
char *perdir, backrefinfo *briRR,
|
|
backrefinfo *briRC);
|
|
|
|
/* URI transformation function */
|
|
static void splitout_queryargs(request_rec *r, int qsappend);
|
|
static void fully_qualify_uri(request_rec *r);
|
|
static void reduce_uri(request_rec *r);
|
|
static void expand_backref_inbuffer(pool *p, char *buf, int nbuf,
|
|
backrefinfo *bri, char c);
|
|
static char *expand_tildepaths(request_rec *r, char *uri);
|
|
static void expand_map_lookups(request_rec *r, char *uri, int uri_len);
|
|
|
|
/* rewrite map support functions */
|
|
static char *lookup_map(request_rec *r, char *name, char *key);
|
|
static char *lookup_map_txtfile(request_rec *r, char *file, char *key);
|
|
#ifndef NO_DBM_REWRITEMAP
|
|
static char *lookup_map_dbmfile(request_rec *r, char *file, char *key);
|
|
#endif
|
|
static char *lookup_map_program(request_rec *r, int fpin,
|
|
int fpout, char *key);
|
|
static char *lookup_map_internal(request_rec *r,
|
|
char *(*func)(request_rec *r, char *key),
|
|
char *key);
|
|
static char *rewrite_mapfunc_toupper(request_rec *r, char *key);
|
|
static char *rewrite_mapfunc_tolower(request_rec *r, char *key);
|
|
static char *rewrite_mapfunc_escape(request_rec *r, char *key);
|
|
static char *rewrite_mapfunc_unescape(request_rec *r, char *key);
|
|
static char *select_random_value_part(request_rec *r, char *value);
|
|
static void rewrite_rand_init(void);
|
|
static int rewrite_rand(int l, int h);
|
|
|
|
/* rewriting logfile support */
|
|
static void open_rewritelog(server_rec *s, pool *p);
|
|
static void rewritelog(request_rec *r, int level, const char *text, ...)
|
|
__attribute__((format(printf,3,4)));
|
|
static char *current_logtime(request_rec *r);
|
|
|
|
/* rewriting lockfile support */
|
|
static void rewritelock_create(server_rec *s, pool *p);
|
|
static void rewritelock_open(server_rec *s, pool *p);
|
|
static void rewritelock_remove(void *data);
|
|
static void rewritelock_alloc(request_rec *r);
|
|
static void rewritelock_free(request_rec *r);
|
|
|
|
/* program map support */
|
|
static void run_rewritemap_programs(server_rec *s, pool *p);
|
|
static int rewritemap_program_child(void *cmd, child_info *pinfo);
|
|
|
|
/* env variable support */
|
|
static void expand_variables_inbuffer(request_rec *r, char *buf, int buf_len);
|
|
static char *expand_variables(request_rec *r, char *str);
|
|
static char *lookup_variable(request_rec *r, char *var);
|
|
static char *lookup_header(request_rec *r, const char *name);
|
|
|
|
/* caching functions */
|
|
static cache *init_cache(pool *p);
|
|
static char *get_cache_string(cache *c, char *res, int mode, time_t mtime,
|
|
char *key);
|
|
static void set_cache_string(cache *c, char *res, int mode, time_t mtime,
|
|
char *key, char *value);
|
|
static cacheentry *retrieve_cache_string(cache *c, char *res, char *key);
|
|
static void store_cache_string(cache *c, char *res, cacheentry *ce);
|
|
|
|
/* misc functions */
|
|
static char *subst_prefix_path(request_rec *r, char *input, char *match,
|
|
char *subst);
|
|
static int parseargline(char *str, char **a1, char **a2, char **a3);
|
|
static int prefix_stat(const char *path, struct stat *sb);
|
|
static void add_env_variable(request_rec *r, char *s);
|
|
|
|
/* File locking */
|
|
static void fd_lock(request_rec *r, int fd);
|
|
static void fd_unlock(request_rec *r, int fd);
|
|
|
|
/* Lexicographic Comparison */
|
|
static int compare_lexicography(char *cpNum1, char *cpNum2);
|
|
|
|
#endif /* _MOD_REWRITE_H */
|
|
|
|
/*EOF*/
|