29#define ASCII_FLAG 0x01
31#define EXTRA_FIELD 0x04
49#define APR_WANT_STRFUNC
55module AP_MODULE_DECLARE_DATA deflate_module;
57#define AP_INFLATE_RATIO_LIMIT 200
58#define AP_INFLATE_RATIO_BURST 3
60#define AP_DEFLATE_ETAG_ADDSUFFIX 0
61#define AP_DEFLATE_ETAG_NOCHANGE 1
62#define AP_DEFLATE_ETAG_REMOVE 2
98#define DEFAULT_COMPRESSION Z_DEFAULT_COMPRESSION
99#define DEFAULT_WINDOWSIZE -15
100#define DEFAULT_MEMLEVEL 9
101#define DEFAULT_BUFFERSIZE 8096
191static void putLong(
unsigned char *
string,
unsigned long x)
193 string[0] = (
unsigned char)(x & 0xff);
194 string[1] = (
unsigned char)((x & 0xff00) >> 8);
195 string[2] = (
unsigned char)((x & 0xff0000) >> 16);
196 string[3] = (
unsigned char)((x & 0xff000000) >> 24);
201static unsigned long getLong(
unsigned char *
string)
203 return ((
unsigned long)
string[0])
204 | (((
unsigned long)
string[1]) << 8)
205 | (((
unsigned long)
string[2]) << 16)
206 | (((
unsigned long)
string[3]) << 24);
239 return "DeflateWindowSize must be between 1 and 15";
241 c->windowSize =
i * -1;
254 return "DeflateBufferSize should be positive";
268 c->note_ratio_name =
arg1;
271 c->note_ratio_name =
arg2;
274 c->note_input_name =
arg2;
277 c->note_output_name =
arg2;
296 return "DeflateMemLevel must be between 1 and 9";
319 return "DeflateAlterETAG accepts only 'NoChange', 'AddSuffix', and 'Remove'";
336 return "Compression Level must be between 1 and 9";
338 c->compressionlevel =
i;
351 return "DeflateInflateLimitRequestBody is not parsable.";
354 return "DeflateInflateLimitRequestBody requires a non-negative integer.";
369 return "DeflateInflateRatioLimit must be positive";
385 return "DeflateInflateRatioBurst must be positive";
413#define VALIDATION_SIZE 8
415#define NO_UPDATE_CRC 0
437 ctx->stream.next_out =
ctx->buffer;
438 ctx->stream.avail_out =
c->bufferSize;
510 if ((etag && ((
etaglen = strlen(etag)) > 2))) {
511 if (etag[
etaglen - 1] ==
'"') {
516 const char *
s = etag;
518 for (;
d <
e; ++
d, ++
s) {
524 for (;
d <
e; ++
d, ++
s) {
539 if (
ctx->stream.total_in) {
540 int ratio =
ctx->stream.total_out /
ctx->stream.total_in;
555 "SSL_COMPRESS_METHOD");
593 "Compression enabled at SSL level; not compressing "
615 "Not compressing very small response of %"
664 "Not compressing (%s)",
reason);
677 "gzip-only-text/html");
680 "Not compressing, (gzip-only-text/html)");
713 while (token && *token) {
715 if (
strcmp(token,
"identity") &&
strcmp(token,
"7bit") &&
718 "Not compressing (content-encoding already "
743 const char *q =
NULL;
747 if (accepts ==
NULL) {
755 while (*accepts ==
';') {
761 if (*accepts ==
',') {
769 while (*accepts ==
';') {
774 "token: '%s' - q: '%s'", token ? token :
"NULL", q);
778 if (!token || token[0] ==
'\0' ||
779 (q && strlen(q) >= 3 &&
strncmp(
"q=0.000", q, strlen(q)) == 0)) {
781 "Not compressing (no Accept-Encoding: gzip or q=0)");
788 "Forcing compression (force-gzip set)");
802 c->windowSize,
c->memlevel,
808 "unable to init Zlib: "
809 "deflateInit2 returned %d: URL %s",
829 ctx->filter_init = 1;
867 ctx->stream.next_out =
ctx->buffer;
868 ctx->stream.avail_out =
c->bufferSize;
869 }
else if (!
ctx->filter_init) {
898 ctx->stream.avail_in = 0;
916 if (
c->note_input_name) {
918 (
ctx->stream.total_in > 0)
920 ctx->stream.total_in)
924 if (
c->note_output_name) {
926 (
ctx->stream.total_out > 0)
928 ctx->stream.total_out)
932 if (
c->note_ratio_name) {
934 (
ctx->stream.total_in > 0)
936 (
int)(
ctx->stream.total_out
938 /
ctx->stream.total_in))
968 "Zlib error %d flushing zlib output buffer (%s)",
998 "failed reading from %s bucket",
e->
type->
name);
1014 ctx->stream.next_in = (
unsigned char *)
data;
1019 while (
ctx->stream.avail_in != 0) {
1020 if (
ctx->stream.avail_out == 0) {
1035 "Zlib error %d deflating data (%s)",
zRC,
1052 if (
ctx->consume_pos == 0) {
1061 if (
ctx->consume_pos == 1) {
1065 ctx->consume_len += ((
unsigned int)**
data) << 8;
1071 ctx->consume_len -= *
len;
1076 *
len -=
ctx->consume_len;
1078 ctx->consume_len =
ctx->consume_pos = 0;
1116 if (
ctx->consume_pos == 0) {
1130 ctx->consume_pos = 0;
1161 if (!
ctx ||
ctx->header_len <
sizeof(
ctx->header)) {
1198 len =
sizeof(
ctx->header) -
ctx->header_len;
1213 if (
ctx->header_len) {
1218 "Encountered premature end-of-stream while "
1219 "reading inflate header");
1233 if (
len && !
ctx->header_len) {
1239 }
while (
ctx->header_len <
sizeof(
ctx->header));
1245 "Zlib: Invalid header");
1249 ctx->zlib_flags =
ctx->header[3];
1252 "Zlib: Invalid flags %02x",
ctx->zlib_flags);
1262 "unable to init Zlib: "
1263 "inflateInit2 returned %d: URL %s",
1270 ctx->stream.next_out =
ctx->buffer;
1271 ctx->stream.avail_out =
c->bufferSize;
1277 if (inflate_limit == 0) {
1309 "Encountered premature end-of-stream while inflating");
1323 ctx->inflate_total +=
ctx->stream.avail_out;
1325 ctx->inflate_total -=
ctx->stream.avail_out;
1329 "Zlib error %d inflating data (%s)",
zRC,
1334 if (inflate_limit &&
ctx->inflate_total > inflate_limit) {
1338 " is larger than the configured limit"
1340 ctx->inflate_total, inflate_limit);
1347 "Inflated content ratio is larger than the "
1348 "configured limit %i by %i time(s)",
1370 "Encountered extra data after compressed data");
1384 if (
ctx->zlib_flags) {
1387 ctx->zlib_flags = 0;
1395 ctx->stream.next_in = (
unsigned char *)
data;
1398 if (!
ctx->validation_buffer) {
1399 while (
ctx->stream.avail_in != 0) {
1400 if (
ctx->stream.avail_out == 0) {
1405 ctx->inflate_total +=
ctx->stream.avail_out;
1407 ctx->inflate_total -=
ctx->stream.avail_out;
1411 "Zlib error %d inflating data (%s)",
zRC,
1416 if (inflate_limit &&
ctx->inflate_total > inflate_limit) {
1420 " is larger than the configured limit"
1422 ctx->inflate_total, inflate_limit);
1429 "Inflated content ratio is larger than the "
1430 "configured limit %i by %i time(s)",
1438 ctx->validation_buffer_length = 0;
1444 if (
ctx->validation_buffer) {
1446 unsigned char *
buf =
ctx->validation_buffer;
1448 avail =
ctx->stream.avail_in;
1450 ctx->validation_buffer_length;
1457 if (avail < valid) {
1459 ctx->stream.next_in, avail);
1460 ctx->validation_buffer_length += avail;
1464 ctx->stream.next_in, valid);
1465 ctx->validation_buffer_length += valid;
1482 "Zlib: CRC error inflating data");
1487 if ((
ctx->stream.total_out & 0xFFFFFFFF) !=
compLen) {
1491 " of inflated data does not match"
1492 " expected value %ld",
1503 if (avail > valid) {
1505 "Encountered extra data after compressed data");
1519 ctx->stream.avail_out <
c->bufferSize) {
1601 ctx->validation_buffer =
NULL;
1602 ctx->validation_buffer_length = 0;
1610 "unable to init Zlib: "
1611 "inflateInit2 returned %d: URL %s",
1630 ctx->stream.next_out =
ctx->buffer;
1631 ctx->stream.avail_out =
c->bufferSize;
1649 ctx->stream.avail_in = 0;
1670 "Zlib: Checksum of inflated stream invalid");
1676 if ((
ctx->stream.total_out & 0xFFFFFFFF) !=
compLen) {
1678 "Zlib: Length of inflated stream invalid");
1684 "Zlib: Validation bytes not present");
1709 if (
ctx->validation_buffer ==
NULL) {
1716 "Zlib error %d flushing inflate buffer (%s)",
1754 if (
ctx->header_len <
sizeof(
ctx->header)) {
1757 rem =
sizeof(
ctx->header) -
ctx->header_len;
1771 "inflate: data not deflated!");
1778 "inflate: bad header");
1781 ctx->zlib_flags =
ctx->header[3];
1784 "inflate: bad flags %02x",
1797 if (
ctx->zlib_flags) {
1800 ctx->zlib_flags = 0;
1809 ctx->stream.next_in = (
unsigned char *)
data;
1810 ctx->stream.avail_in =
len;
1812 if (
ctx->validation_buffer) {
1819 memcpy(
ctx->validation_buffer +
ctx->validation_buffer_length,
1825 if (
ctx->stream.avail_in) {
1827 "Zlib: %d bytes of garbage at the end of "
1828 "compressed stream.",
ctx->stream.avail_in);
1836 ctx->stream.avail_in = 0;
1840 while (
ctx->stream.avail_in != 0) {
1841 if (
ctx->stream.avail_out == 0) {
1856 "Zlib error %d inflating data (%s)",
zRC,
1864 "Inflated content ratio is larger than the "
1865 "configured limit %i by %i time(s)",
1881 "Zlib: %d bytes of garbage at the end of "
1882 "compressed stream.",
1885 else if (
ctx->stream.avail_in > 0) {
1886 ctx->validation_buffer_length =
ctx->stream.avail_in;
1888 if (
ctx->validation_buffer_length)
1890 ctx->validation_buffer_length);
1908#define PROTO_FLAGS AP_FILTER_PROTO_CHANGE|AP_FILTER_PROTO_CHANGE_LENGTH
1922 "Set a note to report on compression ratio"),
1924 RSRC_CONF,
"Set the Deflate window size (1-15)"),
1926 "Set the Deflate Buffer Size"),
1928 "Set the Deflate Memory Level (1-9)"),
1930 "Set the Deflate Compression Level (1-9)"),
1932 "Set a limit on size of inflated input"),
1934 "Set the inflate ratio limit above which inflation is "
1937 "Set the maximum number of following inflate ratios above limit "
1940 "Set how mod_deflate should modify ETAG response headers: 'AddSuffix' (default), 'NoChange' (2.2.x behavior), 'Remove'"),
const char apr_size_t len
APR-UTIL Buckets/Bucket Brigades.
APR Miscellaneous library routines.
APR general purpose library routines.
apr_size_t const unsigned char unsigned int unsigned int d
APR Standard Headers Support.
static apr_pool_t * pconf
#define AP_INIT_TAKE1(directive, func, mconfig, where, help)
#define ap_get_module_config(v, m)
void ap_hook_post_config(ap_HOOK_post_config_t *pf, const char *const *aszPre, const char *const *aszSucc, int nOrder)
#define AP_DECLARE_MODULE(foo)
#define AP_INIT_TAKE12(directive, func, mconfig, where, help)
void ap_remove_input_filter(ap_filter_t *f)
apr_status_t ap_pass_brigade(ap_filter_t *filter, apr_bucket_brigade *bucket)
ap_filter_rec_t * ap_register_output_filter(const char *name, ap_out_filter_func filter_func, ap_init_filter_func filter_init, ap_filter_type ftype)
apr_status_t ap_filter_rec_t * ap_register_input_filter(const char *name, ap_in_filter_func filter_func, ap_init_filter_func filter_init, ap_filter_type ftype)
apr_status_t ap_get_brigade(ap_filter_t *filter, apr_bucket_brigade *bucket, ap_input_mode_t mode, apr_read_type_e block, apr_off_t readbytes)
void ap_remove_output_filter(ap_filter_t *f)
apr_off_t ap_get_limit_req_body(const request_rec *r)
#define APLOG_R_IS_LEVEL(r, level)
const unsigned char * buf
const char * ap_ssl_var_lookup(apr_pool_t *p, server_rec *s, conn_rec *c, request_rec *r, const char *name)
int ap_is_initial_req(request_rec *r)
#define APR_STATUS_IS_EAGAIN(s)
#define APR_BUCKET_IS_FLUSH(e)
#define APR_BUCKET_REMOVE(e)
#define APR_BRIGADE_LAST(b)
#define APR_BUCKET_IS_METADATA(e)
#define APR_BRIGADE_INSERT_TAIL(b, e)
#define apr_bucket_split(e, point)
#define APR_BUCKET_NEXT(e)
#define APR_BRIGADE_CONCAT(a, b)
#define APR_BRIGADE_EMPTY(b)
#define APR_BRIGADE_SENTINEL(b)
#define apr_bucket_delete(e)
#define APR_BUCKET_IS_EOS(e)
apr_brigade_flush void * ctx
#define APR_BRIGADE_FIRST(b)
#define apr_bucket_read(e, str, len, block)
#define APR_BUCKET_PREV(e)
apr_dbd_transaction_t int mode
#define HTTP_NOT_MODIFIED
#define STANDARD20_MODULE_STUFF
int ap_cstr_casecmp(const char *s1, const char *s2)
#define ap_strchr_c(s, c)
char * ap_get_token(apr_pool_t *p, const char **accept_line, int accept_white)
int strcasecmp(const char *a, const char *b)
apr_vformatter_buff_t * c
#define apr_pcalloc(p, size)
void apr_skiplistnode apr_skiplist_compare comp
static const char * deflate_set_inflate_ratio_limit(cmd_parms *cmd, void *dirconf, const char *arg)
struct deflate_ctx_t deflate_ctx
static const char * deflate_set_compressionlevel(cmd_parms *cmd, void *dummy, const char *arg)
static void * create_deflate_server_config(apr_pool_t *p, server_rec *s)
static const char * deflate_set_etag(cmd_parms *cmd, void *dummy, const char *arg)
static void * create_deflate_dirconf(apr_pool_t *p, char *dummy)
static int have_ssl_compression(request_rec *r)
static const char * deflate_set_memlevel(cmd_parms *cmd, void *dummy, const char *arg)
#define AP_INFLATE_RATIO_BURST
static apr_status_t inflate_out_filter(ap_filter_t *f, apr_bucket_brigade *bb)
static const char * deflate_set_window_size(cmd_parms *cmd, void *dummy, const char *arg)
static const char * deflate_set_inflate_ratio_burst(cmd_parms *cmd, void *dirconf, const char *arg)
#define AP_INFLATE_RATIO_LIMIT
struct deflate_filter_config_t deflate_filter_config
static const command_rec deflate_filter_cmds[]
static void putLong(unsigned char *string, unsigned long x)
static const char * deflate_set_buffer_size(cmd_parms *cmd, void *dummy, const char *arg)
#define AP_DEFLATE_ETAG_NOCHANGE
#define AP_DEFLATE_ETAG_ADDSUFFIX
static const char deflateFilterName[]
static void deflate_check_etag(request_rec *r, const char *transform, int etag_opt)
#define DEFAULT_COMPRESSION
static unsigned long getLong(unsigned char *string)
static const char deflate_magic[2]
#define DEFAULT_BUFFERSIZE
static const char * deflate_set_note(cmd_parms *cmd, void *dummy, const char *arg1, const char *arg2)
static int check_gzip(request_rec *r, apr_table_t *hdrs1, apr_table_t *hdrs2)
static void register_hooks(apr_pool_t *p)
#define DEFAULT_WINDOWSIZE
static apr_status_t consume_zlib_flags(deflate_ctx *ctx, const char **data, apr_size_t *len)
static int flush_libz_buffer(deflate_ctx *ctx, deflate_filter_config *c, int(*libz_func)(z_streamp, int), int flush, int crc)
static apr_status_t deflate_out_filter(ap_filter_t *f, apr_bucket_brigade *bb)
static apr_status_t deflate_in_filter(ap_filter_t *f, apr_bucket_brigade *bb, ap_input_mode_t mode, apr_read_type_e block, apr_off_t readbytes)
static int check_ratio(request_rec *r, deflate_ctx *ctx, const deflate_dirconf_t *dc)
static int mod_deflate_post_config(apr_pool_t *pconf, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *s)
static const char gzip_header[10]
#define AP_DEFLATE_ETAG_REMOVE
static apr_status_t deflate_ctx_cleanup(void *data)
static const char * deflate_set_inflate_limit(cmd_parms *cmd, void *dirconf, const char *arg)
#define consume_buffer(ctx, inbuf, bytes, flag)
The representation of a filter chain.
apr_bucket_alloc_t * bucket_alloc
const apr_bucket_type_t * type
apr_bucket_brigade * proc_bb
int(* libz_end_func)(z_streamp)
unsigned char * validation_buffer
apr_size_t validation_buffer_length
const char * note_input_name
const char * note_ratio_name
const char * note_output_name
A structure that represents the current request.
const char * content_type
apr_table_t * err_headers_out
apr_table_t * subprocess_env
struct ap_conf_vector_t * per_dir_config
const char * content_encoding
apr_table_t * headers_out
A structure to store information for each virtual server.
struct ap_conf_vector_t * module_config
ap_input_mode_t
input filtering modes
typedef int(WSAAPI *apr_winapi_fpt_WSAPoll)(IN OUT LPWSAPOLLFD fdArray