bottleneck testcase based on rubbos
[bottlenecks.git] / rubbos / app / httpd-2.0.64 / modules / mappers / mod_rewrite.h
1 /* Licensed to the Apache Software Foundation (ASF) under one or more
2  * contributor license agreements.  See the NOTICE file distributed with
3  * this work for additional information regarding copyright ownership.
4  * The ASF licenses this file to You under the Apache License, Version 2.0
5  * (the "License"); you may not use this file except in compliance with
6  * the License.  You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #ifndef MOD_REWRITE_H
18 #define MOD_REWRITE_H 1
19
20 /*
21 **                       _                            _ _
22 **   _ __ ___   ___   __| |    _ __ _____      ___ __(_) |_ ___
23 **  | '_ ` _ \ / _ \ / _` |   | '__/ _ \ \ /\ / / '__| | __/ _ \
24 **  | | | | | | (_) | (_| |   | | |  __/\ V  V /| |  | | ||  __/
25 **  |_| |_| |_|\___/ \__,_|___|_|  \___| \_/\_/ |_|  |_|\__\___|
26 **                       |_____|
27 **
28 **  URL Rewriting Module
29 **
30 **  This module uses a rule-based rewriting engine (based on a
31 **  regular-expression parser) to rewrite requested URLs on the fly.
32 **
33 **  It supports an unlimited number of additional rule conditions (which can
34 **  operate on a lot of variables, even on HTTP headers) for granular
35 **  matching and even external database lookups (either via plain text
36 **  tables, DBM hash files or even external processes) for advanced URL
37 **  substitution.
38 **
39 **  It operates on the full URLs (including the PATH_INFO part) both in
40 **  per-server context (httpd.conf) and per-dir context (.htaccess) and even
41 **  can generate QUERY_STRING parts on result.   The rewriting result finally
42 **  can lead to internal subprocessing, external request redirection or even
43 **  to internal proxy throughput.
44 **
45 **  This module was originally written in April 1996 and
46 **  gifted exclusively to the The Apache Software Foundation in July 1997 by
47 **
48 **      Ralf S. Engelschall
49 **      rse@engelschall.com
50 **      www.engelschall.com
51 */
52
53 #include "apr.h"
54
55 #define APR_WANT_STRFUNC
56 #define APR_WANT_MEMFUNC
57 #include "apr_want.h"
58
59     /* Include from the underlaying Unix system ... */
60 #if APR_HAVE_STDARG_H
61 #include <stdarg.h>
62 #endif
63 #if APR_HAVE_STDLIB_H
64 #include <stdlib.h>
65 #endif
66 #if APR_HAVE_CTYPE_H
67 #include <ctype.h>
68 #endif
69 #if APR_HAVE_SYS_TYPES_H
70 #include <sys/types.h>
71 #endif
72
73 #if APR_HAS_THREADS
74 #include "apr_thread_mutex.h"
75 #endif
76 #include "apr_optional.h"
77 #include "apr_dbm.h"
78 #include "ap_config.h"
79
80     /* Include from the Apache server ... */
81 #define CORE_PRIVATE
82 #include "httpd.h"
83 #include "http_config.h"
84 #include "http_request.h"
85 #include "http_core.h"
86 #include "http_log.h"
87 #include "http_vhost.h"
88
89     /*
90      * The key in the r->notes apr_table_t wherein we store our accumulated
91      * Vary values, and the one used for per-condition checks in a chain.
92      */
93 #define VARY_KEY "rewrite-Vary"
94 #define VARY_KEY_THIS "rewrite-Vary-this"
95
96 /*
97 **
98 **  Some defines
99 **
100 */
101
102 #define ENVVAR_SCRIPT_URL "SCRIPT_URL"
103 #define ENVVAR_SCRIPT_URI "SCRIPT_URI"
104
105 #define REWRITE_FORCED_MIMETYPE_NOTEVAR "rewrite-forced-mimetype"
106
107 #define CONDFLAG_NONE               1<<0
108 #define CONDFLAG_NOCASE             1<<1
109 #define CONDFLAG_NOTMATCH           1<<2
110 #define CONDFLAG_ORNEXT             1<<3
111
112 #define RULEFLAG_NONE               1<<0
113 #define RULEFLAG_FORCEREDIRECT      1<<1
114 #define RULEFLAG_LASTRULE           1<<2
115 #define RULEFLAG_NEWROUND           1<<3
116 #define RULEFLAG_CHAIN              1<<4
117 #define RULEFLAG_IGNOREONSUBREQ     1<<5
118 #define RULEFLAG_NOTMATCH           1<<6
119 #define RULEFLAG_PROXY              1<<7
120 #define RULEFLAG_PASSTHROUGH        1<<8
121 #define RULEFLAG_FORBIDDEN          1<<9
122 #define RULEFLAG_GONE               1<<10
123 #define RULEFLAG_QSAPPEND           1<<11
124 #define RULEFLAG_NOCASE             1<<12
125 #define RULEFLAG_NOESCAPE           1<<13
126
127 #define ACTION_NORMAL               1<<0
128 #define ACTION_NOESCAPE             1<<1
129
130 #define MAPTYPE_TXT                 1<<0
131 #define MAPTYPE_DBM                 1<<1
132 #define MAPTYPE_PRG                 1<<2
133 #define MAPTYPE_INT                 1<<3
134 #define MAPTYPE_RND                 1<<4
135
136 #define ENGINE_DISABLED             1<<0
137 #define ENGINE_ENABLED              1<<1
138
139 #define OPTION_NONE                 1<<0
140 #define OPTION_INHERIT              1<<1
141
142 #define CACHEMODE_TS                1<<0
143 #define CACHEMODE_TTL               1<<1
144
145 #define CACHE_TLB_ROWS 1024
146 #define CACHE_TLB_COLS 4
147
148 #ifndef FALSE
149 #define FALSE 0
150 #define TRUE  !FALSE
151 #endif
152
153 #ifndef NO
154 #define NO    FALSE
155 #define YES   TRUE
156 #endif
157
158 #ifndef RAND_MAX
159 #define RAND_MAX 32767
160 #endif
161
162 #ifndef LONG_STRING_LEN
163 #define LONG_STRING_LEN 2048
164 #endif
165
166 #define MAX_ENV_FLAGS 15
167 #define MAX_COOKIE_FLAGS 15
168 /*** max cookie size in rfc 2109 ***/
169 #define MAX_COOKIE_LEN 4096
170
171 /* default maximum number of internal redirects */
172 #define REWRITE_REDIRECT_LIMIT 10
173
174
175 /*
176 **
177 **  our private data structures we handle with
178 **
179 */
180
181     /* the list structures for holding the mapfile information
182      * and the rewrite rules
183      */
184 typedef struct {
185     const char *name;              /* the name of the map */
186     const char *datafile;          /* filename for map data files */
187     const char *dbmtype;           /* dbm type for dbm map data files */
188     const char *checkfile;         /* filename to check for map existence */
189     int   type;                    /* the type of the map */
190     apr_file_t *fpin;              /* in  file pointer for program maps */
191     apr_file_t *fpout;             /* out file pointer for program maps */
192     apr_file_t *fperr;             /* err file pointer for program maps */
193     char *(*func)(request_rec *,   /* function pointer for internal maps */
194                   char *);
195     char **argv;
196     char *cachename;               /* name for the cache */
197 } rewritemap_entry;
198
199 typedef struct {
200     char    *input;                /* Input string of RewriteCond */
201     char    *pattern;              /* the RegExp pattern string */
202     regex_t *regexp;
203     int      flags;                /* Flags which control the match */
204 } rewritecond_entry;
205
206 typedef struct {
207     apr_array_header_t *rewriteconds;    /* the corresponding RewriteCond entries */
208     char    *pattern;              /* the RegExp pattern string */
209     regex_t *regexp;               /* the RegExp pattern compilation */
210     char    *output;               /* the Substitution string */
211     int      flags;                /* Flags which control the substitution */
212     char    *forced_mimetype;      /* forced MIME type of substitution */
213     int      forced_responsecode;  /* forced HTTP redirect response status */
214     char    *env[MAX_ENV_FLAGS+1]; /* added environment variables */
215     char    *cookie[MAX_COOKIE_FLAGS+1]; /* added cookies */
216     int      skip;                 /* number of next rules to skip */
217 } rewriterule_entry;
218
219
220     /* the per-server or per-virtual-server configuration
221      * statically generated once on startup for every server
222      */
223 typedef struct {
224     int           state;           /* the RewriteEngine state */
225     int           options;         /* the RewriteOption state */
226     const char   *rewritelogfile;  /* the RewriteLog filename */
227     apr_file_t   *rewritelogfp;    /* the RewriteLog open filepointer */
228     int           rewriteloglevel; /* the RewriteLog level of verbosity */
229     apr_array_header_t *rewritemaps;     /* the RewriteMap entries */
230     apr_array_header_t *rewriteconds;    /* the RewriteCond entries (temporary) */
231     apr_array_header_t *rewriterules;    /* the RewriteRule entries */
232     server_rec   *server;          /* the corresponding server indicator */
233     int          redirect_limit;   /* maximum number of internal redirects */
234 } rewrite_server_conf;
235
236
237     /* the per-directory configuration
238      * generated on-the-fly by Apache server for current request
239      */
240 typedef struct {
241     int           state;           /* the RewriteEngine state */
242     int           options;         /* the RewriteOption state */
243     apr_array_header_t *rewriteconds;    /* the RewriteCond entries (temporary) */
244     apr_array_header_t *rewriterules;    /* the RewriteRule entries */
245     char         *directory;       /* the directory where it applies */
246     const char   *baseurl;         /* the base-URL  where it applies */
247     int          redirect_limit;   /* maximum number of internal redirects */
248 } rewrite_perdir_conf;
249
250
251     /* the per-request configuration
252      */
253 typedef struct {
254     int           redirects;       /* current number of redirects */
255     int           redirect_limit;  /* maximum number of redirects */
256 } rewrite_request_conf;
257
258
259     /* the cache structures,
260      * a 4-way hash apr_table_t with LRU functionality
261      */
262 typedef struct cacheentry {
263     apr_time_t time;
264     char  *key;
265     char  *value;
266 } cacheentry;
267
268 typedef struct tlbentry {
269     int t[CACHE_TLB_COLS];
270 } cachetlbentry;
271
272 typedef struct cachelist {
273     char         *resource;
274     apr_array_header_t *entries;
275     apr_array_header_t *tlb;
276 } cachelist;
277
278 typedef struct cache {
279     apr_pool_t         *pool;
280     apr_array_header_t *lists;
281 #if APR_HAS_THREADS
282     apr_thread_mutex_t *lock;
283 #endif
284 } cache;
285
286
287     /* the regex structure for the
288      * substitution of backreferences
289      */
290 typedef struct backrefinfo {
291     char *source;
292     int nsub;
293     regmatch_t regmatch[AP_MAX_REG_MATCH];
294 } backrefinfo;
295
296
297 /*
298 **
299 **  forward declarations
300 **
301 */
302
303     /* config structure handling */
304 static void *config_server_create(apr_pool_t *p, server_rec *s);
305 static void *config_server_merge (apr_pool_t *p, void *basev, void *overridesv);
306 static void *config_perdir_create(apr_pool_t *p, char *path);
307 static void *config_perdir_merge (apr_pool_t *p, void *basev, void *overridesv);
308
309     /* config directive handling */
310 static const char *cmd_rewriteengine(cmd_parms *cmd,
311                                      void *dconf, int flag);
312 static const char *cmd_rewriteoptions(cmd_parms *cmd,
313                                       void *dconf,
314                                       const char *option);
315 static const char *cmd_rewritelog     (cmd_parms *cmd, void *dconf, const char *a1);
316 static const char *cmd_rewriteloglevel(cmd_parms *cmd, void *dconf, const char *a1);
317 static const char *cmd_rewritemap     (cmd_parms *cmd, void *dconf, 
318                                        const char *a1, const char *a2);
319 static const char *cmd_rewritelock(cmd_parms *cmd, void *dconf, const char *a1);
320 static const char *cmd_rewritebase(cmd_parms *cmd, void *dconf,
321                                    const char *a1);
322 static const char *cmd_rewritecond(cmd_parms *cmd, void *dconf,
323                                    const char *str);
324 static const char *cmd_rewritecond_parseflagfield(apr_pool_t *p,
325                                                   rewritecond_entry *new,
326                                                   char *str);
327 static const char *cmd_rewritecond_setflag(apr_pool_t *p, rewritecond_entry *cfg,
328                                            char *key, char *val);
329 static const char *cmd_rewriterule(cmd_parms *cmd, void *dconf,
330                                    const char *str);
331 static const char *cmd_rewriterule_parseflagfield(apr_pool_t *p,
332                                                   rewriterule_entry *new,
333                                                   char *str);
334 static const char *cmd_rewriterule_setflag(apr_pool_t *p, rewriterule_entry *cfg,
335                                            char *key, char *val);
336
337     /* initialisation */
338 static int pre_config(apr_pool_t *pconf,
339                       apr_pool_t *plog,
340                       apr_pool_t *ptemp);
341 static int post_config(apr_pool_t *pconf,
342                        apr_pool_t *plog,
343                        apr_pool_t *ptemp,
344                        server_rec *s);
345 static void init_child(apr_pool_t *p, server_rec *s);
346
347     /* runtime hooks */
348 static int hook_uri2file   (request_rec *r);
349 static int hook_mimetype   (request_rec *r);
350 static int hook_fixup      (request_rec *r);
351 static int handler_redirect(request_rec *r);
352
353     /* rewriting engine */
354 static int apply_rewrite_list(request_rec *r, apr_array_header_t *rewriterules,
355                               char *perdir);
356 static int apply_rewrite_rule(request_rec *r, rewriterule_entry *p,
357                               char *perdir);
358 static int apply_rewrite_cond(request_rec *r, rewritecond_entry *p,
359                               char *perdir, backrefinfo *briRR,
360                               backrefinfo *briRC);
361
362 static void do_expand(request_rec *r, char *input, char *buffer, int nbuf,
363                       backrefinfo *briRR, backrefinfo *briRC);
364 static void do_expand_env(request_rec *r, char *env[],
365                           backrefinfo *briRR, backrefinfo *briRC);
366 static void do_expand_cookie(request_rec *r, char *cookie[],
367                           backrefinfo *briRR, backrefinfo *briRC);
368
369     /* URI transformation function */
370 static void  splitout_queryargs(request_rec *r, int qsappend);
371 static void  fully_qualify_uri(request_rec *r);
372 static void  reduce_uri(request_rec *r);
373 static unsigned is_absolute_uri(char *uri);
374 static char *escape_absolute_uri(apr_pool_t *p, char *uri, unsigned scheme);
375 static char *expand_tildepaths(request_rec *r, char *uri);
376
377     /* rewrite map support functions */
378 static char *lookup_map(request_rec *r, char *name, char *key);
379 static char *lookup_map_txtfile(request_rec *r, const char *file, char *key);
380 static char *lookup_map_dbmfile(request_rec *r, const char *file, 
381                                 const char *dbmtype, char *key);
382 static char *lookup_map_program(request_rec *r, apr_file_t *fpin,
383                                 apr_file_t *fpout, char *key);
384
385 typedef char *(rewrite_mapfunc_t)(request_rec *r, char *key);
386 static void ap_register_rewrite_mapfunc(char *name, rewrite_mapfunc_t *func);
387 APR_DECLARE_OPTIONAL_FN(void, ap_register_rewrite_mapfunc,
388                         (char *name, rewrite_mapfunc_t *func));
389
390 static char *rewrite_mapfunc_toupper(request_rec *r, char *key);
391 static char *rewrite_mapfunc_tolower(request_rec *r, char *key);
392 static char *rewrite_mapfunc_escape(request_rec *r, char *key);
393 static char *rewrite_mapfunc_unescape(request_rec *r, char *key);
394
395 static char *select_random_value_part(request_rec *r, char *value);
396 static void  rewrite_rand_init(void);
397 static int   rewrite_rand(int l, int h);
398
399     /* rewriting logfile support */
400 static int   open_rewritelog(server_rec *s, apr_pool_t *p);
401 static void  rewritelog(request_rec *r, int level, const char *text, ...)
402                         __attribute__((format(printf,3,4)));
403 static char *current_logtime(request_rec *r);
404
405     /* rewriting lockfile support */
406 static apr_status_t rewritelock_create(server_rec *s, apr_pool_t *p);
407 static apr_status_t rewritelock_remove(void *data);
408
409     /* program map support */
410 static apr_status_t run_rewritemap_programs(server_rec *s, apr_pool_t *p);
411 static apr_status_t rewritemap_program_child(apr_pool_t *p, 
412                                              const char *progname, char **argv,
413                                              apr_file_t **fpout,
414                                              apr_file_t **fpin);
415
416     /* env variable support */
417 static char *lookup_variable(request_rec *r, char *var);
418 static char *lookup_header(request_rec *r, const char *name);
419
420     /* caching functions */
421 static cache *init_cache(apr_pool_t *p);
422 static char  *get_cache_string(cache *c, const char *res, int mode, apr_time_t mtime,
423                                char *key);
424 static void   set_cache_string(cache *c, const char *res, int mode, apr_time_t mtime,
425                                char *key, char *value);
426 static cacheentry *retrieve_cache_string(cache *c, const char *res, char *key);
427 static void   store_cache_string(cache *c, const char *res, cacheentry *ce);
428
429     /* misc functions */
430 static char  *subst_prefix_path(request_rec *r, char *input, char *match,
431                                 const char *subst);
432 static int    parseargline(char *str, char **a1, char **a2, char **a3);
433 static int    prefix_stat(const char *path, apr_pool_t *pool);
434 static void   add_env_variable(request_rec *r, char *s);
435 static void   add_cookie(request_rec *r, char *s);
436 static int    subreq_ok(request_rec *r);
437 static int    is_redirect_limit_exceeded(request_rec *r);
438
439     /* Lexicographic Comparison */
440 static int compare_lexicography(char *cpNum1, char *cpNum2);
441
442     /* Bracketed expression handling */
443 static char *find_closing_bracket(char *s, int left, int right);
444 static char *find_char_in_brackets(char *s, int c, int left, int right);
445
446 #endif /* MOD_REWRITE_H */