int gz_check(const buf_t *b) { const uint8_t *in = buf_c8(b); if(b->b_size < 10 || in[0] != 0x1f || in[1] != 0x8b || in[2] != 0x08) return 0; return 1; }
/** * Load entire image into memory using fileaccess load method. * Faster than open+read+close. */ static pixmap_t * fa_imageloader2(const char *url, const char **vpaths, char *errbuf, size_t errlen, int *cache_control, cancellable_t *c) { buf_t *buf; jpeg_meminfo_t mi; pixmap_type_t fmt; int width = -1, height = -1, orientation = 0; buf = fa_load(url, FA_LOAD_VPATHS(vpaths), FA_LOAD_ERRBUF(errbuf, errlen), FA_LOAD_CACHE_CONTROL(cache_control), FA_LOAD_CANCELLABLE(c), NULL); if(buf == NULL || buf == NOT_MODIFIED) return (pixmap_t *)buf; const uint8_t *p = buf_c8(buf); mi.data = p; mi.size = buf->b_size; if(buf->b_size < 16) goto bad; /* Probe format */ if((p[6] == 'J' && p[7] == 'F' && p[8] == 'I' && p[9] == 'F') || (p[6] == 'E' && p[7] == 'x' && p[8] == 'i' && p[9] == 'f')) { jpeginfo_t ji; if(jpeg_info(&ji, jpeginfo_mem_reader, &mi, JPEG_INFO_DIMENSIONS | JPEG_INFO_ORIENTATION, p, buf->b_size, errbuf, errlen)) { buf_release(buf); return NULL; } fmt = PIXMAP_JPEG; width = ji.ji_width; height = ji.ji_height; orientation = ji.ji_orientation; jpeg_info_clear(&ji); } else if(!memcmp(pngsig, p, 8)) { fmt = PIXMAP_PNG; } else if(!memcmp(gif87sig, p, sizeof(gif87sig)) || !memcmp(gif89sig, p, sizeof(gif89sig))) { fmt = PIXMAP_GIF; } else if(!memcmp(svgsig1, p, sizeof(svgsig1)) || !memcmp(svgsig2, p, sizeof(svgsig2))) { fmt = PIXMAP_SVG; } else { bad: snprintf(errbuf, errlen, "Unknown format"); buf_release(buf); return NULL; } pixmap_t *pm = pixmap_alloc_coded(p, buf->b_size, fmt); if(pm != NULL) { pm->pm_width = width; pm->pm_height = height; pm->pm_orientation = orientation; } else { snprintf(errbuf, errlen, "Out of memory"); } buf_release(buf); return pm; }
buf_t * gz_inflate(buf_t *bin, char *errbuf, size_t errlen) { z_stream z = {0}; unsigned char *out; size_t outlen; int r; if(!gz_check(bin)) { snprintf(errbuf, errlen, "Invalid header"); buf_release(bin); return NULL; } const uint8_t *in = buf_c8(bin); size_t inlen = bin->b_size; if(in[3] != 0) { snprintf(errbuf, errlen, "Header extensions is not supported"); buf_release(bin); return NULL; } in += 10; inlen -= 10; z.next_in = (void *)in; z.avail_in = inlen; if(inflateInit2(&z, -MAX_WBITS) != Z_OK) { snprintf(errbuf, errlen, "Inflate init failed"); buf_release(bin); return NULL; } outlen = inlen * 2; out = mymalloc(outlen + 1); if(out == NULL) { snprintf(errbuf, errlen, "Out of memory"); inflateEnd(&z); buf_release(bin); return NULL; } while(1) { if(outlen - z.total_out == 0) { outlen *= 2; out = realloc(out, outlen+1); } z.next_out = out + z.total_out; z.avail_out = outlen - z.total_out; r = inflate(&z, 0); if(r == Z_STREAM_END) break; if(r != Z_OK) { snprintf(errbuf, errlen, "inflate: %s", z.msg); inflateEnd(&z); free(out); buf_release(bin); return NULL; } } out[z.total_out] = 0; inflateEnd(&z); buf_release(bin); return buf_create_and_adopt(z.total_out, out, &free); }
static image_t * fa_imageloader_buf(buf_t *buf, char *errbuf, size_t errlen) { jpeg_meminfo_t mi; image_coded_type_t fmt; int width = -1, height = -1, orientation = 0, progressive = 0, planes = 0; const uint8_t *p = buf_c8(buf); mi.data = p; mi.size = buf->b_size; if(buf->b_size < 16) goto bad; /* Probe format */ if(p[0] == 0xff && p[1] == 0xd8 && p[2] == 0xff) { jpeginfo_t ji; if(jpeg_info(&ji, jpeginfo_mem_reader, &mi, JPEG_INFO_DIMENSIONS | JPEG_INFO_ORIENTATION, p, buf->b_size, errbuf, errlen)) { return NULL; } fmt = IMAGE_JPEG; width = ji.ji_width; height = ji.ji_height; orientation = ji.ji_orientation; progressive = ji.ji_progressive; planes = ji.ji_components; jpeg_info_clear(&ji); } else if(!memcmp(pngsig, p, 8)) { fmt = IMAGE_PNG; } else if(!memcmp(gif87sig, p, sizeof(gif87sig)) || !memcmp(gif89sig, p, sizeof(gif89sig))) { fmt = IMAGE_GIF; } else if(p[0] == 'B' && p[1] == 'M') { fmt = IMAGE_BMP; } else if(!memcmp(svgsig1, p, sizeof(svgsig1)) || !memcmp(svgsig2, p, sizeof(svgsig2))) { fmt = IMAGE_SVG; } else { bad: snprintf(errbuf, errlen, "Unknown format"); return NULL; } image_t *img = image_coded_create_from_buf(buf, fmt); if(img != NULL) { img->im_width = width; img->im_height = height; img->im_orientation = orientation; img->im_color_planes = planes; if(progressive) img->im_flags |= IMAGE_PROGRESSIVE; } else { snprintf(errbuf, errlen, "Out of memory"); } return img; }