/[Apache-SVN]/httpd/httpd/trunk/modules/filters/mod_deflate.c
ViewVC logotype

Diff of /httpd/httpd/trunk/modules/filters/mod_deflate.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1604353 by covener, Sat Jun 21 13:15:06 2014 UTC revision 1610501 by covener, Mon Jul 14 19:56:15 2014 UTC
# Line 37  Line 37 
37  #include "httpd.h"  #include "httpd.h"
38  #include "http_config.h"  #include "http_config.h"
39  #include "http_log.h"  #include "http_log.h"
40    #include "http_core.h"
41  #include "apr_lib.h"  #include "apr_lib.h"
42  #include "apr_strings.h"  #include "apr_strings.h"
43  #include "apr_general.h"  #include "apr_general.h"
# Line 58  module AP_MODULE_DECLARE_DATA deflate_mo Line 59  module AP_MODULE_DECLARE_DATA deflate_mo
59  #define AP_DEFLATE_ETAG_NOCHANGE  1  #define AP_DEFLATE_ETAG_NOCHANGE  1
60  #define AP_DEFLATE_ETAG_REMOVE    2  #define AP_DEFLATE_ETAG_REMOVE    2
61    
62    #define AP_INFLATE_RATIO_LIMIT 200
63    #define AP_INFLATE_RATIO_BURST 3
64    
65  typedef struct deflate_filter_config_t  typedef struct deflate_filter_config_t
66  {  {
67      int windowSize;      int windowSize;
# Line 70  typedef struct deflate_filter_config_t Line 74  typedef struct deflate_filter_config_t
74      int etag_opt;      int etag_opt;
75  } deflate_filter_config;  } deflate_filter_config;
76    
77    typedef struct deflate_dirconf_t {
78        apr_off_t inflate_limit;
79        int ratio_limit,
80            ratio_burst;
81    } deflate_dirconf_t;
82    
83  /* RFC 1952 Section 2.3 defines the gzip header:  /* RFC 1952 Section 2.3 defines the gzip header:
84   *   *
85   * +---+---+---+---+---+---+---+---+---+---+   * +---+---+---+---+---+---+---+---+---+---+
# Line 212  static void *create_deflate_server_confi Line 222  static void *create_deflate_server_confi
222      return c;      return c;
223  }  }
224    
225    static void *create_deflate_dirconf(apr_pool_t *p, char *dummy)
226    {
227        deflate_dirconf_t *dc = apr_pcalloc(p, sizeof(*dc));
228        dc->ratio_limit = AP_INFLATE_RATIO_LIMIT;
229        dc->ratio_burst = AP_INFLATE_RATIO_BURST;
230        return dc;
231    }
232    
233  static const char *deflate_set_window_size(cmd_parms *cmd, void *dummy,  static const char *deflate_set_window_size(cmd_parms *cmd, void *dummy,
234                                             const char *arg)                                             const char *arg)
235  {  {
# Line 326  static const char *deflate_set_compressi Line 344  static const char *deflate_set_compressi
344      return NULL;      return NULL;
345  }  }
346    
347    
348    static const char *deflate_set_inflate_limit(cmd_parms *cmd, void *dirconf,
349                                          const char *arg)
350    {
351        deflate_dirconf_t *dc = (deflate_dirconf_t*) dirconf;
352        char *errp;
353    
354        if (APR_SUCCESS != apr_strtoff(&dc->inflate_limit, arg, &errp, 10)) {
355            return "DeflateInflateLimitRequestBody is not parsable.";
356        }
357        if (*errp || dc->inflate_limit < 0) {
358            return "DeflateInflateLimitRequestBody requires a non-negative integer.";
359        }
360    
361        return NULL;
362    }
363    
364    static const char *deflate_set_inflate_ratio_limit(cmd_parms *cmd,
365                                                       void *dirconf,
366                                                       const char *arg)
367    {
368        deflate_dirconf_t *dc = (deflate_dirconf_t*) dirconf;
369        int i;
370    
371        i = atoi(arg);
372        if (i <= 0)
373            return "DeflateInflateRatioLimit must be positive";
374    
375        dc->ratio_limit = i;
376    
377        return NULL;
378    }
379    
380    static const char *deflate_set_inflate_ratio_burst(cmd_parms *cmd,
381                                                       void *dirconf,
382                                                       const char *arg)
383    {
384        deflate_dirconf_t *dc = (deflate_dirconf_t*) dirconf;
385        int i;
386    
387        i = atoi(arg);
388        if (i <= 0)
389            return "DeflateInflateRatioBurst must be positive";
390    
391        dc->ratio_burst = i;
392    
393        return NULL;
394    }
395    
396  typedef struct deflate_ctx_t  typedef struct deflate_ctx_t
397  {  {
398      z_stream stream;      z_stream stream;
# Line 338  typedef struct deflate_ctx_t Line 405  typedef struct deflate_ctx_t
405      char header[10]; /* sizeof(gzip_header) */      char header[10]; /* sizeof(gzip_header) */
406      apr_size_t header_len;      apr_size_t header_len;
407      int zlib_flags;      int zlib_flags;
408        int ratio_hits;
409        apr_off_t inflate_total;
410      unsigned int consume_pos,      unsigned int consume_pos,
411                   consume_len;                   consume_len;
412      unsigned int filter_init:1;      unsigned int filter_init:1;
# Line 462  static void deflate_check_etag(request_r Line 531  static void deflate_check_etag(request_r
531      }      }
532  }  }
533    
534    /* Check whether the (inflate) ratio exceeds the configured limit/burst. */
535    static int check_ratio(request_rec *r, deflate_ctx *ctx,
536                           const deflate_dirconf_t *dc)
537    {
538        if (ctx->stream.total_in) {
539            int ratio = ctx->stream.total_out / ctx->stream.total_in;
540            if (ratio < dc->ratio_limit) {
541                ctx->ratio_hits = 0;
542            }
543            else if (++ctx->ratio_hits > dc->ratio_burst) {
544                return 0;
545            }
546        }
547        return 1;
548    }
549    
550  static int have_ssl_compression(request_rec *r)  static int have_ssl_compression(request_rec *r)
551  {  {
552      const char *comp;      const char *comp;
# Line 1036  static apr_status_t deflate_in_filter(ap Line 1121  static apr_status_t deflate_in_filter(ap
1121      int zRC;      int zRC;
1122      apr_status_t rv;      apr_status_t rv;
1123      deflate_filter_config *c;      deflate_filter_config *c;
1124        deflate_dirconf_t *dc;
1125        apr_off_t inflate_limit;
1126    
1127      /* just get out of the way of things we don't want. */      /* just get out of the way of things we don't want. */
1128      if (mode != AP_MODE_READBYTES) {      if (mode != AP_MODE_READBYTES) {
# Line 1043  static apr_status_t deflate_in_filter(ap Line 1130  static apr_status_t deflate_in_filter(ap
1130      }      }
1131    
1132      c = ap_get_module_config(r->server->module_config, &deflate_module);      c = ap_get_module_config(r->server->module_config, &deflate_module);
1133        dc = ap_get_module_config(r->per_dir_config, &deflate_module);
1134    
1135      if (!ctx || ctx->header_len < sizeof(ctx->header)) {      if (!ctx || ctx->header_len < sizeof(ctx->header)) {
1136          apr_size_t len;          apr_size_t len;
# Line 1159  static apr_status_t deflate_in_filter(ap Line 1247  static apr_status_t deflate_in_filter(ap
1247          apr_brigade_cleanup(ctx->bb);          apr_brigade_cleanup(ctx->bb);
1248      }      }
1249    
1250        inflate_limit = dc->inflate_limit;
1251        if (inflate_limit == 0) {
1252            /* The core is checking the deflated body, we'll check the inflated */
1253            inflate_limit = ap_get_limit_req_body(f->r);
1254        }
1255    
1256      if (APR_BRIGADE_EMPTY(ctx->proc_bb)) {      if (APR_BRIGADE_EMPTY(ctx->proc_bb)) {
1257          rv = ap_get_brigade(f->next, ctx->bb, mode, block, readbytes);          rv = ap_get_brigade(f->next, ctx->bb, mode, block, readbytes);
1258    
# Line 1210  static apr_status_t deflate_in_filter(ap Line 1304  static apr_status_t deflate_in_filter(ap
1304                  ctx->stream.next_out = ctx->buffer;                  ctx->stream.next_out = ctx->buffer;
1305                  len = c->bufferSize - ctx->stream.avail_out;                  len = c->bufferSize - ctx->stream.avail_out;
1306    
1307                    ctx->inflate_total += len;
1308                    if (inflate_limit && ctx->inflate_total > inflate_limit) {
1309                        inflateEnd(&ctx->stream);
1310                        ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, APLOGNO()
1311                                "Inflated content length of %" APR_OFF_T_FMT
1312                                " is larger than the configured limit"
1313                                " of %" APR_OFF_T_FMT,
1314                                ctx->inflate_total, inflate_limit);
1315                        return APR_ENOSPC;
1316                    }
1317    
1318                  ctx->crc = crc32(ctx->crc, (const Bytef *)ctx->buffer, len);                  ctx->crc = crc32(ctx->crc, (const Bytef *)ctx->buffer, len);
1319                  tmp_b = apr_bucket_heap_create((char *)ctx->buffer, len,                  tmp_b = apr_bucket_heap_create((char *)ctx->buffer, len,
1320                                                  NULL, f->c->bucket_alloc);                                                  NULL, f->c->bucket_alloc);
# Line 1263  static apr_status_t deflate_in_filter(ap Line 1368  static apr_status_t deflate_in_filter(ap
1368                  while (ctx->stream.avail_in != 0) {                  while (ctx->stream.avail_in != 0) {
1369                      if (ctx->stream.avail_out == 0) {                      if (ctx->stream.avail_out == 0) {
1370                          apr_bucket *tmp_heap;                          apr_bucket *tmp_heap;
1371    
1372                          ctx->stream.next_out = ctx->buffer;                          ctx->stream.next_out = ctx->buffer;
1373                          len = c->bufferSize - ctx->stream.avail_out;                          len = c->bufferSize - ctx->stream.avail_out;
1374    
1375                            ctx->inflate_total += len;
1376                            if (inflate_limit && ctx->inflate_total > inflate_limit) {
1377                                inflateEnd(&ctx->stream);
1378                                ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, APLOGNO()
1379                                        "Inflated content length of %" APR_OFF_T_FMT
1380                                        " is larger than the configured limit"
1381                                        " of %" APR_OFF_T_FMT,
1382                                        ctx->inflate_total, inflate_limit);
1383                                return APR_ENOSPC;
1384                            }
1385    
1386                            if (!check_ratio(r, ctx, dc)) {
1387                                inflateEnd(&ctx->stream);
1388                                ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, APLOGNO()
1389                                        "Inflated content ratio is larger than the "
1390                                        "configured limit %i by %i time(s)",
1391                                        dc->ratio_limit, dc->ratio_burst);
1392                                return APR_EINVAL;
1393                            }
1394    
1395                          ctx->crc = crc32(ctx->crc, (const Bytef *)ctx->buffer, len);                          ctx->crc = crc32(ctx->crc, (const Bytef *)ctx->buffer, len);
1396                          tmp_heap = apr_bucket_heap_create((char *)ctx->buffer, len,                          tmp_heap = apr_bucket_heap_create((char *)ctx->buffer, len,
1397                                                            NULL, f->c->bucket_alloc);                                                            NULL, f->c->bucket_alloc);
# Line 1411  static apr_status_t inflate_out_filter(a Line 1537  static apr_status_t inflate_out_filter(a
1537      int zRC;      int zRC;
1538      apr_status_t rv;      apr_status_t rv;
1539      deflate_filter_config *c;      deflate_filter_config *c;
1540        deflate_dirconf_t *dc;
1541    
1542      /* Do nothing if asked to filter nothing. */      /* Do nothing if asked to filter nothing. */
1543      if (APR_BRIGADE_EMPTY(bb)) {      if (APR_BRIGADE_EMPTY(bb)) {
# Line 1418  static apr_status_t inflate_out_filter(a Line 1545  static apr_status_t inflate_out_filter(a
1545      }      }
1546    
1547      c = ap_get_module_config(r->server->module_config, &deflate_module);      c = ap_get_module_config(r->server->module_config, &deflate_module);
1548        dc = ap_get_module_config(r->per_dir_config, &deflate_module);
1549    
1550      if (!ctx) {      if (!ctx) {
1551    
# Line 1698  static apr_status_t inflate_out_filter(a Line 1826  static apr_status_t inflate_out_filter(a
1826          while (ctx->stream.avail_in != 0) {          while (ctx->stream.avail_in != 0) {
1827              if (ctx->stream.avail_out == 0) {              if (ctx->stream.avail_out == 0) {
1828    
1829                    if (!check_ratio(r, ctx, dc)) {
1830                        ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, APLOGNO()
1831                                "Inflated content ratio is larger than the "
1832                                "configured limit %i by %i time(s)",
1833                                dc->ratio_limit, dc->ratio_burst);
1834                        return APR_EINVAL;
1835                    }
1836    
1837                  ctx->stream.next_out = ctx->buffer;                  ctx->stream.next_out = ctx->buffer;
1838                  len = c->bufferSize - ctx->stream.avail_out;                  len = c->bufferSize - ctx->stream.avail_out;
1839    
# Line 1785  static const command_rec deflate_filter_ Line 1921  static const command_rec deflate_filter_
1921                    "Set the Deflate Compression Level (1-9)"),                    "Set the Deflate Compression Level (1-9)"),
1922      AP_INIT_TAKE1("DeflateAlterEtag", deflate_set_etag, NULL, RSRC_CONF,      AP_INIT_TAKE1("DeflateAlterEtag", deflate_set_etag, NULL, RSRC_CONF,
1923                    "Set how mod_deflate should modify ETAG response headers: 'AddSuffix' (default), 'NoChange' (2.2.x behavior), 'Remove'"),                    "Set how mod_deflate should modify ETAG response headers: 'AddSuffix' (default), 'NoChange' (2.2.x behavior), 'Remove'"),
1924        AP_INIT_TAKE1("DeflateInflateLimitRequestBody", deflate_set_inflate_limit, NULL, OR_ALL,
1925                      "Set a limit on size of inflated input"),
1926        AP_INIT_TAKE1("DeflateInflateRatioLimit", deflate_set_inflate_ratio_limit, NULL, OR_ALL,
1927                      "Set the inflate ratio limit above which inflation is "
1928                      "aborted (default: " APR_STRINGIFY(AP_INFLATE_RATIO_LIMIT) ")"),
1929        AP_INIT_TAKE1("DeflateInflateRatioBurst", deflate_set_inflate_ratio_burst, NULL, OR_ALL,
1930                      "Set the maximum number of following inflate ratios above limit "
1931                      "(default: " APR_STRINGIFY(AP_INFLATE_RATIO_BURST) ")"),
1932      {NULL}      {NULL}
1933  };  };
1934    
# Line 1795  static const command_rec deflate_filter_ Line 1938  static const command_rec deflate_filter_
1938  #endif  #endif
1939  AP_DECLARE_MODULE(deflate) = {  AP_DECLARE_MODULE(deflate) = {
1940      STANDARD20_MODULE_STUFF,      STANDARD20_MODULE_STUFF,
1941      NULL,                         /* dir config creater */      create_deflate_dirconf,       /* dir config creater */
1942      NULL,                         /* dir merger --- default is to override */      NULL,                         /* dir merger --- default is to override */
1943      create_deflate_server_config, /* server config */      create_deflate_server_config, /* server config */
1944      NULL,                         /* merge server config */      NULL,                         /* merge server config */

Legend:
Removed from v.1604353  
changed lines
  Added in v.1610501

infrastructure at apache.org
ViewVC Help
Powered by ViewVC 1.1.26