line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
1
|
|
|
1
|
|
3
|
use strict; |
|
1
|
|
|
|
|
1
|
|
|
1
|
|
|
|
|
24
|
|
2
|
1
|
|
|
1
|
|
2
|
use warnings; |
|
1
|
|
|
|
|
1
|
|
|
1
|
|
|
|
|
24
|
|
3
|
|
|
|
|
|
|
package App::DubiousHTTP::Tests::Compressed; |
4
|
1
|
|
|
1
|
|
2
|
use App::DubiousHTTP::Tests::Common; |
|
1
|
|
|
|
|
1
|
|
|
1
|
|
|
|
|
119
|
|
5
|
1
|
|
|
1
|
|
4
|
use Compress::Raw::Zlib; |
|
1
|
|
|
|
|
1
|
|
|
1
|
|
|
|
|
124
|
|
6
|
1
|
|
|
1
|
|
773
|
use Compress::Raw::Lzma; |
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
7
|
|
|
|
|
|
|
|
8
|
|
|
|
|
|
|
SETUP( |
9
|
|
|
|
|
|
|
'compressed', |
10
|
|
|
|
|
|
|
"Variations on content compression", |
11
|
|
|
|
|
|
|
<<'DESC', |
12
|
|
|
|
|
|
|
Compression of Content is usueally done with a Content-Encoding header and a |
13
|
|
|
|
|
|
|
value of 'gzip' (RFC1952) or 'deflate' (RFC1951). Most browsers additionally |
14
|
|
|
|
|
|
|
accept RFC1950 compressed data (zlib) if 'deflate' is specified. |
15
|
|
|
|
|
|
|
Some browsers also support compression with the Transfer-Encoding header, |
16
|
|
|
|
|
|
|
which is actually specified in the HTTP RFC, but most browsers don't. |
17
|
|
|
|
|
|
|
Some browsers just guess the encoding, e.g. accept gzip even if deflate is |
18
|
|
|
|
|
|
|
specified. |
19
|
|
|
|
|
|
|
And some browsers accept x-gzip and x-deflate specifications, and some even |
20
|
|
|
|
|
|
|
specifications like "x gzip" or "gzip x". |
21
|
|
|
|
|
|
|
Most browsers accept multiple content-encoding headers, even if it does not |
22
|
|
|
|
|
|
|
make much sense to compress content twice with the same encoding. |
23
|
|
|
|
|
|
|
DESC |
24
|
|
|
|
|
|
|
|
25
|
|
|
|
|
|
|
# ------------------------- Tests ---------------------------------------- |
26
|
|
|
|
|
|
|
|
27
|
|
|
|
|
|
|
# these should be fine |
28
|
|
|
|
|
|
|
[ 'VALID: correct compressed requests' ], |
29
|
|
|
|
|
|
|
[ SHOULDBE_VALID, 'ce:gzip;gzip' => 'content-encoding gzip, served gzipped'], |
30
|
|
|
|
|
|
|
[ UNCOMMON_VALID, 'ce:x-gzip;gzip' => 'content-encoding "x-gzip", served gzipped'], # not IE11 |
31
|
|
|
|
|
|
|
[ SHOULDBE_VALID, 'ce:deflate;deflate' => 'content-encoding deflate, served with deflate'], |
32
|
|
|
|
|
|
|
[ VALID, 'ce:deFLaTe;deflate' => 'content-encoding deflate mixed case, served with deflate'], |
33
|
|
|
|
|
|
|
|
34
|
|
|
|
|
|
|
# various kinds of flush between compression parts |
35
|
|
|
|
|
|
|
[ 'UNCOMMON_VALID: various kinds of flush between compression parts' ], |
36
|
|
|
|
|
|
|
[ UNCOMMON_VALID, 'ce:gzip;gzip2p,partial' => 'content-encoding gzip, served gzipped with 2 compressed blocks with partial flush in between'], |
37
|
|
|
|
|
|
|
[ UNCOMMON_VALID, 'ce:deflate;deflate2p,partial' => 'content-encoding deflate, served with deflate with 2 compressed blocks with partial flush in between'], |
38
|
|
|
|
|
|
|
[ UNCOMMON_VALID, 'ce:gzip;gzip2p,block' => 'content-encoding gzip, served gzipped with 2 compressed blocks with block flush in between'], |
39
|
|
|
|
|
|
|
[ UNCOMMON_VALID, 'ce:deflate;deflate2p,block' => 'content-encoding deflate, served with deflate with 2 compressed blocks with block flush in between'], |
40
|
|
|
|
|
|
|
[ UNCOMMON_VALID, 'ce:gzip;gzip2p,sync' => 'content-encoding gzip, served gzipped with 2 compressed blocks with sync flush in between'], |
41
|
|
|
|
|
|
|
[ UNCOMMON_VALID, 'ce:deflate;deflate2p,sync' => 'content-encoding deflate, served with deflate with 2 compressed blocks with sync flush in between'], |
42
|
|
|
|
|
|
|
[ UNCOMMON_VALID, 'ce:gzip;gzip2p' => 'content-encoding gzip, served gzipped with 2 compressed blocks with full flush in between'], |
43
|
|
|
|
|
|
|
[ UNCOMMON_VALID, 'ce:deflate;deflate2p' => 'content-encoding deflate, served with deflate with 2 compressed blocks with full flush in between'], |
44
|
|
|
|
|
|
|
[ INVALID, 'ce:gzip;gzip2p,finish' => 'content-encoding gzip, served gzipped with 2 compressed blocks with finish in between'], |
45
|
|
|
|
|
|
|
[ INVALID, 'ce:deflate;deflate2p,finish' => 'content-encoding deflate, served with deflate with 2 compressed blocks with finish in between'], |
46
|
|
|
|
|
|
|
|
47
|
|
|
|
|
|
|
[ 'INVALID: only part of data compressed, followed by uncompressed data' ], |
48
|
|
|
|
|
|
|
[ INVALID, 'ce:gzip;gzip2s' => 'content-encoding gzip, first segment compressed with gzip, next uncompressed' ], |
49
|
|
|
|
|
|
|
[ INVALID, 'ce:deflate;deflate2s' => 'content-encoding deflate, first segment compressed with deflate, next uncompressed' ], |
50
|
|
|
|
|
|
|
[ INVALID, 'ce:deflate;zlib2s' => 'content-encoding deflate, first segment compressed with zlib, next uncompressed' ], |
51
|
|
|
|
|
|
|
[ INVALID, 'ce:deflate;pkt:zlib+deflate' => 'content-encoding deflate, first segment compressed with zlib but ADLER32 removed, next with deflate in new TCP packet' ], |
52
|
|
|
|
|
|
|
[ INVALID, 'ce:deflate;chk:zlib+deflate' => 'content-encoding deflate, first segment compressed with zlib but ADLER32 removed, next with deflate in new chunk with chunked encoding' ], |
53
|
|
|
|
|
|
|
[ INVALID, 'ce:deflate;pkt:zlib+deflate+deflate' => 'content-encoding deflate, first segment compressed with zlib but ADLER32 removed, next two with deflate in new TCP packets' ], |
54
|
|
|
|
|
|
|
[ INVALID, 'ce:deflate;chk:zlib+deflate+deflate' => 'content-encoding deflate, first segment compressed with zlib but ADLER32 removed, next two with deflate in new chunk with chunked encoding' ], |
55
|
|
|
|
|
|
|
|
56
|
|
|
|
|
|
|
[ 'VALID: lzma (supported by at least Opera)' ], |
57
|
|
|
|
|
|
|
[ UNCOMMON_VALID, 'ce:lzma;lzma1' => 'content-encoding lzma, lzma1 (lzma_alone) encoded'], |
58
|
|
|
|
|
|
|
|
59
|
|
|
|
|
|
|
[ 'VALID: brotli (supported by at least Firefox when used with https)' ], |
60
|
|
|
|
|
|
|
[ UNCOMMON_VALID, 'ce:br;brotli' => 'content-encoding br, encoded with brotli'], |
61
|
|
|
|
|
|
|
|
62
|
|
|
|
|
|
|
[ 'INVALID: gzip header combined with zlib (RFC1952) instead of deflate (RFC1951)' ], |
63
|
|
|
|
|
|
|
[ INVALID, 'ce:gzip;gzip-zlib' => 'content-encoding gzip, encoded with zlib prefixed by gzip header'], |
64
|
|
|
|
|
|
|
|
65
|
|
|
|
|
|
|
# these might be strange/unsupported |
66
|
|
|
|
|
|
|
[ 'VALID: less common but valid requests' ], |
67
|
|
|
|
|
|
|
[ UNCOMMON_VALID, 'ce:deflate;zlib' => 'content-encoding deflate, served with RFC1950 style deflate (zlib)'], |
68
|
|
|
|
|
|
|
[ UNCOMMON_VALID, 'ce:deflate;zlib2p' => 'content-encoding deflate, served with RFC1950 style deflate (zlib) with 2 compressed blocks'], |
69
|
|
|
|
|
|
|
[ UNCOMMON_VALID, 'ce:nl-gzip;gzip' => 'content-encoding gzip but with continuation line, served gzipped'], |
70
|
|
|
|
|
|
|
[ UNCOMMON_VALID, 'ce:nl-deflate;deflate' => 'content-encoding deflate but with continuation line, served with deflate'], |
71
|
|
|
|
|
|
|
[ UNCOMMON_VALID, 'ce:nl-nl-deflate;deflate' => 'content-encoding deflate but with double continuation line, served with deflate'], |
72
|
|
|
|
|
|
|
[ UNCOMMON_VALID, 'ce:deflate,;deflate' => 'content-encoding "deflate,", served with deflate'], |
73
|
|
|
|
|
|
|
[ UNCOMMON_VALID, 'ce:deflate-nl-,;deflate' => 'content-encoding "deflate ,", served with deflate'], |
74
|
|
|
|
|
|
|
[ UNCOMMON_VALID, 'ce:deflate-nl-,-nl-;deflate' => 'content-encoding "deflate , ", served with deflate'], |
75
|
|
|
|
|
|
|
|
76
|
|
|
|
|
|
|
# These should be fine according to RFC, but are not supported in the browsers |
77
|
|
|
|
|
|
|
# Thus treat is as problem if they get supported. |
78
|
|
|
|
|
|
|
[ 'INVALID: transfer-encoding with compression should not be supported' ], |
79
|
|
|
|
|
|
|
[ INVALID, 'te:gzip;gzip' => 'transfer-encoding gzip, served gzipped'], |
80
|
|
|
|
|
|
|
[ INVALID, 'te:deflate;deflate' => 'transfer-encoding deflate, served with deflate'], |
81
|
|
|
|
|
|
|
[ INVALID, 'te:gzip;ce:gzip;gzip;gzip' => 'transfer-encoding and content-encoding gzip, gzipped twice'], |
82
|
|
|
|
|
|
|
|
83
|
|
|
|
|
|
|
# double encodings |
84
|
|
|
|
|
|
|
[ 'VALID: double encodings' ], |
85
|
|
|
|
|
|
|
[ UNCOMMON_VALID, 'ce:gzip;ce:gzip;gzip;gzip' => 'double content-encoding header gzip, served twice gzipped'], |
86
|
|
|
|
|
|
|
[ UNCOMMON_VALID, 'ce:gzip,gzip;gzip;gzip' => 'single content-encoding header "gzip,gzip", served twice gzipped'], |
87
|
|
|
|
|
|
|
[ UNCOMMON_VALID, 'ce:deflate;ce:deflate;deflate;deflate' => 'double content-encoding header deflate, compressed twice with deflate'], |
88
|
|
|
|
|
|
|
[ UNCOMMON_VALID, 'ce:deflate,deflate;deflate;deflate' => 'single content-encoding header "deflate,deflate", compressed twice with deflate'], |
89
|
|
|
|
|
|
|
[ UNCOMMON_VALID, 'ce:deflate-nl-,-nl-deflate;deflate;deflate' => 'single content-encoding header "deflate , deflate", compressed twice with deflate'], |
90
|
|
|
|
|
|
|
[ UNCOMMON_VALID, 'ce:deflate-nl-,-nl-deflate-nl-;deflate;deflate' => 'single content-encoding header "deflate , deflate ", compressed twice with deflate'], |
91
|
|
|
|
|
|
|
|
92
|
|
|
|
|
|
|
[ UNCOMMON_VALID, 'ce:gzip;ce:deflate;gzip;deflate' => 'content-encoding header for gzip and deflate, content compressed in this order'], |
93
|
|
|
|
|
|
|
[ UNCOMMON_VALID, 'ce:gzip,deflate;gzip;deflate' => 'single content-encoding "gzip,deflate", content compressed in this order'], |
94
|
|
|
|
|
|
|
[ UNCOMMON_VALID, 'ce:deflate;ce:gzip;deflate;gzip' => 'content-encoding header for deflate and gzip, content compressed in this order'], |
95
|
|
|
|
|
|
|
[ UNCOMMON_VALID, 'ce:deflate,gzip;deflate;gzip' => 'single content-encoding header "deflate,gzip", content compressed in this order'], |
96
|
|
|
|
|
|
|
|
97
|
|
|
|
|
|
|
# according to RFC2616 identity SHOULD only be used in Accept-Encoding, not Content-Encoding |
98
|
|
|
|
|
|
|
[ 'INVALID: using "content-encoding: identity"' ], |
99
|
|
|
|
|
|
|
[ UNCOMMON_INVALID, 'ce:identity', '"content-encoding:identity", served without encoding' ], |
100
|
|
|
|
|
|
|
[ UNCOMMON_INVALID, 'ce:identity;ce:identity', 'twice "content-encoding:identity", served without encoding' ], |
101
|
|
|
|
|
|
|
[ UNCOMMON_INVALID, 'ce:identity,identity', '"content-encoding:identity,identity", served without encoding' ], |
102
|
|
|
|
|
|
|
[ UNCOMMON_INVALID, 'ce:identity;ce:gzip;gzip' => 'content-encoding header for identity and gzip, compressed with gzip'], |
103
|
|
|
|
|
|
|
[ UNCOMMON_INVALID, 'ce:identity,gzip;gzip' => 'single content-encoding "identity,gzip", compressed with gzip'], |
104
|
|
|
|
|
|
|
[ UNCOMMON_INVALID, 'ce:gzip;ce:identity;gzip' => 'content-encoding header for gzip and identity, compressed with gzip'], |
105
|
|
|
|
|
|
|
[ UNCOMMON_INVALID, 'ce:gzip,identity;gzip' => 'single content-encoding header "gzip,identity", compressed with gzip'], |
106
|
|
|
|
|
|
|
|
107
|
|
|
|
|
|
|
[ UNCOMMON_INVALID, 'ce:identity;ce:deflate;deflate' => 'content-encoding header for identity and deflate, compressed with deflate'], |
108
|
|
|
|
|
|
|
[ UNCOMMON_INVALID, 'ce:identity,deflate;deflate' => 'single content-encoding "identity,deflate", compressed with deflate'], |
109
|
|
|
|
|
|
|
[ UNCOMMON_INVALID, 'ce:deflate;ce:identity;deflate' => 'content-encoding header for deflate and identity, compressed with deflate'], |
110
|
|
|
|
|
|
|
[ UNCOMMON_INVALID, 'ce:deflate,identity;deflate' => 'single content-encoding header "deflate,identity", compressed with deflate'], |
111
|
|
|
|
|
|
|
|
112
|
|
|
|
|
|
|
# triple encodings |
113
|
|
|
|
|
|
|
[ 'VALID: triple encodings' ], |
114
|
|
|
|
|
|
|
[ UNCOMMON_VALID, 'ce:gzip;ce:deflate;ce:gzip;gzip;deflate;gzip' => 'served gzip + deflate + gzip, separate content-encoding header'], |
115
|
|
|
|
|
|
|
[ UNCOMMON_VALID, 'ce:gzip,deflate,gzip;gzip;deflate;gzip' => 'served gzip + deflate + gzip, single content-encoding header'], |
116
|
|
|
|
|
|
|
[ UNCOMMON_VALID, 'ce:gzip,deflate;ce:gzip;gzip;deflate;gzip' => 'served gzip + deflate + gzip, two content-encoding headers'], |
117
|
|
|
|
|
|
|
[ UNCOMMON_VALID, 'ce:deflate;ce:gzip;ce:deflate;deflate;gzip;deflate' => 'served deflate + gzip + gzip, separate content-encoding header'], |
118
|
|
|
|
|
|
|
[ UNCOMMON_VALID, 'ce:deflate,gzip,deflate;deflate;gzip;deflate' => 'served deflate + gzip + deflate, single content-encoding header'], |
119
|
|
|
|
|
|
|
[ UNCOMMON_VALID, 'ce:deflate,gzip;ce:deflate;deflate;gzip;deflate' => 'served deflate + gzip + deflate, two content-encoding headers'], |
120
|
|
|
|
|
|
|
|
121
|
|
|
|
|
|
|
[ 'INVALID: specified double encodings, but content not or only once encoded or in the wrong order' ], |
122
|
|
|
|
|
|
|
[ INVALID, 'ce:gzip;ce:gzip;gzip' => 'double content-encoding header gzip, but served with single gzip'], |
123
|
|
|
|
|
|
|
[ INVALID, 'ce:gzip;ce:gzip' => 'double content-encoding header gzip, but served without encoding'], |
124
|
|
|
|
|
|
|
[ INVALID, 'ce:deflate;ce:deflate;deflate' => 'double content-encoding header deflate, but served with single deflate'], |
125
|
|
|
|
|
|
|
[ INVALID, 'ce:deflate;ce:deflate' => 'double content-encoding header deflate, but server without encoding'], |
126
|
|
|
|
|
|
|
|
127
|
|
|
|
|
|
|
[ INVALID, 'ce:gzip;ce:deflate;deflate;gzip' => 'content-encoding header for gzip and deflate, compressed in opposite order'], |
128
|
|
|
|
|
|
|
[ INVALID, 'ce:gzip;ce:deflate;deflate' => 'content-encoding header for gzip and deflate, but served only with single deflate'], |
129
|
|
|
|
|
|
|
[ INVALID, 'ce:gzip;ce:deflate;gzip' => 'content-encoding header for gzip and deflate, but server only with single gzip'], |
130
|
|
|
|
|
|
|
[ INVALID, 'ce:gzip;ce:deflate' => 'content-encoding header for gzip and deflate, server without encoding'], |
131
|
|
|
|
|
|
|
[ INVALID, 'ce:gzip,deflate;deflate;gzip' => 'single content-encoding header for "gzip,deflate", compressed in opposite order'], |
132
|
|
|
|
|
|
|
[ INVALID, 'ce:gzip,deflate;deflate' => 'single content-encoding header for "gzip,deflate", but served with single deflate'], |
133
|
|
|
|
|
|
|
[ INVALID, 'ce:gzip,deflate;gzip' => 'single content-encoding header for "gzip,deflate", but served with single gzip'], |
134
|
|
|
|
|
|
|
[ INVALID, 'ce:gzip,deflate' => 'single content-encoding header for "gzip,deflate", but served without encoding'], |
135
|
|
|
|
|
|
|
|
136
|
|
|
|
|
|
|
[ INVALID, 'ce:deflate;ce:gzip;gzip;deflate' => 'content-encoding header for deflate and gzip, compressed in opposite order'], |
137
|
|
|
|
|
|
|
[ INVALID, 'ce:deflate;ce:gzip;gzip' => 'content-encoding header for deflate and gzip, but served only with single gzip'], |
138
|
|
|
|
|
|
|
[ INVALID, 'ce:deflate;ce:gzip;deflate' => 'content-encoding header for deflate and gzip, but server only with single deflate'], |
139
|
|
|
|
|
|
|
[ INVALID, 'ce:deflate;ce:gzip' => 'content-encoding header for deflate and gzip, server without encoding'], |
140
|
|
|
|
|
|
|
[ INVALID, 'ce:deflate,gzip;gzip;deflate' => 'single content-encoding header for "deflate,gzip", compressed in opposite order'], |
141
|
|
|
|
|
|
|
[ INVALID, 'ce:deflate,gzip;gzip' => 'single content-encoding header for "deflate,gzip", but served with single gzip'], |
142
|
|
|
|
|
|
|
[ INVALID, 'ce:deflate,gzip;deflate' => 'single content-encoding header for "deflate,gzip", but served with single deflate'], |
143
|
|
|
|
|
|
|
[ INVALID, 'ce:deflate,gzip' => 'single content-encoding header for "deflate,gzip", but served without encoding'], |
144
|
|
|
|
|
|
|
|
145
|
|
|
|
|
|
|
# and the bad ones |
146
|
|
|
|
|
|
|
[ 'INVALID: incorrect compressed response, should not succeed' ], |
147
|
|
|
|
|
|
|
[ INVALID, 'ce:x-deflate;deflate' => 'content-encoding x-deflate, served with deflate'], |
148
|
|
|
|
|
|
|
[ INVALID, 'ce:x-deflate;zlib' => 'content-encoding x-deflate, served with RFC1950 style deflate (zlib)'], |
149
|
|
|
|
|
|
|
[ INVALID, 'ce:gzipx;gzip' => 'content-encoding "gzipx", served with gzip' ], |
150
|
|
|
|
|
|
|
[ INVALID, 'ce:xgzip;gzip' => 'content-encoding "xgzip", served with gzip' ], |
151
|
|
|
|
|
|
|
[ INVALID, 'ce:gzip_x;gzip' => 'content-encoding "gzip x", served with gzip' ], |
152
|
|
|
|
|
|
|
[ INVALID, 'ce:x_gzip;gzip' => 'content-encoding "x gzip", served with gzip' ], |
153
|
|
|
|
|
|
|
[ INVALID, 'ce:deflate;gzip' => 'content-encoding deflate but served with gzip'], |
154
|
|
|
|
|
|
|
[ INVALID, 'ce:gzip;deflate' => 'content-encoding gzip but served with decode'], |
155
|
|
|
|
|
|
|
[ INVALID, 'ce:deflate' => 'content-encoding "deflate", not encoded'], |
156
|
|
|
|
|
|
|
[ INVALID, 'ce:deflate,' => 'content-encoding "deflate,", not encoded'], |
157
|
|
|
|
|
|
|
[ INVALID, 'ce:deflate-nl-,' => 'content-encoding "deflate ,", not encoded'], |
158
|
|
|
|
|
|
|
[ INVALID, 'ce:deflate-nl-,-nl-' => 'content-encoding "deflate , ", not encoded'], |
159
|
|
|
|
|
|
|
|
160
|
|
|
|
|
|
|
[ 'INVALID: invalid content-encodings should not be ignored' ], |
161
|
|
|
|
|
|
|
[ INVALID, 'ce:gzip_x' => 'content-encoding "gzip x", but not encoded' ], |
162
|
|
|
|
|
|
|
[ INVALID, 'ce:deflate;ce:gzip_x;deflate' => 'content-encoding deflate + "gzip x", but only deflated' ], |
163
|
|
|
|
|
|
|
[ INVALID, 'ce:gzip_x;ce:deflate;deflate' => 'content-encoding "gzip x" + deflate, but only deflated' ], |
164
|
|
|
|
|
|
|
[ INVALID, 'ce:foo', '"content-encoding:foo" and no encoding' ], |
165
|
|
|
|
|
|
|
[ INVALID, 'ce:rfc2047-deflate', '"content-encoding:rfc2047(deflate)" and no encoding' ], |
166
|
|
|
|
|
|
|
[ INVALID, 'ce:rfc2047-deflate;deflate', '"content-encoding:rfc2047(deflate)" with encoding' ], |
167
|
|
|
|
|
|
|
|
168
|
|
|
|
|
|
|
[ 'VALID: transfer-encoding should be ignored for compression' ], |
169
|
|
|
|
|
|
|
[ UNCOMMON_VALID,'te:gzip' => 'transfer-encoding gzip but not compressed'], |
170
|
|
|
|
|
|
|
|
171
|
|
|
|
|
|
|
[ 'INVALID: "Hiding the Content-encoding header"' ], |
172
|
|
|
|
|
|
|
[ INVALID, 'ce-space-colon-deflate;deflate' => '"Content-Encoding: deflate", served with deflate' ], |
173
|
|
|
|
|
|
|
[ UNCOMMON_INVALID, 'ce-space-colon-deflate' => '"Content-Encoding: deflate", served not with deflate' ], |
174
|
|
|
|
|
|
|
[ INVALID, 'ce-space-colon-gzip;gzip' => '"Content-Encoding: gzip", served with gzip' ], |
175
|
|
|
|
|
|
|
[ UNCOMMON_INVALID, 'ce-space-colon-gzip' => '"Content-Encoding: gzip", served not with gzip' ], |
176
|
|
|
|
|
|
|
|
177
|
|
|
|
|
|
|
[ INVALID, 'ce-colon-colon-deflate;deflate' => '"Content-Encoding:: deflate", served with deflate' ], |
178
|
|
|
|
|
|
|
[ UNCOMMON_INVALID, 'ce-colon-colon-deflate' => '"Content-Encoding:: deflate", served not with deflate' ], |
179
|
|
|
|
|
|
|
[ INVALID, 'ce-colon-colon-gzip;gzip' => '"Content-Encoding:: gzip", served with gzip' ], |
180
|
|
|
|
|
|
|
[ UNCOMMON_INVALID, 'ce-colon-colon-gzip' => '"Content-Encoding:: gzip", served not with gzip' ], |
181
|
|
|
|
|
|
|
|
182
|
|
|
|
|
|
|
[ INVALID, 'cronly-deflate;deflate' => 'Content-Encoding with only as line delimiter before, served deflate' ], |
183
|
|
|
|
|
|
|
[ INVALID, 'crxonly-deflate;deflate' => 'Only as line delimiter followed by "xContent-Encoding", served deflate' ], |
184
|
|
|
|
|
|
|
[ UNCOMMON_INVALID, 'cronly-deflate' => 'Content-Encoding with only as line delimiter before, not served deflate' ], |
185
|
|
|
|
|
|
|
[ INVALID, 'cronly-gzip;gzip' => 'Content-Encoding with only as line delimiter before, served gzip' ], |
186
|
|
|
|
|
|
|
[ INVALID, 'crxonly-gzip;gzip' => 'Only as line delimiter followed by "xContent-Encoding", served gzip' ], |
187
|
|
|
|
|
|
|
[ UNCOMMON_INVALID, 'cronly-gzip' => 'Content-Encoding with only as line delimiter before, not served gzip' ], |
188
|
|
|
|
|
|
|
|
189
|
|
|
|
|
|
|
[ UNCOMMON_INVALID, 'lfonly-deflate;deflate' => 'Content-Encoding with only as line delimiter before, served deflate' ], |
190
|
|
|
|
|
|
|
[ INVALID, 'lfonly-deflate' => 'Content-Encoding with only as line delimiter before, not served deflate' ], |
191
|
|
|
|
|
|
|
[ UNCOMMON_INVALID, 'lfonly-gzip;gzip' => 'Content-Encoding with only as line delimiter before, served gzip' ], |
192
|
|
|
|
|
|
|
[ INVALID, 'lfonly-gzip' => 'Content-Encoding with only as line delimiter before, not served gzip' ], |
193
|
|
|
|
|
|
|
|
194
|
|
|
|
|
|
|
[ INVALID, 'ce:crdeflate;deflate' => 'Content-Encoding:deflate, served with deflate' ], |
195
|
|
|
|
|
|
|
[ INVALID, 'ce:crdeflate' => 'Content-Encoding:deflate, not served with deflate' ], |
196
|
|
|
|
|
|
|
[ INVALID, 'ce:cr-deflate;deflate' => 'Content-Encoding:deflate, served with deflate' ], |
197
|
|
|
|
|
|
|
[ INVALID, 'ce:cr-deflate' => 'Content-Encoding:deflate, not served with deflate' ], |
198
|
|
|
|
|
|
|
[ INVALID, 'ce:crgzip;gzip' => 'Content-Encoding:gzip, served with gzip' ], |
199
|
|
|
|
|
|
|
[ INVALID, 'ce:crgzip' => 'Content-Encoding:gzip, not served with gzip' ], |
200
|
|
|
|
|
|
|
[ INVALID, 'ce:cr-gzip;gzip' => 'Content-Encoding:gzip, served with gzip' ], |
201
|
|
|
|
|
|
|
[ INVALID, 'ce:cr-gzip' => 'Content-Encoding:gzip, not served with gzip' ], |
202
|
|
|
|
|
|
|
|
203
|
|
|
|
|
|
|
[ 'INVALID: slightly invalid gzip encodings' ], |
204
|
|
|
|
|
|
|
[ INVALID,'ce:gzip;gzip;replace:0,2=1f8c', 'wrong gzip magic header'], |
205
|
|
|
|
|
|
|
[ INVALID,'ce:gzip;gzip;replace:2,1=88', 'wrong compression method 88 instead of 08'], |
206
|
|
|
|
|
|
|
[ UNCOMMON_VALID,'ce:gzip;gzip;replace:3,1|01', 'set flag FTEXT'], |
207
|
|
|
|
|
|
|
[ INVALID,'ce:gzip;gzip;replace:3,1|02', 'set flag FHCRC without having CRC'], |
208
|
|
|
|
|
|
|
[ INVALID,'ce:gzip;gzip;replace:3,1|02;replace:10,0=0000', 'set flag FHCRC and add CRC with 0'], |
209
|
|
|
|
|
|
|
[ UNCOMMON_VALID,'ce:gzip;gzip;replace:3,1|04;replace:10,0=0000', 'set flag FEXTRA and extra part with XLEN 0'], |
210
|
|
|
|
|
|
|
[ UNCOMMON_VALID,'ce:gzip;gzip;replace:3,1|04;replace:10,0=05004170010000', 'set flag FEXTRA and extra part with XLEN 5'], |
211
|
|
|
|
|
|
|
[ INVALID,'ce:gzip;gzip;replace:3,1|04;replace:10,0=0500', 'set flag FEXTRA and XLEN 5 but no extra part'], |
212
|
|
|
|
|
|
|
[ INVALID,'ce:gzip;gzip-payload-as-extra', 'gzip, but hide the real (deflate) payload inside the EXTRA part'], |
213
|
|
|
|
|
|
|
[ UNCOMMON_VALID,'ce:gzip;gzip;replace:3,1|08;replace:10,0=2000', 'set flag FNAME and add short file name'], |
214
|
|
|
|
|
|
|
[ UNCOMMON_VALID,'ce:gzip;gzip;replace:3,1|10;replace:10,0=2000', 'set flag FCOMMENT and add short comment'], |
215
|
|
|
|
|
|
|
[ INVALID,'ce:gzip;gzip;replace:3,1|20', 'set flag reserved bit 5'], |
216
|
|
|
|
|
|
|
[ INVALID,'ce:gzip;gzip;replace:3,1|40', 'set flag reserved bit 6'], |
217
|
|
|
|
|
|
|
[ INVALID,'ce:gzip;gzip;replace:3,1|80', 'set flag reserved bit 7'], |
218
|
|
|
|
|
|
|
[ INVALID,'ce:gzip;gzip;replace:-8,4^ffffffff', 'invalidate final checksum'], |
219
|
|
|
|
|
|
|
[ INVALID,'ce:gzip;gzip;replace:-4,1^ff', 'invalidate length'], |
220
|
|
|
|
|
|
|
[ INVALID,'ce:gzip;gzip;replace:-4,4=', 'remove length'], |
221
|
|
|
|
|
|
|
[ INVALID,'ce:gzip;gzip;replace:-8,8=', 'remove checksum and length'], |
222
|
|
|
|
|
|
|
[ INVALID,'ce:gzip;gzip;replace:-4,4=;clen+4', 'remove length but set content-length header to original size'], |
223
|
|
|
|
|
|
|
[ INVALID,'ce:gzip;gzip;replace:-8,8=;clen+8', 'remove checksum and length but set content-length header to original size'], |
224
|
|
|
|
|
|
|
[ INVALID,'ce:gzip;gzip;replace:-4,4=;noclen', 'remove length and close with eof without sending length'], |
225
|
|
|
|
|
|
|
[ INVALID,'ce:gzip;gzip;replace:-8,8=;noclen', 'remove checksum and and close with eof without sending length'], |
226
|
|
|
|
|
|
|
# and now hide the 'gzip' behind a \r so that some firewalls will use the |
227
|
|
|
|
|
|
|
# heuristics of the antivirus which might be different from the the proxy |
228
|
|
|
|
|
|
|
[ INVALID,'ce:cr-gzip;gzip;replace:3,1|01', 'set flag FTEXT (hide gzip with "content-encoding:\r gzip")'], |
229
|
|
|
|
|
|
|
[ INVALID,'ce:cr-gzip;gzip;replace:3,1|02;replace:10,0=0000', 'set flag FHCRC and add CRC with 0 (hide gzip with "content-encoding:\r gzip")'], |
230
|
|
|
|
|
|
|
[ INVALID,'ce:cr-gzip;gzip;replace:3,1|08;replace:10,0=2000', 'set flag FNAME and add short file name (hide gzip with "content-encoding:\r gzip")'], |
231
|
|
|
|
|
|
|
[ INVALID,'ce:cr-gzip;gzip;replace:3,1|10;replace:10,0=2000', 'set flag FCOMMENT and add short comment (hide gzip with "content-encoding:\r gzip")'], |
232
|
|
|
|
|
|
|
[ INVALID,'ce:cr-gzip;gzip;replace:3,1|04;replace:10,0=0000', 'set flag FEXTRA and extra part with XLEN 0 (hide gzip with "content-encoding:\r gzip")'], |
233
|
|
|
|
|
|
|
[ INVALID,'ce:cr-gzip;gzip;replace:3,1|04;replace:10,0=05004170010000', 'set flag FEXTRA and extra part with XLEN 5 (hide gzip with "content-encoding:\r gzip")'], |
234
|
|
|
|
|
|
|
[ INVALID,'ce:cr-gzip;gzip;replace:3,1|20', 'set flag reserved bit 5 (hide gzip with "content-encoding:\r gzip")'], |
235
|
|
|
|
|
|
|
[ INVALID,'ce:cr-gzip;gzip;replace:3,1|40', 'set flag reserved bit 6 (hide gzip with "content-encoding:\r gzip")'], |
236
|
|
|
|
|
|
|
[ INVALID,'ce:cr-gzip;gzip;replace:3,1|80', 'set flag reserved bit 7 (hide gzip with "content-encoding:\r gzip")'], |
237
|
|
|
|
|
|
|
[ INVALID,'ce:cr-gzip;gzip;replace:-8,4^ffffffff', 'invalidate final checksum (hide gzip with "content-encoding:\r gzip")'], |
238
|
|
|
|
|
|
|
[ INVALID,'ce:cr-gzip;gzip;replace:-4,1^ff', 'invalidate length (hide gzip with "content-encoding:\r gzip")'], |
239
|
|
|
|
|
|
|
[ INVALID,'ce:cr-gzip;gzip;replace:-4,4=', 'remove length (hide gzip with "content-encoding:\r gzip")'], |
240
|
|
|
|
|
|
|
[ INVALID,'ce:cr-gzip;gzip;replace:-8,8=', 'remove checksum and length (hide gzip with "content-encoding:\r gzip")'], |
241
|
|
|
|
|
|
|
# same game, but with Content-Encoding: for other firewalls |
242
|
|
|
|
|
|
|
[ INVALID,'ce-space-colon-gzip;gzip;replace:3,1|01', 'set flag FTEXT (hide gzip with "content-encoding : gzip")'], |
243
|
|
|
|
|
|
|
[ INVALID,'ce-space-colon-gzip;gzip;replace:3,1|02;replace:10,0=0000', 'set flag FHCRC and add CRC with 0 (hide gzip with "content-encoding : gzip")'], |
244
|
|
|
|
|
|
|
[ INVALID,'ce-space-colon-gzip;gzip;replace:3,1|08;replace:10,0=2000', 'set flag FNAME and add short file name (hide gzip with "content-encoding : gzip")'], |
245
|
|
|
|
|
|
|
[ INVALID,'ce-space-colon-gzip;gzip;replace:3,1|10;replace:10,0=2000', 'set flag FCOMMENT and add short comment (hide gzip with "content-encoding : gzip")'], |
246
|
|
|
|
|
|
|
[ INVALID,'ce-space-colon-gzip;gzip;replace:3,1|04;replace:10,0=0000', 'set flag FEXTRA and extra part with XLEN 0 (hide gzip with "content-encoding : gzip")'], |
247
|
|
|
|
|
|
|
[ INVALID,'ce-space-colon-gzip;gzip;replace:3,1|04;replace:10,0=05004170010000', 'set flag FEXTRA and extra part with XLEN 5 (hide gzip with "content-encoding : gzip")'], |
248
|
|
|
|
|
|
|
[ INVALID,'ce-space-colon-gzip;gzip;replace:3,1|20', 'set flag reserved bit 5 (hide gzip with "content-encoding : gzip")'], |
249
|
|
|
|
|
|
|
[ INVALID,'ce-space-colon-gzip;gzip;replace:3,1|40', 'set flag reserved bit 6 (hide gzip with "content-encoding : gzip")'], |
250
|
|
|
|
|
|
|
[ INVALID,'ce-space-colon-gzip;gzip;replace:3,1|80', 'set flag reserved bit 7 (hide gzip with "content-encoding : gzip")'], |
251
|
|
|
|
|
|
|
[ INVALID,'ce-space-colon-gzip;gzip;replace:-8,4^ffffffff', 'invalidate final checksum (hide gzip with "content-encoding : gzip")'], |
252
|
|
|
|
|
|
|
[ INVALID,'ce-space-colon-gzip;gzip;replace:-4,1^ff', 'invalidate length (hide gzip with "content-encoding : gzip")'], |
253
|
|
|
|
|
|
|
[ INVALID,'ce-space-colon-gzip;gzip;replace:-4,4=', 'remove length (hide gzip with "content-encoding : gzip")'], |
254
|
|
|
|
|
|
|
[ INVALID,'ce-space-colon-gzip;gzip;replace:-8,8=', 'remove checksum and length (hide gzip with "content-encoding : gzip")'], |
255
|
|
|
|
|
|
|
|
256
|
|
|
|
|
|
|
# data before gzip |
257
|
|
|
|
|
|
|
[ INVALID,'ce:gzip;gzip;\012-before-body','new line at start of gzip body' ], |
258
|
|
|
|
|
|
|
); |
259
|
|
|
|
|
|
|
|
260
|
|
|
|
|
|
|
sub make_response { |
261
|
|
|
|
|
|
|
my ($self,$page,$spec) = @_; |
262
|
|
|
|
|
|
|
return make_index_page() if $page eq ''; |
263
|
|
|
|
|
|
|
my ($hdr,$data) = content($page,$self->ID."-".$spec) or die "unknown page $page"; |
264
|
|
|
|
|
|
|
my $version = '1.1'; |
265
|
|
|
|
|
|
|
my $clen_extend; |
266
|
|
|
|
|
|
|
my $body_prefix = ''; |
267
|
|
|
|
|
|
|
my $te = 'clen'; |
268
|
|
|
|
|
|
|
my @data; # preferred against $data if given |
269
|
|
|
|
|
|
|
for (split(';',$spec)) { |
270
|
|
|
|
|
|
|
if ($_ eq 'ce:rfc2047-deflate') { |
271
|
|
|
|
|
|
|
$hdr .= "Content-Encoding: =?UTF-8?B?ZGVmbGF0ZQo=?=\r\n"; |
272
|
|
|
|
|
|
|
} elsif ( my ($field,$v) = m{^(ce|te):(.*)$}i ) { |
273
|
|
|
|
|
|
|
my $changed; |
274
|
|
|
|
|
|
|
$changed++ if $v =~s{(?<=cr|lf|nl)-}{ }g; |
275
|
|
|
|
|
|
|
$changed++ if $v =~s{cr}{\r}g; |
276
|
|
|
|
|
|
|
$changed++ if $v =~s{lf}{\n}g; |
277
|
|
|
|
|
|
|
$changed++ if $v =~s{nl}{\r\n}g; |
278
|
|
|
|
|
|
|
$changed++ if $v =~s{_}{ }g; |
279
|
|
|
|
|
|
|
$v =~s{(?
|
280
|
|
|
|
|
|
|
$hdr .= "Connection: close\r\n" if $changed; |
281
|
|
|
|
|
|
|
$hdr .= $field eq 'ce' ? 'Content-Encoding:':'Transfer-Encoding:'; |
282
|
|
|
|
|
|
|
$hdr .= "$v\r\n"; |
283
|
|
|
|
|
|
|
} elsif ( m{^(pkt|chk):zlib\+deflate(\+deflate)?\z} ) { |
284
|
|
|
|
|
|
|
# [zlib-header][deflate][more-deflate].... |
285
|
|
|
|
|
|
|
# zlib will return with Z_DATA_ERROR when trying to process |
286
|
|
|
|
|
|
|
# more-deflate because it actually expected the correct ADLER32 |
287
|
|
|
|
|
|
|
# checksum there. Browsers will then assume that this should be |
288
|
|
|
|
|
|
|
# raw-deflate instead and retry with an edded zlib header. |
289
|
|
|
|
|
|
|
# With some browsers this process can be repeated. |
290
|
|
|
|
|
|
|
|
291
|
|
|
|
|
|
|
my ($enc,$nchunks) = ($1, $2? 3:2); |
292
|
|
|
|
|
|
|
my $size = int(length($data)/$nchunks); |
293
|
|
|
|
|
|
|
@data = (); |
294
|
|
|
|
|
|
|
for(my $i=0;$i<$nchunks;$i++) { |
295
|
|
|
|
|
|
|
push @data, substr($data,0,$size,''); |
296
|
|
|
|
|
|
|
} |
297
|
|
|
|
|
|
|
$data[-1] .= $data; # in case something left |
298
|
|
|
|
|
|
|
$_ = zlib_compress($_,'deflate') for(@data); |
299
|
|
|
|
|
|
|
$data[0] = "\x78\x9c".$data[0]; |
300
|
|
|
|
|
|
|
if ($enc eq 'chk') { |
301
|
|
|
|
|
|
|
$te = 'chunked'; |
302
|
|
|
|
|
|
|
$data = join("", map { |
303
|
|
|
|
|
|
|
sprintf("%x\r\n%s\r\n",length($_),$_) |
304
|
|
|
|
|
|
|
} (@data,'')); |
305
|
|
|
|
|
|
|
@data = (); |
306
|
|
|
|
|
|
|
} |
307
|
|
|
|
|
|
|
} elsif ( m{^(?:(gzip)|deflate|(zlib))(?:(\d+)([ps]))?(?:,(sync|partial|block|full|finish))?$} ) { |
308
|
|
|
|
|
|
|
my $zlib = Compress::Raw::Zlib::Deflate->new( |
309
|
|
|
|
|
|
|
-WindowBits => $1 ? WANT_GZIP : $2 ? +MAX_WBITS() : -MAX_WBITS(), |
310
|
|
|
|
|
|
|
-AppendOutput => 1, |
311
|
|
|
|
|
|
|
); |
312
|
|
|
|
|
|
|
my $size = int(length($data)/($3||1)) || 1; |
313
|
|
|
|
|
|
|
my @chunks; |
314
|
|
|
|
|
|
|
while ($data ne '') { |
315
|
|
|
|
|
|
|
push @chunks,substr($data,0,$size,'') |
316
|
|
|
|
|
|
|
} |
317
|
|
|
|
|
|
|
my $plain_chunk = ''; |
318
|
|
|
|
|
|
|
$plain_chunk = join('',splice(@chunks,1)) if $4 && $4 eq 's'; |
319
|
|
|
|
|
|
|
|
320
|
|
|
|
|
|
|
my $flush = |
321
|
|
|
|
|
|
|
! $5 ? Z_FULL_FLUSH : |
322
|
|
|
|
|
|
|
$5 eq 'partial' ? Z_PARTIAL_FLUSH : |
323
|
|
|
|
|
|
|
$5 eq 'sync' ? Z_SYNC_FLUSH : |
324
|
|
|
|
|
|
|
$5 eq 'full' ? Z_FULL_FLUSH : |
325
|
|
|
|
|
|
|
$5 eq 'block' ? Z_BLOCK : |
326
|
|
|
|
|
|
|
$5 eq 'finish' ? Z_FINISH : |
327
|
|
|
|
|
|
|
die $5; |
328
|
|
|
|
|
|
|
my $newdata = ''; |
329
|
|
|
|
|
|
|
while (@chunks) { |
330
|
|
|
|
|
|
|
$zlib->deflate( shift(@chunks), $newdata); |
331
|
|
|
|
|
|
|
if (defined $flush && @chunks) { |
332
|
|
|
|
|
|
|
$zlib->flush($newdata,$flush); |
333
|
|
|
|
|
|
|
$zlib->deflateReset if $flush == Z_FINISH; |
334
|
|
|
|
|
|
|
} |
335
|
|
|
|
|
|
|
} |
336
|
|
|
|
|
|
|
$zlib->flush($newdata,Z_FINISH); |
337
|
|
|
|
|
|
|
$data = $newdata . $plain_chunk; |
338
|
|
|
|
|
|
|
} elsif (m{^(lzma[12]|xz)$}) { |
339
|
|
|
|
|
|
|
my ($lzma,$status) = |
340
|
|
|
|
|
|
|
$_ eq 'xz' ? Compress::Raw::Lzma::EasyEncoder->new(AppendOutput => 1) : |
341
|
|
|
|
|
|
|
$_ eq 'lzma1' ? Compress::Raw::Lzma::AloneEncoder->new(AppendOutput => 1) : |
342
|
|
|
|
|
|
|
Compress::Raw::Lzma::RawEncoder->new(AppendOutput =>1); |
343
|
|
|
|
|
|
|
$status == LZMA_OK or die "failed to create LZMA object"; |
344
|
|
|
|
|
|
|
my $newdata = ''; |
345
|
|
|
|
|
|
|
$lzma->code($data,$newdata) == LZMA_OK or die "failed to lzma encode data"; |
346
|
|
|
|
|
|
|
$lzma->flush($newdata,LZMA_FINISH) == LZMA_STREAM_END or die "failed to close lzma stream"; |
347
|
|
|
|
|
|
|
$data = $newdata; |
348
|
|
|
|
|
|
|
|
349
|
|
|
|
|
|
|
} elsif ($_ eq 'brotli') { |
350
|
|
|
|
|
|
|
$data = bro_compress($data) or do { |
351
|
|
|
|
|
|
|
# no brotli for this content |
352
|
|
|
|
|
|
|
return "HTTP/$version 500 no brotli\r\nContent-length:0\r\n\r\n"; |
353
|
|
|
|
|
|
|
}; |
354
|
|
|
|
|
|
|
} elsif ($_ eq 'gzip-zlib') { |
355
|
|
|
|
|
|
|
my $zlib = Compress::Raw::Zlib::Deflate->new( |
356
|
|
|
|
|
|
|
-WindowBits => +MAX_WBITS(), |
357
|
|
|
|
|
|
|
-AppendOutput => 1, |
358
|
|
|
|
|
|
|
); |
359
|
|
|
|
|
|
|
my $gzip_hdr = pack("CCCCVCC",0x1f,0x8b,0x8,0,0,2,0); |
360
|
|
|
|
|
|
|
my $gzip_trailer = pack("VV",Compress::Raw::Zlib::crc32($data),length($data)); |
361
|
|
|
|
|
|
|
my $newdata = ''; |
362
|
|
|
|
|
|
|
$zlib->deflate($data,$newdata); |
363
|
|
|
|
|
|
|
$zlib->flush($newdata,Z_FINISH); |
364
|
|
|
|
|
|
|
$data = $gzip_hdr.$newdata.$gzip_trailer; |
365
|
|
|
|
|
|
|
|
366
|
|
|
|
|
|
|
} elsif (m{^ce-space-colon-(.*)}) { |
367
|
|
|
|
|
|
|
$hdr .= "Content-Encoding : $1\r\n"; |
368
|
|
|
|
|
|
|
} elsif (m{^ce-colon-colon-(.*)}) { |
369
|
|
|
|
|
|
|
$hdr .= "Content-Encoding:: $1\r\n"; |
370
|
|
|
|
|
|
|
} elsif ( my ($crlf,$encoding) = m{^((?:lf|cr|x)+)only-(.*)}) { |
371
|
|
|
|
|
|
|
$hdr = "X-Foo: bar" if $hdr !~s{\r\n\z}{}; |
372
|
|
|
|
|
|
|
$crlf =~s{cr}{\r}g; |
373
|
|
|
|
|
|
|
$crlf =~s{lf}{\n}g; |
374
|
|
|
|
|
|
|
$hdr .= $crlf . "Content-Encoding: $encoding\r\n"; |
375
|
|
|
|
|
|
|
} elsif ( my ($off,$len,$op,$replacement) = m{replace:(-?\d+),(\d+)([=|^])(.*)}) { |
376
|
|
|
|
|
|
|
$replacement = pack('C*',map { hex($_) } $replacement=~m{(..)}g); |
377
|
|
|
|
|
|
|
if ($op eq '=') { |
378
|
|
|
|
|
|
|
substr($data,$off,$len,$replacement); |
379
|
|
|
|
|
|
|
} elsif ($op eq '|') { |
380
|
|
|
|
|
|
|
die "'$_' flags are already set" if (substr($data,$off,$len) & $replacement) eq $replacement; |
381
|
|
|
|
|
|
|
substr($data,$off,$len) |= $replacement; |
382
|
|
|
|
|
|
|
} elsif ($op eq '^') { |
383
|
|
|
|
|
|
|
substr($data,$off,$len) ^= $replacement; |
384
|
|
|
|
|
|
|
} else { |
385
|
|
|
|
|
|
|
die "bad op=$op in '$_'" |
386
|
|
|
|
|
|
|
} |
387
|
|
|
|
|
|
|
|
388
|
|
|
|
|
|
|
} elsif ( $_ eq 'gzip-payload-as-extra') { |
389
|
|
|
|
|
|
|
|
390
|
|
|
|
|
|
|
# header with FEXTRA set |
391
|
|
|
|
|
|
|
my $gzip = pack("CCCCVCC",0x1f,0x8b,0x8,0b100,0,2,0); |
392
|
|
|
|
|
|
|
|
393
|
|
|
|
|
|
|
# add XLEN + payload with deflate data |
394
|
|
|
|
|
|
|
my $zlib = Compress::Raw::Zlib::Deflate->new( |
395
|
|
|
|
|
|
|
-WindowBits => -MAX_WBITS(), |
396
|
|
|
|
|
|
|
-AppendOutput => 1, |
397
|
|
|
|
|
|
|
); |
398
|
|
|
|
|
|
|
my $newdata = ''; |
399
|
|
|
|
|
|
|
$zlib->deflate($data,$newdata); |
400
|
|
|
|
|
|
|
$zlib->flush($newdata,Z_FINISH); |
401
|
|
|
|
|
|
|
$gzip .= pack("v/a*",$newdata); |
402
|
|
|
|
|
|
|
|
403
|
|
|
|
|
|
|
# then add some innocent compressed data |
404
|
|
|
|
|
|
|
$data = 'This is not what you are looking for.'; |
405
|
|
|
|
|
|
|
$zlib = Compress::Raw::Zlib::Deflate->new( |
406
|
|
|
|
|
|
|
-WindowBits => -MAX_WBITS(), |
407
|
|
|
|
|
|
|
-AppendOutput => 1, |
408
|
|
|
|
|
|
|
); |
409
|
|
|
|
|
|
|
$newdata = ''; |
410
|
|
|
|
|
|
|
$zlib->deflate($data,$newdata); |
411
|
|
|
|
|
|
|
$zlib->flush($newdata,Z_FINISH); |
412
|
|
|
|
|
|
|
$gzip .= $newdata; |
413
|
|
|
|
|
|
|
|
414
|
|
|
|
|
|
|
# and add the trailer with CRC and length based on the innocent data |
415
|
|
|
|
|
|
|
$gzip .= pack("VV",Compress::Raw::Zlib::crc32($data),length($data)); |
416
|
|
|
|
|
|
|
$data = $gzip; |
417
|
|
|
|
|
|
|
|
418
|
|
|
|
|
|
|
} elsif (m{^clen\+(\d+)$}) { |
419
|
|
|
|
|
|
|
$clen_extend = $1 |
420
|
|
|
|
|
|
|
} elsif ($_ eq 'noclen') { |
421
|
|
|
|
|
|
|
$clen_extend = -1; |
422
|
|
|
|
|
|
|
} elsif (m{(.+)-before-body$}) { |
423
|
|
|
|
|
|
|
( my $d = $1 ) =~s{\\([0-7]{3})}{ chr(oct($1)) }esg; |
424
|
|
|
|
|
|
|
$body_prefix .= $d; |
425
|
|
|
|
|
|
|
} else { |
426
|
|
|
|
|
|
|
die $_ |
427
|
|
|
|
|
|
|
} |
428
|
|
|
|
|
|
|
} |
429
|
|
|
|
|
|
|
|
430
|
|
|
|
|
|
|
$data = $body_prefix . $data; |
431
|
|
|
|
|
|
|
if (! @data) { |
432
|
|
|
|
|
|
|
@data = $data; |
433
|
|
|
|
|
|
|
} else { |
434
|
|
|
|
|
|
|
$data = join('',@data); |
435
|
|
|
|
|
|
|
} |
436
|
|
|
|
|
|
|
my $len = length($data); |
437
|
|
|
|
|
|
|
if ($te eq 'chunked') { |
438
|
|
|
|
|
|
|
$hdr .= "Transfer-Encoding: chunked\r\n" |
439
|
|
|
|
|
|
|
} elsif (!$clen_extend) { |
440
|
|
|
|
|
|
|
$hdr = "Content-length: ".length($data)."\r\n".$hdr; |
441
|
|
|
|
|
|
|
} elsif ($clen_extend<0) { |
442
|
|
|
|
|
|
|
$hdr = "Connection: close\r\n$hdr"; |
443
|
|
|
|
|
|
|
} else { |
444
|
|
|
|
|
|
|
$hdr = "Connection: close\r\nContent-length: ".(length($data)+$clen_extend)."\r\n".$hdr; |
445
|
|
|
|
|
|
|
} |
446
|
|
|
|
|
|
|
return ( |
447
|
|
|
|
|
|
|
"HTTP/$version 200 ok\r\n$hdr\r\n$data[0]", |
448
|
|
|
|
|
|
|
(@data>1) ? (@data[1..$#data]):(), |
449
|
|
|
|
|
|
|
); |
450
|
|
|
|
|
|
|
} |
451
|
|
|
|
|
|
|
|
452
|
|
|
|
|
|
|
1; |