| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
1
|
|
|
1
|
|
3
|
use strict; |
|
|
1
|
|
|
|
|
1
|
|
|
|
1
|
|
|
|
|
22
|
|
|
2
|
1
|
|
|
1
|
|
4
|
use warnings; |
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
24
|
|
|
3
|
|
|
|
|
|
|
package App::DubiousHTTP::Tests::Compressed; |
|
4
|
1
|
|
|
1
|
|
3
|
use App::DubiousHTTP::Tests::Common; |
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
119
|
|
|
5
|
1
|
|
|
1
|
|
3
|
use Compress::Raw::Zlib; |
|
|
1
|
|
|
|
|
1
|
|
|
|
1
|
|
|
|
|
132
|
|
|
6
|
1
|
|
|
1
|
|
922
|
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; |