2010-07-08 2 views
4

Je me demande pourquoi je dois couper les 4 derniers caractères, après avoir utilisé gzcompress().Comment fonctionne gzcompress?

Voici mon code:

header("Content-Encoding: gzip"); 
echo "\x1f\x8b\x08\x00\x00\x00\x00\x00"; 
$index = $smarty->fetch("design/templates/main.htm") ."\n<!-- Compressed by gzip -->"; 
$this->content_size = strlen($index); 
$this->content_crc = crc32($index); 
$index = gzcompress($index, 9); 
$index = substr($index, 0, strlen($index) - 4); // Why cut off ?? 
echo $index; 
echo pack('V', $this->content_crc) . pack('V', $this->content_size); 

Quand je ne suis pas coupé des 4 derniers caractères, la source se termine comme:

[...] 
<!-- Compressed by gzip -->N 

Quand je les ai coupé il lit:

[...] 
<!-- Compressed by gzip --> 

Je ne pouvais voir le N supplémentaire que dans l'inspecteur de code de Chromes (pas dans Firefox et pas dans la source IE). Mais il semble y avoir quatre caractères supplémentaires à la fin du code.

Quelqu'un peut-il m'expliquer, pourquoi j'ai besoin de couper 4 caractères?

+1

Pourquoi la dernière ligne? Ne fait pas écho que corrompre le flux compressé? – Artefacto

Répondre

7

gzcompress met en œuvre la ZLIB compressed data format qui a le following structure:

 0 1 
    +---+---+ 
    |CMF|FLG| (more-->) 
    +---+---+ 

(if FLG.FDICT set) 

    0 1 2 3 
    +---+---+---+---+ 
    |  DICTID | (more-->) 
    +---+---+---+---+ 

    +=====================+---+---+---+---+ 
    |...compressed data...| ADLER32 | 
    +=====================+---+---+---+---+ 

Ici, vous voyez que les quatre derniers octets est un Adler-32 checksum.

Contrairement à cela, la GZIP file format une liste des membres de la soi-disant avec la structure suivante:

+---+---+---+---+---+---+---+---+---+---+ 
    |ID1|ID2|CM |FLG|  MTIME  |XFL|OS | (more-->) 
    +---+---+---+---+---+---+---+---+---+---+ 

(if FLG.FEXTRA set) 

    +---+---+=================================+ 
    | XLEN |...XLEN bytes of "extra field"...| (more-->) 
    +---+---+=================================+ 

(if FLG.FNAME set) 

    +=========================================+ 
    |...original file name, zero-terminated...| (more-->) 
    +=========================================+ 

(if FLG.FCOMMENT set) 

    +===================================+ 
    |...file comment, zero-terminated...| (more-->) 
    +===================================+ 

(if FLG.FHCRC set) 

    +---+---+ 
    | CRC16 | 
    +---+---+ 

    +=======================+ 
    |...compressed blocks...| (more-->) 
    +=======================+ 

    0 1 2 3 4 5 6 7 
    +---+---+---+---+---+---+---+---+ 
    |  CRC32  |  ISIZE  | 
    +---+---+---+---+---+---+---+---+ 

Comme vous pouvez le voir, GZIP utilise un CRC-32 checksum pour le contrôle d'intégrité.

Donc, pour analyser votre code:

  • echo "\x1f\x8b\x08\x00\x00\x00\x00\x00"; - met les champs d'en-tête suivants:
    • 0x1f 0x8b - ID1 et ID2, identifiants pour identifier le format de données (celles-ci sont des valeurs fixes)
    • 0x08 - CM, méthode de compression utilisée; 8 désigne l'utilisation du DEFLATE data compression format (RFC 1951)
    • 0x00 - FLG, drapeaux
    • 0x00000000 - Mtime, modification du temps
    • les champs XFL (flags supplémentaires) et OS (système d'exploitation) sont fixés par le format de compression de données DEFLATE
  • echo $index; - met à données compressées selon le format de compression de données DEFLATE
  • echo pack('V', $this->content_crc) . pack('V', $this->content_size); - met à la somme de contrôle CRC-32 et la taille des données d'entrée non compressés en binaire
+1

Akk. Pour plus d'informations sur le format gzip. – JochenJung

2

gzcompress produit une sortie décrite ici RFC1950, les 4 derniers octets que vous coupez sont la somme de contrôle adler32. C'est l'encodage "deflate", donc vous devriez juste mettre "Content-Encoding: deflate" et ne rien manipuler. Si vous voulez utiliser gzip, utilisez gzencode(), qui utilise le gzip format.

+0

Pouvez-vous comprendre quel est le dernier écho? Pourquoi retire-t-il une somme de contrôle pour en ajouter une autre (bien que différente)? Pourquoi at-il ajouté la longueur? Est-ce un autre format? – Artefacto

+0

Il semble qu'il essaie d'émuler gzip en faisant écho à un en-tête gzip et en ajoutant le crc32 et la longueur (selon la spécification gzip). – nos

+0

Bon point. Les "N" coutures à venir de la dernière ligne. Pas le gzcompress(). Si je commente la dernière ligne et la ligne 4-char-cut-off, il n'y a pas de sortie supplémentaire. A propos de la raison pour laquelle ces lignes sont là, je ne sais pas. Le code provient d'une personne qui travaille sur le même projet avant moi, alors j'essaie de comprendre aussi, pourquoi ces lignes sont là. Vous voulez dire que cela produit un encodage de dégonflement? Je suppose que je serai meilleur avec gzencode() alors. – JochenJung