PHPCon Poland 2024

zlib://

bzip2://

zip://

zlib:// -- bzip2:// -- zip://Flux de compression

Description

compress.zlib:// et compress.bzip2://

zlib: fonctionne comme gzopen(), hormis le fait que le flux peut être utilisé directement avec fread() et les autres fonctions de système de fichiers. Cette notation est obsolète à cause d'ambiguïtés dues aux noms de fichiers contenant des deux points ':'. Utilisez plutôt compress.zlib://.

compress.zlib:// et compress.bzip2:// sont respectivement équivalents à gzopen() et bzopen(), et ils fonctionnent même sur les systèmes qui ne supportent pas fopencookie.

L'extension ZIP fournit l'enveloppe zip:. À partir de PHP 7.2.0 et libzip 1.2.0+, le support des mots de passe pour les archives chiffrées a été ajouté, permettant aux mots de passe d'être fournis par des contextes de flux. Les mots de passe peuvent être définis sur un flux à l'aide de l'option de contexte 'password'.

Utilisation

  • compress.zlib://file.gz
  • compress.bzip2://file.bz2
  • zip://archive.zip#dir/file.txt

Options

Résumé des enveloppes
Attribut Supporté
Limité par allow_url_fopen Non
Autorise la lecture Oui
Autorise l'écriture Oui (sauf zip://)
Autorise l'ajout Oui (sauf zip://)
Autorise la lecture et l'écriture simultanément Non
Support de la fonction stat() Non, utilisez le gestionnaire file:// pour obtenir des informations sur les fichiers compressés.
Support de la fonction unlink() Non, utilisez le gestionnaire file:// pour obtenir des informations sur les fichiers compressés.
Support de la fonction rename() Non
Support de la fonction mkdir() Non
Support de la fonction rmdir() Non

add a note

User Contributed Notes 7 notes

up
18
lewa::cpan.org
7 years ago
One-liners to gzip and ungzip a file:

copy('file.txt', 'compress.zlib://' . 'file.txt.gz');

copy('compress.zlib://' . 'file.txt.gz', 'file.txt');
up
6
feodor at ctm dot ru
8 years ago
Prior to PHP 5.6 i used code like
<?php
file_get_contents
("compress.zlib://php://input");
?>
to read gz-compressed or plain input file. Not it doesn't work.
Simple workaround :
<?php
//file_get_contents("compress.zlib://php://input");

class gzip_header_filter8 extends php_user_filter {
private
$filtered = 0;
public function
filter($in, $out, &$consumed, $closing) {
while (
$bucket = stream_bucket_make_writeable($in)) {
if(
$this->filtered == 0) {
$header_len = 8;
$header = substr($bucket->data, 0, 8);
$flags = ord($header[1]);
if(
$flags & 0x08) {
// a filename is present
$header_len = strpos($bucket->data, "\0", 8) + 1;
}
$bucket->data = substr($bucket->data, $header_len);
$this->filtered = $header_len;
}
$consumed += $bucket->datalen;
stream_bucket_append($out, $bucket);
}
return
PSFS_PASS_ON;
}
}

stream_filter_register('gzip_header_filter8', 'gzip_header_filter8');

$READ_LEN = 64*1024;
$MAX_BUF_LEN = $READ_LEN*1024;

$mode_plain=true;
$src=fopen("php://input","rb"); //test if OK!!!!
$magic_number=fread($src,2);
$input="";
if(
strlen($magic_number)==2)
if(
(
ord($magic_number[0])==31)
&& (
ord($magic_number[1])==139)
)
{
$mode_plain=false;
stream_filter_append($src, "gzip_header_filter8", STREAM_FILTER_READ);
stream_filter_append($src, "zlib.inflate", STREAM_FILTER_READ);
}
else
{
$input=$magic_number;
}

/* read starts here*/
$k = 0;
while (!
feof($src) && $k <= $MAX_BUF_LEN) {
$inp = fread($src,$READ_LEN);
$k += strlen($inp);
$input.=$inp;
}
echo
$input;
fclose($src);
?>
up
11
alvaro at demogracia dot com
13 years ago
Example on how to read an entry from a ZIP archive (file "bar.txt" inside "./foo.zip"):

<?php

$fp
= fopen('zip://./foo.zip#bar.txt', 'r');
if(
$fp ){
while( !
feof($fp) ){
echo
fread($fp, 8192);
}
fclose($fp);
}

?>

Also, apparently, the "zip:" wrapper does not allow writing as of PHP/5.3.6. You can read http://php.net/ziparchive-getstream for further reference since the underlying code is probably the same.
up
1
arava dot box at gmail dot com
4 years ago
This is the solution how to read stream from zip:

$fp = fopen('zip://foo.zip#bar.txt', 'r');
if( $fp ){
while( !feof($fp) ){
echo fread($fp, 8192);
}
fclose($fp);
}
up
3
joshualross at gmail dot com
16 years ago
I had a difficult time finding how to use compress.zlib with an http resource so I thought I would post what I found
<?php
$file
= 'compress.zlib://http://www.example.com/myarchive.gz';
$fr = fopen($file, 'rb');
?>

Per the bugreport I found here (http://bugs.php.net/bug.php?id=29045)
up
0
jdoll at wildwestcyber dot com
22 hours ago
<?php
/**
* Improved version of the original code by feodor at ctm dot ru.
* This version includes security enhancements to handle gzip input streams securely.
*
* Security Patches:
* 1. Input Validation: Checks for valid input lengths and formats.
* 2. Memory Usage Control: Enforces limits on buffer sizes to prevent DoS attacks.
* 3. Decompression Safeguards: Protects against zip bombs by ensuring input size does not exceed limits.
* 4. Input Sanitization: Uses htmlspecialchars() to sanitize output, preventing XSS attacks.
* 5. Graceful Error Handling: Ensures the script exits gracefully on error conditions.
*
* Note: This code is untested.
*/

class gzip_header_filter8 extends php_user_filter {
private
$filtered = 0;
public function
filter($in, $out, &$consumed, $closing) {
while (
$bucket = stream_bucket_make_writeable($in)) {
if (
$this->filtered == 0) {
$header_len = 8;
$header = substr($bucket->data, 0, 8);
$flags = ord($header[1]);
if (
$flags & 0x08) {
// a filename is present
$header_len = strpos($bucket->data, "\0", 8) + 1;
}
$bucket->data = substr($bucket->data, $header_len);
$this->filtered = $header_len;
}
$consumed += $bucket->datalen;
stream_bucket_append($out, $bucket);
}
return
PSFS_PASS_ON;
}
}

// Registering the custom filter
stream_filter_register('gzip_header_filter8', 'gzip_header_filter8');

// Buffer size constants
$READ_LEN = 64*1024;
$MAX_BUF_LEN = $READ_LEN*1024;

$mode_plain = true;
$src = fopen("php://input", "rb");
$magic_number = fread($src, 2);
$input = "";

if (
strlen($magic_number) == 2) {
if ((
ord($magic_number[0]) == 31) && (ord($magic_number[1]) == 139)) {
$mode_plain = false;
stream_filter_append($src, "gzip_header_filter8", STREAM_FILTER_READ);
stream_filter_append($src, "zlib.inflate", STREAM_FILTER_READ);
} else {
$input = $magic_number;
}
} else {
die(
"Invalid input"); // Graceful error handling for invalid input
}

// Reading data from the input stream
$k = 0;
while (!
feof($src) && $k <= $MAX_BUF_LEN) {
$inp = fread($src, $READ_LEN);
if (
$inp === false) {
break;
}
$k += strlen($inp);
if (
$k > $MAX_BUF_LEN) {
die(
"Input size exceeds maximum buffer length"); // Memory usage control
}
$input .= $inp;
}

if (
$k > $MAX_BUF_LEN) {
die(
"Input size exceeds maximum buffer length"); // Additional check for safety
}

// Output the final input data, sanitized to prevent XSS
echo htmlspecialchars($input, ENT_QUOTES, 'UTF-8');
fclose($src);
?>

/**
* Summary of Changes for Improved Security:
*
* 1. **Input Validation:**
* - Added checks to ensure the input data has a valid length and format.
* - Example: `if (strlen($magic_number) == 2) { ... } else { die("Invalid input"); }`
*
* 2. **Memory Usage Control:**
* - Enforced limits on buffer sizes to prevent excessive memory usage.
* - Example: `if ($k > $MAX_BUF_LEN) { die("Input size exceeds maximum buffer length"); }`
*
* 3. **Decompression Safeguards:**
* - Protected against zip bombs by ensuring the decompressed data size stays within limits.
* - Example: Added checks during data reading loop.
*
* 4. **Input Sanitization:**
* - Used `htmlspecialchars()` to sanitize the output and prevent XSS attacks.
* - Example: `echo htmlspecialchars($input, ENT_QUOTES, 'UTF-8');`
*
* 5. **Graceful Error Handling:**
* - Ensured the script exits gracefully on encountering invalid input or buffer limits.
* - Example: `die("Invalid input");` and `die("Input size exceeds maximum buffer length");`
*
* These changes enhance the security of the script, making it more robust and safe for production use.
*
* Note: This code is untested.
*/
up
-20
eragonjml at googlemail dot com
10 years ago
@alvaro at demogracia dot com

well in fact that is wrong!
right code is:

<?php

$fp
= fopen('compress.zip://./foo.zip#bar.txt', 'r');
if(
$fp ){
while( !
feof($fp) ){
echo
fread($fp, 8192);
}
fclose($fp);
}

?>

as you might see you just have to add a "compress."

maybe when you posted this note is was right (2 years ago) but today its wrong... :/

sry for my english i am german :)
To Top