private byte[] loadCompressedBinaryData(InputStream is) throws IOException,
			UnsupportedEncodingException {

		ByteArrayOutputStream output = new ByteArrayOutputStream();
		byte[] buffer = new byte[4096];

		int bytesRead;
		// load md5 sum
		MessageDigest md;
		try {
			md = MessageDigest.getInstance(DIGEST_MD52);
		} catch (NoSuchAlgorithmException e) {
			throw new RuntimeException(e);
		}
		byte[] md5 = new byte[md.getDigestLength()];
		bytesRead = is.read(md5, 0, md5.length);
		if (bytesRead != md.getDigestLength())
			throw new IOException(UNEXPECTED_END_OF_FILE);

		// load size
		bytesRead = is.read(buffer, 0, 4);
		if (bytesRead != 4)
			throw new IOException(UNEXPECTED_END_OF_FILE);
		int dataSize = (((int) buffer[3] & 0xFF) << 24)
				| (((int) buffer[2] & 0xFF) << 16)
				| (((int) buffer[1] & 0xFF) << 8) | ((int) buffer[0] & 0xFF);
		log.debug("uncompressed file size: " + dataSize);

		GZIPInputStream gzipIs = new GZIPInputStream(is);
		while ((bytesRead = gzipIs.read(buffer)) != -1) {
			md.update(buffer, 0, bytesRead);
			output.write(buffer, 0, bytesRead);
			if (dumpData)
				System.out.print(new String(buffer, 0, bytesRead,
						CHARSET_cp1252));
		}
		if (dumpData)
			System.out.println();

		buffer = md.digest();
		for (int i = 0; i < buffer.length; i++)
			if (buffer[i] != md5[i])
				throw new IOException("MD5 mismatch");

		if (output.size() != dataSize)
			throw new IOException(String.format(
					"File size mismatch: %d instead of %d", output.size(),
					dataSize));

		log.debug("MD5 ok");

		return output.toByteArray();
	}