static u_char*
ngx_http_find_location(ngx_http_advertise_ctx_t *ctx,
                                ngx_http_advertise_format *adver)
{
    u_char *location = NULL;
    u_char *strbpk = ngx_strnstr(adver->anchor.data, (char*)g_advertise_strbpk_s.data, adver->anchor.len);

    if (strbpk) {
        
        size_t  anchor_new_length = strbpk - adver->anchor.data;
        location = ngx_strlcasestrn(ctx->html, ctx->last, 
                               adver->anchor.data, anchor_new_length - 1);
        if (location == NULL) {
            return NULL;
        }
        if (adver->location == 0) {
            return location;
        }
        
        u_char *suffix = strbpk + g_advertise_strbpk_s.len;
        size_t suffix_len = adver->anchor.data + adver->anchor.len - suffix;
        location = ngx_strlcasestrn(location + anchor_new_length, ctx->last, suffix, suffix_len - 1);
        if (location) {
            return location + suffix_len;
        }
    } else {
        location = ngx_strlcasestrn(ctx->html, ctx->last, adver->anchor.data, adver->anchor.len - 1);
        if (location) {
            location = (adver->location == 0) ? location : location + adver->anchor.len;
        }
    }
    return location;
}
static ngx_int_t
ngx_tcp_process_http_header(ngx_tcp_lua_http_parse_ctx_t *r,
    ngx_buf_t *b, lua_State *L)
{
    ngx_int_t                       rc;
    size_t                          header_name_len;                        
    size_t                          header_len;                        

    for ( ;; ) {

        rc = ngx_tcp_parse_http_header_line(r, b, 1);

        if (rc == NGX_OK) {

            /* a header line has been parsed successfully */

            header_name_len = r->header_name_end - r->header_name_start;
            header_len = r->header_end - r->header_start;

            lua_pushlstring(L, (const char*)r->header_name_start, header_name_len);
            lua_pushlstring(L, (const char*)r->header_start, header_len);
            lua_rawset(L, -3);
            
            if (0 == ngx_strncasecmp(r->header_name_start, (u_char *) "content-length", header_name_len)
                || 0 == ngx_strncasecmp(r->header_name_start, (u_char *) "content_length", header_name_len) ) {
                r->content_length_n = ngx_atoof(r->header_start, header_len);
            }
            
            if ( (0 == ngx_strncasecmp(r->header_name_start, (u_char *) "transfer-encoding", header_name_len)
                || 0 == ngx_strncasecmp(r->header_name_start, (u_char *) "transfer-encoding", header_name_len) )
                &&  ngx_strlcasestrn(r->header_start, r->header_end, (u_char *) "chunked", 7 - 1) != NULL ) {
                r->chunked = 1;
            }

            continue;
        }

        if (rc == NGX_TCP_HTTP_PARSE_HEADER_DONE) {

            /* a whole header has been parsed successfully */

            //ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
            //               "http proxy header done");

            return NGX_OK;
        }

        if (rc == NGX_AGAIN) {
            return NGX_AGAIN;
        }

        //rc = NGX_HTTP_PARSE_INVALID_HEADER
        /* there was error while a header line parsing */

        //ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
        //              "upstream sent invalid header");
        r->error_code = NGX_TCP_LUA_SOCKET_ERR_HEADERS;
        return NGX_ERROR;
    }
}
Beispiel #3
0
ngx_int_t nchan_detect_chunked_subscriber_request(ngx_http_request_t *r) {
  static ngx_str_t   TE_HEADER = ngx_string("TE");
  ngx_str_t         *tmp;
  u_char            *cur, *last;
  
  if(r->method != NGX_HTTP_GET) {
    return 0;
  }
  
  if((tmp = nchan_get_header_value(r, TE_HEADER)) != NULL) {
    last = tmp->data + tmp->len;
    cur = ngx_strlcasestrn(tmp->data, last, (u_char *)"chunked", 7 - 1);
    
    if(cur == NULL) {
      return 0;
    }
    
    //see if there's a qvalue
    cur += 7;
    if((cur + 1 <= last) && cur[0]==' ') { 
      //no qvalue. assume non-zero, meaning it's legit
      return 1;
    }
    else if((cur + 4) < last) {
      //maybe there is...
      if(cur[0]==';' && cur[1]=='q' && cur[2]=='=') {
        //parse the freaking qvalue
        cur += 3;
        ngx_int_t qval_fp;
        qval_fp = ngx_atofp(cur, last - cur, 2);
        if(qval_fp == NGX_ERROR) {
          DBG("invalid qval. reject.");
          return 0;
        }
        else if(qval_fp > 0) {
          //got nonzero qval. accept
          return 1;
        }
        else {
          //qval=0. reject
          return 0;
        }
      }
      else {
        //we're looking at  "chunkedsomething", not "chunked;q=<...>". reject.
        return 0;
      }
    }
    else if (cur == last){
      //last thing in the header. "chunked". accept
      return 1;
    }
    else {
      //too small to have a qvalue, not followed by a space. must be "chunkedsomething"
      return 0;
    }
  }
  else return 0;
}
static ngx_int_t
ngx_captcha_get_request_parameter_value( ngx_http_request_t *r, u_char *buffer, ngx_str_t *name, ngx_str_t *value ) {
    
    u_char              *p      = NULL;
    u_char              *v      = NULL; 
    u_char              *last   = NULL;
 
    value->data = NULL;
    value->len = 0;

    if ( buffer == NULL ) {
        return NGX_ERROR;
    }

    ngx_log_debug( NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "searching for %s (%d)", name->data, name->len );

    last = buffer + ngx_strlen( buffer ) ;
    
    for ( p = buffer; p < last; p++ ) {
        // we need '=' after name, so drop one char from last 
        p = ngx_strlcasestrn(p, last - 1, name->data, name->len - 1);
        if ( p == NULL ) {
            return NGX_ERROR;
        }

        if ((p == buffer || *(p - 1) == '&') && *(p + name->len) == '=') {
            size_t val_len = 0; 
            size_t dst_len = 0;

            v = p + name->len + 1;
            
            p = ngx_strlchr(p, last, '&');
            if (p == NULL) {
                p = last;
            }
            
            val_len = (p-v);
            
            /* Allocate buffer for request parameter value */
            value->data = ngx_pcalloc(r->pool, val_len + 1);
            if ( value->data == NULL ) {
                ngx_log_debug( NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "--->> BOOOM" );
                return NGX_ERROR;
            }
            /* Unescape parameter value */
            dst_len = (size_t)value->data;
            ngx_unescape_uri(&value->data, &v, val_len, NGX_UNESCAPE_URI);
            dst_len = (size_t) value->data - dst_len;
            *(value->data) = '\0';
            value->data -= dst_len;            
            value->len = dst_len;

            return NGX_OK;
        }
    }

    return ( (value->data == NULL) ? NGX_ERROR: NGX_OK );
}
static ngx_int_t
ngx_http_google_request_parse_cookie_pref(ngx_http_request_t    * r,
                                          ngx_http_google_ctx_t * ctx)
{
  ngx_uint_t i;
  ngx_keyval_t * kv, * hd = ctx->cookies->elts;
  
  for (i = 0; i < ctx->cookies->nelts; i++) {
    kv = hd + i;
    if (ngx_strncasecmp(kv->key.data, (u_char *)"PREF", 2)) continue;
    u_char * last = kv->value.data + kv->value.len;
    if (ngx_strlcasestrn(kv->value.data, last, (u_char *)"CR=", 2)) ctx->ncr = 1;
    break;
  }
  
  return NGX_OK;
}
Beispiel #6
0
ngx_int_t
ngx_http_arg(ngx_http_request_t *r, u_char *name, size_t len, ngx_str_t *value)
{
		syslog(LOG_INFO, "[%s:%s:%d]\n", __FILE__, __func__, __LINE__);
    u_char  *p, *last;

    if (r->args.len == 0) {
        return NGX_DECLINED;
    }

    p = r->args.data;
    last = p + r->args.len;

    for ( /* void */ ; p < last; p++) {

        /* we need '=' after name, so drop one char from last */

        p = ngx_strlcasestrn(p, last - 1, name, len - 1);

        if (p == NULL) {
            return NGX_DECLINED;
        }

        if ((p == r->args.data || *(p - 1) == '&') && *(p + len) == '=') {

            value->data = p + len + 1;

            p = ngx_strlchr(p, last, '&');

            if (p == NULL) {
                p = r->args.data + r->args.len;
            }

            value->len = p - value->data;

            return NGX_OK;
        }
    }

    return NGX_DECLINED;
}
Beispiel #7
0
//获取get值
static ngx_int_t ngx_http_get_value(ngx_http_request_t *r, ngx_str_t *get_var,
		ngx_array_t *get_values) {
	ngx_str_t *v, arg;
	u_char *p, *pos, *last;

	v = ngx_array_push(get_values);
	if (v == NULL) {
		return NGX_ERROR;
	}

	arg.len = get_var->len + 1;
	arg.data = ngx_palloc(r->pool, arg.len + 1);
	ngx_memzero(arg.data, sizeof(arg.data));

	pos = ngx_copy(arg.data, get_var->data, get_var->len);
	last = ngx_copy(pos, "=", strlen("="));

	p = ngx_strlcasestrn(r->args.data, r->args.data + r->args.len - 1,
			arg.data, arg.len);

	pos = p + arg.len;

	//*(r->args.data + r->args.len - 1) = '\0';

	//fprintf(stderr, "%s", r->args.data);

	last = ngx_strlchr(pos, r->args.data + r->args.len - 1, '&');

	v->data = ngx_palloc(r->pool, last - pos);
	v->len = last - pos;

	last = ngx_copy(v->data, pos, v->len);

	fprintf(stderr, "test%s", "lijianwei");

	return NGX_OK;
}
static ngx_int_t
ngx_http_session_sticky_rewrite(ngx_http_request_t *r, ngx_table_elt_t *table)
{
    u_char             *p, *st, *en, *last, *start;
    ngx_http_ss_ctx_t  *ctx;
    enum {
        pre_equal = 0,
        pre_value,
        value
    } state;

    ctx = ngx_http_get_module_ctx(r, ngx_http_upstream_session_sticky_module);
    p = ngx_strlcasestrn(table->value.data,
                         table->value.data + table->value.len,
                         ctx->sscf->cookie.data,
                         ctx->sscf->cookie.len - 1);
    if (p == NULL) {
        return NGX_AGAIN;
    }

    st = p;
    start = table->value.data;
    last = table->value.data + table->value.len;

    state = 0;
    while (p < last) {
        switch (state) {
        case pre_equal:
            if (*p == '=') {
                state = pre_value;

            } else if (*p == ';') {
                goto success;
            }

            break;

        case pre_value:
            if (!is_space(*p)) {
                state = value;
                p--;
            }
            break;

        case value:
            if (*p == ';') {
                goto success;
            }
            break;

        default:
            break;
        }

        p++;
    }

    if (p >= last && (state == value || state == pre_equal)) {
        goto success;
    }

    return NGX_AGAIN;

success:

    en = p;
    table->value.len = table->value.len
                     - (en - st)
                     + ctx->sscf->cookie.len
                     + 1 /* '=' */
                     + ctx->sid.len;

    p = ngx_pnalloc(r->pool, table->value.len);
    if (p == NULL) {
        return NGX_ERROR;
    }

    table->value.data = p;
    p = ngx_cpymem(p, start, st - start);
    p = ngx_cpymem(p, ctx->sscf->cookie.data, ctx->sscf->cookie.len);
    *p++ = '=';
    p = ngx_cpymem(p, ctx->sid.data, ctx->sid.len);
    p = ngx_cpymem(p, en, last - en);

    return NGX_OK;
}
static ngx_int_t
ngx_http_session_sticky_prefix(ngx_http_request_t *r, ngx_table_elt_t *table)
{
    u_char             *p, *s, *t, *last;
    ngx_http_ss_ctx_t  *ctx;
    enum {
        pre_equal = 0,
        pre_value
    } state;

    ctx = ngx_http_get_module_ctx(r, ngx_http_upstream_session_sticky_module);
    p = ngx_strlcasestrn(table->value.data,
                         table->value.data + table->value.len,
                         ctx->sscf->cookie.data,
                         ctx->sscf->cookie.len - 1);
    if (p == NULL) {
        return NGX_AGAIN;
    }

    last = table->value.data + table->value.len;
    state = 0;
    p += ctx->sscf->cookie.len;
    while (p < last) {
        switch (state) {
        case pre_equal:
            if (*p == '=') {
                state = pre_value;
            }
            break;

        case pre_value:
            if (*p == ';') {
                goto success;
            } else if (!is_space(*p)) {
                goto success;
            }
            break;

        default:
            break;
        }

        p++;
    }

    return NGX_AGAIN;

success:

    table->value.len += ctx->sid.len + 1;
    s = ngx_pnalloc(r->pool, table->value.len);
    if (s == NULL) {
        return NGX_ERROR;
    }

    t = s;
    t = ngx_cpymem(t, table->value.data, p - table->value.data);
    t = ngx_cpymem(t, ctx->sid.data, ctx->sid.len);
    *t++ = '~';
    t = ngx_cpymem(t, p, last - p);

    table->value.data = s;

    return NGX_OK;
}
/* fork from ngx_http_arg.
 * read argument(s) with name arg_name and length arg_len into value variable,
 * if multi flag is set, multi arguments with name arg_name will be read and
 * stored in an ngx_array_t struct, this can be operated by directives in
 * array-var-nginx-module */
static ngx_int_t
ngx_http_form_input_arg(ngx_http_request_t *r, u_char *arg_name, size_t arg_len,
    ngx_str_t *value, ngx_flag_t multi)
{
    u_char              *p, *v, *last, *buf;
    ngx_chain_t         *cl;
    size_t               len = 0;
    ngx_array_t         *array = NULL;
    ngx_str_t           *s;
    ngx_buf_t           *b;

    if (multi) {
        array = ngx_array_create(r->pool, 1, sizeof(ngx_str_t));
        if (array == NULL) {
            return NGX_ERROR;
        }
        value->data = (u_char *)array;
        value->len = sizeof(ngx_array_t);

    } else {
        ngx_str_set(value, "");
    }

    /* we read data from r->request_body->bufs */
    if (r->request_body == NULL || r->request_body->bufs == NULL) {
        dd("empty rb or empty rb bufs");
        return NGX_OK;
    }

    if (r->request_body->bufs->next != NULL) {
        /* more than one buffer...we should copy the data out... */
        len = 0;
        for (cl = r->request_body->bufs; cl; cl = cl->next) {
            b = cl->buf;

            if (b->in_file) {
                ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
                        "form-input: in-file buffer found. aborted. "
                        "consider increasing your client_body_buffer_size "
                        "setting");

                return NGX_OK;
            }

            len += b->last - b->pos;
        }

        dd("len=%d", (int) len);

        if (len == 0) {
            return NGX_OK;
        }

        buf = ngx_palloc(r->pool, len);
        if (buf == NULL) {
            return NGX_ERROR;
        }

        p = buf;
        last = p + len;

        for (cl = r->request_body->bufs; cl; cl = cl->next) {
            p = ngx_copy(p, cl->buf->pos, cl->buf->last - cl->buf->pos);
        }

        dd("p - buf = %d, last - buf = %d", (int) (p - buf),
           (int) (last - buf));

        dd("copied buf (len %d): %.*s", (int) len, (int) len,
           buf);

    } else {
        dd("XXX one buffer only");

        b = r->request_body->bufs->buf;
        if (ngx_buf_size(b) == 0) {
            return NGX_OK;
        }

        buf = b->pos;
        last = b->last;
    }

    for (p = buf; p < last; p++) {
        /* we need '=' after name, so drop one char from last */

        p = ngx_strlcasestrn(p, last - 1, arg_name, arg_len - 1);
        if (p == NULL) {
            return NGX_OK;
        }

        dd("found argument name, offset: %d", (int) (p - buf));

        if ((p == buf || *(p - 1) == '&') && *(p + arg_len) == '=') {
            v = p + arg_len + 1;
            dd("v = %d...", (int) (v - buf));

            dd("buf now (len %d): %.*s",
                    (int) (last - v), (int) (last - v), v);
            p = ngx_strlchr(v, last, '&');
            if (p == NULL) {
                dd("& not found, pointing it to last...");
                p = last;

            } else {
                dd("found &, pointing it to %d...", (int) (p - buf));
            }

            if (multi) {
                s = ngx_array_push(array);
                if (s == NULL) {
                    return NGX_ERROR;
                }
                s->data = v;
                s->len = p - v;
                dd("array var:%.*s", (int) s->len, s->data);

            } else {
                value->data = v;
                value->len = p - v;
                dd("value: [%.*s]", (int) value->len, value->data);
                return NGX_OK;
            }
        }
    }

#if 0
    if (multi) {
        value->data = (u_char *) array;
        value->len = sizeof(ngx_array_t);
    }
#endif

    return NGX_OK;
}
static ngx_int_t
ngx_http_google_response_header_location(ngx_http_request_t    * r,
                                         ngx_http_google_ctx_t * ctx,
                                         ngx_str_t             * v)
{
  ngx_http_google_loc_conf_t * glcf;
  glcf = ngx_http_get_module_loc_conf(r, ngx_http_google_filter_module);
  
  u_char *  last = v->data + v->len;
  ngx_uint_t add = 0;
  
  if        (!ngx_strncasecmp(v->data, (u_char *)"http://", 7)) {
    add = 7;
  } else if (!ngx_strncasecmp(v->data, (u_char *)"https://", 8)) {
    add = 8;
  } else {
    return NGX_OK;
  }
  
  ngx_str_t host;
  host.data = v->data + add;
  host.len  = last - host.data;
  
  ngx_str_t uri;
  uri.data = ngx_strlchr(host.data, last, '/');
  if (uri.data) {
    uri .len = last - uri.data;
    host.len = uri.data - host.data;
  } else {
    uri.len = 0;
  }
  
  if (!ngx_strlcasestrn(host.data, host.data + host.len,
                        (u_char *)"google", 6 - 1))
  {
    // none google domains
    // just return back
    return NGX_OK;
  }
  
  if (!ngx_strncasecmp(host.data, (u_char *)"ipv", 3)) {
    ngx_str_t nuri;
    nuri.len  = uri.len + 5;
    nuri.data = ngx_pcalloc(r->pool, nuri.len);
    if (!nuri.data) return NGX_ERROR;
    ngx_snprintf(nuri.data, nuri.len, "/ipv%c%V", host.data[3], &uri);
    uri = nuri;
  } else if (glcf->scholar == 1 &&
             !ngx_strncasecmp(host.data, (u_char *)"scholar", 7))
  {
    if (uri.len &&
        ngx_strncasecmp(uri.data, (u_char *)"/scholar", 8))
    {
      ngx_str_t nuri;
      nuri.len  = uri.len + 8;
      nuri.data = ngx_pcalloc(r->pool, nuri.len);
      if (!nuri.data) return NGX_ERROR;
      ngx_snprintf(nuri.data, nuri.len, "/scholar%V", &uri);
      uri = nuri;
    }
  }
  
  ngx_str_t nv;
  nv.len  = (ctx->ssl ? 8 : 7) + ctx->host->len + uri.len;
  nv.data = ngx_pcalloc(r->pool, nv.len);
  
  if (!nv.data) return NGX_ERROR;
  
  ngx_snprintf(nv.data, nv.len, "%s%V%V",
               ctx->ssl ? "https://" : "http://",
               ctx->host, &uri);
  *v = nv;
  
  return NGX_OK;
}
ngx_int_t
ngx_http_srcache_response_no_cache(ngx_http_request_t *r,
    ngx_http_srcache_loc_conf_t *conf, ngx_http_srcache_ctx_t *ctx)
{
    ngx_table_elt_t   **ccp;
    ngx_table_elt_t    *h;
    ngx_uint_t          i;
    u_char             *p, *last;
    ngx_int_t           n;
    time_t              expires;

    dd("checking response cache control settings");

    ccp = r->headers_out.cache_control.elts;

    if (ccp == NULL) {
        goto check_expires;
    }

    for (i = 0; i < r->headers_out.cache_control.nelts; i++) {
        if (!ccp[i]->hash) {
            continue;
        }

        p = ccp[i]->value.data;
        last = p + ccp[i]->value.len;

        if (!conf->store_private
            && ngx_strlcasestrn(p, last, (u_char *) "private", 7 - 1) != NULL)
        {
            return NGX_OK;
        }

        if (!conf->store_no_store
            && ngx_strlcasestrn(p, last, (u_char *) "no-store", 8 - 1) != NULL)
        {
            return NGX_OK;
        }

        if (!conf->store_no_cache
            && ngx_strlcasestrn(p, last, (u_char *) "no-cache", 8 - 1) != NULL)
        {
            return NGX_OK;
        }

        if (ctx->valid_sec != 0) {
            continue;
        }

        p = ngx_strlcasestrn(p, last, (u_char *) "max-age=", 8 - 1);

        if (p == NULL) {
            continue;
        }

        n = 0;

        for (p += 8; p < last; p++) {
            if (*p == ',' || *p == ';' || *p == ' ') {
                break;
            }

            if (*p >= '0' && *p <= '9') {
                n = n * 10 + *p - '0';
                continue;
            }

            return NGX_OK;
        }

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

        ctx->valid_sec = ngx_time() + n;
    }

check_expires:
    dd("valid_sec after processing cache-control: %d", (int) ctx->valid_sec);

    if (ctx->valid_sec == 0) {
        h = r->headers_out.expires;

        dd("expires header: %p", h);

        if (h != NULL && h->hash != 0) {
            expires = ngx_http_parse_time(h->value.data, h->value.len);

            if (expires == NGX_ERROR || expires <= ngx_time()) {
                return NGX_OK;
            }

            ctx->valid_sec = expires;
        }
    }

    return NGX_DECLINED;
}
static ngx_int_t
ngx_http_google_request_parse_scholar(ngx_http_request_t    * r,
                                      ngx_http_google_ctx_t * ctx)
{
  if (ngx_http_google_request_parse_cookie_pref(r, ctx)) return NGX_ERROR;
  
  if (ctx->uri->len == 12 && ctx->args) {
    
    u_char * refer = ctx->uri->data + 9;
    
    if (!ngx_strncmp(refer, "bib", 3) ||
        !ngx_strncmp(refer, "enw", 3) ||
        !ngx_strncmp(refer, "ris", 3) ||
        !ngx_strncmp(refer, "rfw", 3))
    {
      ngx_uint_t i;
      ngx_keyval_t * kv, * hd = ctx->args->elts;
      
      for (i = 0; i < ctx->args->nelts; i++)
      {
        kv = hd + i;
        if (!kv->key.len || *kv->key.data != 'q') continue;
        
        u_char * last = kv->value.data + kv->value.len;
        u_char * find = ngx_strlcasestrn(kv->value.data, last,
                                         ctx->host->data, ctx->host->len - 1);
        
        if (!find) break;
        kv->value.len = find - kv->value.data;
        
        ngx_str_t nval;
        nval.len  = kv->value.len + sizeof("scholar.google.com");
        nval.data = ngx_pcalloc(r->pool, nval.len);
        
        if (!nval.data) return NGX_ERROR;
        ngx_snprintf(nval.data, nval.len, "%Vscholar.google.com/", &kv->value);
        kv->value = nval;
        
        break;
      } // end of for args
    } // end of if refer
  } else {
    
    if (!ngx_strncasecmp(ctx->uri->data, (u_char *)"/schhp", 6) ||
        !ctx->args->nelts)
    {
      ngx_str_set(ctx->uri, "/");
    }
    
    if (!ngx_strncasecmp(ctx->uri->data, (u_char *)"/scholar", 8))
    {
      ngx_uint_t i, strip = 1;
      ngx_keyval_t * kv, * hd = ctx->args->elts;
      
      for (i = 0; i < ctx->args->nelts; i++) {
        kv = hd + i;
        if (!kv->key.len) continue;
        if (kv->key.len == 1 && *kv->key.data == 'q')
        {
          strip = 0; break;
        }
        if (kv->key.len == 5 && !ngx_strncasecmp(kv->key.data,
                                                (u_char *)"cites", 5))
        {
          strip = 0; break;
        }
        if (kv->key.len == 7 && !ngx_strncasecmp(kv->key.data,
                                                (u_char *)"cluster", 7))
        {
          strip = 0; break;
        }
        
      }
      
      if (strip) {
        ctx->uri->data += 8;
        ctx->uri->len  -= 8;
      }
    }
  }
  
  if (!ctx->ncr && ctx->uri->len == 1) {
    ngx_str_set(ctx->uri, "/ncr");
  }
  
  ngx_str_set(ctx->pass, "scholar.google.com");
  
  return NGX_OK;
}
ngx_int_t
ngx_stream_upm_process_resp_header(ngx_stream_session_t *s)
{
    ngx_int_t                           rc;
    ngx_array_t                         *resp_headers;
    ngx_table_elt_t                     *h;
    ngx_stream_upm_ctx_t                *ctx;
    ngx_stream_upstream_t               *u;
    //ngx_stream_upm_main_conf_t           *ummcf;
    //ngx_http_upstream_header_t          *hh;
    //ngx_stream_upstream_srv_conf_t      *umcf;
    ngx_stream_upm_resp_header_ctx_t     hctx;
    
    //ummcf = ngx_stream_get_module_srv_conf(s, ngx_stream_upm_module);
    ctx = ngx_stream_get_module_ctx(s, ngx_stream_upm_module);

    u = s->upstream;
    resp_headers = ctx->resp_headers;
    if (resp_headers == NULL) {
        resp_headers = ngx_array_create(ctx->pool, 4, sizeof(ngx_table_elt_t));
        if (resp_headers == NULL) {
            return NGX_ERROR;
        }
        ctx->resp_headers = resp_headers;
    }
    ngx_memzero(&hctx, sizeof(ngx_stream_upm_resp_header_ctx_t));

    for ( ;; ) {

        rc = ngx_stream_upm_parse_header_line(&hctx, &u->upstream_buf, 1);

        if (rc == NGX_OK) {

            /* a header line has been parsed successfully */

            h = ngx_array_push(resp_headers);
            if (h == NULL) {
                return NGX_ERROR;
            }

            h->hash = hctx.header_hash;

            h->key.len = hctx.header_name_end - hctx.header_name_start;
            h->value.len = hctx.header_end - hctx.header_start;

            h->key.data = hctx.header_name_start;
            h->value.data = hctx.header_start;

            /*No need to care lowcase_key
            if (h->key.len == r->lowcase_index) {
                ngx_memcpy(h->lowcase_key, r->lowcase_header, h->key.len);
            } else {
                ngx_strlow(h->lowcase_key, h->key.data, h->key.len);
            }*/

            ngx_log_debug2(NGX_LOG_DEBUG_STREAM, r->connection->log, 0,
                           "stream header: \"%V: %V\"",
                           &h->key, &h->value);

            if (h->key.len == 14 && ngx_strncmp(h->key.data, "Content-Length", h->key.len) == 0) {
                ctx->content_length_n = ngx_atoof(h->value.data, h->value.len);
            }

            if (h->key.len == 17 && ngx_strncmp(h->key.data, "Transfer-Encoding", h->key.len) == 0) {
                if (ngx_strlcasestrn(h->value.data, h->value.data + h->value.len,
                         (u_char *) "chunked", 7 - 1) != NULL) {
                    ctx->chunked = 1;
                }
            }
            continue;
        }

        if (rc == NGX_HTTP_PARSE_HEADER_DONE) {

            /* a whole header has been parsed successfully */
            ngx_log_debug0(NGX_LOG_DEBUG_STREAM, r->connection->log, 0,
                           "stream upm header done");

            /* Get content length */
            u = s->upstream;

            if (ctx->chunked) {
                ctx->content_length_n = -1;
            }

            /*
             * set u->keepalive if response has no body; this allows to keep
             * connections alive in case of r->header_only or X-Accel-Redirect
             */
            return NGX_DONE;
        }

        if (rc == NGX_AGAIN) {
            return NGX_AGAIN;
        }

        /* there was error while a header line parsing */

        ngx_log_error(NGX_LOG_ERR, s->connection->log, 0,
                      "upm upstream sent invalid header");

        return NGX_HTTP_UPSTREAM_INVALID_HEADER;
    }
}
static ngx_int_t
ngx_http_session_sticky_insert(ngx_http_request_t *r)
{
    u_char             *p;
    ngx_uint_t          i;
    ngx_list_part_t    *part;
    ngx_table_elt_t    *set_cookie, *table;
    ngx_http_ss_ctx_t  *ctx;

    ctx = ngx_http_get_module_ctx(r, ngx_http_upstream_session_sticky_module);
    if (ctx->frist != 1 && ctx->sscf->maxidle == NGX_CONF_UNSET) {
        return NGX_OK;
    }

    set_cookie = NULL;
    if (ctx->sscf->flag & NGX_HTTP_SESSION_STICKY_INDIRECT) {
        part = &r->headers_out.headers.part;
        while (part && set_cookie == NULL) {
            table = (ngx_table_elt_t *) part->elts;
            for (i = 0; i < part->nelts; i++) {
                if (table[i].key.len == (sizeof("set-cookie") - 1)
                    && ngx_strncasecmp(table[i].key.data,
                                       (u_char *) "set-cookie",
                                       table[i].key.len) == 0)
                {
                    p = ngx_strlcasestrn(table[i].value.data,
                                         table[i].value.data +
                                         table[i].value.len,
                                         ctx->sscf->cookie.data,
                                         ctx->sscf->cookie.len - 1);
                    if (p != NULL) {
                        set_cookie = &table[i];
                        break;
                    }
                }
            }
            part = part->next;
        }
    }

    if (set_cookie == NULL) {
        set_cookie = ngx_list_push(&r->headers_out.headers);
        if (set_cookie == NULL) {
            return NGX_ERROR;
        }

        set_cookie->hash = 1;
        ngx_str_set(&set_cookie->key, "Set-Cookie");
    }

    set_cookie->value.len = ctx->sscf->cookie.len
                          + sizeof("=") - 1
                          + ctx->sid.len
                          + sizeof("; Domain=") - 1
                          + ctx->sscf->domain.len
                          + sizeof("; Path=") - 1
                          + ctx->sscf->path.len;

    if (ctx->sscf->maxidle != NGX_CONF_UNSET) {
        set_cookie->value.len = set_cookie->value.len
                              + ctx->s_lastseen.len
                              + ctx->s_firstseen.len
                              + 2; /* '|' and '|' */
    } else {
        set_cookie->value.len = set_cookie->value.len
                              + sizeof("; Max-Age=") - 1
                              + ctx->sscf->maxage.len
                              + sizeof("; Expires=") - 1
                              + sizeof("Xxx, 00-Xxx-00 00:00:00 GMT") - 1;
    }

    p = ngx_pnalloc(r->pool, set_cookie->value.len);
    if (p == NULL) {
        return NGX_ERROR;
    }

    set_cookie->value.data = p;

    p = ngx_cpymem(p, ctx->sscf->cookie.data, ctx->sscf->cookie.len);
    *p++ = '=';
    p = ngx_cpymem(p, ctx->sid.data, ctx->sid.len);
    if (ctx->sscf->maxidle != NGX_CONF_UNSET) {
        *(p++) = NGX_HTTP_SESSION_STICKY_DELIMITER;
        p = ngx_cpymem(p, ctx->s_lastseen.data, ctx->s_lastseen.len);
        *(p++) = NGX_HTTP_SESSION_STICKY_DELIMITER;
        p = ngx_cpymem(p, ctx->s_firstseen.data, ctx->s_firstseen.len);
    }
    if (ctx->sscf->domain.len) {
        p = ngx_cpymem(p, "; Domain=", sizeof("; Domain=") - 1);
        p = ngx_cpymem(p, ctx->sscf->domain.data, ctx->sscf->domain.len);
    }
    if (ctx->sscf->path.len) {
        p = ngx_cpymem(p, "; Path=", sizeof("; Path=") - 1);
        p = ngx_cpymem(p, ctx->sscf->path.data, ctx->sscf->path.len);
    }
    if (ctx->sscf->maxidle == NGX_CONF_UNSET && ctx->sscf->maxage.len) {
        p = ngx_cpymem(p, "; Max-Age=", sizeof("; Max-Age=") - 1);
        p = ngx_cpymem(p, ctx->sscf->maxage.data, ctx->sscf->maxage.len);
        p = ngx_cpymem(p, "; Expires=", sizeof("; Expires=") - 1);
        ngx_uint_t maxage = ngx_atoi(ctx->sscf->maxage.data,
                                      ctx->sscf->maxage.len);
        p = ngx_http_cookie_time(p, ngx_time() + maxage);
    }

    set_cookie->value.len = p - set_cookie->value.data;

    return NGX_OK;
}
ngx_int_t
ngx_http_srcache_request_no_cache(ngx_http_request_t *r, unsigned *no_store)
{
    ngx_table_elt_t                 *h;
    ngx_list_part_t                 *part;
    u_char                          *p;
    u_char                          *last;
    ngx_uint_t                       i;
    unsigned                         no_cache;

    part = &r->headers_in.headers.part;
    h = part->elts;

    *no_store = 0;
    no_cache = 0;

    for (i = 0; /* void */; i++) {

        if (i >= part->nelts) {
            if (part->next == NULL) {
                break;
            }

            part = part->next;
            h = part->elts;
            i = 0;
        }

        if (h[i].key.len == sizeof("Cache-Control") - 1
            && ngx_strncasecmp(h[i].key.data, (u_char *) "Cache-Control",
                               sizeof("Cache-Control") - 1) == 0)
        {
            p = h[i].value.data;
            last = p + h[i].value.len;

            if (!*no_store
                && ngx_strlcasestrn(p, last, (u_char *) "no-store", 8 - 1)
                   != NULL)
            {
                *no_store = 1;
            }

            if (ngx_strlcasestrn(p, last, (u_char *) "no-cache", 8 - 1) != NULL)
            {
                no_cache = 1;
            }

            continue;
        }

        if (h[i].key.len == sizeof("Pragma") - 1
            && ngx_strncasecmp(h[i].key.data, (u_char *) "Pragma",
                               sizeof("Pragma") - 1) == 0)
        {
            p = h[i].value.data;
            last = p + h[i].value.len;

            if (ngx_strlcasestrn(p, last, (u_char *) "no-cache", 8 - 1) != NULL)
            {
                no_cache = 1;
            }
        }
    }

    return no_cache ? NGX_OK : NGX_DECLINED;
}
ngx_int_t
ngx_http_request_parser_post_arg(ngx_http_request_t *r, u_char *arg_name, size_t arg_len, ngx_str_t *value) {

    u_char *p, *v, *last, *buf;
    ngx_chain_t *cl;
    size_t len = 0;
    ngx_buf_t *b;


    ngx_str_set(value, "");

    /* we read data from r->request_body->bufs */
    if (r->request_body == NULL || r->request_body->bufs == NULL) {
        return NGX_OK;
    }

    if (r->request_body->bufs->next != NULL) {
        /* more than one buffer...we should copy the data out... */
        len = 0;
        for (cl = r->request_body->bufs; cl; cl = cl->next) {
            b = cl->buf;

            if (b->in_file) {
                return NGX_OK;
            }

            len += b->last - b->pos;
        }

        if (len == 0) {
            return NGX_OK;
        }

        buf = ngx_palloc(r->pool, len);
        if (buf == NULL) {
            return NGX_ERROR;
        }

        p = buf;
        last = p + len;

        for (cl = r->request_body->bufs; cl; cl = cl->next) {
            p = ngx_copy(p, cl->buf->pos, cl->buf->last - cl->buf->pos);
        }

    } else {
        b = r->request_body->bufs->buf;
        if (ngx_buf_size(b) == 0) {
            return NGX_OK;
        }

        buf = b->pos;
        last = b->last;
    }

    for (p = buf; p < last; p++) {
        /* we need '=' after name, so drop one char from last */

        p = ngx_strlcasestrn(p, last - 1, arg_name, arg_len - 1);
        if (p == NULL) {
            return NGX_OK;
        }

        if ((p == buf || *(p - 1) == '&') && *(p + arg_len) == '=') {
            v = p + arg_len + 1;
            p = ngx_strlchr(v, last, '&');
            if (p == NULL) {

                p = last;

            } else {
            }
            value->data = v;
            value->len = p - v;

            return NGX_OK;
        }
    }
    return NGX_OK;
}