static ngx_int_t ngx_http_google_response_header_set_cookie(ngx_http_request_t * r, ngx_http_google_ctx_t * ctx, ngx_table_elt_t * tb) { ngx_array_t * kvs = ngx_http_google_explode_kv(r, &tb->value, ";"); if (!kvs) return NGX_ERROR; ngx_uint_t i; ngx_keyval_t * kv, * hd = kvs->elts; for (i = 0; i < kvs->nelts; i++) { kv = hd + i; if (!ngx_strncasecmp(kv->key.data, ctx->conf->data, ctx->conf->len)) { if (ngx_http_google_response_header_set_cookie_conf(r, ctx, &kv->value)) { return NGX_ERROR; } } if (!ngx_strncasecmp(kv->key.data, (u_char *)"GOOGLE_ABUSE_EXEMPTION", 22)) { if (ngx_http_google_response_header_set_cookie_exempt(r, ctx, kvs)) { return NGX_ERROR; } } if (!ngx_strncasecmp(kv->key.data, (u_char *)"domain", 6)) { kv->value = *ctx->domain; } if (!ngx_strncasecmp(kv->key.data, (u_char *)"path", 4)) { ngx_str_set(&kv->value, "/"); } } // unset this key if (!kvs->nelts) { tb->hash = 0; return NGX_OK; } ngx_str_t * set_cookie = ngx_http_google_implode_kv(r, kvs, "; "); if (!set_cookie) return NGX_ERROR; // reset set cookie tb->value = *set_cookie; return NGX_OK; }
static ngx_int_t ngx_http_google_response_header_set_cookie_conf(ngx_http_request_t * r, ngx_http_google_ctx_t * ctx, ngx_str_t * v) { if (ctx->type != ngx_http_google_type_main && ctx->type != ngx_http_google_type_scholar) return NGX_OK; if (ctx->ncr) return NGX_OK; ngx_uint_t i; ngx_array_t * kvs = ngx_http_google_explode_kv(r, v, ":"); if (!kvs) return NGX_ERROR; ngx_int_t nw = 0; ngx_keyval_t * kv, * hd; hd = kvs->elts; for (i = 0; i < kvs->nelts; i++) { kv = hd + i; if (!ngx_strncasecmp(kv->key.data, (u_char *)"LD", 2)) { if (ctx->lang->len) kv->value = *ctx->lang; else { ngx_str_set(&kv->value, "zh-CN"); } } if (!ngx_strncasecmp(kv->key.data, (u_char *)"NW", 2)) nw = 1; } if (!nw) { kv = ngx_array_push(kvs); if (!kv) return NGX_ERROR; ngx_str_set(&kv->key, "NW"); ngx_str_set(&kv->value, "1"); } // sort with length ngx_sort(kvs->elts, kvs->nelts, sizeof(ngx_keyval_t), ngx_http_google_response_header_sort_cookie_conf); ngx_str_t * nv = ngx_http_google_implode_kv(r, kvs, ":"); if (!nv) return NGX_ERROR; *v = *nv; return NGX_OK; }
static ngx_int_t ngx_http_google_request_parser(ngx_http_request_t * r, ngx_http_google_ctx_t * ctx) { // parse arg u_char * last = r->unparsed_uri.data + r->unparsed_uri.len; ctx->arg->data = ngx_strlchr(ctx->uri->data, last, '?'); // parse uri if (ctx->arg->data) { ctx->arg->len = last - ++ctx->arg->data; ctx->uri->len -= ctx->arg->len + 1; } // parse args if (ctx->arg->len) { ctx->args = ngx_http_google_explode_kv(r, ctx->arg, "&"); } else { ctx->args = ngx_array_create(r->pool, 4, sizeof(ngx_keyval_t)); } if (!ctx->args) return NGX_ERROR; // parse cookies if (r->headers_in.cookies.nelts) { ngx_table_elt_t ** ck = r->headers_in.cookies.elts; ctx->cookies = ngx_http_google_explode_kv(r, &(*ck)->value, ";"); } else { ctx->cookies = ngx_array_create(r->pool, 4, sizeof(ngx_keyval_t)); } if (!ctx->cookies) return NGX_ERROR; // parse host if (ngx_http_google_request_parse_host(r, ctx)) return NGX_ERROR; // traverse headers ngx_uint_t i, acl = 0; ngx_list_part_t * pt = &r->headers_in.headers.part; ngx_table_elt_t * hd = pt->elts, * tb; for (i = 0; /* void */; i++) { if (i >= pt->nelts) { if (pt->next == NULL) break; pt = pt->next; hd = pt->elts; i = 0; } tb = hd + i; if (!ngx_strncasecmp(tb->key.data, (u_char *)"Accept-Language", 15)) { acl = 1; tb->value = *ctx->lang; } } if (!acl) { tb = ngx_list_push(&r->headers_in.headers); if (!tb) return NGX_ERROR; ngx_str_set(&tb->key, "Accept-Language"); tb->value = *ctx->lang; tb->hash = ngx_hash_key_lc(tb->key.data, tb->key.len); } return NGX_OK; }