<?phpfunction hex2char($matches){ return chr(hexdec('0x' . $matches[1]));}class II_Xml_Filter extends php_user_filter { private $buffer; private $boundary = "\n"; // boundary string /** * This method is called on fwrite, fread, etc * * @param bucket_brigade $in * @param bucket_brigade $out * @param integer $consumed * @param boolean $closing * @return integer PSFS_* constants */ function filter($in, $out, &$consumed, $closing) { /** * We must create the bucket buffer here because contructor is never called * (this gets instantiated internally within PHP and constructor is not automatically called) * * onCreate() can't be used either, because $this->stream is not available then */ if(!$this->buffer){ $this->buffer = stream_bucket_new($this->stream, ''); } while ($bucket = stream_bucket_make_writeable($in)) { // the last "safe" position for replacement $lastBoundary = strripos($bucket->data, $this->boundary); if($lastBoundary === false){ // boundary not found, buffer the bucket and FEED ME more data! $this->buffer->data .= $bucket->data; return PSFS_FEED_ME; }else{ $lastBoundary += strlen($this->boundary); } // buffer + chars from bucket up until (and including) the last boundary string $toReplace = $this->buffer->data . substr($bucket->data, 0, $lastBoundary); // characters from the last boundary string to the end of the bucket data $this->buffer->data = substr($bucket->data, $lastBoundary); // do string replace $bucket->data = $this->replace($toReplace); // ?? no idea if this is correct :-/ $consumed += strlen($toReplace); // stick it into the out brigade stream_bucket_append($out, $bucket); } // this is the last time through, so flush the buffer onto the output brigade if($closing && $this->buffer->data){ $this->buffer->data = $this->replace($this->buffer->data); stream_bucket_append($out, $this->buffer); } // pass on to the next filter return PSFS_PASS_ON; } function replace($str) { return preg_replace_callback('/_x([a-f0-9]{4})_/iu', 'hex2char', $str); }}// usage:-$filename = 'output.txt';stream_filter_register("II_Xml_Filter", "II_Xml_Filter");$fp = fopen($filename, "w");if($fp){ stream_filter_append($fp, "II_Xml_Filter"); // cross boundary test fwrite($fp, "o_x0021_o_x0"); fwrite($fp, "021_o\n"); fclose($fp); readfile($filename);}else{ echo 'could not open ', $filename;}