compress.c (10322B)
1 #include "links.h" 2 3 #include <zlib.h> 4 5 int decompressed_cache_size = 0; 6 7 static int 8 display_error(struct terminal *term, unsigned char *msg, int *errp) 9 { 10 if (errp) 11 *errp = 1; 12 if (!term) 13 return 0; 14 if (!errp) 15 if (find_msg_box(term, msg, NULL, NULL)) 16 return 0; 17 return 1; 18 } 19 20 static void 21 decoder_memory_init(unsigned char **p, size_t *size, off_t init_length) 22 { 23 if (init_length > 0 && init_length < INT_MAX) 24 *size = (int)init_length; 25 else 26 *size = 4096; 27 *p = xmalloc(*size); 28 } 29 30 static int 31 decoder_memory_expand(unsigned char **p, size_t size, size_t *addsize) 32 { 33 size_t add = size / 4 + 1; 34 if (size + add < size) { 35 if (add > 1) 36 add >>= 1; 37 else 38 overalloc(); 39 } 40 *p = xrealloc(*p, size + add); 41 *addsize = add; 42 return 0; 43 } 44 45 static void 46 decompress_error(struct terminal *term, struct cache_entry *ce, 47 unsigned char *lib, unsigned char *msg, int *errp) 48 { 49 unsigned char *u, *server; 50 if ((u = parse_http_header(ce->head, cast_uchar "Content-Encoding", 51 NULL))) { 52 free(u); 53 if ((server = get_host_name(ce->url))) { 54 add_blacklist_entry(server, BL_NO_COMPRESSION); 55 free(server); 56 } 57 } 58 if (!display_error(term, TEXT_(T_DECOMPRESSION_ERROR), errp)) 59 return; 60 u = display_url(term, ce->url, 1); 61 msg_box(term, getml(u, NULL), TEXT_(T_DECOMPRESSION_ERROR), AL_CENTER, 62 TEXT_(T_ERROR_DECOMPRESSING_), u, TEXT_(T__wITH_), lib, 63 cast_uchar ": ", msg, MSG_BOX_END, NULL, 1, TEXT_(T_CANCEL), 64 msg_box_null, B_ENTER | B_ESC); 65 } 66 67 static int 68 decode_gzip(struct terminal *term, struct cache_entry *ce, int defl, int *errp) 69 { 70 unsigned char err; 71 unsigned char memory_error; 72 unsigned char skip_gzip_header; 73 unsigned char old_zlib; 74 z_stream z; 75 off_t offset; 76 int r; 77 unsigned char *p; 78 struct fragment *f = NULL; 79 struct list_head *lf; 80 size_t size; 81 82 retry_after_memory_error: 83 memory_error = 0; 84 decoder_memory_init(&p, &size, ce->length); 85 init_again: 86 err = 0; 87 skip_gzip_header = 0; 88 old_zlib = 0; 89 memset(&z, 0, sizeof(z)); 90 z.next_in = NULL; 91 z.avail_in = 0; 92 z.next_out = p; 93 z.avail_out = (unsigned)size; 94 z.zalloc = NULL; 95 z.zfree = NULL; 96 z.opaque = NULL; 97 r = inflateInit2(&z, defl == 1 ? 15 : defl == 2 ? -15 : 15 + 16); 98 init_failed: 99 switch (r) { 100 case Z_OK: 101 break; 102 case Z_MEM_ERROR: 103 memory_error = 1; 104 err = 1; 105 goto after_inflateend; 106 case Z_STREAM_ERROR: 107 if (!defl && !old_zlib) { 108 if (defrag_entry(ce)) { 109 memory_error = 1; 110 err = 1; 111 goto after_inflateend; 112 } 113 r = inflateInit2(&z, -15); 114 skip_gzip_header = 1; 115 old_zlib = 1; 116 goto init_failed; 117 } 118 decompress_error(term, ce, cast_uchar "zlib", 119 z.msg ? (unsigned char *)z.msg 120 : (unsigned char *)"Invalid parameter", 121 errp); 122 err = 1; 123 goto after_inflateend; 124 case Z_VERSION_ERROR: 125 decompress_error(term, ce, cast_uchar "zlib", 126 z.msg ? (unsigned char *)z.msg 127 : (unsigned char *)"Bad zlib version", 128 errp); 129 err = 1; 130 goto after_inflateend; 131 default: 132 decompress_error( 133 term, ce, cast_uchar "zlib", 134 z.msg ? (unsigned char *)z.msg 135 : (unsigned char 136 *)"Unknown return value on inflateInit2", 137 errp); 138 err = 1; 139 goto after_inflateend; 140 } 141 offset = 0; 142 foreach (struct fragment, f, lf, ce->frag) { 143 if (f->offset != offset) 144 break; 145 z.next_in = f->data; 146 z.avail_in = (unsigned)f->length; 147 if ((off_t)z.avail_in != f->length) 148 overalloc(); 149 repeat_frag: 150 if (skip_gzip_header == 2) { 151 if (z.avail_in < 8) 152 goto finish; 153 z.next_in = (unsigned char *)z.next_in + 8; 154 z.avail_in -= 8; 155 skip_gzip_header = 1; 156 } 157 if (skip_gzip_header) { 158 /* FIXME */ 159 /* if zlib is old, we have to skip gzip header manually 160 otherwise zlib 1.2.x can do it automatically */ 161 unsigned char *head = z.next_in; 162 unsigned headlen = 10; 163 if (z.avail_in <= 11) 164 goto finish; 165 if (head[0] != 0x1f || head[1] != 0x8b) { 166 decompress_error(term, ce, cast_uchar "zlib", 167 TEXT_(T_COMPRESSED_ERROR), 168 errp); 169 err = 1; 170 goto finish; 171 } 172 if (head[2] != 8 || head[3] & 0xe0) { 173 decompress_error( 174 term, ce, cast_uchar "zlib", 175 TEXT_(T_UNKNOWN_COMPRESSION_METHOD), errp); 176 err = 1; 177 goto finish; 178 } 179 if (head[3] & 0x04) { 180 headlen += 2 + head[10] + (head[11] << 8); 181 if (headlen >= z.avail_in) 182 goto finish; 183 } 184 if (head[3] & 0x08) 185 do { 186 headlen++; 187 if (headlen >= z.avail_in) 188 goto finish; 189 } while (head[headlen - 1]); 190 if (head[3] & 0x10) 191 do { 192 headlen++; 193 if (headlen >= z.avail_in) 194 goto finish; 195 } while (head[headlen - 1]); 196 if (head[3] & 0x01) { 197 headlen += 2; 198 if (headlen >= z.avail_in) 199 goto finish; 200 } 201 z.next_in = (unsigned char *)z.next_in + headlen; 202 z.avail_in -= headlen; 203 skip_gzip_header = 0; 204 } 205 r = inflate(&z, f->list_entry.next == &ce->frag ? Z_SYNC_FLUSH 206 : Z_NO_FLUSH); 207 switch (r) { 208 case Z_OK: 209 case Z_BUF_ERROR: 210 break; 211 case Z_STREAM_END: 212 r = inflateEnd(&z); 213 if (r != Z_OK) 214 goto end_failed; 215 r = inflateInit2(&z, old_zlib ? -15 216 : defl ? 15 217 : 15 + 16); 218 if (r != Z_OK) { 219 old_zlib = 0; 220 goto init_failed; 221 } 222 if (old_zlib) 223 skip_gzip_header = 2; 224 break; 225 case Z_NEED_DICT: 226 case Z_DATA_ERROR: 227 if (defl == 1) { 228 defl = 2; 229 r = inflateEnd(&z); 230 if (r != Z_OK) 231 goto end_failed; 232 goto init_again; 233 } 234 decompress_error(term, ce, cast_uchar "zlib", 235 z.msg ? (unsigned char *)z.msg 236 : TEXT_(T_COMPRESSED_ERROR), 237 errp); 238 err = 1; 239 goto finish; 240 case Z_STREAM_ERROR: 241 decompress_error( 242 term, ce, cast_uchar "zlib", 243 z.msg 244 ? (unsigned char *)z.msg 245 : (unsigned char *)"Internal error on inflate", 246 errp); 247 err = 1; 248 goto finish; 249 case Z_MEM_ERROR: 250 memory_error = 1; 251 err = 1; 252 goto finish; 253 default: 254 decompress_error( 255 term, ce, cast_uchar "zlib", 256 z.msg ? (unsigned char *)z.msg 257 : (unsigned char 258 *)"Unknown return value on inflate", 259 errp); 260 err = 1; 261 break; 262 } 263 if (!z.avail_out) { 264 size_t addsize; 265 decoder_memory_expand(&p, size, &addsize); 266 z.next_out = p + size; 267 z.avail_out = (unsigned)addsize; 268 size += addsize; 269 } 270 if (z.avail_in) 271 goto repeat_frag; 272 /* FIXME */ 273 /* In zlib 1.1.3, inflate(Z_SYNC_FLUSH) doesn't work. 274 The following line fixes it --- for last fragment, loop until 275 we get an eof. */ 276 if (r == Z_OK && f->list_entry.next == &ce->frag) 277 goto repeat_frag; 278 offset += f->length; 279 } 280 finish: 281 r = inflateEnd(&z); 282 end_failed: 283 switch (r) { 284 case Z_OK: 285 break; 286 case Z_STREAM_ERROR: 287 decompress_error( 288 term, ce, cast_uchar "zlib", 289 z.msg ? (unsigned char *)z.msg 290 : (unsigned char *)"Internal error on inflateEnd", 291 errp); 292 err = 1; 293 break; 294 case Z_MEM_ERROR: 295 memory_error = 1; 296 err = 1; 297 break; 298 default: 299 decompress_error( 300 term, ce, cast_uchar "zlib", 301 z.msg 302 ? (unsigned char *)z.msg 303 : (unsigned char *)"Unknown return value on inflateEnd", 304 errp); 305 err = 1; 306 break; 307 } 308 after_inflateend: 309 if (memory_error) { 310 free(p); 311 if (out_of_memory()) 312 goto retry_after_memory_error; 313 decompress_error(term, ce, cast_uchar "zlib", 314 z.msg ? (unsigned char *)z.msg 315 : TEXT_(T_OUT_OF_MEMORY), 316 errp); 317 return 1; 318 } 319 if (err && (unsigned char *)z.next_out == p) { 320 free(p); 321 return 1; 322 } 323 ce->decompressed = p; 324 ce->decompressed_len = (unsigned char *)z.next_out - (unsigned char *)p; 325 decompressed_cache_size += ce->decompressed_len; 326 ce->decompressed = xrealloc(ce->decompressed, ce->decompressed_len); 327 return 0; 328 } 329 330 int 331 get_file_by_term(struct terminal *term, struct cache_entry *ce, 332 unsigned char **start, size_t *len, int *errp) 333 { 334 unsigned char *enc; 335 struct fragment *fr; 336 int e; 337 if (errp) 338 *errp = 0; 339 *start = NULL; 340 *len = 0; 341 if (!ce) 342 return 1; 343 if (ce->decompressed) { 344 return_decompressed: 345 *start = ce->decompressed; 346 *len = ce->decompressed_len; 347 return 0; 348 } 349 enc = get_content_encoding(ce->head, ce->url, 0); 350 if (enc) { 351 if (!casestrcmp(enc, cast_uchar "gzip") 352 || !casestrcmp(enc, cast_uchar "x-gzip") 353 || !casestrcmp(enc, cast_uchar "deflate")) { 354 int defl = !casestrcmp(enc, cast_uchar "deflate"); 355 free(enc); 356 if (decode_gzip(term, ce, defl, errp)) 357 goto uncompressed; 358 goto return_decompressed; 359 } 360 free(enc); 361 goto uncompressed; 362 } 363 uncompressed: 364 if ((e = defrag_entry(ce)) < 0) { 365 unsigned char *msg = get_err_msg(e); 366 if (display_error(term, TEXT_(T_ERROR), errp)) { 367 unsigned char *u = display_url(term, ce->url, 1); 368 msg_box(term, getml(u, NULL), TEXT_(T_ERROR), AL_CENTER, 369 TEXT_(T_ERROR_LOADING), cast_uchar " ", u, 370 cast_uchar ":\n\n", msg, MSG_BOX_END, NULL, 1, 371 TEXT_(T_CANCEL), msg_box_null, B_ENTER | B_ESC); 372 } 373 } 374 if (list_empty(ce->frag)) 375 return 1; 376 fr = list_struct(ce->frag.next, struct fragment); 377 if (fr->offset || !fr->length) 378 return 1; 379 *start = fr->data; 380 *len = fr->length; 381 return 0; 382 } 383 384 int 385 get_file(struct object_request *o, unsigned char **start, size_t *len) 386 { 387 struct terminal *term; 388 *start = NULL; 389 *len = 0; 390 if (!o) 391 return 1; 392 term = find_terminal(o->term); 393 return get_file_by_term(term, o->ce, start, len, NULL); 394 } 395 396 void 397 free_decompressed_data(struct cache_entry *e) 398 { 399 if (e->decompressed) { 400 if (decompressed_cache_size < e->decompressed_len) 401 internal("free_decompressed_data: " 402 "decompressed_cache_size underflow %lu, %lu", 403 (unsigned long)decompressed_cache_size, 404 (unsigned long)e->decompressed_len); 405 decompressed_cache_size -= e->decompressed_len; 406 e->decompressed_len = 0; 407 free(e->decompressed); 408 e->decompressed = NULL; 409 } 410 } 411 412 size_t 413 add_compress_methods(unsigned char **s, size_t sl) 414 { 415 sl = add_to_str(s, sl, cast_uchar "ZLIB"); 416 #ifdef zlib_version 417 sl = add_to_str(s, sl, cast_uchar " ("); 418 sl = add_to_str(s, sl, (unsigned char *)zlib_version); 419 sl = add_chr_to_str(s, sl, ')'); 420 #endif 421 return sl; 422 }