CascadeStudio icon indicating copy to clipboard operation
CascadeStudio copied to clipboard

Recreating code deflation and inflation in other languages

Open mayjs opened this issue 2 years ago • 1 comments

I'm trying to create a simple Python script that can take a local file and open it using CascadeStudio. My idea was to encode the file in the same format CascadeStudio uses and building a URL with that.

Encoding the parameter from python did not work (Trying to compress through zlib, encoding as base64 and then apply url encoding), so I set out to try and decode the code parameter value for the default code:

import urllib.parse
import base64
import zlib

url_data = "lZPbahsxEIbv%2FRRj3zgGpd4cXGhLbmqnJNCSEKe0TciFKo28IrJmkbSJ8%2FYdaX3CFEqXPfyaw6fZ2dnxGH6gU7RESARTGZXUCPPUakt9ALjCgCD5ijmkjWhaB6b1Klny8WNvPAa4D9JHJxMejQTcUVqruZKuiG82BApZffeclcXMGsNkr0rAtU8YIhbm0agwP9OqMJqaw7KavjnrNRbMlHyx3eMqnc2yuiX3ttgm3xgTMWX75SqFVu8Vpvct%2BELupchb25TnVzIlr2C%2BWOcwXeoFxrJrLZdc9GZdQubObmqqUT3%2F7qrOdV37pi2oWaBG02uurcc4qMnhndS2jXCxyR90hoGAswoEnObbeTX61GXE0gTIx8WmI5PszU617stDdv7t2DZut3HeoRLAjcADyq9MWX%2FCx0qciOpJwIdK%2FItygPm5j2HIf2B6u2niAoDPSU7eG5iuHQIet7uJXf07%2BfB0iDs%2BnRTgeQauZ2dwZfu57e%2FZ8%2B6E%2FUMerkhOxmFJ5488Iz9MYCgs%2BA35J2naWINdNhR4nIACkDrWaKznVaxlgxGs57io0OO8M%2FBSag2pxmXW%2FIRXCs%2BxkQr7fwA%3D&gui=q1ZKzs8tyM9LzSvxS8xNVbJSSk4sTk5MSQ3LTC1X0lHyTS3OCEotVrIy0DPUUXJOTM5ItVeyKikqTdVRci%2FKL81LCchJzEMWy0yBc4ISUzJLgXqNDWoB"

binary_data = base64.b64decode(urllib.parse.unquote(url_data))

code = zlib.decompress(binary_data)

This will always fail on the decompression step with zlib.error: Error -3 while decompressing data: incorrect header check. It seems like other people have also come across this issue with js-deflate: https://github.com/dankogai/js-deflate/issues/15 .

Any tips on how to get this to work? If this really is an issue js-deflate, would you consider switching to a different compression library or do you want to keep compatibility with old URLs between versions?

mayjs avatar Jun 16 '22 16:06 mayjs

(For reference, these are the calls into RawInflate and RawDeflate: https://github.com/zalo/CascadeStudio/blob/master/js/MainPage/CascadeMain.js#L631-L634 )

It’s been a while since I dug into this, but I think you’re on the right track with the headers missing. iirc the benefit of doing it “Raw” means saving space by leaving out the headers (which would otherwise just describe the default parameters of the inflate/deflate algorithm).

This stackoverflow answer suggests using a negative argument with zlib to avoid the header error: https://stackoverflow.com/questions/1089662/python-inflate-and-deflate-implementations

zalo avatar Jul 08 '22 06:07 zalo

Thanks for your answer! I finally had some time to take a look at this again. You are right, the StackOverflow answer contains exactly the right snippet.

For reference, if you want to decode either the code or GUI parameter you can use something like this:

import urllib.parse
import base64
import zlib

url_data = "lZPbahsxEIbv%2FRRj3zgGpd4cXGhLbmqnJNCSEKe0TciFKo28IrJmkbSJ8%2FYdaX3CFEqXPfyaw6fZ2dnxGH6gU7RESARTGZXUCPPUakt9ALjCgCD5ijmkjWhaB6b1Klny8WNvPAa4D9JHJxMejQTcUVqruZKuiG82BApZffeclcXMGsNkr0rAtU8YIhbm0agwP9OqMJqaw7KavjnrNRbMlHyx3eMqnc2yuiX3ttgm3xgTMWX75SqFVu8Vpvct%2BELupchb25TnVzIlr2C%2BWOcwXeoFxrJrLZdc9GZdQubObmqqUT3%2F7qrOdV37pi2oWaBG02uurcc4qMnhndS2jXCxyR90hoGAswoEnObbeTX61GXE0gTIx8WmI5PszU617stDdv7t2DZut3HeoRLAjcADyq9MWX%2FCx0qciOpJwIdK%2FItygPm5j2HIf2B6u2niAoDPSU7eG5iuHQIet7uJXf07%2BfB0iDs%2BnRTgeQauZ2dwZfu57e%2FZ8%2B6E%2FUMerkhOxmFJ5488Iz9MYCgs%2BA35J2naWINdNhR4nIACkDrWaKznVaxlgxGs57io0OO8M%2FBSag2pxmXW%2FIRXCs%2BxkQr7fwA%3D&gui=q1ZKzs8tyM9LzSvxS8xNVbJSSk4sTk5MSQ3LTC1X0lHyTS3OCEotVrIy0DPUUXJOTM5ItVeyKikqTdVRci%2FKL81LCchJzEMWy0yBc4ISUzJLgXqNDWoB"

binary_data = base64.b64decode(urllib.parse.unquote(url_data)) # binary_data is the deflated binary representation of the parameter (i.e. the compressed code or JSON GUI descriptor). This does NOT contain a header but only the compressed data.
decompressed = zlib.decompress(binary_data, wbits=-zlib.MAX_WBITS) # decompressed contains the the code or JSON object in binary form, you can further decode this using .decode("utf-8") 

If you need to encode a code or GUI parameter you can do this:

import urllib.parse
import base64
import zlib

text_to_encode = '{"componentName":"cascadeView","MeshRes":0.1,"Cache?":true,"GroundPlane?":true,"Grid?":true}' # This is an example gui parameter, but it could just as well be code

compressobj = zlib.compressobj(wbits=-zlib.MAX_WBITS) # Compress without a header by setting a negative wbits value
compressobj.compress(text_to_encode.encode("utf-8"))
compressed = compressobj.flush()
encoded = base64.b64encode(compressed)
url_compatible = urllib.parse.quote(encoded)

mayjs avatar Aug 13 '22 20:08 mayjs

I’m glad it helped!

zalo avatar Aug 13 '22 23:08 zalo