<?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>Dancing Mammoth</title>
	<atom:link href="http://dancingmammoth.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://dancingmammoth.com</link>
	<description>Cleaner Websites for a Cleaner Future</description>
	<lastBuildDate>Thu, 28 Oct 2010 16:28:04 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Removing UTF8 Gremlins</title>
		<link>http://dancingmammoth.com/2010/10/28/removing-utf8-gremlins/</link>
		<comments>http://dancingmammoth.com/2010/10/28/removing-utf8-gremlins/#comments</comments>
		<pubDate>Thu, 28 Oct 2010 16:01:08 +0000</pubDate>
		<dc:creator>Francis Avila</dc:creator>
				<category><![CDATA[Lab]]></category>
		<category><![CDATA[encodings]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://dancingmammoth.com/?p=370</guid>
		<description><![CDATA[If you work with documents from many different sources, you&#8217;ve probably seen this before: Thatâ€™s good. &#8220;Oh no&#8221;, you think, &#8220;A utf-8 encoding problem.&#8221; That three-letter combo should be a single close-quote, like this: That’s good. Sometimes the problem is that your application is reading the file as a win-1252 (or cp1252, or the kinda-sorta [...]]]></description>
			<content:encoded><![CDATA[<p>If you work with documents from many different sources, you&#8217;ve probably seen this before:</p>
<blockquote><p>Thatâ€™s good.</p></blockquote>
<p>&#8220;Oh no&#8221;, you think, &#8220;A utf-8 encoding problem.&#8221; That three-letter combo should be a single close-quote, like this:</p>
<blockquote><p>That’s good.</p></blockquote>
<p>Sometimes the problem is that your application is reading the file as a win-1252 (or cp1252, or the kinda-sorta iso-8859-1 used on the web).  In this case the solution is easy: instruct your application to reopen the file as utf8.</p>
<p>But sometimes, your file <em>really does</em> say &#8220;â€™&#8221;, even when decoded as utf-8. How this happens is that someone took some utf8 text, pasted it into a win1252 document, and then saved the document as utf8. So now the bytes in your document are:</p>
<blockquote><p>That<code>[c3][a2][e2][82][ac][e2][84][a2]</code>s good</p></blockquote>
<p>instead of</p>
<blockquote><p>That<code>[e2][80][99]</code>s good.</p></blockquote>
<p>So how do you fix it?</p>
<p>I wrote a tool.</p>
<p>The Python code below uses Python&#8217;s <a href="http://docs.python.org/library/codecs.html">codec interface</a> to register a simple stateless encoder that turns these utf8 gremlin bytes back into pure utf8 bytes. You can use it from the command line like <code>removeUTF8Gremlins.py infile.txt -o outfile.txt</code> or you can use it as a library by importing it and then using the <code>CP1252asUTF8gremlins</code> pseudo-codec anywhere you can use a stateless codec.</code></p>
<pre class="brush: python;">
#!/usr/bin/env python
# encoding: utf-8

# BSD LICENSE
# Copyright (c) 2010, Dancing Mammoth Inc
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# Redistributions of source code must retain the above copyright notice, this
# list of conditions and the following disclaimer.
#
# Redistributions in binary form must reproduce the above copyright notice, this
# list of conditions and the following disclaimer in the documentation and/or
# other materials provided with the distribution.
#
# Neither the name of Dancing Mammoth nor the names of its contributors may
# be used to endorse or promote products derived from this software without
# specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS &quot;AS IS&quot;
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

&quot;&quot;&quot;
removeUTF8Gremlins.py

Will recode file with utf8 gremlins to a proper utf8 file.

When used as a library, will register the codec 'CP1252asUTF8gremlins', which
provides a stateless decoder which will convert bytes with gremlins into pure
utf8 bytes.

We call a 'utf8 gremlin' a byte sequence that results when a utf8 byte is read
as a cp1252 encoding into unicode chars, and then written out as utf8.

The tell-tale sign of it is bytes that look like this in a file read as utf8.

Original: That’s good.
Bytes as utf8: That[e2][80][99]s good.
When read as CP1252: Thatâ€™s good. (acute lowercase a, euro symbol, trademark symbol)
Bytes as utf8 gremlins: That[c3][a2][e2][82][ac][e2][84][a2]s good.

This utility turns &quot;Bytes as utf8 gremlins&quot; back into &quot;Bytes as utf8&quot;

Created by Francis Avila on 2010-10-27.
Copyright (c) 2010 Dancing Mammoth, Inc. All rights reserved.
&quot;&quot;&quot;

import sys
import getopt
import codecs
import re

help_message = '''
Fix a conversion error where a utf8 file got interpreted as a win1252 file
and then saved as utf8, producing three-character multibyte gremlins.
'''

def win1252_to_utf8_gremlin_table(mapping={}):
	if mapping:
		return mapping
	def makemapping(mapping):
		for i in range(256):
			byte = ('%02x' % i).decode('hex_codec')
			try:
				cp1252uni = byte.decode('cp1252')
			except UnicodeDecodeError:
				cp1252uni = byte.decode('iso-8859-1')

			if cp1252uni:
				realutf8 = cp1252uni.encode('utf-8')
				try:
					asuni = realutf8.decode('cp1252')
				except UnicodeDecodeError:
					asuni = realutf8.decode('iso-8859-1')
				if asuni:
					utf8gremlin = asuni.encode('utf8')
					mapping[utf8gremlin] = realutf8
	makemapping(mapping)
	return mapping

def win1252_to_utf8_gremlin_re():
	mapping = win1252_to_utf8_gremlin_table()
	rechars = []
	for k,v in mapping.items():
		if k != v:
			rechars.append(k.encode('string_escape'))
	regex = '(?:%s)' % '|'.join(rechars)
	return re.compile(regex)

def reverse_win1252_to_utf8_gremlins(bytes, errors='strict'):
	regex = win1252_to_utf8_gremlin_re()
	mapping = win1252_to_utf8_gremlin_table()
	def replace(mo):
		try:
			newchar = mapping[mo.group(0)]
		except KeyError:
			if errors=='strict':
				raise ValueError('Encountered bytes with no pure utf8 equivalent.')
			else:
				if errors=='ignore':
					newchar = ''
				elif errors=='replace':
					newchar = '?'
		return newchar
	newbytes = re.sub(regex, replace, bytes)
	return (newbytes, len(bytes))

def register_win1252_to_utf8_gremlins(encoding):
	ci = None
	if encoding == 'cp1252asutf8gremlins':
		ci = codecs.CodecInfo(None, reverse_win1252_to_utf8_gremlins, name='CP1252asUTF8gremlins')
	return ci

codecs.register(register_win1252_to_utf8_gremlins)

class Usage(Exception):
	def __init__(self, msg):
		self.msg = msg

def main(argv=None):
	if argv is None:
		argv = sys.argv
	options = {}
	try:
		try:
			opts, args = getopt.getopt(argv[1:], &quot;ho:v&quot;, [&quot;help&quot;, &quot;output=&quot;])
		except getopt.error, msg:
			raise Usage(msg)

		# option processing
		for option, value in opts:
			if option == &quot;-v&quot;:
				options['verbose'] = True
			if option in (&quot;-h&quot;, &quot;--help&quot;):
				raise Usage(help_message)
			if option in (&quot;-o&quot;, &quot;--output&quot;):
				options['outputfile'] = value

	except Usage, err:
		print &gt;&gt; sys.stderr, sys.argv[0].split(&quot;/&quot;)[-1] + &quot;: &quot; + str(err.msg)
		print &gt;&gt; sys.stderr, &quot;\t for help use --help&quot;
		return 2

	bytes = file(args[0], 'rb').read()
	outfp = file(options['outputfile'], 'wb') if 'outputfile' in options else sys.stdout
	bytes = bytes.decode('CP1252asUTF8gremlins')
	outfp.write(bytes)
	outfp.close()

if __name__ == &quot;__main__&quot;:
	sys.exit(main())
</pre>
]]></content:encoded>
			<wfw:commentRss>http://dancingmammoth.com/2010/10/28/removing-utf8-gremlins/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Six simple design changes The Daily Caller should make today…</title>
		<link>http://dancingmammoth.com/2010/01/11/six-simple-design-changes-the-daily-caller-should-make-today%e2%80%a6/</link>
		<comments>http://dancingmammoth.com/2010/01/11/six-simple-design-changes-the-daily-caller-should-make-today%e2%80%a6/#comments</comments>
		<pubDate>Mon, 11 Jan 2010 20:15:59 +0000</pubDate>
		<dc:creator>PJ Doland</dc:creator>
				<category><![CDATA[Miscellaneous]]></category>
		<category><![CDATA[Daily Caller]]></category>
		<category><![CDATA[design]]></category>

		<guid isPermaLink="false">http://dancingmammoth.com/?p=356</guid>
		<description><![CDATA[The Arial is out of hand. I understand that it&#8217;s a web safe typeface. That still doesn&#8217;t mean it&#8217;s a good idea to use it for your masthead. Since you&#8217;re already willing to render the text as an image, you can definitely find something better. In fact, almost anything would be better (even some cliché [...]]]></description>
			<content:encoded><![CDATA[<ol>
<li>The Arial is out of hand. I understand that it&#8217;s a web safe typeface. That still doesn&#8217;t mean it&#8217;s a good idea to use it for your masthead. Since you&#8217;re already willing to render the text as an image, you can definitely find something better. In fact, almost anything would be better (even some cliché blackletter). And please don&#8217;t use Arial for those feature headlines if you&#8217;re going to make them that large. The kerning is atrocious, which you can see in the example below if you look at the awkward space between the &#8220;Pa&#8221; and the &#8220;Fo&#8221;:<br />
<img style="border:1px solid #CCC;margin-top:10px;" title="Bad Arial Kerning" src="http://dancingmammoth.com/wp-content/uploads/bad-arial-kerning.png" alt="Bad Arial Kerning" width="333" height="64" /></li>
<li>It&#8217;s true that there&#8217;s no &#8220;above the fold&#8221; on the web. That doesn&#8217;t mean it&#8217;s OK to have a feature graphic and headline so large that a visitor can&#8217;t even see the whole image when their browser resolution is set to 1024 x 768. And yes, it&#8217;s bad when Drudge does it. Save that kind of thing for V-I Day, should we ever be so lucky.</li>
<li>Kill the scrolling news ticker at the top of the page. This isn&#8217;t 1998 and your website isn&#8217;t a cable television news channel. Professional designers stopped using scrolling marquees for a reason.</li>
<li>Show me bylines on all the news items in the center column of the homepage before I click through to the story&#8211;even if it shows you&#8217;re running syndicated content.</li>
<li>You&#8217;re a new publication and you&#8217;re not established enough to get away branding your inside pages by just showing &#8220;The DC&#8221; in the upper left corner of the page. Show the full name of the site.</li>
<li>The line-height should be increased on all body text to make the copy easier to read.</li>
</ol>
]]></content:encoded>
			<wfw:commentRss>http://dancingmammoth.com/2010/01/11/six-simple-design-changes-the-daily-caller-should-make-today%e2%80%a6/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>The New Reason.com</title>
		<link>http://dancingmammoth.com/2009/11/12/the-new-reason-com/</link>
		<comments>http://dancingmammoth.com/2009/11/12/the-new-reason-com/#comments</comments>
		<pubDate>Thu, 12 Nov 2009 21:38:00 +0000</pubDate>
		<dc:creator>Matt</dc:creator>
				<category><![CDATA[Case Studies]]></category>

		<guid isPermaLink="false">http://dancingmammoth.com/?p=300</guid>
		<description><![CDATA[When Reason Magazine needed a new publishing system and a visual refresh of their website, one of the criteria was that the layout and content organization remain as consistent with the previous version as possible. The introduction of a completely new design can be aggravating for existing users, particularly when features that they&#8217;ve taken the [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://reason.com" target="_blank"><img src="http://dancingmammoth.com/wp-content/uploads/reasonscreenshot-350x232.jpg" alt="Reason.com Screenshot" title="Reason.com Screenshot" width="350" height="232" class="image alignright size-medium wp-image-310" /></a>When Reason Magazine needed a new publishing system and a visual refresh of their website, one of the criteria was that the layout and content organization remain as consistent with the previous version as possible.</p>
<p>The introduction of a completely new design can be aggravating for existing users, particularly when features that they&#8217;ve taken the time to learn are suddenly relocated, or removed altogether.</p>
<p>To avoid disorienting users, we reused the existing site format while updating the visual design and improving elements such as spacing and contrast. This way, Reason&#8217;s readers benefit from the enhanced features made possible by the new publishing system, without the inconvenience of relearning how to use the site.</p>
<p>For example, Reason, like many other websites, structures content with a static three column layout. The left hand column is dedicated to navigational links, masthead information and advertising. The center column contains the featured content well and links to categorized content, and the right column promotes additional highlighted content, with space for advertising.</p>
<p>The old version of the site was well organized with plenty of white space, but the design was flat and lacked visual interest and depth. The new design is more appealing, has a more natural visual hierarchy, and does a better job of keeping content separated without feeling unnecessarily boxy.</p>
]]></content:encoded>
			<wfw:commentRss>http://dancingmammoth.com/2009/11/12/the-new-reason-com/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>A Fresh Website for Your Fresh Linens</title>
		<link>http://dancingmammoth.com/2009/10/21/fresh-website-for-your-fresh-linens/</link>
		<comments>http://dancingmammoth.com/2009/10/21/fresh-website-for-your-fresh-linens/#comments</comments>
		<pubDate>Wed, 21 Oct 2009 18:00:36 +0000</pubDate>
		<dc:creator>Matt</dc:creator>
				<category><![CDATA[Case Studies]]></category>
		<category><![CDATA[color scheme]]></category>
		<category><![CDATA[design]]></category>
		<category><![CDATA[laundry]]></category>
		<category><![CDATA[linens of the week]]></category>
		<category><![CDATA[mockups]]></category>

		<guid isPermaLink="false">http://dancingmammoth.com/?p=275</guid>
		<description><![CDATA[Linens of the Week came to us looking for a clean and up-to-date design for their website. In addition, they were seeking enhanced functionality to allow customer access to invoices and orders. We sent over two design variations, making sure to reuse their currently branded blue whenever possible. Their feedback follows&#8230; &#8220;Can I see this [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://linensoftheweek.com"><img class="alignright size-thumbnail wp-image-287 image" title="Picture-3" src="http://dancingmammoth.com/wp-content/uploads/Picture-3-350x240.jpg" alt="Picture-3" width="350" height="240" /></a>Linens of the Week came to us looking for a clean and up-to-date design for their website. In addition, they were seeking enhanced functionality to allow customer access to invoices and orders.</p>
<p>We sent over two design variations, making sure to reuse their currently branded blue whenever possible. Their feedback follows&#8230;</p>
<p>&#8220;Can I see this with a completely different color scheme?&#8221;</p>
<p>Hearing this might make a designer cringe, but it&#8217;s very important to make sure the client is happy.  Fortunately, the project was still in the early stages, so alterations were relatively easy to make.</p>
<p>After a brief consultation, we agreed to work on some new variations while keeping within the same basic palette. This would mean shifting the use of color around while adding shades and tints to create more variety. This type of consultation helps keep everyone happy by taking the middle ground. We aren&#8217;t creating designs with wildly conflicting colors, and the client doesn&#8217;t have to hear a flat out refusal on our end.</p>
<p><a class="thumbs" href="http://dancingmammoth.com/wp-content/uploads/linens-1a.jpg"><img class="alignnone size-thumbnail wp-image-279" title="linens-1a" src="http://dancingmammoth.com/wp-content/uploads/linens-1asm.jpg" alt="linens-1a" /></a><a class="thumbs" href="http://dancingmammoth.com/wp-content/uploads/linens-1c.jpg"><img class="alignnone size-thumbnail wp-image-279" title="linens-1c" src="http://dancingmammoth.com/wp-content/uploads/linens-1csm.jpg" alt="linens-1c" /></a><a class="thumbs" href="http://dancingmammoth.com/wp-content/uploads/linens-1b.jpg"><img class="alignnone size-thumbnail wp-image-279" title="linens-1b" src="http://dancingmammoth.com/wp-content/uploads/linens-1bsm.jpg" alt="linens-1b" /></a></p>
<p>We submitted the above mockups, two of which rotated color usage in sections like the highlight column (bottom right corner), and one of which used a monochromatic scheme (third mockup from the left).</p>
<p>When only one color is used for a design, the overall feel can often be flat or what I&#8217;d consider &#8220;overly emotional&#8221;. A design that only uses red can make you feel too hectic or heated without a cool compliment for balance. Similarly, a design that only uses blue would make you feel too serious or cold without warm oranges or reds. When it came time to show our client the revisions, we made sure to bring this up as a possible issue.</p>
<p>In the end, they went with the primarily orange/gold design, giving the site a bright and light feeling while still leaving room to use the complimenting blue for their logo and headings.</p>
]]></content:encoded>
			<wfw:commentRss>http://dancingmammoth.com/2009/10/21/fresh-website-for-your-fresh-linens/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>An Interactive US Map Without Flash.</title>
		<link>http://dancingmammoth.com/2009/09/24/an-interactive-us-map-without-flash/</link>
		<comments>http://dancingmammoth.com/2009/09/24/an-interactive-us-map-without-flash/#comments</comments>
		<pubDate>Thu, 24 Sep 2009 15:47:56 +0000</pubDate>
		<dc:creator>Brian Kieffer</dc:creator>
				<category><![CDATA[Case Studies]]></category>
		<category><![CDATA[Lab]]></category>

		<guid isPermaLink="false">http://dancingmammoth.com/?p=252</guid>
		<description><![CDATA[A client recently requested a feature for their website that would allow users to access state by state data by rolling over a map of the US. At first, I considered using one of the available Flash packages, but the design took a couple of twists that made that much more difficult. So I opted [...]]]></description>
			<content:encoded><![CDATA[<p>A client recently requested a feature for their website that would allow users to access state by state data by rolling over a map of the US. At first, I considered using one of the available Flash packages, but the design took a couple of twists that made that much more difficult. So I opted to implement the map with plain old HTML, CSS and Javascript.</p>
<p><a href="/wp-content/demos/usmap/">Here is the map</a>.</p>
<p>The benefit of using HTML, CSS and Javascript instead of Flash, is that the map will function in just about any browser without having to install additional components. Mobile browsers such as Safari on iPhone, older browsers, or browsers without Javascript enabled, can still use the map. Here is how it works.</p>
<p>The map consists of three layers.</p>
<p align="center"><img class="size-full wp-image-253   aligncenter" title="layers" src="http://dancingmammoth.com/wp-content/uploads/layers.jpg" alt="layers" width="509" height="203" /></p>
<p>The bottom layer contains the full map as a background image. This loads when the page is opened, along with the top layer which contains the maparea linked to a transparent GIF that matches the size of the map. The layers are positioned over one another with CSS.</p>
<pre class="brush: css;">
div#usmap{
position: absolute;
top: 0px;
left: 0px;
}

div#mapareas{
position: absolute;
top: 0px;
left: 0px;
z-index: 99;
}
</pre>
<p>The middle layer is where all of the animation takes place. When a user mouses over one of the mapareas, jQuery prepends the preloaded image for an individual state and positions it in the middle layer. Some images also have a corresponding mask to maintain the illusion that the state is popping up away from the page. The individual state images were created by cutting apart the main US image, and the positioning is done with jQuery&#8217;s css method. This can be somewhat time consuming for complex maps.</p>
<pre class="brush: jscript;">
$(&quot;#usmap&quot;).prepend(img);
$(&quot;#usmap&quot;).prepend(imgmask);
positionimage();
</pre>
<pre class="brush: css;">
.state-copy {
position: absolute;
z-index:2;
}
.state-mask {
position: absolute;
z-index:1;
}
</pre>
<p>Then jQuery calcuates the current size and zoomed size, and executes the animation.</p>
<pre class="brush: jscript;">
$(&quot;.state-copy&quot;).each(function(){
var width = $(this).width();
var height = $(this).height();

var zoomheight = height * 1.2;
var zoomwidth = width * 1.2;

var	centerheight = (zoomheight - height)/2;
var	centerwidth = (zoomwidth - width)/2;

$(this).animate({
top: '-=' + centerheight,
left: '-=' + centerwidth,
width: zoomwidth,
height: zoomheight
}, 100);

});
</pre>
<p>This method will work for just about any similar image that you want to animate.</p>
]]></content:encoded>
			<wfw:commentRss>http://dancingmammoth.com/2009/09/24/an-interactive-us-map-without-flash/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>PHP Stream Filters: Unchunking HTTP Streams</title>
		<link>http://dancingmammoth.com/2009/08/29/php-stream-filters-unchunking-http-streams/</link>
		<comments>http://dancingmammoth.com/2009/08/29/php-stream-filters-unchunking-http-streams/#comments</comments>
		<pubDate>Sat, 29 Aug 2009 05:13:35 +0000</pubDate>
		<dc:creator>Francis Avila</dc:creator>
				<category><![CDATA[Lab]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://dancingmammoth.com/?p=223</guid>
		<description><![CDATA[Slinging php code to and fro one day, I found myself needing to process a potentially large result from a url&#8211;a result too large to fit within PHP&#8217;s memory limit.  However, I could process this result a line at a time, so I could avoid buffering the entire thing in memory.  I couldn&#8217;t use cURL, [...]]]></description>
			<content:encoded><![CDATA[<p>Slinging php code to and fro one day, I found myself needing to process a potentially large result from a url&#8211;a result too large to fit within PHP&#8217;s memory limit.  However, I could process this result a line at a time, so I could avoid buffering the entire thing in memory.  I couldn&#8217;t use cURL, since it buffers everything, but I could use PHP&#8217;s handy file-like stream interface, fetch the url with an <code>fopen('http://my-url.n.e.t/', 'r');</code> and then use <code>fgets()</code> to keep only a line in memory at a time.</p>
<p>It was a great plan, but I noticed that I occasionally got garbage lines or bogus input.  Using http cli tools like wget and curl revealed nothing out of the ordinary, until I realized that those garbage lines were the uninterpreted length markers for <code>Transfer-Encoding: chunked</code>.  PHP&#8217;s http stream handler does not decode chunked transfers.</p>
<p>There is a pecl function <a href="http://php.net/manual/en/function.http-chunked-decode.php"><code>http_chunked_decode()</code></a>, but it operates on strings, not streams, so I would still have to buffer the entire input first.</p>
<p>PHP&#8217;s streams allow you to attach a chain of <a href="http://php.net/manual/en/stream.filters.php">stream filters</a> to a stream to process input and output (it&#8217;s the same mechanism <code>ob_gzhandler()</code> uses).  My plan was to create a stream filter to transparently unchunk the stream.  Unfortunately, the documentation on writing your own stream filter is pretty sparse, and the examples I could find on the web were all very trivial.</p>
<p>After a few false starts, however, I was able to create an http stream unchunker:</p>
<pre class="brush: php;">
/**
* A stream filter for removing the 'chunking' of a 'Transfer-Encoding: chunked'
* http response
*
* The http stream wrapper on php does not support chunked transfer
* encoding, making this filter necessary.
*
* Add to a file resource with &lt;code&gt;stream_filter_append($fp, 'http_unchunk_filter',
* STREAM_FILTER_READ);&lt;/code&gt;
*
* If the wrapper metadata for $fp does not contain a &lt;code&gt;transfer-encoding:
* chunked&lt;/code&gt; header, this filter passes data through unchanged.
*
* @license BSD
* @author Francis Avila
*/
// Stream filters must subclass php_user_filter
class http_unchunk_filter extends php_user_filter {
	protected $chunkremaining = 0; //bytes remaining in the current chunk
	protected $ischunked = null; //whether the stream is chunk-encoded. null=not sure yet

	// this is the meat of the filter.
	// The class must have a function with this name and prototype
	// It must return a status--one of the PSFS_* constants;
	function filter($in, $out, &amp;$consumed, $closing) {
		if ($this-&gt;ischunked===null) {
			$this-&gt;ischunked = self::ischunked($this-&gt;stream);
		}
		// $in and $out are opaque &quot;bucket brigade&quot; objects which consist of a
		// sequence of opaque &quot;buckets&quot;, which contain the actual stream data.
		// The only way to use these objects is the stream_bucket_* functions.
		// Unfortunately, there doesn't seem to be any way to access a bucket
		// without turning it into a string using stream_bucket_make_writeable(),
		// even if you want to pass the bucket along unmodified.

		// Each call to this pops a bucket from the bucket brigade and
		// converts it into an object with two properties: datalen and data.
		// This same object interface is accepted by stream_bucket_append().
		while ($bucket = stream_bucket_make_writeable($in)) {
			if (!$this-&gt;ischunked) {
				$consumed += $bucket-&gt;datalen;
				stream_bucket_append($out, $bucket);
				continue;
			}
			$outbuffer = '';
			$offset = 0;
			// Loop through the string.  For efficiency, we don't advance a character
			// at a time but try to zoom ahead to where we think the next chunk
			// boundary should be.

			// Since the stream filter divides the data into buckets arbitrarily,
			// we have to maintain state ($this-&gt;chunkremaining) across filter() calls.
			while ($offset &lt; $bucket-&gt;datalen) {
				if ($this-&gt;chunkremaining===0) { // start of new chunk, or the start of the transfer
					$firstline = strpos($bucket-&gt;data, &quot;\r\n&quot;, $offset);
					$chunkline = substr($bucket-&gt;data, $offset, $firstline-$offset);
					$chunklen = current(explode(';', $chunkline, 2)); // ignore MIME-like extensions
					$chunklen = trim($chunklen);
					if (!ctype_xdigit($chunklen)) {
					// There should have been a chunk length specifier here, but since
					// there are non-hex digits something must have gone wrong.
						return PSFS_ERR_FATAL;
					}
					$this-&gt;chunkremaining = hexdec($chunklen);
					// $firstline already includes $offset in it
					$offset = $firstline+2; // +2 is CRLF
					if ($this-&gt;chunkremaining===0) { //end of the transfer
						break;  // ignore possible trailing headers
					}
				}
				// get as much data as available in a single go...
				$nibble = substr($bucket-&gt;data, $offset, $this-&gt;chunkremaining);
				$nibblesize = strlen($nibble);
				$offset += $nibblesize; // ...but recognize we may not have got all of it
				if ($nibblesize === $this-&gt;chunkremaining) {
					$offset += 2; // skip over trailing CRLF
				}
				$this-&gt;chunkremaining -= $nibblesize;
				$outbuffer .= $nibble;
			}
			$consumed += $bucket-&gt;datalen;
			$bucket-&gt;data = $outbuffer;
			stream_bucket_append($out, $bucket);
		}
		return PSFS_PASS_ON;
	}

	protected static function ischunked($stream) {
		$metadata = stream_get_meta_data($stream);
		$headers = $metadata['wrapper_data'];
		return (bool) preg_grep('/^Transfer-Encoding:\s+chunked\s*$/i', $headers);
	}

	function onCreate() {
		if (isset($this-&gt;stream)) { // This is usually not defined until the first filter() call.
			$this-&gt;ischunked = self::ischunked($this-&gt;stream);
		}
	}
}

stream_filter_register('http_unchunk_filter', 'http_unchunk_filter');
</pre>
<p>What you are left with is a stream filter you can then use like so:</p>
<pre class="brush: php;">
$fp = fopen('http://my.url', 'r');
stream_filter_append($fp, 'http_unchunk_filter', STREAM_FILTER_READ);
</pre>
<p>If the http stream has a chunked transfer encoding, the filter will automatically unchunk it.  However, it ignores extended data (anything after the hex-encoded chunk-length) and trailing headers, both of which are in the http specification but hardly ever used.</p>
]]></content:encoded>
			<wfw:commentRss>http://dancingmammoth.com/2009/08/29/php-stream-filters-unchunking-http-streams/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>In Which the Summer Mammoth Introduces Himself&#8230;</title>
		<link>http://dancingmammoth.com/2009/06/15/in-which-the-summer-mammoth-introduces-himself/</link>
		<comments>http://dancingmammoth.com/2009/06/15/in-which-the-summer-mammoth-introduces-himself/#comments</comments>
		<pubDate>Mon, 15 Jun 2009 15:57:35 +0000</pubDate>
		<dc:creator>Tim Lee</dc:creator>
				<category><![CDATA[Miscellaneous]]></category>

		<guid isPermaLink="false">http://dancingmammoth.com/?p=217</guid>
		<description><![CDATA[My name is Tim and I&#8217;ll be a part of the Dancing Mammoth team for the summer. During the school year I&#8217;m a PhD student in computer science at Princeton, working with these fine folks. Princeton keeps us pretty busy during the school year, but during the summer, they turn us loose and force us [...]]]></description>
			<content:encoded><![CDATA[<p>My name is Tim and I&#8217;ll be a part of the Dancing Mammoth team for the summer. During the school year I&#8217;m a PhD student in computer science at Princeton, working with <a href="http://citp.princeton.edu/">these fine folks.</a> Princeton keeps us pretty busy during the school year, but during the summer, they turn us loose and force us to fend for ourselves in the &#8220;real world.&#8221;</p>
<p>I&#8217;ve been doing web development on and off for more than a decade. During college, I was the webmaster of the University of Minnesota&#8217;s computer science department, where I developed a variety of web applications and gave <a href="http://www.cs.umn.edu/">our department website</a> a fresh new look (recently replaced by an even fresher, newer look). I got lots of practice with Apache, Perl, JavaScript, MySQL, and the usual alphabet soup of three- and four-letter acronyms. More recently, I&#8217;ve gotten into web development using Python and the Django framework.</p>
<p>After college, I worked as a journalist, blogger, and policy analyst, writing for <a href="http://arstechnica.com/authors/timothy-b-lee/"><em>Ars Technica</em></a>, the <a href="http://roomfordebate.blogs.nytimes.com/2009/02/18/facebook-rules/"><em>New York Times</em></a>, <a href="http://www.slate.com/id/2184367/"><em>Slate</em></a>, the <a href="http://www.cato.org/pub_display.php?pub_id=9775">Cato Institute,</a> and <a href="http://www.techdirt.com/">various</a> <a href="http://freedom-to-tinker.com/">other</a> <a href="http://showmeinstitute.org/scholar/id.24/staff_detail.asp">places.</a> Writing prose is fun, but after a few years I started to miss writing code and decided to go back to grad school.</p>
<p>For years, PJ has provided web design and hosting services to a number of my favorite <a href="http://www.theagitator.com/">blogs</a> (including one I <a href="http://www.techliberation.com/">contribute to</a>), <a href="http://reason.tv/">magazines</a>, and non-profits and I&#8217;ve always been impressed by his minimalist design sense and bulletproof hosting methodology. So I was excited when he invited me to join the team for the summer. I&#8217;m expecting to learn a lot about web development while helping clients solve their problems.</p>
]]></content:encoded>
			<wfw:commentRss>http://dancingmammoth.com/2009/06/15/in-which-the-summer-mammoth-introduces-himself/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Wanted: Junior Developer/Proboscidean</title>
		<link>http://dancingmammoth.com/2009/02/16/wanted-junior-developer/</link>
		<comments>http://dancingmammoth.com/2009/02/16/wanted-junior-developer/#comments</comments>
		<pubDate>Mon, 16 Feb 2009 21:59:44 +0000</pubDate>
		<dc:creator>Gary DuVall</dc:creator>
				<category><![CDATA[Miscellaneous]]></category>
		<category><![CDATA[careers]]></category>

		<guid isPermaLink="false">http://dancingmammoth.com/?p=213</guid>
		<description><![CDATA[Are you comfortable talking to important people at 9:00am in your underwear? Have you ever wanted to get to know your home more intimately? Dancing Mammoth, a web development firm based in Reston, VA, is seeking a self-starting, highly-responsible Junior Developer to work from home with demonstrated skills in the following areas: PHP 5 (OOP [...]]]></description>
			<content:encoded><![CDATA[<p>Are you comfortable talking to important people at 9:00am in your underwear? Have you ever wanted to get to know your home more intimately? Dancing Mammoth, a web development firm based in Reston, VA, is seeking a self-starting, highly-responsible Junior Developer to work from home with demonstrated skills in the following areas:</p>
<ul>
<li>PHP 5 (OOP skills a requirement)</li>
<li>MySQL 5</li>
<li>XHTML</li>
<li>CSS</li>
<li>JavaScript</li>
<li>JQuery</li>
<li>Python experience a plus.</li>
</ul>
<p>The right candidate will fit right in with our fast-paced virtual office environment and be able to hit the ground running with our varied base of clients and growing stable of in-house initiatives. We&#8217;re preferential to applicants in or around Chicago, Washington D.C., or Reston, VA but will consider other areas for the right person. Starting salary will be commensurate with experience, talent, and knowledge of the movie Xanadu.</p>
<p>Interested? Feel compelled to make your mark? We&#8217;d like to hear from you! Send your resume to <a href="careers@dancingmammoth.com">careers@dancingmammoth.com</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://dancingmammoth.com/2009/02/16/wanted-junior-developer/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>When You Have Your Own Iconic Brand&#8230;</title>
		<link>http://dancingmammoth.com/2009/01/16/when-you-have-your-own-iconic-brand/</link>
		<comments>http://dancingmammoth.com/2009/01/16/when-you-have-your-own-iconic-brand/#comments</comments>
		<pubDate>Fri, 16 Jan 2009 23:42:57 +0000</pubDate>
		<dc:creator>PJ Doland</dc:creator>
				<category><![CDATA[Miscellaneous]]></category>
		<category><![CDATA[design]]></category>
		<category><![CDATA[Theft]]></category>

		<guid isPermaLink="false">http://dancingmammoth.com/?p=200</guid>
		<description><![CDATA[Did Gibson think that nobody would notice when they completely-ripped off Apple for  their new website design?   For reference, here is a screencap of Apple&#8217;s site:   Which brings me to two points: When you have your own iconic brand, you really shouldn&#8217;t need to steal so shamelessly. It&#8217;s 2009, Gibson. Did you really [...]]]></description>
			<content:encoded><![CDATA[<p>Did <a href="http://gibson.com/">Gibson</a> think that nobody would notice when they completely-ripped off Apple for  their new website design?</p>
<p style="text-align: center;"><a href="http://gibson.com/"><img class="size-large wp-image-207 aligncenter" title="Gibson's New Site" src="http://dancingmammoth.com/wp-content/uploads/090116-gibson-1024x899.png" alt="Gibson's New Site" width="614" height="539" /></a></p>
<p align="center"> </p>
<p>For reference, here is a screencap of <a href="http://apple.com">Apple&#8217;s</a> site:</p>
<p style="text-align: center;"><a href="http://apple.com"><img class="size-large wp-image-209 aligncenter" title="Apple's Current Site" src="http://dancingmammoth.com/wp-content/uploads/090116-apple-1024x899.png" alt="Apple's Current Site" width="614" height="539" /></a></p>
<p align="center"> </p>
<p>Which brings me to two points:</p>
<ol>
<li>When you have your own iconic brand, you really shouldn&#8217;t need to steal so shamelessly.</li>
<li>It&#8217;s 2009, Gibson. Did you really think table-based layout was still a good idea?</li>
</ol>
]]></content:encoded>
			<wfw:commentRss>http://dancingmammoth.com/2009/01/16/when-you-have-your-own-iconic-brand/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>No Need for Wax, IWF Is Shiny Enough</title>
		<link>http://dancingmammoth.com/2009/01/06/no-need-for-wax-iwf-is-shiny-enough/</link>
		<comments>http://dancingmammoth.com/2009/01/06/no-need-for-wax-iwf-is-shiny-enough/#comments</comments>
		<pubDate>Tue, 06 Jan 2009 22:35:55 +0000</pubDate>
		<dc:creator>Matt</dc:creator>
				<category><![CDATA[Case Studies]]></category>

		<guid isPermaLink="false">http://dancingmammoth.com/?p=170</guid>
		<description><![CDATA[The Independent Women&#8217;s Forum came to us in early 2007 for an update on their site design and ended up with the sparkly interface you now see. The design of the site lends itself nicely for a journey through the magical land of color distribution. So grab a cup of coffee and buckle up as [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://iwf.org" target="_blank"><img class="alignright size-medium image" title="iwf" src="http://dancingmammoth.com/wp-content/uploads/iwf-318x270.gif" alt="" width="318" height="270" /></a><a href="http://iwf.org" target="_blank">The Independent Women&#8217;s Forum</a> came to us in early 2007 for an update on their site design and ended up with the sparkly interface you now see. The design of the site lends itself nicely for a journey through the magical land of color distribution. So grab a cup of coffee and buckle up as the ride begins.</p>
<p>To help explain what we mean by color distribution, take a look at this <a href="/wp-content/uploads/iwf-colormap.gif">little map</a> we created using IWF.org as a base.</p>
<p>On occasion, we start layouts by grabbing all the content the client would like to see on the main page, making it black, and dumping it all into a new Photoshop file. Next, we make textual hierarchy changes by pumping up the weight and size for headings and subheadings. After some spacing and alignment changes its ready, but start collecting color only after these steps have been completed</p>
<p><img class="floatleft" src="http://dancingmammoth.com/wp-content/uploads/iwf1.gif" alt="" />First,  we establish any existing colors which will need to be incorporated into our palette due to existing branding. In the example using IWF.org, the red from the logo needed to be added.</p>
<p><img class="floatleft" src="http://dancingmammoth.com/wp-content/uploads/iwf3.gif" alt="" />We needed to pay attention to an additional client request, which was that we keep the site feeling open and bright. Yellow or yellow used as a gradient is good for this.</p>
<p><img class="floatleft" src="http://dancingmammoth.com/wp-content/uploads/iwf5.gif" alt="" /><img class="floatleft" src="http://dancingmammoth.com/wp-content/uploads/iwf4.gif" alt="" />You can add two colors to the palette by choosing one with a rich hue (aka saturation), in this case blue, then <a href="http://dancingmammoth.com/wp-content/uploads/blues.png" target="_blank">branch off by grabbing a tint of the same hue</a>.</p>
<p><img class="floatleft" src="http://dancingmammoth.com/wp-content/uploads/iwf2.gif" alt="" />We also always grab something fairly neutral to use as borders, or for headings and backgrounds which require less emphasis than areas with brighter hues. For IWF.org, we chose a medium gray that is used on all borders and dividing lines.</p>
<p>Now the color palette is ready. Most, if not all of your color usage will be dictated by the palette. You can deviate, but only by shifting the base hue with shades and tints. Start by identifying which elements should use the same color. For example, all links within the main content area need the same color. All first-level headings need the same color as well.</p>
<p>Now you can experiment by using the colors in your palette in these positions. Any colors that are too light can be used for text as long as there is a background behind it with good color contrast to make everything readable.</p>
<p>Remember to use white as a color as well, not just for backgrounds. Any of the colors in your palette can be used for a background, which means any text on top of it can be white (depending on readability).</p>
]]></content:encoded>
			<wfw:commentRss>http://dancingmammoth.com/2009/01/06/no-need-for-wax-iwf-is-shiny-enough/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
