Question Daniel Raderstrong 路 Apr 18, 2024

Need to decompress string compressed with zlib. Can I manually add the "customized wrapper" intersystems requires for $System.Util.Decompress()

Hi,

We're getting a string sent to us by a client that was compressed using a java deflater (the zlib algorithm) and when trying to use $System.Util.Decompress() I get an "illegal value" error. I gather from other community posts that this is because the raw compressed string is missing the customized wrapper Iris automatically adds. I know this has been a longstanding issue for a while...just wanted to check if there'd been any updates to this functionality, or successful workarounds for decompressing raw zlib compressed data. Thanks in advance!

Product version: IRIS 2023.3
$ZV: IRIS for UNIX (Red Hat Enterprise Linux 8 for x86-64) 2022.1 (Build 209_0_22062U ) Fri Dec 9 2022 10:20:46 EST

Comments

Daniel Raderstrong  Apr 19, 2024 to Enrico Parisi

Hi thanks! In the previous post you said "Unfortunately Decompress() needs the custom wrapper, and I don't know how to make it up" which is what I'd be looking to do. I need to decompress raw contents. So is there a way to add that wrapper? Or some other workaround to to accomplish this? 
Appreciate the quick reply!

0
Enrico Parisi  Apr 19, 2024 to Daniel Raderstrong

If I understand correctly you need to deflate and I suppose you want to add the custom wrapper to use $System.Util.Decompress(), if so...you can't. I mean you can't use $System.Util.Decompress() BUT, you can indeed deflate using I/O as in the example I posted in that post/thread.

0
Enrico Parisi  Apr 19, 2024 to Daniel Raderstrong

Here is a sample method to deflate without using file I/O and using XDEV instead.

ClassMethod UnDeflate(Compressed As %String, Output UnDeflated As %String) As %Status
{
    Set sc=$$$OK
    Try {
        ; open XDEV device
        Set dev="|XDEV|"_+$JOB
        Open dev:($ZF(-6,$$$XSLTLibrary,12):/HOSTNAME="XSLT") Use dev
        ; write compressed string
        Write Compressed
        ; flush buffers
        Write *-3
        ; change device mode to deflate and rewind
        Use dev:(:/COMPRESS="DEFLATE":/POSITION=0)
        ; read uncompressed content
        Read UnDeflated
    } Catch CatchError {
        #dim CatchError as %Exception.SystemException
        Set sc=CatchError.AsStatus()
    }
    Close dev
    Quit sc
}

I really wish that InterSystems implement the various compress/deflate/gzip functionality available in device I/O as utility methods. Without silly wrappers! 馃槈

Another wish, please InterSystems document XDEV device I/O.

0
Daniel Raderstrong 路 Apr 19, 2024

Thank you! So we already have the deflated data sent to us from a client in an http header - we need to decompress it only (not compress it). It seems like this is not possible, but I appreciate you confirming! We're looking into pulling in a python library for the decompression. 

Agreed it would be nice for intersystems to add this for generic zlib compression/decmopression

0
Enrico Parisi  Apr 19, 2024 to Daniel Raderstrong

The code I posted does exactly what you need.

You can compress/decompress with deflate or gzip using device I/O.

0
Daniel Raderstrong 路 Apr 19, 2024

Oh thank you for clarifying! When trying to implement this code we're getting a <WRITE> error at zUnDeflate + 7, the line "Write Compressed" - have you ever experienced that before?

0
Enrico Parisi  Apr 19, 2024 to Daniel Raderstrong
EPTEST>Set comp=$system.Encryption.Base64Decode("y61UKEstqlTIyc9LVyguKcoEUuUZmckZCnmpqSnFCiX5CkmpCimpaTmJJakpAA==")
 
EPTEST>Set sc=##class(Community.Compress).UnDeflate(comp,.uncomp)
 
EPTEST>Write uncomp
my very long string which needs to be deflated

Works fine for me

0
Daniel Raderstrong  Apr 22, 2024 to Enrico Parisi

Thank you for verifying - when we run it from terminal using the string you provided we get an "End of File" error. Maybe this means our systems our configured differently?

Regardless thank you for the quick responses and information!

0
Lynn Lantz 路 Jun 11, 2025

Just dropping this here because I spent DAYS try to figure out how to get PDF to read a zlib from Intersystems.

You'll see code above to use $e(string,4,*-5) to make it "deflate" but PDF wants ZLIB.

The issue turned out to be that Intersystems adds a first # character and a last character around the zlib compression.

If you do this:

S pdfcompress=$E($System.Util.Compress(instring,"zlib"),2,*-1) ; remove first and last character

THEN the pdf reader properly reads and processes that in the stream object (when using /FlateDecode)

Wasted days just because of 2 added characters.  Hope this helps someone else.

0