You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@httpd.apache.org by br...@apache.org on 2002/05/10 09:51:16 UTC

cvs commit: httpd-2.0/modules/metadata mod_setenvif.c

brianp      02/05/10 00:51:16

  Modified:    modules/metadata mod_setenvif.c
  Log:
  Performance fix: When a BrowserMatch or SetEnvIf pattern doesn't
  actually require regular expression parsing, use a fast string search
  instead.
  
  Revision  Changes    Path
  1.34      +84 -8     httpd-2.0/modules/metadata/mod_setenvif.c
  
  Index: mod_setenvif.c
  ===================================================================
  RCS file: /home/cvs/httpd-2.0/modules/metadata/mod_setenvif.c,v
  retrieving revision 1.33
  retrieving revision 1.34
  diff -u -r1.33 -r1.34
  --- mod_setenvif.c	13 Mar 2002 20:47:53 -0000	1.33
  +++ mod_setenvif.c	10 May 2002 07:51:16 -0000	1.34
  @@ -123,6 +123,7 @@
   
   #include "apr.h"
   #include "apr_strings.h"
  +#include "apr_strmatch.h"
   
   #define APR_WANT_STRFUNC
   #include "apr_want.h"
  @@ -149,6 +150,7 @@
       regex_t *pnamereg;          /* compiled header name regex */
       char *regex;                /* regex to match against */
       regex_t *preg;              /* compiled regex */
  +    const apr_strmatch_pattern *pattern; /* non-regex pattern to match */
       apr_table_t *features;      /* env vars to set (or unset) */
       enum special special_type;  /* is it a "special" header ? */
       int icase;                  /* ignoring case? */
  @@ -219,10 +221,68 @@
       }
       return 0;
   }
  +
  +/* If the input string does not take advantage of regular
  + * expression metacharacters, return a pointer to an equivalent
  + * string that can be searched using apr_strmatch().  (The
  + * returned string will often be the input string.  But if
  + * the input string contains escaped characters, the returned
  + * string will be a copy with the escapes removed.)
  + */
  +static const char *non_regex_pattern(apr_pool_t *p, const char *s)
  +{
  +    const char *src = s;
  +    int escapes_found = 0;
  +    int in_escape = 0;
  +
  +    while (*src) {
  +        if (in_escape) {
  +            in_escape = 0;
  +        }
  +        else {
  +            switch (*src) {
  +            case '^':
  +            case '.':
  +            case '$':
  +            case '|':
  +            case '(':
  +            case ')':
  +            case '[':
  +            case ']':
  +            case '*':
  +            case '+':
  +            case '?':
  +            case '{':
  +            case '}':
  +                return NULL;
  +            case '\\':
  +                in_escape = 1;
  +                escapes_found = 1;
  +            }
  +        }
  +        src++;
  +    }
  +    if (!escapes_found) {
  +        return s;
  +    }
  +    else {
  +        char *unescaped = (char *)apr_palloc(p, src - s + 1);
  +        char *dst = unescaped;
  +        src = s;
  +        do {
  +            if (*src == '\\') {
  +                src++;
  +            }
  +        } while ((*dst++ = *src++));
  +        return unescaped;
  +    }
  +}
  +
   static const char *add_setenvif_core(cmd_parms *cmd, void *mconfig,
   				     char *fname, const char *args)
   {
       char *regex;
  +    const char *simple_pattern;
       const char *feature;
       sei_cfg_rec *sconf;
       sei_entry *new;
  @@ -279,13 +339,25 @@
   	new->name = fname;
   	new->regex = regex;
   	new->icase = icase;
  -	new->preg = ap_pregcomp(cmd->pool, regex,
  -				(REG_EXTENDED | REG_NOSUB
  -				 | (icase ? REG_ICASE : 0)));
  -	if (new->preg == NULL) {
  -	    return apr_pstrcat(cmd->pool, cmd->cmd->name,
  -			      " regex could not be compiled.", NULL);
  -	}
  +        if ((simple_pattern = non_regex_pattern(cmd->pool, regex))) {
  +            new->pattern = apr_strmatch_precompile(cmd->pool,
  +                                                   simple_pattern, 1);
  +            if (new->pattern == NULL) {
  +                return apr_pstrcat(cmd->pool, cmd->cmd->name,
  +                                   " pattern could not be compiled.", NULL);
  +            }
  +            new->preg = NULL;
  +        }
  +        else {
  +            new->preg = ap_pregcomp(cmd->pool, regex,
  +                                    (REG_EXTENDED | REG_NOSUB
  +                                     | (icase ? REG_ICASE : 0)));
  +            if (new->preg == NULL) {
  +                return apr_pstrcat(cmd->pool, cmd->cmd->name,
  +                                   " regex could not be compiled.", NULL);
  +            }
  +            new->pattern = NULL;
  +        }
   	new->features = apr_table_make(cmd->pool, 2);
   
   	if (!strcasecmp(fname, "remote_addr")) {
  @@ -408,6 +480,7 @@
       sei_entry *entries;
       const apr_table_entry_t *elts;
       const char *val;
  +    apr_size_t val_len = 0;
       int i, j;
       char *last_name;
   
  @@ -477,6 +550,7 @@
                       }
                   }
   	    }
  +            val_len = val ? strlen(val) : 0;
           }
   
   	/*
  @@ -487,9 +561,11 @@
   	 */
           if (val == NULL) {
               val = "";
  +            val_len = 0;
           }
   
  -        if (!ap_regexec(b->preg, val, 0, NULL, 0)) {
  +        if (b->pattern ? apr_strmatch(b->pattern, val, val_len) :
  +            !ap_regexec(b->preg, val, 0, NULL, 0)) {
   	    const apr_array_header_t *arr = apr_table_elts(b->features);
               elts = (const apr_table_entry_t *) arr->elts;