J'ai créé des données compressées zlib en Python, comme ceci:
import zlib
s = '...'
z = zlib.compress(s)
with open('/tmp/data', 'w') as f:
f.write(z)
(ou one-liner dans Shell: echo -n '...' | python2 -c 'import sys,zlib; sys.stdout.write(zlib.compress(sys.stdin.read()))' > /tmp/data
)
Maintenant, je veux décompresser les données dans Shell. Ni zcat
ni uncompress
ne fonctionnent:
$ 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
Il semble que j'ai créé un fichier de type gzip, mais sans en-tête. Malheureusement, je ne vois aucune option pour décompresser ces données brutes dans la page de manuel de gzip, et le paquet zlib ne contient aucun utilitaire exécutable.
Existe-t-il un utilitaire pour décompresser les données zlib brutes?
Il est également possible de le décompresser en utilisant le standard Shell-script + gzip , si vous n'en avez pas, ou souhaitez utiliser openssl ou autre outils.
L'astuce consiste à ajouter le nombre magique gzip et méthode de compression aux données réelles de zlib.compress
:
printf "\x1f\x8b\x08\x00\x00\x00\x00\x00" |cat - /tmp/data |gzip -dc >/tmp/out
Modifications:
@ d0sboots a commenté: Pour les données RAW Deflate, vous devez ajouter 2 octets nuls supplémentaires:
→ "\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\x00"
Ce Q sur SO donne plus d'informations sur cette approche. Une réponse suggère qu'il existe également un pied de page de 8 octets.
Les utilisateurs @ Vitali-Kushner et @ mark-bessey ont rapporté le succès même avec des fichiers tronqués, donc un pied de page gzip ne semble pas strictement requis.
@ tobias-kienzler a proposé cette fonction pour bashrc :zlipd() (printf "\x1f\x8b\x08\x00\x00\x00\x00\x00" |cat - $@ |gzip -dc)
zlib-flate -uncompress < FILE
J'ai essayé cela et cela a fonctionné pour moi.
zlib-flate
peut être trouvé dans le paquet qpdf
(dans Debian Squeeze et Fedora 23, selon les commentaires dans d'autres réponses)
(Merci à l'utilisateur @tino qui a fourni ceci en tant que commentaire sous la réponse OpenSSL. Fabriqué en réponse propper pour un accès facile.)
J'ai trouvé une solution (l'une des possibles), elle utilise openssl:
$ openssl zlib -d < /tmp/data
ou
$ openssl zlib -d -in /tmp/data
* REMARQUE: la fonctionnalité zlib est apparemment disponible dans les versions récentes d'OpenSL> = 1.0.0 (OpenSSL doit être configuré/construit avec l'option zlib ou zlib-dynamic, cette dernière est par défaut)
Je recommande pigz de Mark Adler , co-auteur de la bibliothèque de compression zlib. Exécutez pigz
pour voir les indicateurs disponibles.
Tu remarqueras:
-z --zlib Compress to zlib (.zz) instead of gzip format.
Vous pouvez décompresser en utilisant le -d
drapeau:
-d --decompress --uncompress Decompress the compressed input.
En supposant un fichier nommé 'test':
pigz -z test
- crée un fichier compressé zlib nommé test.zzpigz -d -z test.zz
- convertit test.zz en fichier de test décompresséSur OSX, vous pouvez exécuter brew install pigz
Cela pourrait le faire:
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)
Ensuite, exécutez-le comme ceci:
$ python expander.py data/*
Sur macOS, qui est un UNIX complet compatible POSIX (officiellement certifié!), OpenSSL
ne prend pas en charge zlib
, il n'y a pas non plus zlib-flate
Et même si la première solution fonctionne également comme toutes les solutions Python, la première solution nécessite que les données Zip soient dans un fichier et toutes les autres solutions vous obligent à créer un script Python.
Voici une solution basée sur Perl qui peut être utilisée comme une ligne de commande, obtient son entrée via un tuyau STDIN et qui fonctionne immédiatement avec un macOS fraîchement installé:
cat file.compressed | Perl -e 'use Compress::Raw::Zlib;my $d=new Compress::Raw::Zlib::Inflate();my $o;undef $/;$d->inflate(<>,$o);print $o;'
Mieux formaté, le script Perl ressemble à ceci:
use Compress::Raw::Zlib;
my $decompressor = new Compress::Raw::Zlib::Inflate();
my $output;
undef $/;
$decompressor->inflate(<>, $output);
print $output;
L'exemple de programme zpipe.c
trouvé ici par Mark Adler lui-même (fourni avec la distribution source de la bibliothèque zlib) est très utile pour ces scénarios avec des données zlib brutes. Compiler avec cc -o zpipe zpipe.c -lz
et pour décompresser: zpipe -d < raw.zlib > decompressed
. Il peut également effectuer la compression sans le -d
drapeau.
Vous pouvez l'utiliser pour compresser avec zlib:
openssl enc -z -none -e < /file/to/deflate
Et ceci pour dégonfler:
openssl enc -z -none -d < /file/to/deflate
Pendant le développement du code lié à eIDAS, j'ai trouvé un script bash, qui décode le paramètre SAMLRequest SSO (SingleSignOn), qui est généralement codé par base64 et raw-deflate (php gzdeflate)
#!/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
Vous pouvez l'utiliser comme
> decode_saml_request.sh /path/to/file_with_sso_url
# or
> echo "y00tLk5MT1VISSxJBAA%3D" | decode_saml_request.sh
Le script est également publié sous le nom de Gist ici: https://Gist.github.com/smarek/77dacb9703ac8b715b5eced5314d5085 donc je ne peux pas maintenir cette réponse mais je maintiendrai le Gist source