At long last we come to the end (hopefully) of the MagpieRSS and PHP 4.3.2 saga, the good guys win, the bad guys unforunatley got away and will live to program again, but for now all is peaceful. Look for MagpieRSS 0.5.2 later this evening.

When using fread() on a network stream, it must be called in a loop

When reading from network streams or pipes reading will stop after a packet is available. – PHP Manual: fread

The documentation goes on to say, “when reading from network streams or pipes, you should collect the data together in chunks”. There, could it be any clearer!

Migration Headache

Why yes, yes it could. You see, it didn’t used to be like that. I’m not sure how long the documentation has been changed, but until recently fread() was quite content to read past the end of a packet until you had all the information you asked for. Migration is complicated by the fact that this new behaviour happens very very quietly, and seemingly sporadically. You would never know anything had changed until your XML started showing up mangled causing only the first item in an RSS feed to show up, or your gzip encoded data was delivered improperly formatted causing gzinflate(): buffer errors (to choose 2 hypothetical example).

And then of course there is the, ahem, questionable “example” of using fread() with a network socket one finds in the fread documentation.. (more on that later)

Steve Minutillo

But first, I’d like to go on record and say Steve is the genius, and a very nice person who figured this all out. I was still stuck swearing at expat, and then on a clue from Steve I was swearing at PHP’s bundled zlib. Neither of whom were to blame. It was Snoopy’s old style fread() usage, compounded by my gzip encoding hack. (Here is a patch to make the upstream Snoopy work with 4.3.2)

Now Back to Trashing PHP

Okay, what the hell is up with that example in the manual? We’re going to play a game, called “how many really really egregious bugs can you spot in this code”. No, poor style doesn’t count as a bug (but icky C inspired examples are a perfectly valid reason to stake someone over an anthill)


<?php
$handle = fopen ("http://www.php.net/", "rb");
$contents = "";
do {
    $data = fread ($handle, filesize ($filename));
    if (strlen($data) == 0) {
        break;
    }
    $contents .= $data;
}
fclose ($handle);
?>

I count 2, plus a minor one. And while I’ll be the first to admit PHP is not my best language, can someone tell me what is wrong with the much simpler, or are they just trying to trip people?


while ( $data = fread($handle, 10240) ) {
    $results .= $data;

}

So yeah if you’ve upgraded to 4.3.2 and you’re seeing cropped data, make sure you (or the library you depend upon) has been updated for the new, stricter fread regime.