aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/http/ngx_http_core_module.c151
1 files changed, 136 insertions, 15 deletions
diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c
index cfb7eb9d0..544fd747e 100644
--- a/src/http/ngx_http_core_module.c
+++ b/src/http/ngx_http_core_module.c
@@ -70,6 +70,7 @@ static char *ngx_http_core_internal(ngx_conf_t *cf, ngx_command_t *cmd,
static char *ngx_http_core_resolver(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
#if (NGX_HTTP_GZIP)
+static ngx_int_t ngx_http_gzip_accept_encoding(ngx_str_t *ae);
static char *ngx_http_gzip_disable(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
#endif
@@ -2013,7 +2014,6 @@ ngx_http_auth_basic_user(ngx_http_request_t *r)
ngx_int_t
ngx_http_gzip_ok(ngx_http_request_t *r)
{
- u_char *g;
time_t date, expires;
ngx_uint_t p;
ngx_array_t *cc;
@@ -2031,25 +2031,25 @@ ngx_http_gzip_ok(ngx_http_request_t *r)
return NGX_DECLINED;
}
- if (ngx_strncmp(ae->value.data, "gzip,", 5) == 0) {
- /*
- * test for the most common case "gzip,...":
- * MSIE: "gzip, deflate"
- * Firefox: "gzip,deflate"
- * Chrome: "gzip,deflate,sdch"
- * Safari: "gzip, deflate"
- * Opera: "gzip, deflate"
- */
- goto found;
+ if (ae->value.len < 5) {
+ return NGX_DECLINED;
}
- g = ngx_strcasestrn(ae->value.data, "gzip", 4 - 1);
- if (g == NULL) {
+ /*
+ * test first for the most common case "gzip,...":
+ * MSIE: "gzip, deflate"
+ * Firefox: "gzip,deflate"
+ * Chrome: "gzip,deflate,sdch"
+ * Safari: "gzip, deflate"
+ * Opera: "gzip, deflate"
+ */
+
+ if (ngx_memcmp(ae->value.data, "gzip,", 5) != 0
+ && ngx_http_gzip_accept_encoding(&ae->value) != NGX_OK)
+ {
return NGX_DECLINED;
}
-found:
-
clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
if (r->headers_in.msie6 && clcf->gzip_disable_msie6) {
@@ -2171,6 +2171,127 @@ ok:
return NGX_OK;
}
+
+/*
+ * gzip is enabled for the following quantities:
+ * "gzip; q=0.001" ... "gzip; q=0.999", "gzip; q=1"
+ * gzip is disabled for the following quantities:
+ * "gzip; q=0" ... "gzip; q=0.000", and for any invalid cases
+ */
+
+static ngx_int_t
+ngx_http_gzip_accept_encoding(ngx_str_t *ae)
+{
+ u_char c, *p, *start, *last;
+ ngx_uint_t n, q;
+
+ start = ae->data;
+ last = start + ae->len;
+
+ for ( ;; ) {
+ p = ngx_strcasestrn(start, "gzip", 4 - 1);
+ if (p == NULL) {
+ return NGX_DECLINED;
+ }
+
+ if (p > start && (*(p - 1) == ',' || *(p - 1) == ' ')) {
+ break;
+ }
+
+ start = p + 4;
+ }
+
+ p += 4;
+
+ while (p < last) {
+ switch(*p++) {
+ case ',':
+ return NGX_OK;
+ case ';':
+ goto quantity;
+ case ' ':
+ continue;
+ default:
+ return NGX_DECLINED;
+ }
+ }
+
+ return NGX_OK;
+
+quantity:
+
+ while (p < last) {
+ switch(*p++) {
+ case 'q':
+ case 'Q':
+ goto equal;
+ case ' ':
+ continue;
+ default:
+ return NGX_DECLINED;
+ }
+ }
+
+ return NGX_OK;
+
+equal:
+
+ if (p + 2 > last || *p++ != '=') {
+ return NGX_DECLINED;
+ }
+
+ c = *p++;
+
+ if (c == '1') {
+ if (p == last || *p == ',' || *p == ' ') {
+ return NGX_OK;
+ }
+ return NGX_DECLINED;
+ }
+
+ if (c != '0') {
+ return NGX_DECLINED;
+ }
+
+ if (p == last) {
+ return NGX_DECLINED;
+ }
+
+ if (*p++ != '.') {
+ return NGX_DECLINED;
+ }
+
+ n = 0;
+ q = 0;
+
+ while (p < last) {
+ c = *p++;
+
+ if (c == ',') {
+ break;
+ }
+
+ if (c >= '1' && c <= '9') {
+ n++;
+ q++;
+ continue;
+ }
+
+ if (c == '0') {
+ n++;
+ continue;
+ }
+
+ return NGX_DECLINED;
+ }
+
+ if (n < 4 && q != 0) {
+ return NGX_OK;
+ }
+
+ return NGX_DECLINED;
+}
+
#endif