Diff for /embedaddon/lighttpd/src/configfile-glue.c between versions 1.1.1.1 and 1.1.1.2

version 1.1.1.1, 2013/10/14 10:32:47 version 1.1.1.2, 2016/11/02 10:35:00
Line 1 Line 1
   #include "first.h"
   
 #include "base.h"  #include "base.h"
 #include "buffer.h"  #include "buffer.h"
 #include "array.h"  #include "array.h"
Line 8 Line 10
   
 #include <string.h>  #include <string.h>
 #include <stdlib.h>  #include <stdlib.h>
   #ifndef _WIN32
   #include <arpa/inet.h>
   #endif
   
 /**  /**
  * like all glue code this file contains functions which   * like all glue code this file contains functions which
Line 24 Line 29
 /* handle global options */  /* handle global options */
   
 /* parse config array */  /* parse config array */
int config_insert_values_internal(server *srv, array *ca, const config_values_t cv[]) {int config_insert_values_internal(server *srv, array *ca, const config_values_t cv[], config_scope_type_t scope) {
         size_t i;          size_t i;
         data_unset *du;          data_unset *du;
   
Line 36  int config_insert_values_internal(server *srv, array * Line 41  int config_insert_values_internal(server *srv, array *
                         continue;                          continue;
                 }                  }
   
                   if ((T_CONFIG_SCOPE_SERVER == cv[i].scope)
                       && (T_CONFIG_SCOPE_SERVER != scope)) {
                           /* server scope options should only be set in server scope, not in conditionals */
                           log_error_write(srv, __FILE__, __LINE__, "ss",
                                   "DEPRECATED: don't set server options in conditionals, variable:",
                                   cv[i].key);
                   }
   
                 switch (cv[i].type) {                  switch (cv[i].type) {
                 case T_CONFIG_ARRAY:                  case T_CONFIG_ARRAY:
                         if (du->type == TYPE_ARRAY) {                          if (du->type == TYPE_ARRAY) {
Line 43  int config_insert_values_internal(server *srv, array * Line 56  int config_insert_values_internal(server *srv, array *
                                 data_array *da = (data_array *)du;                                  data_array *da = (data_array *)du;
   
                                 for (j = 0; j < da->value->used; j++) {                                  for (j = 0; j < da->value->used; j++) {
                                        if (da->value->data[j]->type == TYPE_STRING) {                                        data_unset *ds = da->value->data[j];
                                                data_string *ds = data_string_init();                                        if (ds->type == TYPE_STRING) {
                                                array_insert_unique(cv[i].destination, ds->copy(ds));
                                                buffer_copy_string_buffer(ds->value, ((data_string *)(da->value->data[j]))->value); 
                                                if (!da->is_index_key) { 
                                                        /* the id's were generated automaticly, as we copy now we might have to renumber them 
                                                         * this is used to prepend server.modules by mod_indexfile as it has to be loaded 
                                                         * before mod_fastcgi and friends */ 
                                                        buffer_copy_string_buffer(ds->key, ((data_string *)(da->value->data[j]))->key); 
                                                } 
 
                                                array_insert_unique(cv[i].destination, (data_unset *)ds); 
                                         } else {                                          } else {
                                                log_error_write(srv, __FILE__, __LINE__, "sssd",                                                log_error_write(srv, __FILE__, __LINE__, "sssbsd",
                                                                "the key of an array can only be a string or a integer, variable:",                                                                "the value of an array can only be a string, variable:",
                                                                cv[i].key, "type:", da->value->data[j]->type);                                                                cv[i].key, "[", ds->key, "], type:", ds->type);
   
                                                 return -1;                                                  return -1;
                                         }                                          }
Line 73  int config_insert_values_internal(server *srv, array * Line 77  int config_insert_values_internal(server *srv, array *
                         if (du->type == TYPE_STRING) {                          if (du->type == TYPE_STRING) {
                                 data_string *ds = (data_string *)du;                                  data_string *ds = (data_string *)du;
   
                                buffer_copy_string_buffer(cv[i].destination, ds->value);                                buffer_copy_buffer(cv[i].destination, ds->value);
                         } else {                          } else {
                                 log_error_write(srv, __FILE__, __LINE__, "ssss", cv[i].key, "should have been a string like ... = \"...\"");                                  log_error_write(srv, __FILE__, __LINE__, "ssss", cv[i].key, "should have been a string like ... = \"...\"");
   
Line 135  int config_insert_values_internal(server *srv, array * Line 139  int config_insert_values_internal(server *srv, array *
                                         }                                          }
                                 }                                  }
   
   
                                 log_error_write(srv, __FILE__, __LINE__, "ssb", "got a string but expected an integer:", cv[i].key, ds->value);                                  log_error_write(srv, __FILE__, __LINE__, "ssb", "got a string but expected an integer:", cv[i].key, ds->value);
   
                                 return -1;                                  return -1;
Line 185  int config_insert_values_internal(server *srv, array * Line 188  int config_insert_values_internal(server *srv, array *
         return 0;          return 0;
 }  }
   
int config_insert_values_global(server *srv, array *ca, const config_values_t cv[]) {int config_insert_values_global(server *srv, array *ca, const config_values_t cv[], config_scope_type_t scope) {
         size_t i;          size_t i;
         data_unset *du;          data_unset *du;
   
Line 202  int config_insert_values_global(server *srv, array *ca Line 205  int config_insert_values_global(server *srv, array *ca
                 touched = data_string_init();                  touched = data_string_init();
   
                 buffer_copy_string_len(touched->value, CONST_STR_LEN(""));                  buffer_copy_string_len(touched->value, CONST_STR_LEN(""));
                buffer_copy_string_buffer(touched->key, du->key);                buffer_copy_buffer(touched->key, du->key);
   
                 array_insert_unique(srv->config_touched, (data_unset *)touched);                  array_insert_unique(srv->config_touched, (data_unset *)touched);
         }          }
   
        return config_insert_values_internal(srv, ca, cv);        return config_insert_values_internal(srv, ca, cv, scope);
 }  }
   
 static unsigned short sock_addr_get_port(sock_addr *addr) {  static unsigned short sock_addr_get_port(sock_addr *addr) {
Line 218  static unsigned short sock_addr_get_port(sock_addr *ad Line 221  static unsigned short sock_addr_get_port(sock_addr *ad
 #endif  #endif
 }  }
   
   static const char* cond_result_to_string(cond_result_t cond_result) {
           switch (cond_result) {
           case COND_RESULT_UNSET: return "unset";
           case COND_RESULT_SKIP: return "skipped";
           case COND_RESULT_FALSE: return "false";
           case COND_RESULT_TRUE: return "true";
           default: return "invalid cond_result_t";
           }
   }
   
   static int config_addrstr_eq_remote_ip_mask(server *srv, const char *addrstr, int nm_bits, sock_addr *rmt) {
           /* special-case 0 == nm_bits to mean "all bits of the address" in addrstr */
           sock_addr val;
   #ifdef HAVE_INET_PTON
           if (1 == inet_pton(AF_INET, addrstr, &val.ipv4.sin_addr))
   #else
           if (INADDR_NONE != (val.ipv4.sin_addr = inet_addr(addrstr)))
   #endif
           {
                   /* build netmask */
                   uint32_t nm;
                   if (nm_bits > 32) {
                           log_error_write(srv, __FILE__, __LINE__, "sd", "ERROR: ipv4 netmask too large:", nm_bits);
                           return -1;
                   }
                   nm = htonl(~((1u << (32 - (0 != nm_bits ? nm_bits : 32))) - 1));
   
                   if (rmt->plain.sa_family == AF_INET) {
                           return ((val.ipv4.sin_addr.s_addr & nm) == (rmt->ipv4.sin_addr.s_addr & nm));
   #ifdef HAVE_IPV6
                   } else if (rmt->plain.sa_family == AF_INET6
                              && IN6_IS_ADDR_V4MAPPED(&rmt->ipv6.sin6_addr)) {
                         #ifdef s6_addr32
                           in_addr_t x = rmt->ipv6.sin6_addr.s6_addr32[3];
                         #else
                           in_addr_t x;
                           memcpy(&x, rmt->ipv6.sin6_addr.s6_addr+12, sizeof(in_addr_t));
                         #endif
                           return ((val.ipv4.sin_addr.s_addr & nm) == (x & nm));
   #endif
                   } else {
                           return 0;
                   }
   #if defined(HAVE_INET_PTON) && defined(HAVE_IPV6)
           } else if (1 == inet_pton(AF_INET6, addrstr, &val.ipv6.sin6_addr)) {
                   if (nm_bits > 128) {
                           log_error_write(srv, __FILE__, __LINE__, "sd", "ERROR: ipv6 netmask too large:", nm_bits);
                           return -1;
                   }
                   if (rmt->plain.sa_family == AF_INET6) {
                           uint8_t *a = (uint8_t *)&val.ipv6.sin6_addr.s6_addr[0];
                           uint8_t *b = (uint8_t *)&rmt->ipv6.sin6_addr.s6_addr[0];
                           int match;
                           do {
                                   match = (nm_bits >= 8)
                                     ? *a++ == *b++
                                     : (*a >> (8 - nm_bits)) == (*b >> (8 - nm_bits));
                           } while (match && (nm_bits -= 8) > 0);
                           return match;
                   } else if (rmt->plain.sa_family == AF_INET
                              && IN6_IS_ADDR_V4MAPPED(&val.ipv6.sin6_addr)) {
                           uint32_t nm =
                             nm_bits < 128 ? htonl(~(~0u >> (nm_bits > 96 ? nm_bits - 96 : 0))) : ~0u;
                         #ifdef s6_addr32
                           in_addr_t x = val.ipv6.sin6_addr.s6_addr32[3];
                         #else
                           in_addr_t x;
                           memcpy(&x, val.ipv6.sin6_addr.s6_addr+12, sizeof(in_addr_t));
                         #endif
                           return ((x & nm) == (rmt->ipv4.sin_addr.s_addr & nm));
                   } else {
                           return 0;
                   }
   #endif
           } else {
                   log_error_write(srv, __FILE__, __LINE__, "ss", "ERROR: ip addr is invalid:", addrstr);
                   return -1;
           }
   }
   
   static int config_addrbuf_eq_remote_ip_mask(server *srv, buffer *string, char *nm_slash, sock_addr *rmt) {
           char *err;
           int nm_bits = strtol(nm_slash + 1, &err, 10);
           size_t addrstrlen = (size_t)(nm_slash - string->ptr);
           char addrstr[64]; /*(larger than INET_ADDRSTRLEN and INET6_ADDRSTRLEN)*/
   
           if (*err) {
                   log_error_write(srv, __FILE__, __LINE__, "sbs", "ERROR: non-digit found in netmask:", string, err);
                   return -1;
           }
   
           if (nm_bits <= 0) {
                   if (*(nm_slash+1) == '\0') {
                           log_error_write(srv, __FILE__, __LINE__, "sb", "ERROR: no number after / ", string);
                   } else {
                           log_error_write(srv, __FILE__, __LINE__, "sbs", "ERROR: invalid netmask <= 0:", string, err);
                   }
                   return -1;
           }
   
           if (addrstrlen >= sizeof(addrstr)) {
                   log_error_write(srv, __FILE__, __LINE__, "sb", "ERROR: address string too long:", string);
                   return -1;
           }
   
           memcpy(addrstr, string->ptr, addrstrlen);
           addrstr[addrstrlen] = '\0';
   
           return config_addrstr_eq_remote_ip_mask(srv, addrstr, nm_bits, rmt);
   }
   
 static cond_result_t config_check_cond_cached(server *srv, connection *con, data_config *dc);  static cond_result_t config_check_cond_cached(server *srv, connection *con, data_config *dc);
   
 static cond_result_t config_check_cond_nocache(server *srv, connection *con, data_config *dc) {  static cond_result_t config_check_cond_nocache(server *srv, connection *con, data_config *dc) {
         buffer *l;          buffer *l;
         server_socket *srv_sock = con->srv_socket;          server_socket *srv_sock = con->srv_socket;
           cond_cache_t *cache = &con->cond_cache[dc->context_ndx];
   
         /* check parent first */          /* check parent first */
         if (dc->parent && dc->parent->context_ndx) {          if (dc->parent && dc->parent->context_ndx) {
Line 236  static cond_result_t config_check_cond_nocache(server  Line 351  static cond_result_t config_check_cond_nocache(server 
                 }                  }
   
                 switch (config_check_cond_cached(srv, con, dc->parent)) {                  switch (config_check_cond_cached(srv, con, dc->parent)) {
                 case COND_RESULT_FALSE:  
                         return COND_RESULT_FALSE;  
                 case COND_RESULT_UNSET:                  case COND_RESULT_UNSET:
                           /* decide later */
                         return COND_RESULT_UNSET;                          return COND_RESULT_UNSET;
                default:                case COND_RESULT_SKIP:
                 case COND_RESULT_FALSE:
                         /* failed precondition */
                         return COND_RESULT_SKIP;
                 case COND_RESULT_TRUE:
                         /* proceed */
                         break;                          break;
                 }                  }
         }          }
   
         if (dc->prev) {          if (dc->prev) {
                 /**                  /**
                 * a else branch                 * a else branch; can only be executed if the previous branch
                 *                 * was evaluated as "false" (not unset/skipped/true)
                 * we can only be executed, if all of our previous brothers  
                 * are false 
                  */                   */
                 if (con->conf.log_condition_handling) {                  if (con->conf.log_condition_handling) {
                         log_error_write(srv, __FILE__, __LINE__,  "sb", "go prev", dc->prev->key);                          log_error_write(srv, __FILE__, __LINE__,  "sb", "go prev", dc->prev->key);
                 }                  }
   
                 /* make sure prev is checked first */                  /* make sure prev is checked first */
                config_check_cond_cached(srv, con, dc->prev);                switch (config_check_cond_cached(srv, con, dc->prev)) {
                case COND_RESULT_UNSET:
                /* one of prev set me to FALSE */                        /* decide later */
                switch (con->cond_cache[dc->context_ndx].result) {                        return COND_RESULT_UNSET;
                 case COND_RESULT_SKIP:
                 case COND_RESULT_TRUE:
                         /* failed precondition */
                         return COND_RESULT_SKIP;
                 case COND_RESULT_FALSE:                  case COND_RESULT_FALSE:
                        return con->cond_cache[dc->context_ndx].result;                        /* proceed */
                default: 
                         break;                          break;
                 }                  }
         }          }
Line 273  static cond_result_t config_check_cond_nocache(server  Line 393  static cond_result_t config_check_cond_nocache(server 
                         log_error_write(srv, __FILE__, __LINE__,  "dss",                           log_error_write(srv, __FILE__, __LINE__,  "dss", 
                                 dc->comp,                                  dc->comp,
                                 dc->key->ptr,                                  dc->key->ptr,
                                con->conditional_is_valid[dc->comp] ? "yeah" : "nej");                                "not available yet");
                 }                  }
   
                 return COND_RESULT_UNSET;                  return COND_RESULT_UNSET;
         }          }
   
           /* if we had a real result before and weren't cleared just return it */
           switch (cache->local_result) {
           case COND_RESULT_TRUE:
           case COND_RESULT_FALSE:
                   return cache->local_result;
           default:
                   break;
           }
   
         /* pass the rules */          /* pass the rules */
   
         switch (dc->comp) {          switch (dc->comp) {
         case COMP_HTTP_HOST: {          case COMP_HTTP_HOST: {
                 char *ck_colon = NULL, *val_colon = NULL;                  char *ck_colon = NULL, *val_colon = NULL;
   
                if (!buffer_is_empty(con->uri.authority)) {                if (!buffer_string_is_empty(con->uri.authority)) {
   
                         /*                          /*
                          * append server-port to the HTTP_POST if necessary                           * append server-port to the HTTP_POST if necessary
Line 301  static cond_result_t config_check_cond_nocache(server  Line 430  static cond_result_t config_check_cond_nocache(server 
   
                                 if (NULL != ck_colon && NULL == val_colon) {                                  if (NULL != ck_colon && NULL == val_colon) {
                                         /* condition "host:port" but client send "host" */                                          /* condition "host:port" but client send "host" */
                                        buffer_copy_string_buffer(srv->cond_check_buf, l);                                        buffer_copy_buffer(srv->cond_check_buf, l);
                                         buffer_append_string_len(srv->cond_check_buf, CONST_STR_LEN(":"));                                          buffer_append_string_len(srv->cond_check_buf, CONST_STR_LEN(":"));
                                        buffer_append_long(srv->cond_check_buf, sock_addr_get_port(&(srv_sock->addr)));                                        buffer_append_int(srv->cond_check_buf, sock_addr_get_port(&(srv_sock->addr)));
                                         l = srv->cond_check_buf;                                          l = srv->cond_check_buf;
                                 } else if (NULL != val_colon && NULL == ck_colon) {                                  } else if (NULL != val_colon && NULL == ck_colon) {
                                         /* condition "host" but client send "host:port" */                                          /* condition "host" but client send "host:port" */
Line 315  static cond_result_t config_check_cond_nocache(server  Line 444  static cond_result_t config_check_cond_nocache(server 
                                 break;                                  break;
                         }                          }
 #if defined USE_OPENSSL && ! defined OPENSSL_NO_TLSEXT  #if defined USE_OPENSSL && ! defined OPENSSL_NO_TLSEXT
                } else if (!buffer_is_empty(con->tlsext_server_name)) {                } else if (!buffer_string_is_empty(con->tlsext_server_name)) {
                         l = con->tlsext_server_name;                          l = con->tlsext_server_name;
 #endif  #endif
                 } else {                  } else {
Line 336  static cond_result_t config_check_cond_nocache(server  Line 465  static cond_result_t config_check_cond_nocache(server 
   
                 if ((dc->cond == CONFIG_COND_EQ ||                  if ((dc->cond == CONFIG_COND_EQ ||
                      dc->cond == CONFIG_COND_NE) &&                       dc->cond == CONFIG_COND_NE) &&
                     (con->dst_addr.plain.sa_family == AF_INET) &&  
                     (NULL != (nm_slash = strchr(dc->string->ptr, '/')))) {                      (NULL != (nm_slash = strchr(dc->string->ptr, '/')))) {
                        int nm_bits;                        switch (config_addrbuf_eq_remote_ip_mask(srv, dc->string, nm_slash, &con->dst_addr)) {
                        long nm;                        case  1: return (dc->cond == CONFIG_COND_EQ) ? COND_RESULT_TRUE : COND_RESULT_FALSE;
                        char *err;                        case  0: return (dc->cond == CONFIG_COND_EQ) ? COND_RESULT_FALSE : COND_RESULT_TRUE;
                        struct in_addr val_inp;                        case -1: return COND_RESULT_FALSE; /*(error parsing configfile entry)*/
 
                        if (*(nm_slash+1) == '\0') { 
                                log_error_write(srv, __FILE__, __LINE__, "sb", "ERROR: no number after / ", dc->string); 
 
                                return COND_RESULT_FALSE; 
                         }                          }
   
                         nm_bits = strtol(nm_slash + 1, &err, 10);  
   
                         if (*err) {  
                                 log_error_write(srv, __FILE__, __LINE__, "sbs", "ERROR: non-digit found in netmask:", dc->string, err);  
   
                                 return COND_RESULT_FALSE;  
                         }  
   
                         /* take IP convert to the native */  
                         buffer_copy_string_len(srv->cond_check_buf, dc->string->ptr, nm_slash - dc->string->ptr);  
 #ifdef __WIN32  
                         if (INADDR_NONE == (val_inp.s_addr = inet_addr(srv->cond_check_buf->ptr))) {  
                                 log_error_write(srv, __FILE__, __LINE__, "sb", "ERROR: ip addr is invalid:", srv->cond_check_buf);  
   
                                 return COND_RESULT_FALSE;  
                         }  
   
 #else  
                         if (0 == inet_aton(srv->cond_check_buf->ptr, &val_inp)) {  
                                 log_error_write(srv, __FILE__, __LINE__, "sb", "ERROR: ip addr is invalid:", srv->cond_check_buf);  
   
                                 return COND_RESULT_FALSE;  
                         }  
 #endif  
   
                         /* build netmask */  
                         nm = htonl(~((1 << (32 - nm_bits)) - 1));  
   
                         if ((val_inp.s_addr & nm) == (con->dst_addr.ipv4.sin_addr.s_addr & nm)) {  
                                 return (dc->cond == CONFIG_COND_EQ) ? COND_RESULT_TRUE : COND_RESULT_FALSE;  
                         } else {  
                                 return (dc->cond == CONFIG_COND_EQ) ? COND_RESULT_FALSE : COND_RESULT_TRUE;  
                         }  
                 } else {  
                         l = con->dst_addr_buf;  
                 }                  }
                   l = con->dst_addr_buf;
                 break;                  break;
         }          }
         case COMP_HTTP_SCHEME:          case COMP_HTTP_SCHEME:
Line 479  static cond_result_t config_check_cond_nocache(server  Line 567  static cond_result_t config_check_cond_nocache(server 
 #ifdef HAVE_PCRE_H  #ifdef HAVE_PCRE_H
         case CONFIG_COND_NOMATCH:          case CONFIG_COND_NOMATCH:
         case CONFIG_COND_MATCH: {          case CONFIG_COND_MATCH: {
                 cond_cache_t *cache = &con->cond_cache[dc->context_ndx];  
                 int n;                  int n;
   
 #ifndef elementsof  #ifndef elementsof
 #define elementsof(x) (sizeof(x) / sizeof(x[0]))  #define elementsof(x) (sizeof(x) / sizeof(x[0]))
 #endif  #endif
                n = pcre_exec(dc->regex, dc->regex_study, l->ptr, l->used - 1, 0, 0,                n = pcre_exec(dc->regex, dc->regex_study, CONST_BUF_LEN(l), 0, 0,
                                 cache->matches, elementsof(cache->matches));                                  cache->matches, elementsof(cache->matches));
   
                 cache->patterncount = n;                  cache->patterncount = n;
                 if (n > 0) {                  if (n > 0) {
                         cache->comp_value = l;                          cache->comp_value = l;
                         cache->comp_type  = dc->comp;  
                         return (dc->cond == CONFIG_COND_MATCH) ? COND_RESULT_TRUE : COND_RESULT_FALSE;                          return (dc->cond == CONFIG_COND_MATCH) ? COND_RESULT_TRUE : COND_RESULT_FALSE;
                 } else {                  } else {
                         /* cache is already cleared */                          /* cache is already cleared */
Line 512  static cond_result_t config_check_cond_cached(server * Line 598  static cond_result_t config_check_cond_cached(server *
         cond_cache_t *caches = con->cond_cache;          cond_cache_t *caches = con->cond_cache;
   
         if (COND_RESULT_UNSET == caches[dc->context_ndx].result) {          if (COND_RESULT_UNSET == caches[dc->context_ndx].result) {
                if (COND_RESULT_TRUE == (caches[dc->context_ndx].result = config_check_cond_nocache(srv, con, dc))) {                caches[dc->context_ndx].result = config_check_cond_nocache(srv, con, dc);
                        if (dc->next) {                switch (caches[dc->context_ndx].result) {
                                data_config *c;                case COND_RESULT_FALSE:
                                if (con->conf.log_condition_handling) {                case COND_RESULT_TRUE:
                                        log_error_write(srv, __FILE__, __LINE__, "s",                        /* remember result of local condition for a partial reset */
                                                        "setting remains of chaining to false");                        caches[dc->context_ndx].local_result = caches[dc->context_ndx].result;
                                }                        break;
                                for (c = dc->next; c; c = c->next) {                default:
                                        caches[c->context_ndx].result = COND_RESULT_FALSE;                        break;
                                } 
                        } 
                 }                  }
                 caches[dc->context_ndx].comp_type = dc->comp;  
   
                 if (con->conf.log_condition_handling) {                  if (con->conf.log_condition_handling) {
                        log_error_write(srv, __FILE__, __LINE__, "dss", dc->context_ndx,                        log_error_write(srv, __FILE__, __LINE__, "dss",
                                        "(uncached) result:",                                dc->context_ndx,
                                        caches[dc->context_ndx].result == COND_RESULT_UNSET ? "unknown" :                                "(uncached) result:",
                                                (caches[dc->context_ndx].result == COND_RESULT_TRUE ? "true" : "false"));                                cond_result_to_string(caches[dc->context_ndx].result));
                 }                  }
         } else {          } else {
                 if (con->conf.log_condition_handling) {                  if (con->conf.log_condition_handling) {
                        log_error_write(srv, __FILE__, __LINE__, "dss", dc->context_ndx,                        log_error_write(srv, __FILE__, __LINE__, "dss",
                                        "(cached) result:",                                dc->context_ndx,
                                        caches[dc->context_ndx].result == COND_RESULT_UNSET ? "unknown" :                                 "(cached) result:",
                                                (caches[dc->context_ndx].result == COND_RESULT_TRUE ? "true" : "false"));                                cond_result_to_string(caches[dc->context_ndx].result));
                 }                  }
         }          }
         return caches[dc->context_ndx].result;          return caches[dc->context_ndx].result;
 }  }
   
   /* if we reset the cache result for a node, we also need to clear all
    * child nodes and else-branches*/
   static void config_cond_clear_node(server *srv, connection *con, data_config *dc) {
           /* if a node is "unset" all children are unset too */
           if (con->cond_cache[dc->context_ndx].result != COND_RESULT_UNSET) {
                   size_t i;
   
                   con->cond_cache[dc->context_ndx].patterncount = 0;
                   con->cond_cache[dc->context_ndx].comp_value = NULL;
                   con->cond_cache[dc->context_ndx].result = COND_RESULT_UNSET;
   
                   for (i = 0; i < dc->children.used; ++i) {
                           data_config *dc_child = dc->children.data[i];
                           if (NULL == dc_child->prev) {
                                   /* only call for first node in if-else chain */
                                   config_cond_clear_node(srv, con, dc_child);
                           }
                   }
                   if (NULL != dc->next) config_cond_clear_node(srv, con, dc->next);
           }
   }
   
 /**  /**
  * reset the config-cache for a named item   * reset the config-cache for a named item
  *   *
Line 552  void config_cond_cache_reset_item(server *srv, connect Line 657  void config_cond_cache_reset_item(server *srv, connect
         size_t i;          size_t i;
   
         for (i = 0; i < srv->config_context->used; i++) {          for (i = 0; i < srv->config_context->used; i++) {
                if (item == COMP_LAST_ELEMENT ||                 data_config *dc = (data_config *)srv->config_context->data[i];
                    con->cond_cache[i].comp_type == item) {
                        con->cond_cache[i].result = COND_RESULT_UNSET;                if (item == dc->comp) {
                        con->cond_cache[i].patterncount = 0;                        /* clear local_result */
                        con->cond_cache[i].comp_value = NULL;                        con->cond_cache[i].local_result = COND_RESULT_UNSET;
                         /* clear result in subtree (including the node itself) */
                         config_cond_clear_node(srv, con, dc);
                 }                  }
         }          }
 }  }
Line 567  void config_cond_cache_reset_item(server *srv, connect Line 674  void config_cond_cache_reset_item(server *srv, connect
 void config_cond_cache_reset(server *srv, connection *con) {  void config_cond_cache_reset(server *srv, connection *con) {
         size_t i;          size_t i;
   
        config_cond_cache_reset_all_items(srv, con);        /* resetting all entries; no need to follow children as in config_cond_cache_reset_item */
         for (i = 0; i < srv->config_context->used; i++) {
                 con->cond_cache[i].result = COND_RESULT_UNSET;
                 con->cond_cache[i].local_result = COND_RESULT_UNSET;
                 con->cond_cache[i].patterncount = 0;
                 con->cond_cache[i].comp_value = NULL;
         }
   
         for (i = 0; i < COMP_LAST_ELEMENT; i++) {          for (i = 0; i < COMP_LAST_ELEMENT; i++) {
                 con->conditional_is_valid[i] = 0;                  con->conditional_is_valid[i] = 0;
Line 594  int config_append_cond_match_buffer(connection *con, d Line 707  int config_append_cond_match_buffer(connection *con, d
                         cache->matches[n + 1] - cache->matches[n]);                          cache->matches[n + 1] - cache->matches[n]);
         return 1;          return 1;
 }  }
   

Removed from v.1.1.1.1  
changed lines
  Added in v.1.1.1.2


FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>