Cocoa
Cocoa

Reputation: 105

Decompress zlib data in Haskell -- Incorrect header check

I wrote a simple Haskell program that fetches some compressed data from a certain website and then decompress it, but I always get an error said 'incorrect header check'.

I've wrote the same program in D lang and it works fine.

For now, I can fetch the raw compressed data in Haskell, the only problem seems to be the window bits and buffer size in DecompressParams. (DecompressParam in Haskell doesn't accept negative value)

FYI: You can pass '4750304' to the program for testing.

Here is my Haskell code

module Main where

import Codec.Compression.Zlib
import Network.HTTP
import System.Environment (getArgs)
import Data.ByteString.Lazy.Char8

commentURL :: [Char] -> [Char]
commentURL cid = do
    "http://comment.bilibili.com/" ++ cid ++ ".xml"

main :: IO ()
main = do
    (arg:_) <- getArgs
    do
        body <- simpleHTTP (getRequest $ commentURL arg) >>= getResponseBody
        let params = DecompressParams {
                        decompressWindowBits = WindowBits 15, 
                        decompressBufferSize = 0, 
                        decompressDictionary = Nothing
                     }
        let p = decompressWith params (pack body)
        Data.ByteString.Lazy.Char8.putStrLn p

And the working code in D lang

import std.stdio;
import std.net.curl;
import std.array;
import std.string;
import std.zlib;

void main(string[] args) {
    if (args[1].length <= 14 && args[1].isNumeric) {
        auto url = appender!string;
        url.put("comment.bilibili.com/");
        url.put(args[1]);
        url.put(".xml");

        auto deflate = get(url.data);
        auto data = cast(char[])uncompress(deflate, 0, -15);
        // DecompressParam in Haskell doesn't accept negative value

        File file = File(args[1]~".xml", "wb");
        file.write(data);
        file.close();
    } else {
        writeln("Usage: "~args[0]~" [cid]");
    }
}

Upvotes: 1

Views: 4257

Answers (1)

JP Moresmau
JP Moresmau

Reputation: 7403

Change your ZLib import to

import Codec.Compression.Zlib.Raw

And even the default params work on my machine:

body <- simpleHTTP (getRequest $ commentURL arg) >>= getResponseBody
let p = decompress (pack body)
Data.ByteString.Lazy.Char8.putStrLn p

give me

<?xml version="1.0" encoding="UTF-8"?><i><chatserver>chat.bilibili.com</chatserver><chatid>4750304</chatid><mission>...

Note: you can avoid packing the string, add network-uri to your cabal file, add the import Network.URI (parseURI) import and

let Just u = parseURI $ commentURL arg
do
    body <- simpleHTTP (mkRequest GET u) >>= getResponseBody
    let p = decompress body

To work only with ByteStrings.

Upvotes: 2

Related Questions