<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>code-diesel &#187; streams</title>
	<atom:link href="http://www.codediesel.com/tag/streams/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.codediesel.com</link>
	<description>/* PHP &#38; MySQL Journal */</description>
	<lastBuildDate>Thu, 02 Feb 2012 13:19:04 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
<xhtml:meta xmlns:xhtml="http://www.w3.org/1999/xhtml" name="robots" content="noindex" />
		<item>
		<title>Creating custom stream filters</title>
		<link>http://www.codediesel.com/php/creating-custom-stream-filters/</link>
		<comments>http://www.codediesel.com/php/creating-custom-stream-filters/#comments</comments>
		<pubDate>Mon, 15 Jun 2009 13:49:47 +0000</pubDate>
		<dc:creator>sameer</dc:creator>
				<category><![CDATA[php]]></category>
		<category><![CDATA[streams]]></category>

		<guid isPermaLink="false">http://www.codediesel.com/?p=1001</guid>
		<description><![CDATA[php custom stream filter tutorial]]></description>
			<content:encoded><![CDATA[<p>In this post we will see how to create a custom stream filter. <em>Streams</em>, first introduced in PHP 4.3, provide an abstration layer for file access. A number of different resources besides files &#8211; like network connections, compression protocols etc. can be regarded as &#8220;streams&#8221; of data which can be serially read and written to.<br />
<span id="more-1001"></span></p>
<p>By default there are a number of filters registered with PHP. You can get the list of filters registered on your system by the following call:</p>

<div class="wp_codebox"><table><tr id="p10011"><td class="code" id="p1001code1"><pre class="php" style="font-family:monospace;"><span style="color: #990000;">print_r</span> <span style="color: #009900;">&#40;</span><span style="color: #990000;">stream_get_filters</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></td></tr></table></div>

<p>On my system it returns the following registered filters.</p>

<div class="wp_codebox"><table><tr id="p10012"><td class="code" id="p1001code2"><pre class="php" style="font-family:monospace;"><span style="color: #990000;">Array</span>
<span style="color: #009900;">&#40;</span>
    <span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=&gt;</span> convert<span style="color: #339933;">.</span><span style="color: #990000;">iconv</span><span style="color: #339933;">.*</span>
    <span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=&gt;</span> string<span style="color: #339933;">.</span>rot13
    <span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">2</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=&gt;</span> string<span style="color: #339933;">.</span>toupper
    <span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">3</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=&gt;</span> string<span style="color: #339933;">.</span>tolower
    <span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">4</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=&gt;</span> string<span style="color: #339933;">.</span><span style="color: #990000;">strip_tags</span>
    <span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">5</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=&gt;</span> convert<span style="color: #339933;">.*</span>
    <span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">6</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=&gt;</span> consumed
    <span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">7</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=&gt;</span> zlib<span style="color: #339933;">.*</span>
    <span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">8</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=&gt;</span> bzip2<span style="color: #339933;">.*</span>
<span style="color: #009900;">&#41;</span></pre></td></tr></table></div>

<p>For example to strip html tags from a input string you add the &#8216;string.strip_tags&#8217; filter to the stream resource as below.</p>

<div class="wp_codebox"><table><tr id="p10013"><td class="code" id="p1001code3"><pre class="php" style="font-family:monospace;"><span style="color: #000088;">$html</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'The &lt;b&gt;World&lt;/b&gt; is safe &lt;i&gt;again&lt;/i&gt;.'</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000088;">$fp</span> <span style="color: #339933;">=</span> <span style="color: #990000;">fopen</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;php://output&quot;</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">&quot;r&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #990000;">stream_filter_prepend</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$fp</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">&quot;string.strip_tags&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #990000;">fwrite</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$fp</span><span style="color: #339933;">,</span> <span style="color: #000088;">$html</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #990000;">fclose</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$fp</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></td></tr></table></div>

<p>Which will than output:</p>

<div class="wp_codebox"><table><tr id="p10014"><td class="code" id="p1001code4"><pre class="html" style="font-family:monospace;">The World is safe again.</pre></td></tr></table></div>

<p><strong>Creating a custom filter</strong><br />
In this section we will create a filter to replace urls in the input stream with a<br />
 &#8216;[----URL----]&#8216; string. Now this may not look like much of a helpful filter, but this is just for illustrative purpose. You can use any replacement string you like. The complete source for the filter class is shown below.</p>

<div class="wp_codebox"><table><tr id="p10015"><td class="code" id="p1001code5"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">class</span> URLFilter <span style="color: #000000; font-weight: bold;">extends</span> PHP_User_Filter
<span style="color: #009900;">&#123;</span>
    <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000088;">$_data</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #009933; font-style: italic;">/* Called when the filter is initialized */</span>
    <span style="color: #000000; font-weight: bold;">function</span> onCreate<span style="color: #009900;">&#40;</span> <span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_data <span style="color: #339933;">=</span> <span style="color: #0000ff;">''</span><span style="color: #339933;">;</span>
        <span style="color: #000000; font-weight: bold;">return</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #009933; font-style: italic;">/* This is where the actual stream data conversion takes place */</span>
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> filter<span style="color: #009900;">&#40;</span><span style="color: #000088;">$in</span><span style="color: #339933;">,</span> <span style="color: #000088;">$out</span><span style="color: #339933;">,</span> <span style="color: #339933;">&amp;</span><span style="color: #000088;">$consumed</span><span style="color: #339933;">,</span> <span style="color: #000088;">$closing</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
&nbsp;
        <span style="color: #009933; font-style: italic;">/* We read all the stream data and store it in 
           the '$_data' variable 
        */</span>
        <span style="color: #000000; font-weight: bold;">while</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$bucket</span> <span style="color: #339933;">=</span> <span style="color: #990000;">stream_bucket_make_writeable</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$in</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
        <span style="color: #009900;">&#123;</span>
            <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_data <span style="color: #339933;">.=</span> <span style="color: #000088;">$bucket</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">data</span><span style="color: #339933;">;</span>
            <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">bucket</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$bucket</span><span style="color: #339933;">;</span>
            <span style="color: #000088;">$consumed</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
&nbsp;
        <span style="color: #009933; font-style: italic;">/* Now that we have read all the data from the stream we process 
          it and save it again to the bucket.
        */</span>
        <span style="color: #000000; font-weight: bold;">if</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$closing</span><span style="color: #009900;">&#41;</span>
        <span style="color: #009900;">&#123;</span>
            <span style="color: #000088;">$consumed</span> <span style="color: #339933;">+=</span> <span style="color: #990000;">strlen</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_data<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
            <span style="color: #000088;">$pattern</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;#http(s)?://([\w-]+\.)+[\w-]+(/[\w-./?%&amp;=]*)?#&quot;</span><span style="color: #339933;">;</span>
            <span style="color: #000088;">$str</span> <span style="color: #339933;">=</span> <span style="color: #990000;">preg_replace</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$pattern</span><span style="color: #339933;">,</span>
                                <span style="color: #0000ff;">'[----URL----]'</span><span style="color: #339933;">,</span>
                                <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_data<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
            <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">bucket</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">data</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$str</span><span style="color: #339933;">;</span>
            <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">bucket</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">datalen</span> <span style="color: #339933;">=</span> <span style="color: #990000;">strlen</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_data<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
            <span style="color: #000000; font-weight: bold;">if</span><span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #990000;">empty</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">bucket</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">data</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
                <span style="color: #990000;">stream_bucket_append</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$out</span><span style="color: #339933;">,</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">bucket</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
            <span style="color: #000000; font-weight: bold;">return</span> PSFS_PASS_ON<span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
&nbsp;
        <span style="color: #000000; font-weight: bold;">return</span> PSFS_FEED_ME<span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">?&gt;</span></pre></td></tr></table></div>

<p>All the action takes place in the <em>filter()</em> method, where we collect all the data from the buckets. The data is retrieved in the fashion of a <a target="_blank" href="http://en.wikipedia.org/wiki/Bucket_brigade">bucket brigade</a>. The <em>stream_bucket_make_writable()</em> function reads a portion of the data from the input bucket and converts it to a PHP bucket object. The data property of the bucket object is a string holding the bucket&#8217;s data, whereas datalen stores its length. We could convert the data in the filter() function itself, but rather we store all the data retrieved in the $_data variable and convert it at a single go. </p>
<p>Once all the data from the stream is read the $closing parameter is set to <em>true</em>. Now we can check for that and than process the data in any fashion we like. Once the data processing is done we add the processed data to the bucket and return a <em>PSFS_PASS_ON</em> to imply that we have successfully processed the stream data.</p>
<p><strong>An Example</strong><br />
Before we use the filter we have to register the filter and append it to the stream. A example using the above class is shown below, which gets the content from Google.com and than replaces all the urls in the source with the &#8216;[----URL----]&#8216; string.</p>

<div class="wp_codebox"><table><tr id="p10016"><td class="code" id="p1001code6"><pre class="php" style="font-family:monospace;">&nbsp;
<span style="color: #990000;">stream_filter_register</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'myFilter'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'URLFilter'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$handle</span> <span style="color: #339933;">=</span> <span style="color: #990000;">fopen</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;http://www.google.com/&quot;</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">&quot;r&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #990000;">stream_filter_append</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$handle</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">&quot;myFilter&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">while</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #990000;">feof</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$handle</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
  <span style="color: #000088;">$contents</span> <span style="color: #339933;">.=</span> <span style="color: #990000;">fread</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$handle</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">8192</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #990000;">fclose</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$handle</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">echo</span> <span style="color: #000088;">$contents</span><span style="color: #339933;">;</span></pre></td></tr></table></div>

]]></content:encoded>
			<wfw:commentRss>http://www.codediesel.com/php/creating-custom-stream-filters/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
	</channel>
</rss>

