it-swarm.com.de

Wie dekomprimiere ich zlib-Daten unter UNIX?

Ich habe zlib-komprimierte Daten in Python wie folgt erstellt:

import zlib
s = '...'
z = zlib.compress(s)
with open('/tmp/data', 'w') as f:
    f.write(z)

(oder Einzeiler in Shell: echo -n '...' | python2 -c 'import sys,zlib; sys.stdout.write(zlib.compress(sys.stdin.read()))' > /tmp/data)

Jetzt möchte ich die Daten in Shell dekomprimieren. Weder zcat noch uncompress funktionieren:

$ cat /tmp/data | gzip -d -
gzip: stdin: not in gzip format

$ zcat /tmp/data 
gzip: /tmp/data.gz: not in gzip format

$ cat /tmp/data | uncompress -
gzip: stdin: not in gzip format

Es scheint, dass ich eine gzip-ähnliche Datei erstellt habe, aber ohne Header. Leider sehe ich keine Möglichkeit, solche Rohdaten in der gzip-Manpage zu dekomprimieren, und das zlib-Paket enthält kein ausführbares Dienstprogramm.

Gibt es ein Dienstprogramm zum Dekomprimieren von zlib-Rohdaten?

121
mykhal

Es ist auch möglich, es mit Standard Shell-Skript + gzip zu dekomprimieren, wenn Sie openssl oder ein anderes nicht haben oder verwenden möchten Werkzeuge.
Der Trick besteht darin, den tatsächlichen Daten aus zlib.compress Das gzip magic number and compress method voranzustellen:

printf "\x1f\x8b\x08\x00\x00\x00\x00\x00" |cat - /tmp/data |gzip -dc >/tmp/out

Bearbeitungen:
@ D0sboots kommentiert: Für RAW Deflate-Daten müssen Sie 2 weitere Null-Bytes hinzufügen:
"\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\x00"

Dieses Q zu SO enthält weitere Informationen zu diesem Ansatz. Eine Antwort dort deutet darauf hin, dass es auch eine 8-Byte-Fußzeile gibt.

Die Benutzer @ Vitali-Kushner und @ mark-bessey meldeten auch bei abgeschnittenen Dateien Erfolge, sodass eine gzip-Fußzeile nicht unbedingt erforderlich zu sein scheint.

@ tobias-kienzler schlug diese Funktion für bashrc vor:
zlipd() (printf "\x1f\x8b\x08\x00\x00\x00\x00\x00" |cat - [email protected] |gzip -dc)

146
wkpark
zlib-flate -uncompress < FILE

Ich habe es versucht und es hat bei mir funktioniert.

zlib-flate finden Sie im Paket qpdf (in Debian Squeeze und Fedora 23, laut Kommentaren in anderen Antworten)

(Vielen Dank an den Benutzer @tino, der dies als Kommentar unter der OpenSSL-Antwort angegeben hat. In die richtige Antwort für den einfachen Zugriff umgewandelt.)

81
Catskul

Ich habe eine Lösung gefunden (eine der möglichen), sie verwendet openssl:

$ openssl zlib -d < /tmp/data

oder

$ openssl zlib -d -in /tmp/data

* HINWEIS: Die zlib-Funktionalität ist anscheinend in den letzten openssl-Versionen> = 1.0.0 verfügbar (OpenSSL muss mit der Option zlib oder zlib-dynamic konfiguriert/erstellt werden, letztere ist Standard).

63
mykhal

Ich empfehle pigz von Mark Adler , Co-Autor der zlib-Komprimierungsbibliothek. Führen Sie pigz aus, um die verfügbaren Flags anzuzeigen.

Du wirst bemerken:

-z --zlib Compress to zlib (.zz) instead of gzip format.

Sie können mit dem Flag -d Dekomprimieren:

-d --decompress --uncompress Decompress the compressed input.

Angenommen, eine Datei mit dem Namen 'test':

  • pigz -z test - Erstellt eine zlib-komprimierte Datei mit dem Namen test.zz
  • pigz -d -z test.zz - konvertiert test.zz in die dekomprimierte Testdatei

Unter OSX können Sie brew install pigz Ausführen.

30
snodnipper

zlib implementiert die von gzip verwendete Komprimierung, jedoch nicht das Dateiformat. Verwenden Sie stattdessen das Modul gzip , das selbst zlib verwendet.

import gzip
s = '...'
with gzip.open('/tmp/data', 'w') as f:
    f.write(s)
11
Jeremy Banks

Dies könnte es tun:

import glob
import zlib
import sys

for filename in sys.argv:
    with open(filename, 'rb') as compressed:
        with open(filename + '-decompressed', 'wb') as expanded:
            data = zlib.decompress(compressed.read())
            expanded.write(data)

Führen Sie es dann folgendermaßen aus:

$ python expander.py data/*
3
Jeremy Banks

Unter macOS, einem vollständig POSIX-kompatiblen UNIX (formal zertifiziert!), Unterstützt OpenSSL keine zlib, es gibt auch keinen zlib-flate, Und während die erste Lösung ebenfalls funktioniert Wie bei allen Python - Lösungen müssen sich bei der ersten Lösung die Zip-Daten in einer Datei befinden, und bei allen anderen Lösungen müssen Sie ein Python - Skript erstellen.

Hier ist eine Perl-basierte Lösung, die als Einzeiler für die Befehlszeile verwendet werden kann, ihre Eingabe über die STDIN-Pipe erhält und mit einem frisch installierten MacOS sofort funktioniert:

cat file.compressed | Perl -e 'use Compress::Raw::Zlib;my $d=new Compress::Raw::Zlib::Inflate();my $o;undef $/;$d->inflate(<>,$o);print $o;'

Das Perl-Skript ist besser formatiert und sieht folgendermaßen aus:

use Compress::Raw::Zlib;
my $decompressor = new Compress::Raw::Zlib::Inflate();
my $output;
undef $/;
$decompressor->inflate(<>, $output);
print $output;
3
Mecki

Das Beispielprogramm zpipe.chier zu finden von Mark Adler selbst (im Lieferumfang der Quelldistribution der zlib-Bibliothek enthalten) ist für diese Szenarien mit zlib-Rohdaten sehr nützlich. Kompilieren Sie mit cc -o zpipe zpipe.c -lz Und dekomprimieren Sie: zpipe -d < raw.zlib > decompressed. Die Komprimierung kann auch ohne das Flag -d Durchgeführt werden.

3
Henno Brandsma

Sie können dies verwenden, um mit zlib zu komprimieren:

openssl enc -z -none -e < /file/to/deflate

Und das zu entleeren:

openssl enc -z -none -d < /file/to/deflate
1
Danny R

Während der Entwicklung von eIDAS-bezogenem Code habe ich ein Bash-Skript entwickelt, das den SSL (SingleSignOn) SAMLRequest-Parameter dekodiert, der normalerweise von base64 und raw-deflate (php gzdeflate) codiert wird.

#!/bin/bash
# file decode_saml_request.sh

urldecode() { : "${*//+/ }"; echo -e "${_//%/\\x}"; }

if [[ $contents == *"SAMLRequest" ]]; then
  # extract param SAMLRequest from URL, strip all following params
  contents=$(cat ${1} | awk -F 'SAMLRequest=' '{print $2}' | awk -F '&' '{print $1}')
else
  # work with raw base64 encoded string
  contents=$(cat ${1})
fi

# add gzip raw-deflate header bytes and gunzip (`gzip -dc` can be replaced by `gunzip`)
printf "\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\x00" | cat - <(echo `urldecode $contents` | base64 -d) | gzip -dc

Sie können es wie verwenden

> decode_saml_request.sh /path/to/file_with_sso_url
# or
> echo "y00tLk5MT1VISSxJBAA%3D" | decode_saml_request.sh

Das Skript wird hier auch als Gist veröffentlicht: https://Gist.github.com/smarek/77dacb9703ac8b715b5eced5314d5085 Daher kann ich diese Antwort möglicherweise nicht beibehalten, aber ich werde den Quell-Gist beibehalten

0
Marek Sebera