예제 #1
0
void	*
dummy_rx(ngx_conf_t *r, ngx_str_t *tmp, ngx_http_rule_t *rule)
{
  ngx_regex_compile_t  *rgc;
  ngx_str_t	       ha;
  

  if (!rule->br)
    return (NGX_CONF_ERROR);
  //just prepare a string to hold the directive without 'rx:'
  ha.data = tmp->data+strlen(RX_T);
  ha.len = tmp->len-strlen(RX_T);
  rgc = ngx_pcalloc(r->pool, sizeof(ngx_regex_compile_t));
  if (!rgc)
    return (NGX_CONF_ERROR);
  rgc->options = PCRE_CASELESS|PCRE_MULTILINE;
  rgc->pattern = ha;
  rgc->pool = r->pool;
  rgc->err.len = 0;
  rgc->err.data = NULL;
  
  if (ngx_regex_compile(rgc) != NGX_OK) {
#ifdef rx_debug
      ngx_conf_log_error(NGX_LOG_EMERG, r, 0, "XX-FAILED RX:%V",
			 tmp);
#endif
      return (NGX_CONF_ERROR);
    }
  rule->br->rx = rgc;
#ifdef rx_debug
  ngx_conf_log_error(NGX_LOG_EMERG, r, 0, "XX- RX:[%V]",
		     &(rule->br->rx->pattern));  
#endif
  return (NGX_CONF_OK);
}
예제 #2
0
/*
1. 调用ngx_regex_compile编译正则表达式,并且得到相关的数据,比如子模式数目,命名子模式数目,列表等。
2.	将正则表达式信息存储到ngx_http_regex_t里面,包括正则句柄,子模式数目
3. 	将命名子模式 加入到cmcf->variables_keys和cmcf->variables中。以备后续通过名字查找变量值。*/
ngx_http_regex_t * ngx_http_regex_compile(ngx_conf_t *cf, ngx_regex_compile_t *rc) {
    u_char                     *p;
    size_t                      size;
    ngx_str_t                   name;
    ngx_uint_t                  i, n;
    ngx_http_variable_t        *v;
    ngx_http_regex_t           *re;
    ngx_http_regex_variable_t  *rv;
    ngx_http_core_main_conf_t  *cmcf;

    rc->pool = cf->pool;
    if (ngx_regex_compile(rc) != NGX_OK) {//调用pcre_compile编译正则表达。返回结果存在rc->regex = re;
        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%V", &rc->err);
        return NULL;
    }
    re = ngx_pcalloc(cf->pool, sizeof(ngx_http_regex_t));
    if (re == NULL) {
        return NULL;
    }

    re->regex = rc->regex;
    re->ncaptures = rc->captures;//得到$2,$3有多少个。pcre_fullinfo(re, NULL, PCRE_INFO_CAPTURECOUNT, &rc->captures);
    cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);
    cmcf->ncaptures = ngx_max(cmcf->ncaptures, re->ncaptures);
    n = (ngx_uint_t) rc->named_captures;//命名的子模式: pcre_fullinfo(re, NULL, PCRE_INFO_NAMECOUNT, &rc->named_captures);
    if (n == 0) {
        return re;
    }
    rv = ngx_palloc(rc->pool, n * sizeof(ngx_http_regex_variable_t));
    if (rv == NULL) {//为每一个命名变量申请空间单独存储。
        return NULL;
    }
    re->variables = rv;//记录这种命名的子模式
    re->nvariables = n;
    re->name = rc->pattern;//记录正则表达式字符串

    size = rc->name_size;
    p = rc->names;//正则的命名子模式的二维表,里面记录了子模式的名称,以及在所有模式中的下标.
    //names是这么得到的: pcre_fullinfo(re, NULL, PCRE_INFO_NAMETABLE, &rc->names);
    //一个命名子模式的二维表存储在p的位置。每一行是一个命名模式,每行的字节数为name_size
    for (i = 0; i < n; i++) {//遍历每一个named_captures,
        rv[i].capture = 2 * ((p[0] << 8) + p[1]);//第一个自己左移8位+第二个字节等于这个命名子模式在所有模式中的下标。
        name.data = &p[2];//第三个字节开始就是命名的名字。
        name.len = ngx_strlen(name.data);//名字长度
		///将这个命名子模式加入到cmcf->variables_keys中
        v = ngx_http_add_variable(cf, &name, NGX_HTTP_VAR_CHANGEABLE);
        if (v == NULL) {
            return NULL;
        }
		//然后从cmcf->variables中查找这个变量对应的下标是多少,如果没有,当然就增加到里面去。
        rv[i].index = ngx_http_get_variable_index(cf, &name);
        if (rv[i].index == NGX_ERROR) {
            return NULL;
        }
        v->get_handler = ngx_http_variable_not_found;//初始化为空函数
        p += size;
    }
    return re;
}
static char *
ngx_http_data_dome_auth_merge_conf(ngx_conf_t *cf, void *parent, void *child)
{
    ngx_http_data_dome_auth_conf_t *prev = parent;
    ngx_http_data_dome_auth_conf_t *conf = child;

#if (NGX_PCRE)
    ngx_regex_compile_t   rc;
    u_char                errstr[NGX_MAX_CONF_ERRSTR];
#endif

    if (conf->uri_lengths == NULL) {
        conf->uri_lengths = prev->uri_lengths;
        conf->uri_values = prev->uri_values;
    }
    ngx_conf_merge_uint_value(conf->learning, prev->learning, 0);
	ngx_conf_merge_value(conf->pass_internal_redirect, prev->pass_internal_redirect, 1);

#if (NGX_PCRE)
    if (conf->uri_regex == NULL) {
    conf->uri_regex = prev->uri_regex;
	conf->uri_regex_raw = prev->uri_regex_raw;

	if (conf->uri_regex == NULL) {
	    ngx_str_set(&conf->uri_regex_raw, "");

	}
    }

        if (conf->uri_regex_exclusion == NULL) {
  conf->uri_regex_exclusion = prev->uri_regex_exclusion;
	conf->uri_regex_exclusion_raw = prev->uri_regex_exclusion_raw;

	if (conf->uri_regex_exclusion == NULL) {
	    ngx_memzero(&rc, sizeof(ngx_regex_compile_t));

	    ngx_str_set(&rc.pattern, "\\.(js|css|jpg|jpeg|png|ico|gif|tiff|svg|woff|woff2|ttf|eot|mp4|otf)$");
	    rc.pool = cf->pool;
	    rc.options = NGX_REGEX_CASELESS;
	    rc.err.len = NGX_MAX_CONF_ERRSTR;
	    rc.err.data = errstr;

	    if (ngx_regex_compile(&rc) != NGX_OK) {
		ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%V", &rc.err);
		return NGX_CONF_ERROR;
	    }

	    conf->uri_regex_exclusion = rc.regex;
	    conf->uri_regex_exclusion_raw = rc.pattern;
	}
    }
#endif

    ngx_conf_merge_ptr_value(conf->vars, prev->vars, NULL);

    return NGX_CONF_OK;
}
예제 #4
0
static ngx_int_t
ngx_http_add_regex_referer(ngx_conf_t *cf, ngx_http_referer_conf_t *rlcf,
    ngx_str_t *name)
{
#if (NGX_PCRE)
    ngx_regex_elt_t      *re;
    ngx_regex_compile_t   rc;
    u_char                errstr[NGX_MAX_CONF_ERRSTR];

    if (name->len == 1) {
        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "empty regex in \"%V\"", name);
        return NGX_ERROR;
    }

    if (rlcf->regex == NGX_CONF_UNSET_PTR) {
        rlcf->regex = ngx_array_create(cf->pool, 2, sizeof(ngx_regex_elt_t));
        if (rlcf->regex == NULL) {
            return NGX_ERROR;
        }
    }

    re = ngx_array_push(rlcf->regex);
    if (re == NULL) {
        return NGX_ERROR;
    }

    name->len--;
    name->data++;

    ngx_memzero(&rc, sizeof(ngx_regex_compile_t));

    rc.pattern = *name;
    rc.pool = cf->pool;
    rc.options = NGX_REGEX_CASELESS;
    rc.err.len = NGX_MAX_CONF_ERRSTR;
    rc.err.data = errstr;

    if (ngx_regex_compile(&rc) != NGX_OK) {
        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%V", &rc.err);
        return NGX_ERROR;
    }

    re->regex = rc.regex;
    re->name = name->data;

    return NGX_OK;

#else

    ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
                       "the using of the regex \"%V\" requires PCRE library",
                       name);

    return NGX_ERROR;

#endif
}
static char *
ngx_http_advertise_blackhost(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
    ngx_http_advertise_conf_t  *accf = conf;

#if (NGX_PCRE)

    ngx_str_t            *value;
    ngx_uint_t            i;
    ngx_regex_elt_t      *re;
    ngx_regex_elt_t      *tmp;
    ngx_regex_compile_t   rc;
    u_char                errstr[NGX_MAX_CONF_ERRSTR];

    value = cf->args->elts;
    
    ngx_memzero(&rc, sizeof(ngx_regex_compile_t));

    rc.pool = cf->pool;
    rc.err.len = NGX_MAX_CONF_ERRSTR;
    rc.err.data = errstr;

    tmp = accf->black_hosts->elts;

    for (i = 0; i < accf->black_hosts->nelts; i++) {
        if (ngx_strncasecmp(value[0].data, tmp[i].name, value[0].len) == 0) {
            return NGX_CONF_OK;
        }
    }

    re = ngx_array_push(accf->black_hosts);
    if (re == NULL) {
        return NGX_CONF_ERROR;
    }

    rc.pattern = value[0];
    rc.options = NGX_REGEX_CASELESS;

    if (ngx_regex_compile(&rc) != NGX_OK) {
        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%V", &rc.err);
        return NGX_CONF_ERROR;
    }

    re->regex = rc.regex;
    re->name = value[0].data;

    return NGX_CONF_OK;
#else
    ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
                           "without PCRE library \"advert filter\" supports ");
    return NGX_CONF_ERROR;
#endif
}
static char *
ngx_http_cors_add(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
    ngx_http_cors_loc_conf_t *hclf = conf;

    u_char               errstr[NGX_MAX_CONF_ERRSTR];
    ngx_str_t           *value;
    ngx_regex_elt_t     *re;
    ngx_regex_compile_t rc;

    if (hclf->cors == NULL) {
        hclf->cors = ngx_array_create(cf->pool, 1, sizeof(ngx_regex_elt_t));
        if (hclf->cors == NULL) {
            return NGX_CONF_ERROR;
        }
    }

    ngx_memzero(&rc, sizeof(ngx_regex_compile_t));

    value = cf->args->elts;
    rc.pattern.len = value[1].len;
    rc.pattern.data = value[1].data;
    rc.pool = cf->pool;
    rc.options = 0;
    rc.err.len = NGX_MAX_CONF_ERRSTR;
    rc.err.data = errstr;

#if (NGX_PCRE)
    if (ngx_regex_compile(&rc) != NGX_OK) {
        ngx_log_error(NGX_LOG_ERR, cf->log, 0, "[cors]: compile regex error");
        return NGX_CONF_ERROR;
    }
#else
    ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
     "the using of the regex cors requires PCRE library");

    return NGX_ERROR;
#endif

    re = ngx_array_push(hclf->cors);
    if (re == NULL) {
        return NGX_CONF_ERROR;
    }
    re->regex = rc.regex;
    re->name = value[1].data;

    return NGX_CONF_OK;
}
ngx_int_t ngx_http_small_light_parse_define_pattern(ngx_http_request_t *r, ngx_str_t *unparsed_uri, ngx_str_t *define_pattern)
{
    char *pattern_s = "small_light\\(([^\\)]*)\\)";
    int rc, captures[(1 + 2) * 3];
    u_char errstr[NGX_MAX_CONF_ERRSTR];
    ngx_str_t pattern;
    ngx_regex_compile_t rgc;
    u_char *define_pattern_s;

    ngx_memzero(&rgc, sizeof(ngx_regex_compile_t));

    pattern.data = (u_char *)pattern_s;
    pattern.len  = ngx_strlen(pattern_s);

    rgc.pattern  = pattern;
    rgc.pool     = r->pool;
    rgc.err.len  = NGX_MAX_CONF_ERRSTR;
    rgc.err.data = errstr;

    if (ngx_regex_compile(&rgc) != NGX_OK) {
        ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "%V", &rgc.err);
        return NGX_ERROR;
    }

    rc = ngx_regex_exec(rgc.regex, unparsed_uri, captures, (1 + 2) * 3);

    if (rc >= 0) {
        int capture_start = captures[2];
        int capture_end   = captures[3];
        int capture_len   = capture_end - capture_start;
        define_pattern_s  = ngx_pcalloc(r->pool, capture_len + 1);
        if (define_pattern_s == NULL) {
            return NGX_ERROR;
        }
        ngx_cpystrn(define_pattern_s, unparsed_uri->data + capture_start, capture_len + 1);
        define_pattern->data = define_pattern_s;
        define_pattern->len  = capture_len;
    } else {
        return NGX_ERROR;
    }

    return NGX_OK;
}
static char *
ngx_http_data_dome_auth_uri_regex(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
#if (NGX_PCRE)
    ngx_http_data_dome_auth_conf_t *acf = conf;

    ngx_str_t            *value;
    ngx_regex_compile_t   rc;
    u_char                errstr[NGX_MAX_CONF_ERRSTR];

    value = cf->args->elts;

    ngx_memzero(&rc, sizeof(ngx_regex_compile_t));

    rc.pattern = value[1];
    rc.pool = cf->pool;
    rc.options = NGX_REGEX_CASELESS;
    rc.err.len = NGX_MAX_CONF_ERRSTR;
    rc.err.data = errstr;

    if (ngx_regex_compile(&rc) != NGX_OK) {
	ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%V", &rc.err);
	return NGX_CONF_ERROR;
    }

    acf->uri_regex = rc.regex;
    acf->uri_regex_raw = value[1];

    return NGX_CONF_OK;

#else

    ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
		       "\"%V\" requires PCRE library", &cmd->name);
    return NGX_CONF_ERROR;

#endif
}
static char *
ngx_http_methods_filter_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
{
    ngx_http_methods_filter_loc_conf_t *prev = parent;
    ngx_http_methods_filter_loc_conf_t *conf = child;

    ngx_conf_merge_str_value(conf->allowed_methods, prev->allowed_methods, NGX_HTTP_METHODS_FILTER_DEFAULT_ALLOWED_METHODS);

    if (conf->allowed_methods.len == 0) {
        return NGX_CONF_OK;
    }

    ngx_http_methods_filter_used = 1;

    if (conf->allowed_methods_regex == NULL) {
        u_char errstr[NGX_MAX_CONF_ERRSTR];
        ngx_regex_compile_t *rc = NULL;
        if ((rc = ngx_pcalloc(cf->pool, sizeof(ngx_regex_compile_t))) == NULL) {
            ngx_conf_log_error(NGX_LOG_ERR, cf, 0, "methods filter module: unable to allocate memory to compile pattern");
            return NGX_CONF_ERROR;
        }

        rc->pattern = conf->allowed_methods;
        rc->pool = cf->pool;
        rc->err.len = NGX_MAX_CONF_ERRSTR;
        rc->err.data = errstr;

        if (ngx_regex_compile(rc) != NGX_OK) {
            ngx_conf_log_error(NGX_LOG_ERR, cf, 0, "methods filter module: unable to compile bypass url pattern %V", &conf->allowed_methods);
            return NGX_CONF_ERROR;
        }

        conf->allowed_methods_regex = rc->regex;
    }

    return NGX_CONF_OK;
}
예제 #10
0
static ngx_int_t
ngx_http_subs_filter_regex_compile(sub_pair_t *pair,
    ngx_http_script_compile_t *sc, ngx_conf_t *cf)
{
    ngx_int_t                   n, options;
    ngx_uint_t                  mask;
    ngx_str_t                  *value;

    value = cf->args->elts;

    /* Caseless match can only be implemented in regex. */
#if (NGX_PCRE)
    ngx_str_t         err;
    u_char            errstr[NGX_MAX_CONF_ERRSTR];

    err.len = NGX_MAX_CONF_ERRSTR;
    err.data = errstr;

    options = (pair->insensitive ? NGX_REGEX_CASELESS : 0);

    /* make nginx-0.8.25+ happy */
#if defined(nginx_version) && nginx_version >= 8025
    ngx_regex_compile_t   rc;

    rc.pattern = pair->match;
    rc.pool = cf->pool;
    rc.err = err;
    rc.options = options;

    if (ngx_regex_compile(&rc) != NGX_OK) {
        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%V", &rc.err);
        return NGX_ERROR;
    }

    pair->match_regex = rc.regex;

#else
    pair->match_regex = ngx_regex_compile(&pair->match, options,
                                          cf->pool, &err);
#endif

    if (pair->match_regex == NULL) {
        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%V", &err);
        return NGX_ERROR;
    }

    n = ngx_http_subs_regex_capture_count(pair->match_regex);

    if (pair->has_captured) {
        mask = ((1 << (n + 1)) - 1);
        if ( mask < sc->captures_mask ) {
            ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
                               "You want to capture too many regex substrings, "
                               "more than %i in \"%V\"",
                               n, &value[2]);

            return NGX_ERROR;
        }
    }
#else
    ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
                       "the using of the regex \"%V\" requires PCRE library",
                       &pair->match);

    return NGX_ERROR;
#endif

    return NGX_OK;
}
예제 #11
0
ngx_http_regex_t *
ngx_http_regex_compile(ngx_conf_t *cf, ngx_regex_compile_t *rc)
{
    u_char                     *p;
    size_t                      size;
    ngx_str_t                   name;
    ngx_uint_t                  i, n;
    ngx_http_variable_t        *v;
    ngx_http_regex_t           *re;
    ngx_http_regex_variable_t  *rv;
    ngx_http_core_main_conf_t  *cmcf;

    rc->pool = cf->pool;

    if (ngx_regex_compile(rc) != NGX_OK) {
        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%V", &rc->err);
        return NULL;
    }

    re = ngx_pcalloc(cf->pool, sizeof(ngx_http_regex_t));
    if (re == NULL) {
        return NULL;
    }

    re->regex = rc->regex;
    re->ncaptures = rc->captures;

    cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);
    cmcf->ncaptures = ngx_max(cmcf->ncaptures, re->ncaptures);

    n = (ngx_uint_t) rc->named_captures;

    if (n == 0) {
        return re;
    }

    rv = ngx_palloc(rc->pool, n * sizeof(ngx_http_regex_variable_t));
    if (rv == NULL) {
        return NULL;
    }

    re->variables = rv;
    re->nvariables = n;
    re->name = rc->pattern;

    size = rc->name_size;
    p = rc->names;

    for (i = 0; i < n; i++) {
        rv[i].capture = 2 * ((p[0] << 8) + p[1]);

        name.data = &p[2];
        name.len = ngx_strlen(name.data);

        v = ngx_http_add_variable(cf, &name, NGX_HTTP_VAR_CHANGEABLE);
        if (v == NULL) {
            return NULL;
        }

        rv[i].index = ngx_http_get_variable_index(cf, &name);
        if (rv[i].index == NGX_ERROR) {
            return NULL;
        }

        v->get_handler = ngx_http_variable_not_found;

        p += size;
    }

    return re;
}
static char*
ngx_http_fancyindex_ignore(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
    ngx_http_fancyindex_loc_conf_t *alcf = conf;
    ngx_str_t *value;

#if (NGX_PCRE)
    ngx_uint_t          i;
    ngx_regex_elt_t    *re;
    ngx_regex_compile_t rc;
    u_char              errstr[NGX_MAX_CONF_ERRSTR];

    if (alcf->ignore == NGX_CONF_UNSET_PTR) {
        alcf->ignore = ngx_array_create(cf->pool, 2, sizeof(ngx_regex_elt_t));
        if (alcf->ignore == NULL) {
            return NGX_CONF_ERROR;
        }
    }

    value = cf->args->elts;

    ngx_memzero(&rc, sizeof(ngx_regex_compile_t));

    rc.err.data = errstr;
    rc.err.len  = NGX_MAX_CONF_ERRSTR;
    rc.pool     = cf->pool;

    for (i = 1; i < cf->args->nelts; i++) {
        re = ngx_array_push(alcf->ignore);
        if (re == NULL) {
            return NGX_CONF_ERROR;
        }

        rc.pattern = value[i];
        rc.options = NGX_REGEX_CASELESS;

        if (ngx_regex_compile(&rc) != NGX_OK) {
            ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%V", &rc.err);
            return NGX_CONF_ERROR;
        }

        re->name  = value[i].data;
        re->regex = rc.regex;
    }

    return NGX_CONF_OK;
#else /* !NGX_PCRE */
    ngx_uint_t i;
    ngx_str_t *str;

    if (alcf->ignore == NGX_CONF_UNSET_PTR) {
        alcf->ignore = ngx_array_create(cf->pool, 2, sizeof(ngx_str_t));
        if (alcf->ignore == NULL) {
            return NGX_CONF_ERROR;
        }
    }

    value = cf->args->elts;

    for (i = 1; i < cf->args->nelts; i++) {
        str = ngx_array_push(alcf->ignore);
        if (str == NULL) {
            return NGX_CONF_ERROR;
        }

        str->data = value[i].data;
        str->len  = value[i].len;
    }

    return NGX_CONF_OK;
#endif /* NGX_PCRE */

}
예제 #13
0
ngx_int_t
ngx_http_dummy_create_hashtables_n(ngx_http_dummy_loc_conf_t *dlc, 
				   ngx_conf_t *cf)
{
  int				zone, uri_idx, name_idx, ret;
  ngx_http_rule_t		*curr_r/*, *father_r*/;
  ngx_http_whitelist_rule_t	*father_wlr;
  ngx_http_rule_t **rptr;
  ngx_regex_compile_t *rgc;
  char			*fullname;
  uint	i;

  if (!dlc->whitelist_rules  || dlc->whitelist_rules->nelts < 1) {
    NX_LOG_DEBUG(_debug_whitelist_heavy    ,
		 NGX_LOG_EMERG, cf, 0, 
		 "No whitelist registred, but it's your call.");    

    return (NGX_OK);
  }
  NX_LOG_DEBUG(_debug_whitelist_heavy,
  NGX_LOG_EMERG, cf, 0, 
	       "Building whitelist hashtables, %d items in list",
	       dlc->whitelist_rules->nelts);
  
  dlc->tmp_wlr = ngx_array_create(cf->pool, dlc->whitelist_rules->nelts,
  				  sizeof(ngx_http_whitelist_rule_t));
  /* iterate through each stored whitelist rule. */
  for (i = 0; i < dlc->whitelist_rules->nelts; i++) {
    uri_idx = name_idx = zone = -1;
    /*a whitelist is in fact just another basic_rule_t */
    curr_r = &(((ngx_http_rule_t*)(dlc->whitelist_rules->elts))[i]);
    NX_LOG_DEBUG(_debug_whitelist_heavy,
		 NGX_LOG_EMERG, cf, 0,
		 "Processing wl %d/%p", i, curr_r);
    
    /*no custom location at all means that the rule is disabled */
    if (!curr_r->br->custom_locations) {
      NX_LOG_DEBUG(_debug_whitelist_heavy,
		   NGX_LOG_EMERG, cf, 0,
		   "WL %d is a disable rule.", i);
      
      if (ngx_http_wlr_push_disabled(cf, dlc, curr_r) == NGX_ERROR)
	return (NGX_ERROR);
      continue;
    }
    ret = ngx_http_wlr_identify(cf, dlc, curr_r, &zone, &uri_idx, &name_idx);
    if (ret != NGX_OK) /* LCOV_EXCL_START */
      {
	ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, 
			   "Following whitelist doesn't target any zone or is incorrect :");
	if (name_idx != -1)
	  ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "whitelist target name : %V", 
			     &(custloc_array(curr_r->br->custom_locations->elts)[name_idx].target));
	else
	  ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "whitelist has no target name.");
	if (uri_idx != -1)
	  ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "whitelist target uri : %V", 
			     &(custloc_array(curr_r->br->custom_locations->elts)[uri_idx].target));
	else
	  ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "whitelists has no target uri.");
	return (NGX_ERROR);
      } /* LCOV_EXCL_STOP */
    curr_r->br->zone = zone;
    /*
    ** Handle regular-expression-matchzone rules :
    ** Store them in a separate linked list, parsed
    ** at runtime.
    */
    if (curr_r->br->rx_mz == 1) {
      if (!dlc->rxmz_wlr) {
	dlc->rxmz_wlr = ngx_array_create(cf->pool, 1,
					 sizeof(ngx_http_rule_t *));
	if (!dlc->rxmz_wlr) return (NGX_ERROR); /* LCOV_EXCL_LINE */
      }
      if (name_idx != -1 && !custloc_array(curr_r->br->custom_locations->elts)[name_idx].target_rx) {
	custloc_array(curr_r->br->custom_locations->elts)[name_idx].target_rx = 
	  ngx_pcalloc(cf->pool, sizeof(ngx_regex_compile_t));
	rgc = custloc_array(curr_r->br->custom_locations->elts)[name_idx].target_rx;
	rgc->options = PCRE_CASELESS|PCRE_MULTILINE;
	rgc->pattern = custloc_array(curr_r->br->custom_locations->elts)[name_idx].target;
	rgc->pool = cf->pool;
	rgc->err.len = 0;
	rgc->err.data = NULL;
	//custloc_array(curr_r->br->custom_locations->elts)[name_idx].target;
	if (ngx_regex_compile(rgc) != NGX_OK)
	  return (NGX_ERROR);
      }
      if (uri_idx != -1 && !custloc_array(curr_r->br->custom_locations->elts)[uri_idx].target_rx) {
	custloc_array(curr_r->br->custom_locations->elts)[uri_idx].target_rx = 
	  ngx_pcalloc(cf->pool, sizeof(ngx_regex_compile_t));
	rgc = custloc_array(curr_r->br->custom_locations->elts)[uri_idx].target_rx;
	rgc->options = PCRE_CASELESS|PCRE_MULTILINE;
	rgc->pattern = custloc_array(curr_r->br->custom_locations->elts)[uri_idx].target;
	rgc->pool = cf->pool;
	rgc->err.len = 0;
	rgc->err.data = NULL;
	//custloc_array(curr_r->br->custom_locations->elts)[name_idx].target;
	if (ngx_regex_compile(rgc) != NGX_OK)
	  return (NGX_ERROR);
      }
      
      rptr = ngx_array_push(dlc->rxmz_wlr);
      if (!rptr)
	return (NGX_ERROR);
      *rptr = curr_r;
      continue;
    }
    /*
    ** Handle static match-zones for hashtables
    */
    father_wlr = ngx_http_wlr_find(cf, dlc, curr_r, zone, uri_idx, name_idx, (char **) &fullname);
    if (!father_wlr) {
      NX_LOG_DEBUG(_debug_whitelist_heavy,
		   NGX_LOG_EMERG, cf, 0, 
		   "creating fresh WL [%s].", fullname);
      
      /* creates a new whitelist rule in the right place.
	 setup name and zone, create a new (empty) whitelist_location, as well
	 as a new (empty) id aray. */
      father_wlr = ngx_array_push(dlc->tmp_wlr);
      if (!father_wlr)
	return (NGX_ERROR);
      memset(father_wlr, 0, sizeof(ngx_http_whitelist_rule_t));
      father_wlr->name = ngx_pcalloc(cf->pool, sizeof(ngx_str_t));
      if (!father_wlr->name)
	return (NGX_ERROR);
      father_wlr->name->len = strlen((const char *) fullname);
      father_wlr->name->data = (unsigned char *) fullname;
      father_wlr->zone = zone;
      /* If there is URI and no name idx, specify it,
	 so that WL system won't get fooled by an argname like an URL */
      if (uri_idx != -1 && name_idx == -1)
	father_wlr->uri_only = 1;
      /* If target_name is present in son, report it. */
      if (curr_r->br->target_name)
        father_wlr->target_name = curr_r->br->target_name; 
    }
    /*merges the two whitelist rules together, including custom_locations. */
    if (ngx_http_wlr_merge(cf, father_wlr, curr_r) != NGX_OK)
      return (NGX_ERROR);
  }
  
  /* and finally, build the hashtables for various zones. */
  if (ngx_http_wlr_finalize_hashtables(cf, dlc) != NGX_OK)
    return (NGX_ERROR);
  /* TODO : Free old whitelist_rules (dlc->whitelist_rules)*/
  return (NGX_OK);
}
static char *
ngx_http_push_stream_init_main_conf(ngx_conf_t *cf, void *parent)
{
    ngx_http_push_stream_main_conf_t     *conf = parent;

    if (!conf->enabled) {
        return NGX_CONF_OK;
    }

    ngx_conf_init_value(conf->message_ttl, NGX_HTTP_PUSH_STREAM_DEFAULT_MESSAGE_TTL);
    ngx_conf_init_value(conf->channel_inactivity_time, NGX_HTTP_PUSH_STREAM_DEFAULT_CHANNEL_INACTIVITY_TIME);
    ngx_conf_merge_str_value(conf->channel_deleted_message_text, conf->channel_deleted_message_text, NGX_HTTP_PUSH_STREAM_CHANNEL_DELETED_MESSAGE_TEXT);
    ngx_conf_merge_str_value(conf->ping_message_text, conf->ping_message_text, NGX_HTTP_PUSH_STREAM_PING_MESSAGE_TEXT);
    ngx_conf_merge_str_value(conf->wildcard_channel_prefix, conf->wildcard_channel_prefix, NGX_HTTP_PUSH_STREAM_DEFAULT_WILDCARD_CHANNEL_PREFIX);
    ngx_conf_init_value(conf->timeout_with_body, 0);

    // sanity checks
    // shm size should be set
    if (conf->shm_zone == NULL) {
        ngx_conf_log_error(NGX_LOG_ERR, cf, 0, "push stream module: push_stream_shared_memory_size must be set.");
        return NGX_CONF_ERROR;
    }

    // max number of channels cannot be zero
    if ((conf->max_number_of_channels != NGX_CONF_UNSET_UINT) && (conf->max_number_of_channels == 0)) {
        ngx_conf_log_error(NGX_LOG_ERR, cf, 0, "push stream module: push_stream_max_number_of_channels cannot be zero.");
        return NGX_CONF_ERROR;
    }

    // max number of wildcard channels cannot be zero
    if ((conf->max_number_of_wildcard_channels != NGX_CONF_UNSET_UINT) && (conf->max_number_of_wildcard_channels == 0)) {
        ngx_conf_log_error(NGX_LOG_ERR, cf, 0, "push stream module: push_stream_max_number_of_wildcard_channels cannot be zero.");
        return NGX_CONF_ERROR;
    }

    // message ttl cannot be zero
    if ((conf->message_ttl != NGX_CONF_UNSET) && (conf->message_ttl == 0)) {
        ngx_conf_log_error(NGX_LOG_ERR, cf, 0, "push stream module: push_stream_message_ttl cannot be zero.");
        return NGX_CONF_ERROR;
    }

    // max subscriber per channel cannot be zero
    if ((conf->max_subscribers_per_channel != NGX_CONF_UNSET_UINT) && (conf->max_subscribers_per_channel == 0)) {
        ngx_conf_log_error(NGX_LOG_ERR, cf, 0, "push stream module: push_stream_max_subscribers_per_channel cannot be zero.");
        return NGX_CONF_ERROR;
    }

    // max messages stored per channel cannot be zero
    if ((conf->max_messages_stored_per_channel != NGX_CONF_UNSET_UINT) && (conf->max_messages_stored_per_channel == 0)) {
        ngx_conf_log_error(NGX_LOG_ERR, cf, 0, "push stream module: push_stream_max_messages_stored_per_channel cannot be zero.");
        return NGX_CONF_ERROR;
    }

    // max channel id length cannot be zero
    if ((conf->max_channel_id_length != NGX_CONF_UNSET_UINT) && (conf->max_channel_id_length == 0)) {
        ngx_conf_log_error(NGX_LOG_ERR, cf, 0, "push stream module: push_stream_max_channel_id_length cannot be zero.");
        return NGX_CONF_ERROR;
    }

    ngx_regex_compile_t *backtrack_parser = NULL;
    u_char               errstr[NGX_MAX_CONF_ERRSTR];

    if ((backtrack_parser = ngx_pcalloc(cf->pool, sizeof(ngx_regex_compile_t))) == NULL) {
        ngx_conf_log_error(NGX_LOG_ERR, cf, 0, "push stream module: push stream module: unable to allocate memory to compile backtrack parser");
        return NGX_CONF_ERROR;
    }

    backtrack_parser->pattern = NGX_HTTP_PUSH_STREAM_BACKTRACK_PATTERN;
    backtrack_parser->pool = cf->pool;
    backtrack_parser->err.len = NGX_MAX_CONF_ERRSTR;
    backtrack_parser->err.data = errstr;

    if (ngx_regex_compile(backtrack_parser) != NGX_OK) {
        ngx_conf_log_error(NGX_LOG_ERR, cf, 0, "push stream module: unable to compile backtrack parser pattern %V", &NGX_HTTP_PUSH_STREAM_BACKTRACK_PATTERN);
        return NGX_CONF_ERROR;
    }

    conf->backtrack_parser_regex = backtrack_parser->regex;

    return NGX_CONF_OK;
}
static ngx_int_t 
ngx_tcp_cmd_parse_ini_conf(ngx_cycle_t *cycle)
{
    ngx_str_t            cmdso_path = CMDSO_PATH_STR;
    ngx_str_t            cmdso_file = CMDSO_INI_FILE_STR;
    char                *path_file;
    FILE                *p_file;
    int                  lines;
    char                 line_buf[CMDSO_INI_FILE_LINE_MAXLEN];
#define PCRE_OVECTOR_SIZE 16
    int                  ovector[PCRE_OVECTOR_SIZE];
    ngx_regex_compile_t  re_section;
    ngx_regex_compile_t  re_line;
    int                  rc;
    ngx_str_t            ini_section = ngx_null_string;
    ngx_map_t           *section_map;

    cmdso_conf = ngx_map_create(NGX_MAP_STR_T, NGX_MAP_PTR_T, 
        cycle->pool, (ngx_palloc_pt)ngx_palloc, (ngx_pfree_pt)ngx_pfree);
    if (cmdso_conf == NULL) {
        ngx_log_error(NGX_LOG_ERR, cycle->log, 0, 
            "ngx_tcp_cmd_parse_ini_conf|cmdso_conf == NULL\n");
        return NGX_ERROR;
    }

    /* the cmdso_path->data will end with '\0' */
    ngx_conf_full_name(cycle, &cmdso_path, 0);
    path_file = ngx_tcp_cmd_concat_filename((const char *)cmdso_path.data, 
        (const char *)cmdso_file.data);
    p_file = fopen(path_file, "r");
    free(path_file);
    if (p_file == NULL) {
        ngx_log_error(NGX_LOG_WARN, cycle->log, 0, 
            "ngx_tcp_cmd_parse_ini_conf|%V has'n %V\n", &cmdso_path, &cmdso_file);
        ngx_map_destroy(cmdso_conf);
        cmdso_conf = NULL;
        return NGX_OK;
    }

    ngx_memset(&re_section, 0, sizeof(ngx_regex_compile_t));
    re_section.pool = cycle->pool;
    re_section.pattern.data = (u_char *)CMDSO_INI_SECTION_PATTERN;
    re_section.pattern.len = sizeof(CMDSO_INI_SECTION_PATTERN) - 1;
    if (ngx_regex_compile(&re_section) != NGX_OK) {
        ngx_log_error(NGX_LOG_ERR, cycle->log, 0, 
            "ngx_tcp_cmd_parse_ini_conf|pattern = %s|pcre_err is %V.\n", 
            CMDSO_INI_SECTION_PATTERN, &re_section.err);
        goto failed;
    }
    ngx_memset(&re_line, 0, sizeof(ngx_regex_compile_t));
    re_line.pool = cycle->pool;
    re_line.pattern.data = (u_char *)CMDSO_INI_LINE_PATTERN;
    re_line.pattern.len = sizeof(CMDSO_INI_LINE_PATTERN) - 1;
    if (ngx_regex_compile(&re_line) != NGX_OK) {
        ngx_log_error(NGX_LOG_ERR, cycle->log, 0, 
            "ngx_tcp_cmd_parse_ini_conf|pattern = %s|pcre_err is %V.\n", 
            CMDSO_INI_LINE_PATTERN, &re_line.err);
        goto failed;
    }

    lines = 0;
    while (fgets(line_buf, CMDSO_INI_FILE_LINE_MAXLEN, p_file) != NULL
        && !feof(p_file)) {
        int str_len;
        int i = 0;
        ++lines;
        while(line_buf[i] 
            && (line_buf[i] == ' ' || line_buf[i] == '\t' 
                || line_buf[i] == '\n')) {
            ++i;
        }
        if (!line_buf[i] || line_buf[i] == '#')
            continue;
        rc = pcre_exec(re_section.regex->code, NULL, line_buf, ngx_strlen(line_buf), 
                       0, 0, ovector, PCRE_OVECTOR_SIZE);
        if (rc < 0) {
            goto __pcre_exec_after_ini_section__;
        }
        if (ini_section.data != NULL ) {
            free(ini_section.data);
            ini_section.data = NULL;
        }
        str_len = ovector[3] - ovector[2];
        ini_section.data = (u_char *)strndup(&line_buf[0] + ovector[2], str_len);
        ini_section.len = str_len;
        section_map = ngx_map_create(NGX_MAP_NGXSTR_T, NGX_MAP_NGXSTR_T, 
            cycle->pool, (ngx_palloc_pt)ngx_palloc, (ngx_pfree_pt)ngx_pfree); 
        if (cmdso_conf == NULL) {
            ngx_log_error(NGX_LOG_ERR, cycle->log, 0, 
                "ngx_tcp_cmd_parse_ini_conf|cmdso_conf == NULL\n");
            goto failed;
        }
        if (ngx_map_set_str_ptr(cmdso_conf, (const char *)ini_section.data, section_map) 
            != NGX_OK) {
            ngx_log_error(NGX_LOG_ERR, cycle->log, 0, 
                "ngx_tcp_cmd_parse_ini_conf|ngx_map_set_str_ptr %s\n", 
                ini_section.data);
            goto failed;
        }
        section_map = NULL;
        continue;

__pcre_exec_after_ini_section__:
        rc = pcre_exec(re_line.regex->code, NULL, line_buf, ngx_strlen(line_buf), 
                       0, 0, ovector, PCRE_OVECTOR_SIZE);
        if (rc < 0) {
            ngx_log_error(NGX_LOG_ERR, cycle->log, 0, 
                "ngx_tcp_cmd_parse_ini_conf|pcre_exec %s, line number %d\n",
                line_buf, lines);
            goto failed;
        }
        if (ini_section.data == NULL ) {
            ngx_log_error(NGX_LOG_ERR, cycle->log, 0, 
                "ngx_tcp_cmd_parse_ini_conf|no section line %s, line number %d\n",
                line_buf, lines);
            goto failed;
        }
        if (ngx_map_find_str_ptr(cmdso_conf, (const char *)ini_section.data, 
            (void **)&section_map) != NGX_OK) {
            ngx_log_error(NGX_LOG_ERR, cycle->log, 0, 
                "ngx_tcp_cmd_parse_ini_conf|find section %s, line number %d\n",
                ini_section.data, lines);
            goto failed;
        }
        {
            ngx_str_t k,v;

            k.data = (u_char *)(line_buf + ovector[2]);
            k.len = ovector[3] - ovector[2];
            v.data = (u_char *)(line_buf + ovector[4]);
            v.len = ovector[5] - ovector[4];

            ngx_map_set_ngxstr_ngxstr(section_map, &k, &v);
        }
    } // end while
    fclose(p_file);

    return NGX_OK;

failed:
    if (ini_section.data != NULL ) {
        free(ini_section.data);
        ini_section.data = NULL;
    }
    if (p_file != NULL) {
        fclose(p_file);
        p_file = NULL;
    }
    return NGX_ERROR;
}