dgaudet     98/03/15 13:39:56

  Modified:    htdocs/manual/mod mod_setenvif.html
               src      CHANGES
               src/modules/standard mod_setenvif.c
  Log:
  - The "merging" optimization in mod_setenvif did not deal with
    SetEnvIfNoCase properly; and it used strcmp() to compare header
    names when it should use strcasecmp().
  
  - Change the merging optimization so that it only considers the most
    recent setenvif for merging.  This means that mod_setenvif will
    consider all directives in the order they appear in the config file.
  
  - Document that mod_setenvif considers directives in the order they
    appear, and give an example use.
  
  - Perform more comparisons at compile-time in order to speed up things
    at compile-time.
  
  Revision  Changes    Path
  1.3       +10 -0     apache-1.3/htdocs/manual/mod/mod_setenvif.html
  
  Index: mod_setenvif.html
  ===================================================================
  RCS file: /export/home/cvs/apache-1.3/htdocs/manual/mod/mod_setenvif.html,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- mod_setenvif.html 1998/01/28 19:11:57     1.2
  +++ mod_setenvif.html 1998/03/15 21:39:50     1.3
  @@ -26,6 +26,16 @@
     regular expressions you specify.  These envariables can be used by
     other parts of the server to make decisions about actions to be taken.
     </P>
  +  <p>The directives are considered in the order they appear in the
  +  configuration files.  So more complex sequences can be used, such
  +  as this example, which sets <code>netscape</code> if the browser
  +  is mozilla but not MSIE.
  +  <blockquote><pre>
  +  BrowserMatch ^Mozilla netscape
  +  BrowserMatch MSIE !netscape
  +  </pre></blockquote>
  +  </p>
  +
     <H2>Directives</H2>
     <UL>
      <LI><A HREF="#BrowserMatch">BrowserMatch</A>
  
  
  
  1.712     +13 -1     apache-1.3/src/CHANGES
  
  Index: CHANGES
  ===================================================================
  RCS file: /export/home/cvs/apache-1.3/src/CHANGES,v
  retrieving revision 1.711
  retrieving revision 1.712
  diff -u -r1.711 -r1.712
  --- CHANGES   1998/03/14 16:25:44     1.711
  +++ CHANGES   1998/03/15 21:39:52     1.712
  @@ -1,5 +1,17 @@
   Changes with Apache 1.3b6
  -  
  +
  +  *) Clean up some undocumented behaviour of mod_setenvif related to
  +     "merging" two SetEnvIf directives when they match the same header
  +     and regex.  Document that mod_setenvif will perform comparisons in
  +     the order they appear in the config file.  Optimize mod_setenvif by
  +     doing more work at config time rather than at runtime.
  +     [Dean Gaudet]
  +
  +  *) mod_setenvif would incorrectly merge a SetEnvIf and SetEnvIfNoCase (or
  +     BrowserMatch and BrowserMatchNoCase) when they matched the same header
  +     and regex.  Fix this; but also fix it so that this merging optimization
  +     only happens
  +
     *) src/include/ap_config.h now wraps it's #define's with #ifndef/#endif's
        to allow for modules to overrule them and to reduce redefinition
        warnings [Jim Jagielski]
  
  
  
  1.19      +96 -37    apache-1.3/src/modules/standard/mod_setenvif.c
  
  Index: mod_setenvif.c
  ===================================================================
  RCS file: /export/home/cvs/apache-1.3/src/modules/standard/mod_setenvif.c,v
  retrieving revision 1.18
  retrieving revision 1.19
  diff -u -r1.18 -r1.19
  --- mod_setenvif.c    1998/03/13 19:20:43     1.18
  +++ mod_setenvif.c    1998/03/15 21:39:55     1.19
  @@ -115,11 +115,21 @@
   #include "http_core.h"
   #include "http_log.h"
   
  +enum special {
  +    SPECIAL_NOT,
  +    SPECIAL_REMOTE_ADDR,
  +    SPECIAL_REMOTE_HOST,
  +    SPECIAL_REMOTE_USER,
  +    SPECIAL_REQUEST_URI,
  +    SPECIAL_REQUEST_METHOD
  +};
   typedef struct {
       char *name;                 /* header name */
       char *regex;                /* regex to match against */
       regex_t *preg;              /* compiled regex */
       table *features;            /* env vars to set (or unset) */
  +    enum special special_type : 4;   /* is it a "special" header ? */
  +    unsigned icase : 1;              /* ignoring case? */
   } sei_entry;
   
   typedef struct {
  @@ -161,6 +171,7 @@
       char *var;
       int i;
       int beenhere = 0;
  +    unsigned icase;
   
       /* get regex */
       regex = getword_conf(cmd->pool, &args);
  @@ -170,33 +181,68 @@
       }
   
       /*
  -     * First, try to merge into an existing entry
  +     * If we've already got a sei_entry with the same name we want to
  +     * just copy the name pointer... so that later on we can compare
  +     * two header names just by comparing the pointers.
        */
   
       for (i = 0; i < sconf->conditionals->nelts; ++i) {
           new = &entries[i];
  -        if (!strcmp(new->name, fname) && !strcmp(new->regex, regex))
  -         goto gotit;
  +     if (!strcasecmp(new->name, fname)) {
  +         fname = new->name;
  +         break;
  +     }
       }
   
  -    /*
  -     * If none was found, create a new entry
  +    /* if the last entry has an idential headername and regex then
  +     * merge with it
        */
  -
  -    new = push_array(sconf->conditionals);
  -    new->name = fname;
  -    new->regex = regex;
  -    new->preg = pregcomp(cmd->pool, regex,
  -                         (REG_EXTENDED | REG_NOSUB
  -                      | (cmd->info == ICASE_MAGIC ? REG_ICASE : 0)));
  -    if (new->preg == NULL) {
  -        return pstrcat(cmd->pool, cmd->cmd->name,
  -                        " regex could not be compiled.", NULL);
  +    i = sconf->conditionals->nelts - 1;
  +    icase = cmd->info == ICASE_MAGIC;
  +    if (i < 0
  +     || entries[i].name != fname
  +     || entries[i].icase != icase
  +     || strcmp(entries[i].regex, regex)) {
  +
  +     /* no match, create a new entry */
  +
  +     new = push_array(sconf->conditionals);
  +     new->name = fname;
  +     new->regex = regex;
  +     new->icase = icase;
  +     new->preg = pregcomp(cmd->pool, regex,
  +                         (REG_EXTENDED | REG_NOSUB
  +                         | (icase ? REG_ICASE : 0)));
  +     if (new->preg == NULL) {
  +         return pstrcat(cmd->pool, cmd->cmd->name,
  +                         " regex could not be compiled.", NULL);
  +     }
  +     new->features = make_table(cmd->pool, 2);
  +
  +     if (!strcasecmp(fname, "remote_addr")) {
  +         new->special_type = SPECIAL_REMOTE_ADDR;
  +     }
  +     else if (!strcasecmp(fname, "remote_host")) {
  +         new->special_type = SPECIAL_REMOTE_HOST;
  +     }
  +     else if (!strcasecmp(fname, "remote_user")) {
  +         new->special_type = SPECIAL_REMOTE_USER;
  +     }
  +     else if (!strcasecmp(fname, "request_uri")) {
  +         new->special_type = SPECIAL_REQUEST_URI;
  +     }
  +     else if (!strcasecmp(fname, "request_method")) {
  +         new->special_type = SPECIAL_REQUEST_METHOD;
  +     }
  +     else {
  +         new->special_type = SPECIAL_NOT;
  +     }
  +    }
  +    else {
  +     new = &entries[i];
       }
  -    new->features = make_table(cmd->pool, 5);
   
  -gotit:
  -    for( ; ; ) {
  +    for (;;) {
        feature = getword_conf(cmd->pool, &args);
        if(!*feature)
            break;
  @@ -265,30 +311,43 @@
                                                              &setenvif_module);
       sei_entry *entries = (sei_entry *) sconf->conditionals->elts;
       table_entry *elts;
  -    char *val;
  +    const char *val;
       int i, j;
  +    char *last_name;
   
  +    last_name = NULL;
  +    val = NULL;
       for (i = 0; i < sconf->conditionals->nelts; ++i) {
           sei_entry *b = &entries[i];
   
  -        if (!strcasecmp(b->name, "remote_addr")) {
  -            val = r->connection->remote_ip;
  -        }
  -        else if (!strcasecmp(b->name, "remote_host")) {
  -            val = (char *) get_remote_host(r->connection, r->per_dir_config,
  -                                           REMOTE_NAME);
  -        }
  -        else if (!strcasecmp(b->name, "remote_user")) {
  -            val = r->connection->user;
  -        }
  -        else if (!strcasecmp(b->name, "request_uri")) {
  -            val = r->uri;
  -        }
  -        else if (!strcasecmp(b->name, "request_method")) {
  -            val = r->method;
  -        }
  -        else {
  -            val = table_get(r->headers_in, b->name);
  +     /* Optimize the case where a bunch of directives in a row use the
  +      * same header.  Remember we don't need to strcmp the two header
  +      * names because we made sure the pointers were equal during
  +      * configuration.
  +      */
  +     if (b->name != last_name) {
  +         last_name = b->name;
  +         switch (b->special_type) {
  +         case SPECIAL_REMOTE_ADDR:
  +             val = r->connection->remote_ip;
  +             break;
  +         case SPECIAL_REMOTE_HOST:
  +             val =  get_remote_host(r->connection, r->per_dir_config,
  +                                         REMOTE_NAME);
  +             break;
  +         case SPECIAL_REMOTE_USER:
  +             val = r->connection->user;
  +             break;
  +         case SPECIAL_REQUEST_URI:
  +             val = r->uri;
  +             break;
  +         case SPECIAL_REQUEST_METHOD:
  +             val = r->method;
  +             break;
  +         case SPECIAL_NOT:
  +             val = table_get(r->headers_in, b->name);
  +             break;
  +         }
           }
   
           if (!val) {
  
  
  

Reply via email to