Main Page | Modules | Namespace List | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals | Related Pages | Examples

mod_rewrite.h

Go to the documentation of this file.
00001 /* Copyright 1999-2005 The Apache Software Foundation or its licensors, as
00002  * applicable.
00003  *
00004  * Licensed under the Apache License, Version 2.0 (the "License");
00005  * you may not use this file except in compliance with the License.
00006  * You may obtain a copy of the License at
00007  *
00008  *     http://www.apache.org/licenses/LICENSE-2.0
00009  *
00010  * Unless required by applicable law or agreed to in writing, software
00011  * distributed under the License is distributed on an "AS IS" BASIS,
00012  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  * See the License for the specific language governing permissions and
00014  * limitations under the License.
00015  */
00016 
00017 #ifndef MOD_REWRITE_H
00018 #define MOD_REWRITE_H 1
00019 
00020 /*
00021 **                       _                            _ _
00022 **   _ __ ___   ___   __| |    _ __ _____      ___ __(_) |_ ___
00023 **  | '_ ` _ \ / _ \ / _` |   | '__/ _ \ \ /\ / / '__| | __/ _ \
00024 **  | | | | | | (_) | (_| |   | | |  __/\ V  V /| |  | | ||  __/
00025 **  |_| |_| |_|\___/ \__,_|___|_|  \___| \_/\_/ |_|  |_|\__\___|
00026 **                       |_____|
00027 **
00028 **  URL Rewriting Module
00029 **
00030 **  This module uses a rule-based rewriting engine (based on a
00031 **  regular-expression parser) to rewrite requested URLs on the fly.
00032 **
00033 **  It supports an unlimited number of additional rule conditions (which can
00034 **  operate on a lot of variables, even on HTTP headers) for granular
00035 **  matching and even external database lookups (either via plain text
00036 **  tables, DBM hash files or even external processes) for advanced URL
00037 **  substitution.
00038 **
00039 **  It operates on the full URLs (including the PATH_INFO part) both in
00040 **  per-server context (httpd.conf) and per-dir context (.htaccess) and even
00041 **  can generate QUERY_STRING parts on result.   The rewriting result finally
00042 **  can lead to internal subprocessing, external request redirection or even
00043 **  to internal proxy throughput.
00044 **
00045 **  This module was originally written in April 1996 and
00046 **  gifted exclusively to the The Apache Software Foundation in July 1997 by
00047 **
00048 **      Ralf S. Engelschall
00049 **      rse@engelschall.com
00050 **      www.engelschall.com
00051 */
00052 
00053 #include "apr.h"
00054 
00055 #define APR_WANT_STRFUNC
00056 #define APR_WANT_MEMFUNC
00057 #include "apr_want.h"
00058 
00059     /* Include from the underlaying Unix system ... */
00060 #if APR_HAVE_STDARG_H
00061 #include <stdarg.h>
00062 #endif
00063 #if APR_HAVE_STDLIB_H
00064 #include <stdlib.h>
00065 #endif
00066 #if APR_HAVE_CTYPE_H
00067 #include <ctype.h>
00068 #endif
00069 #if APR_HAVE_SYS_TYPES_H
00070 #include <sys/types.h>
00071 #endif
00072 
00073 #if APR_HAS_THREADS
00074 #include "apr_thread_mutex.h"
00075 #endif
00076 #include "apr_optional.h"
00077 #include "apr_dbm.h"
00078 #include "ap_config.h"
00079 
00080     /* Include from the Apache server ... */
00081 #define CORE_PRIVATE
00082 #include "httpd.h"
00083 #include "http_config.h"
00084 #include "http_request.h"
00085 #include "http_core.h"
00086 #include "http_log.h"
00087 #include "http_vhost.h"
00088 
00089     /*
00090      * The key in the r->notes apr_table_t wherein we store our accumulated
00091      * Vary values, and the one used for per-condition checks in a chain.
00092      */
00093 #define VARY_KEY "rewrite-Vary"
00094 #define VARY_KEY_THIS "rewrite-Vary-this"
00095 
00096 /*
00097 **
00098 **  Some defines
00099 **
00100 */
00101 
00102 #define ENVVAR_SCRIPT_URL "SCRIPT_URL"
00103 #define ENVVAR_SCRIPT_URI "SCRIPT_URI"
00104 
00105 #define REWRITE_FORCED_MIMETYPE_NOTEVAR "rewrite-forced-mimetype"
00106 
00107 #define CONDFLAG_NONE               1<<0
00108 #define CONDFLAG_NOCASE             1<<1
00109 #define CONDFLAG_NOTMATCH           1<<2
00110 #define CONDFLAG_ORNEXT             1<<3
00111 
00112 #define RULEFLAG_NONE               1<<0
00113 #define RULEFLAG_FORCEREDIRECT      1<<1
00114 #define RULEFLAG_LASTRULE           1<<2
00115 #define RULEFLAG_NEWROUND           1<<3
00116 #define RULEFLAG_CHAIN              1<<4
00117 #define RULEFLAG_IGNOREONSUBREQ     1<<5
00118 #define RULEFLAG_NOTMATCH           1<<6
00119 #define RULEFLAG_PROXY              1<<7
00120 #define RULEFLAG_PASSTHROUGH        1<<8
00121 #define RULEFLAG_FORBIDDEN          1<<9
00122 #define RULEFLAG_GONE               1<<10
00123 #define RULEFLAG_QSAPPEND           1<<11
00124 #define RULEFLAG_NOCASE             1<<12
00125 #define RULEFLAG_NOESCAPE           1<<13
00126 
00127 #define ACTION_NORMAL               1<<0
00128 #define ACTION_NOESCAPE             1<<1
00129 
00130 #define MAPTYPE_TXT                 1<<0
00131 #define MAPTYPE_DBM                 1<<1
00132 #define MAPTYPE_PRG                 1<<2
00133 #define MAPTYPE_INT                 1<<3
00134 #define MAPTYPE_RND                 1<<4
00135 
00136 #define ENGINE_DISABLED             1<<0
00137 #define ENGINE_ENABLED              1<<1
00138 
00139 #define OPTION_NONE                 1<<0
00140 #define OPTION_INHERIT              1<<1
00141 
00142 #define CACHEMODE_TS                1<<0
00143 #define CACHEMODE_TTL               1<<1
00144 
00145 #define CACHE_TLB_ROWS 1024
00146 #define CACHE_TLB_COLS 4
00147 
00148 #ifndef FALSE
00149 #define FALSE 0
00150 #define TRUE  !FALSE
00151 #endif
00152 
00153 #ifndef NO
00154 #define NO    FALSE
00155 #define YES   TRUE
00156 #endif
00157 
00158 #ifndef RAND_MAX
00159 #define RAND_MAX 32767
00160 #endif
00161 
00162 #ifndef LONG_STRING_LEN
00163 #define LONG_STRING_LEN 2048
00164 #endif
00165 
00166 #define MAX_ENV_FLAGS 15
00167 #define MAX_COOKIE_FLAGS 15
00168 /*** max cookie size in rfc 2109 ***/
00169 #define MAX_COOKIE_LEN 4096
00170 
00171 /* default maximum number of internal redirects */
00172 #define REWRITE_REDIRECT_LIMIT 10
00173 
00174 
00175 /*
00176 **
00177 **  our private data structures we handle with
00178 **
00179 */
00180 
00181     /* the list structures for holding the mapfile information
00182      * and the rewrite rules
00183      */
00184 typedef struct {
00185     const char *name;              /* the name of the map */
00186     const char *datafile;          /* filename for map data files */
00187     const char *dbmtype;           /* dbm type for dbm map data files */
00188     const char *checkfile;         /* filename to check for map existence */
00189     int   type;                    /* the type of the map */
00190     apr_file_t *fpin;              /* in  file pointer for program maps */
00191     apr_file_t *fpout;             /* out file pointer for program maps */
00192     apr_file_t *fperr;             /* err file pointer for program maps */
00193     char *(*func)(request_rec *,   /* function pointer for internal maps */
00194                   char *);
00195     char **argv;
00196     char *cachename;               /* name for the cache */
00197 } rewritemap_entry;
00198 
00199 typedef struct {
00200     char    *input;                /* Input string of RewriteCond */
00201     char    *pattern;              /* the RegExp pattern string */
00202     regex_t *regexp;
00203     int      flags;                /* Flags which control the match */
00204 } rewritecond_entry;
00205 
00206 typedef struct {
00207     apr_array_header_t *rewriteconds;    /* the corresponding RewriteCond entries */
00208     char    *pattern;              /* the RegExp pattern string */
00209     regex_t *regexp;               /* the RegExp pattern compilation */
00210     char    *output;               /* the Substitution string */
00211     int      flags;                /* Flags which control the substitution */
00212     char    *forced_mimetype;      /* forced MIME type of substitution */
00213     int      forced_responsecode;  /* forced HTTP redirect response status */
00214     char    *env[MAX_ENV_FLAGS+1]; /* added environment variables */
00215     char    *cookie[MAX_COOKIE_FLAGS+1]; /* added cookies */
00216     int      skip;                 /* number of next rules to skip */
00217 } rewriterule_entry;
00218 
00219 
00220     /* the per-server or per-virtual-server configuration
00221      * statically generated once on startup for every server
00222      */
00223 typedef struct {
00224     int           state;           /* the RewriteEngine state */
00225     int           options;         /* the RewriteOption state */
00226     const char   *rewritelogfile;  /* the RewriteLog filename */
00227     apr_file_t   *rewritelogfp;    /* the RewriteLog open filepointer */
00228     int           rewriteloglevel; /* the RewriteLog level of verbosity */
00229     apr_array_header_t *rewritemaps;     /* the RewriteMap entries */
00230     apr_array_header_t *rewriteconds;    /* the RewriteCond entries (temporary) */
00231     apr_array_header_t *rewriterules;    /* the RewriteRule entries */
00232     server_rec   *server;          /* the corresponding server indicator */
00233     int          redirect_limit;   /* maximum number of internal redirects */
00234 } rewrite_server_conf;
00235 
00236 
00237     /* the per-directory configuration
00238      * generated on-the-fly by Apache server for current request
00239      */
00240 typedef struct {
00241     int           state;           /* the RewriteEngine state */
00242     int           options;         /* the RewriteOption state */
00243     apr_array_header_t *rewriteconds;    /* the RewriteCond entries (temporary) */
00244     apr_array_header_t *rewriterules;    /* the RewriteRule entries */
00245     char         *directory;       /* the directory where it applies */
00246     const char   *baseurl;         /* the base-URL  where it applies */
00247     int          redirect_limit;   /* maximum number of internal redirects */
00248 } rewrite_perdir_conf;
00249 
00250 
00251     /* the per-request configuration
00252      */
00253 typedef struct {
00254     int           redirects;       /* current number of redirects */
00255     int           redirect_limit;  /* maximum number of redirects */
00256 } rewrite_request_conf;
00257 
00258 
00259     /* the cache structures,
00260      * a 4-way hash apr_table_t with LRU functionality
00261      */
00262 typedef struct cacheentry {
00263     apr_time_t time;
00264     char  *key;
00265     char  *value;
00266 } cacheentry;
00267 
00268 typedef struct tlbentry {
00269     int t[CACHE_TLB_COLS];
00270 } cachetlbentry;
00271 
00272 typedef struct cachelist {
00273     char         *resource;
00274     apr_array_header_t *entries;
00275     apr_array_header_t *tlb;
00276 } cachelist;
00277 
00278 typedef struct cache {
00279     apr_pool_t         *pool;
00280     apr_array_header_t *lists;
00281 #if APR_HAS_THREADS
00282     apr_thread_mutex_t *lock;
00283 #endif
00284 } cache;
00285 
00286 
00287     /* the regex structure for the
00288      * substitution of backreferences
00289      */
00290 typedef struct backrefinfo {
00291     char *source;
00292     int nsub;
00293     regmatch_t regmatch[AP_MAX_REG_MATCH];
00294 } backrefinfo;
00295 
00296 
00297 /*
00298 **
00299 **  forward declarations
00300 **
00301 */
00302 
00303     /* config structure handling */
00304 static void *config_server_create(apr_pool_t *p, server_rec *s);
00305 static void *config_server_merge (apr_pool_t *p, void *basev, void *overridesv);
00306 static void *config_perdir_create(apr_pool_t *p, char *path);
00307 static void *config_perdir_merge (apr_pool_t *p, void *basev, void *overridesv);
00308 
00309     /* config directive handling */
00310 static const char *cmd_rewriteengine(cmd_parms *cmd,
00311                                      void *dconf, int flag);
00312 static const char *cmd_rewriteoptions(cmd_parms *cmd,
00313                                       void *dconf,
00314                                       const char *option);
00315 static const char *cmd_rewritelog     (cmd_parms *cmd, void *dconf, const char *a1);
00316 static const char *cmd_rewriteloglevel(cmd_parms *cmd, void *dconf, const char *a1);
00317 static const char *cmd_rewritemap     (cmd_parms *cmd, void *dconf, 
00318                                        const char *a1, const char *a2);
00319 static const char *cmd_rewritelock(cmd_parms *cmd, void *dconf, const char *a1);
00320 static const char *cmd_rewritebase(cmd_parms *cmd, void *dconf,
00321                                    const char *a1);
00322 static const char *cmd_rewritecond(cmd_parms *cmd, void *dconf,
00323                                    const char *str);
00324 static const char *cmd_rewritecond_parseflagfield(apr_pool_t *p,
00325                                                   rewritecond_entry *new,
00326                                                   char *str);
00327 static const char *cmd_rewritecond_setflag(apr_pool_t *p, rewritecond_entry *cfg,
00328                                            char *key, char *val);
00329 static const char *cmd_rewriterule(cmd_parms *cmd, void *dconf,
00330                                    const char *str);
00331 static const char *cmd_rewriterule_parseflagfield(apr_pool_t *p,
00332                                                   rewriterule_entry *new,
00333                                                   char *str);
00334 static const char *cmd_rewriterule_setflag(apr_pool_t *p, rewriterule_entry *cfg,
00335                                            char *key, char *val);
00336 
00337     /* initialisation */
00338 static int pre_config(apr_pool_t *pconf,
00339                       apr_pool_t *plog,
00340                       apr_pool_t *ptemp);
00341 static int post_config(apr_pool_t *pconf,
00342                        apr_pool_t *plog,
00343                        apr_pool_t *ptemp,
00344                        server_rec *s);
00345 static void init_child(apr_pool_t *p, server_rec *s);
00346 
00347     /* runtime hooks */
00348 static int hook_uri2file   (request_rec *r);
00349 static int hook_mimetype   (request_rec *r);
00350 static int hook_fixup      (request_rec *r);
00351 static int handler_redirect(request_rec *r);
00352 
00353     /* rewriting engine */
00354 static int apply_rewrite_list(request_rec *r, apr_array_header_t *rewriterules,
00355                               char *perdir);
00356 static int apply_rewrite_rule(request_rec *r, rewriterule_entry *p,
00357                               char *perdir);
00358 static int apply_rewrite_cond(request_rec *r, rewritecond_entry *p,
00359                               char *perdir, backrefinfo *briRR,
00360                               backrefinfo *briRC);
00361 
00362 static void do_expand(request_rec *r, char *input, char *buffer, int nbuf,
00363                       backrefinfo *briRR, backrefinfo *briRC);
00364 static void do_expand_env(request_rec *r, char *env[],
00365                           backrefinfo *briRR, backrefinfo *briRC);
00366 static void do_expand_cookie(request_rec *r, char *cookie[],
00367                           backrefinfo *briRR, backrefinfo *briRC);
00368 
00369     /* URI transformation function */
00370 static void  splitout_queryargs(request_rec *r, int qsappend);
00371 static void  fully_qualify_uri(request_rec *r);
00372 static void  reduce_uri(request_rec *r);
00373 static unsigned is_absolute_uri(char *uri);
00374 static char *escape_absolute_uri(apr_pool_t *p, char *uri, unsigned scheme);
00375 static char *expand_tildepaths(request_rec *r, char *uri);
00376 
00377     /* rewrite map support functions */
00378 static char *lookup_map(request_rec *r, char *name, char *key);
00379 static char *lookup_map_txtfile(request_rec *r, const char *file, char *key);
00380 static char *lookup_map_dbmfile(request_rec *r, const char *file, 
00381                                 const char *dbmtype, char *key);
00382 static char *lookup_map_program(request_rec *r, apr_file_t *fpin,
00383                                 apr_file_t *fpout, char *key);
00384 
00385 typedef char *(rewrite_mapfunc_t)(request_rec *r, char *key);
00386 static void ap_register_rewrite_mapfunc(char *name, rewrite_mapfunc_t *func);
00387 APR_DECLARE_OPTIONAL_FN(void, ap_register_rewrite_mapfunc,
00388                         (char *name, rewrite_mapfunc_t *func));
00389 
00390 static char *rewrite_mapfunc_toupper(request_rec *r, char *key);
00391 static char *rewrite_mapfunc_tolower(request_rec *r, char *key);
00392 static char *rewrite_mapfunc_escape(request_rec *r, char *key);
00393 static char *rewrite_mapfunc_unescape(request_rec *r, char *key);
00394 
00395 static char *select_random_value_part(request_rec *r, char *value);
00396 static void  rewrite_rand_init(void);
00397 static int   rewrite_rand(int l, int h);
00398 
00399     /* rewriting logfile support */
00400 static int   open_rewritelog(server_rec *s, apr_pool_t *p);
00401 static void  rewritelog(request_rec *r, int level, const char *text, ...)
00402                         __attribute__((format(printf,3,4)));
00403 static char *current_logtime(request_rec *r);
00404 
00405     /* rewriting lockfile support */
00406 static apr_status_t rewritelock_create(server_rec *s, apr_pool_t *p);
00407 static apr_status_t rewritelock_remove(void *data);
00408 
00409     /* program map support */
00410 static apr_status_t run_rewritemap_programs(server_rec *s, apr_pool_t *p);
00411 static apr_status_t rewritemap_program_child(apr_pool_t *p, 
00412                                              const char *progname, char **argv,
00413                                              apr_file_t **fpout,
00414                                              apr_file_t **fpin);
00415 
00416     /* env variable support */
00417 static char *lookup_variable(request_rec *r, char *var);
00418 static char *lookup_header(request_rec *r, const char *name);
00419 
00420     /* caching functions */
00421 static cache *init_cache(apr_pool_t *p);
00422 static char  *get_cache_string(cache *c, const char *res, int mode, apr_time_t mtime,
00423                                char *key);
00424 static void   set_cache_string(cache *c, const char *res, int mode, apr_time_t mtime,
00425                                char *key, char *value);
00426 static cacheentry *retrieve_cache_string(cache *c, const char *res, char *key);
00427 static void   store_cache_string(cache *c, const char *res, cacheentry *ce);
00428 
00429     /* misc functions */
00430 static char  *subst_prefix_path(request_rec *r, char *input, char *match,
00431                                 const char *subst);
00432 static int    parseargline(char *str, char **a1, char **a2, char **a3);
00433 static int    prefix_stat(const char *path, apr_pool_t *pool);
00434 static void   add_env_variable(request_rec *r, char *s);
00435 static void   add_cookie(request_rec *r, char *s);
00436 static int    subreq_ok(request_rec *r);
00437 static int    is_redirect_limit_exceeded(request_rec *r);
00438 
00439     /* Lexicographic Comparison */
00440 static int compare_lexicography(char *cpNum1, char *cpNum2);
00441 
00442     /* Bracketed expression handling */
00443 static char *find_closing_bracket(char *s, int left, int right);
00444 static char *find_char_in_brackets(char *s, int c, int left, int right);
00445 
00446 #endif /* MOD_REWRITE_H */