Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>Looking through <a href="http://svn.php.net/viewvc/php/php-src/trunk/ext/zlib/zlib_filter.c?revision=316627&amp;view=markup" rel="nofollow">the C source code</a>, the problem is that the filter always lets <a href="http://zlib.net/manual.html#Basic" rel="nofollow">zlib's <code>deflate()</code> function</a> decide how much data to accumulate before producing compressed output. The deflate filter does not create a new data bucket to pass on unless <code>deflate()</code> outputs some data (see line 235) or the <code>PSFS_FLAG_FLUSH_CLOSE</code> flag bit is set (line 250). That's why you only see the header bytes until you close <code>$in</code>; the first call to <code>deflate()</code> outputs the two header bytes, so <code>data-&gt;strm.avail_out</code> is 2 and a new bucket is created for these two bytes to pass on.</p> <p>Note that <code>fflush()</code> does not work because of a known issue with the zlib filter. See: <a href="https://bugs.php.net/bug.php?id=48725" rel="nofollow">Bug #48725 Support for flushing in zlib stream</a>.</p> <p>Unfortunately, there does not appear to be a nice work-around to this. I started writing a filter in PHP by extending <code>php_user_filter</code>, but quickly ran into the problem that <code>php_user_filter</code> does not expose the flag bits, only whether <code>flags &amp; PSFS_FLAG_FLUSH_CLOSE</code> (the fourth parameter to the <code>filter()</code> method, a boolean argument commonly named <code>$closing</code>). You would need to modify the C sources yourself to fix Bug #48725. Alternatively, re-write it.</p> <p>Personally I would consider re-writing it because there seems to be a few eyebrow-raising issues with the code:</p> <ul> <li><code>status = deflate(&amp;(data-&gt;strm), flags &amp; PSFS_FLAG_FLUSH_CLOSE ? Z_FULL_FLUSH : (flags &amp; PSFS_FLAG_FLUSH_INC ? Z_SYNC_FLUSH : Z_NO_FLUSH));</code> seems odd because when writing, I don't know why <code>flags</code> would be anything other than <code>PSFS_FLAG_NORMAL</code>. Is it possible to write &amp; flush at the same time? In any case, handling the flags should be done outside of the <code>while</code> loop through the "in" bucket brigade, like how <code>PSFS_FLAG_FLUSH_CLOSE</code> is handled outside of this loop.</li> <li><p>Line 221, the <code>memcpy</code> to <code>data-&gt;strm.next_in</code> seems to ignore the fact that <code>data-&gt;strm.avail_in</code> may be non-zero, so the compressed output might skip some data of a write. See, for example, the following text from the zlib manual:</p> <blockquote> <p>If not all input can be processed (because there is not enough room in the output buffer), <code>next_in</code> and <code>avail_in</code> are updated and processing will resume at this point for the next call of <code>deflate()</code>.</p> </blockquote> <p>In other words, it is possible that <code>avail_in</code> is non-zero.</p></li> <li>The <code>if</code> statement on line 235, <code>if (data-&gt;strm.avail_out &lt; data-&gt;outbuf_len)</code> should probably be <code>if (data-&gt;strm.avail_out)</code> or perhaps <code>if (data-&gt;strm.avail_out &gt; 2)</code>.</li> <li><s>I'm not sure why <code>*bytes_consumed = consumed;</code> isn't <code>*bytes_consumed += consumed;</code>. The example streams at <a href="http://www.php.net/manual/en/function.stream-filter-register.php" rel="nofollow">http://www.php.net/manual/en/function.stream-filter-register.php</a> all use <code>+=</code> to update <code>$consumed</code>.</s></li> </ul> <p><strong>EDIT:</strong> <code>*bytes_consumed = consumed;</code> is correct. <a href="http://svn.php.net/viewvc/php/php-src/trunk/ext/standard/filters.c?revision=316627&amp;view=markup" rel="nofollow">The standard filter implementations</a> all use <code>=</code> rather than <code>+=</code> to update the <code>size_t</code> value pointed to by the fifth parameter. Also, even though <code>$consumed += ...</code> on the PHP side effectively translates to <code>+=</code> on the <code>size_t</code> (see lines 206 and 231 of <a href="http://svn.php.net/viewvc/php/php-src/trunk/ext/standard/user_filters.c?revision=316627&amp;view=markup" rel="nofollow"><code>ext/standard/user_filters.c</code></a>), the native filter function is called with either a <code>NULL</code> pointer or a pointer to a <code>size_t</code> set to 0 for the fifth argument (see lines 361 and 452 of <a href="http://svn.php.net/viewvc/php/php-src/trunk/main/streams/filter.c?revision=316627&amp;view=markup" rel="nofollow"><code>main/streams/filter.c</code></a>).</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload