<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss 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/" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">

<channel>
	<title>Skookum Blog</title>
	
	<link>http://skookum.com</link>
	<description>We're a web development firm jumping into product development and sharing everything we learn about design, development, and marketing as we go.</description>
	<lastBuildDate>Wed, 22 Feb 2012 12:22:33 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/skookum/blog" /><feedburner:info uri="skookum/blog" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><geo:lat>35.227192</geo:lat><geo:long>-80.844193</geo:long><item>
		<title>Dynamic Screenshots on the Server with PhantomJS</title>
		<link>http://feedproxy.google.com/~r/skookum/blog/~3/BOVWkHY1KzE/</link>
		<comments>http://skookum.com/blog/dynamic-screenshots-on-the-server-with-phantomjs/#comments</comments>
		<pubDate>Wed, 22 Feb 2012 12:22:33 +0000</pubDate>
		<dc:creator>Chad</dc:creator>
				<category><![CDATA[Development]]></category>

		<guid isPermaLink="false">http://skookum.com/?p=1751</guid>
		<description><![CDATA[Scraping Data from websites is pretty cool. But what if we could not only grab and parse the markup from external websites, but take full-blown screenshots and even modify that markup before we take that screenshot? We can do all that with an excellent package called PhantomJS. A Browser without the Browser. PhantomJS describes itself [...]]]></description>
			<content:encoded><![CDATA[<p><a href="/blog/scraping-poorly-formatted-data-with-curl-and-phpquery/">Scraping Data</a> from websites is pretty cool. But what if we could not only grab and parse the markup from external websites, but take full-blown screenshots and even modify that markup before we take that screenshot? We can do all that with an excellent package called <a href="http://www.phantomjs.org/" target="_blank">PhantomJS</a>.</p>
<h3>A Browser without the Browser.</h3>
<p>PhantomJS describes itself as a &#8220;headless WebKit with JavaScript API&#8221;. For those that are not familiar, <a href="http://www.webkit.org/" target="_blank">WebKit</a> is the open-source web browsing engine that powers popular browsers including Chrome and Safari. &#8220;Headless&#8221; refers to fact that the program can be run from the command line without a window system, making it perfect for the server environment. The JavaScript API means that we can easily write scripts that interact with PhantomJS in the language of the web, allowing us to modify the browser output on the fly, just like you can do with Firebug or Developer Tools locally!</p>
<h3>Installation</h3>
<p>The hardest part of working with PhantomJS is getting it installed. Because of the requirements you are not going to be able to run this on a standard shared host, but an average vps will handle it fine. The following instructions are for getting things up and running with Ubuntu 11.10 on Linode.</p>
<h4>Step1: Install PhantomJS Requirements</h4>
<p>This will install everything we need to compile PhantomJS, along with the ability to run it virtually without a window system.<br />
<script type="text/javascript" src="https://gist.github.com/1872144.js?file=install.sh"></script></p>
<h4>Step2: Install Browser Goodies</h4>
<p>Installs flash plugin and windows fonts so sites appear more accurate.<script type="text/javascript" src="https://gist.github.com/1877794.js?file=browserstuff.sh"></script></p>
<h4>Step3: Compile!</h4>
<p>Clone the repo and build from source.<br />
<script type="text/javascript" src="https://gist.github.com/1872160.js?file=compile.sh"></script>After everything finishes we should now have the program installed. Test it at the command-line by typing &#8220;phantomjs&#8221;</p>
<h3>Taking Screenshots</h3>
<p>Since PhantomJS scripts are simply javascript with some extra api calls baked in, the barrier to entry for web developers is zero! Create the following script and save it somewhere on your server as &#8220;shotty.js&#8221;. Check out the comments for an explanation of what is happening.<script type="text/javascript" src="https://gist.github.com/1872266.js?file=shotty.js"></script><br />
To run this script, navigate to where the script lives on your server and run the following command. We run &#8220;Xvfb -screen 0 1024x768x24&amp;&#8221;  first to set the parameters of our Xvfb screen buffer. This is basically a virtual screen that allows us to emulate a window environment. Then we call the script with &#8220;DISPLAY=:0 phantomjs &#8211;load-plugins=yes shotty.js&#8221; to ensure Phantom runs in the buffer. PhantomJS will execute our script and save our screenshot in the same folder the script is in. If everything went well our screenshot of espn.com should look just like the real thing. How cool is that?</p>
<p><a href="http://skookum.com/wp-content/uploads/2012/02/ss1.png"><img class="alignnone size-full wp-image-1818" title="ss1" src="http://skookum.com/wp-content/uploads/2012/02/ss1.png" alt="" width="944" height="760" /></a></p>
<h3>Muck&#8217;n with Markup</h3>
<p>Because PhantomJS scripts are JavaScript, that means we can easily perform actions on the result of a page, and then take a screenshot of the results! Below we have created a script that grabs a page, embeds jQuery, and then performs some DOM manipulation before finally taking a screenshot. Priceless. The following code will allow us to edit the headline on espn.com to say whatever we want.<br />
<script type="text/javascript" src="https://gist.github.com/1877653.js?file=shotty2.js"></script><br />
<a href="http://skookum.com/wp-content/uploads/2012/02/ss2.png"><img class="alignnone size-full wp-image-1819" title="ss2" src="http://skookum.com/wp-content/uploads/2012/02/ss2.png" alt="" width="944" height="759" /></a></p>
<p>I&#8217;m sure by now your gears are already turning on fun uses of this technology. In Part II of this series I will go over how to integrate with Node.js to create a Phantom powered web app.</p>
<img src="http://feeds.feedburner.com/~r/skookum/blog/~4/BOVWkHY1KzE" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://skookum.com/blog/dynamic-screenshots-on-the-server-with-phantomjs/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		<feedburner:origLink>http://skookum.com/blog/dynamic-screenshots-on-the-server-with-phantomjs/</feedburner:origLink></item>
		<item>
		<title>Skookum Digital Works has The Fire. We Will Share it with You.</title>
		<link>http://feedproxy.google.com/~r/skookum/blog/~3/mwL5uXf5JAY/</link>
		<comments>http://skookum.com/blog/skookum-digital-works-has-the-fire-we-will-share-it-with-you/#comments</comments>
		<pubDate>Tue, 21 Feb 2012 14:15:44 +0000</pubDate>
		<dc:creator>Chris</dc:creator>
				<category><![CDATA[Culture]]></category>

		<guid isPermaLink="false">http://skookum.com/?p=1763</guid>
		<description><![CDATA[While attending NodeSummit in San Francisco a couple weeks ago, I was approached by very sweet older lady named Gretchen. She was strolling through the exhibition area for unrelated reasons and stopped in her tracks when she saw the word “Skookum” on our banner. Gretchen is a retired school teacher from the Pacific Northwest, and [...]]]></description>
			<content:encoded><![CDATA[<p>While attending <a href="http://nodesummit.com/">NodeSummit</a> in San Francisco a couple weeks ago, I was approached by very sweet older lady named Gretchen. She was strolling through the exhibition area for unrelated reasons and stopped in her tracks when she saw the word “Skookum” on our <a href="https://twitter.com/#!/Skookum/media/slideshow?url=pic.twitter.com%2Fo4JqFoay">banner</a>. Gretchen is a retired school teacher from the Pacific Northwest, and she told me a story about the “Skookums” that her students loved to hear and that she had told for many years. </p>
<p><img src="http://skookum.com/wp-content/uploads/2012/02/blog_illus_1_b.png" alt="" title="Skookum Digital Works Space Mountain Fire Volcano Logo" width="555" height="230" class="aligncenter size-full wp-image-1787" /></p>
<p>At the beginning of the world, people had no fire. The only fire anywhere was on top of a high mountain, guarded by the Skookums. You see, these Skookums were not like the fine and friendly Skookums we have today, these Skookums were total hoarders. They didn’t want the people to have fire, because if they did, then maybe they would become as powerful as the Skookums. </p>
<p><img src="http://skookum.com/wp-content/uploads/2012/02/blog_illus_3.png" alt="" title="Skookum Digtial Works Coyote Face" width="555" height="230" class="aligncenter size-full wp-image-1768" /></p>
<p>A coyote thought he’d be sly and go steal a brand of fire and bring it to the people. After consulting his three sisters for advice, (in an odd twist of events, the three sisters lived in the coyote&#8217;s stomach in the form of huckleberries&#8230;but I digress), the coyote lined up all the animals in strategic places along the mountainside in a line between the Skookum’s fire and the people. </p>
<p><img src="http://skookum.com/wp-content/uploads/2012/02/blog_illus_4.png" alt="" title="Skookum Digital Works relay race" width="555" height="230" class="aligncenter size-full wp-image-1769" /></p>
<p>The coyote stole some fire while the Skookum’s were chillaxing, then the animals basically relayed raced the fire until eventually an antelope gave the fire to a frog, who swallowed it. The frog then spat out the fire onto a piece of wood. The Skookum’s—kinda mad at this point—couldn’t figure out how undo the frog-fire-wood-spit, so they went back to the top of the mountain, presumably to resume chillaxing. The coyote then showed the people how to get the fire out of the wood by rubbing sticks together—and that’s why you can eat and be warm now. </p>
<p><img src="http://skookum.com/wp-content/uploads/2012/02/blog_illus_5.png" alt="" title="Skookum Digital Works Fire Sticks" width="555" height="230" class="aligncenter size-full wp-image-1770" /></p>
<p>So, why did I tell you this story? Because today’s Skookums aren&#8217;t hoarders. We don’t want to withhold our technology expertise, our “fire” if you will, from the people.</p>
<p><img src="http://skookum.com/wp-content/uploads/2012/02/blog_illus_2.png" alt="" title="Skookum Digital Works Coyote" width="555" height="230" class="aligncenter size-full wp-image-1767" /></p>
<p>We don’t want coyotes up in our business either. So trust me, we’ll give you the fire. Just ask. Or come to a <a href="http://techtalk.skookum.com/events/calendar/">Friday Tech Talk</a>.</p>
<p><em>*Illustrations by <a href="https://twitter.com/#!/rrobinson81">Rich</a>!</em></p>
<img src="http://feeds.feedburner.com/~r/skookum/blog/~4/mwL5uXf5JAY" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://skookum.com/blog/skookum-digital-works-has-the-fire-we-will-share-it-with-you/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		<feedburner:origLink>http://skookum.com/blog/skookum-digital-works-has-the-fire-we-will-share-it-with-you/</feedburner:origLink></item>
		<item>
		<title>Non-Programmer to Programmer: Introducing Case-Study Jason</title>
		<link>http://feedproxy.google.com/~r/skookum/blog/~3/HePfSYt2was/</link>
		<comments>http://skookum.com/blog/introducing-jason-snodgrass/#comments</comments>
		<pubDate>Mon, 13 Feb 2012 15:05:24 +0000</pubDate>
		<dc:creator>jason</dc:creator>
				<category><![CDATA[Announcements]]></category>
		<category><![CDATA[Culture]]></category>
		<category><![CDATA[learning]]></category>
		<category><![CDATA[new hire]]></category>
		<category><![CDATA[tech talks]]></category>

		<guid isPermaLink="false">http://skookum.com/?p=1706</guid>
		<description><![CDATA[Jason started working at Skookum about five months ago. Before that, he worked at a company that installed and seviced ShoreTel VoIP phone systems. We asked Jason to introduce himself and talk about what he&#8217;s learned coming from a non-programming (though still technical) career into software development. Take it away, Jason. At my last job, [...]]]></description>
			<content:encoded><![CDATA[<p><img class="alignright size-medium wp-image-1712" title="skookum man" src="http://skookum.com/wp-content/uploads/2012/02/skookum-man-300x179.jpg" alt="" width="300" height="179" /></p>
<p><em>Jason started working at Skookum about five months ago. Before that, he worked at a company that installed and seviced ShoreTel VoIP phone systems.</em></p>
<p>We asked Jason to introduce himself and talk about what he&#8217;s learned coming from  a non-programming (though still technical) career into software development. Take it away, Jason.</p>
<hr />
<p>At my last job, along with installing the phone systems, diagnostics and upgrades to the current network were almost always needed to get the needed voice quality. The company was just five people including the owner. The relationships formed within a small team like that are awesome. So why move to NC and take a new job then? <em><a href="http://countrystudies.us/united-states/weather/north-carolina/charlotte.htm">The weather</a>!</em> I lived in north central Ohio&#8230;and like a lot of other NC transplants, I&#8217;d have a hard time going back to grey skies and bad winters.</p>
<p>But from a technical angle, I also was excited about the challenge of doing and learning something new. I&#8217;ve had a desire to improve my knowledge and toolset for some time. Coming to Skookum Digital Works, I really didn&#8217;t know what I would be doing, but it was clear they thought I had the capacity to grow if surrounded with the right teammates.</p>
<p>SDW does software development. I had some experience&#8230;mostly with ASP Classic (no laughing). No PHP. No node, No JavaScript, No CSS. No HTML5. Basically, no experience. Would I measure up? Would I really pick up those languages with the right guides?</p>
<p>Well here I am, five months in. I have not done any ASP Classic programming, but that&#8217;s (more than) OK. What I have done is learned a whole lot. I&#8217;ve picked up more programming skills in the last five months than I had in the rest of my previous jobs combined. I have used PHP, JavaScript and jQuery, node, knockout, CSS, and HTML5. I&#8217;ve also picked up some design and layout tricks, and I&#8217;ve even learned how to stretch and use WordPress as way-more-than a simple CMS.</p>
<p>And, do I like it here? Well, the work environment has a very similar feel to the small company I was at before. Everyone at SDW is awesome, smart, and willing to help when asked. Everyone here likes to operate out of their comfort zone and continue learning new things. And when someone makes a breakthrough, there&#8217;s usually a <a title="Skookum Tech Talks" href="http://techtalk.skookum.com/" target="_blank">tech talk</a> to coincide.</p>
<p>Looking toward the future, I hope to learn as much about new technologies and languages as I can. I want to learn more <a href="http://nodejs.org/" target="_blank">node</a>, and wouldn&#8217;t mind learning Ruby at some point. I also would like to build an iPhone, iPad, or Mac app. There are things I need to be better at, and I am trying hard. My CSS, javascript, and code testing all need improving. I am learning as fast as I possibly can and look forward to learning even more. And as I move forward, a goal of mine is to help keep people informed of the new awesomeness that I find, because we all know, we will never know it all.</p>
<img src="http://feeds.feedburner.com/~r/skookum/blog/~4/HePfSYt2was" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://skookum.com/blog/introducing-jason-snodgrass/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		<feedburner:origLink>http://skookum.com/blog/introducing-jason-snodgrass/</feedburner:origLink></item>
		<item>
		<title>Scraping Poorly Formatted Data with cURL and phpQuery</title>
		<link>http://feedproxy.google.com/~r/skookum/blog/~3/PsQGUMG7J6Q/</link>
		<comments>http://skookum.com/blog/scraping-poorly-formatted-data-with-curl-and-phpquery/#comments</comments>
		<pubDate>Mon, 06 Feb 2012 16:55:31 +0000</pubDate>
		<dc:creator>Mark</dc:creator>
				<category><![CDATA[Code Samples]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[cURL]]></category>
		<category><![CDATA[data]]></category>
		<category><![CDATA[data scraping]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[phpQuery]]></category>

		<guid isPermaLink="false">http://skookum.com/?p=1716</guid>
		<description><![CDATA[cURL is a fantastic way to scrape data from websites. It&#8217;s pretty ubiquitous on LAMP servers nowadays, so you probably don&#8217;t even have to do anything to enable it and start using it. You can essentially get data that&#8217;s behind a login form by spoofing a browser logging into the site. I&#8217;m not going to do a [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://skookum.com/wp-content/uploads/2012/02/poorly_formatted_data.png"><img class="alignright size-medium wp-image-1720" title="poorly_formatted_data" src="http://skookum.com/wp-content/uploads/2012/02/poorly_formatted_data-300x153.png" alt="" width="300" height="153" /></a><a href="http://curl.haxx.se/" target="_blank">cURL</a> is a fantastic way to scrape data from websites. It&#8217;s pretty ubiquitous on LAMP servers nowadays, so you probably don&#8217;t even have to do anything to enable it and start using it. You can essentially get data that&#8217;s behind a login form by spoofing a browser logging into the site.</p>
<p>I&#8217;m not going to do a dissertation on the nuances of using cURL. Instead, I&#8217;d like to discuss how to process data after you&#8217;ve gotten the HTML string from a page using the <span style="font-family: monospace;">curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);</span> setting. The general process using cURL to get the data from a password protected site goes something like this:</p>
<ol>
<li>Make sure your &#8220;cookie jar&#8221; is set up and working so that your session can be saved while you&#8217;re scraping other pages after login.</li>
<li>Get the HTML for the login page.</li>
<ol>
<li>Get the form post location.</li>
<li>Get any special tokens or hidden variables.</li>
</ol>
<li>Post to the login script with your authorized username and password.</li>
<li>Scrape any pages you need to get and process them.</li>
</ol>
<h2>Getting auth tokens and stuff</h2>
<p>Sometimes login pages make it difficult to figure out what to post because of &#8220;authentication tokens&#8221; or similar variables that change every time a page is hit and then have to be posted <em>back</em> along with the username and password. This is most common among .NET applications since it&#8217;s built right in to the .NET form creation classes. The process of finding these variables is made a lot easier if you use <a href="http://code.google.com/p/phpquery/" target="_blank">phpQuery</a>. It&#8217;s a project that attempts to replicate what jQuery does but with PHP. You pass phpQuery a string with all the HTML content in it and then you can perform <a href="http://api.jquery.com/category/selectors/" target="_blank">selectors</a> and <a href="http://api.jquery.com/category/traversing/" target="_blank">traverse</a> the DOM just like with jQuery. What you do with the HTML after that is up to you.</p>
<script src="https://gist.github.com/1752657.js"></script><noscript><p>View the code on <a href="https://gist.github.com/1752657">Gist</a>.</p></noscript>
<p>In the above example, I already had the HTML string of the login page and simply used phpQuery to get all the inputs on the page with a very jQuery-like selector syntax and then looped through the results to get all my input fields for the form so I could use them in my next call to post the data back to the login script.</p>
<h2>Getting poorly formatted data and stuff</h2>
<p>I consider &#8220;well formatted&#8221; data to be in formats like JSON, XML, CSV, etc. that are specifically meant for data transfer. But what heppens when you need to scrape data from HTML tables or DIVs?</p>
<p>phpQuery to the rescue! You can do the same thing as above but parse the newly acquired HTML string of the data you&#8217;re looking for. Here&#8217;s an example of looking at a two column table of data to get all sorts of neat stuff and format it into an array. Then I check for an element outside of the table loop and set another variable.</p>
<script src="https://gist.github.com/1752759.js"></script><noscript><p>View the code on <a href="https://gist.github.com/1752759">Gist</a>.</p></noscript>
<h2>Using the data and stuff</h2>
<p>After you&#8217;re done with that, you have all this useful data in an array and you can basically do whatever you want to it. Since this example I created originated from code used in a real life client project (with variable names changed to protect the innocent), I went on to take that array and save it out to a JSON file that I could easily read in and do what I wanted to with the data.</p>
<p>You may need to go through some tests to get the right kind of cleaning or data sanitization for your values, but phpQuery makes it really easy to scrape this kind of data if you&#8217;re used to jQuery&#8217;s selectors and traversing. Instead of scraping the site each time to get the data, I like saving out the html string to a file and then playing with selectors and traversing to get the data I want form a local file so I don&#8217;t put a lot of strain on the server.</p>
<h2>And don&#8217;t forget stealth&#8230;</h2>
<p>If you&#8217;re not sure how friendly the server (or serveradmin) is to you doing this, make sure you set the cURL user agent for each request. I like  pretending I&#8217;m GoogleBot, but any common user agent string would suffice so that the server doesn&#8217;t explicitly know you&#8217;re PHP trying to log in.</p>
<p>By default, cURL spits out a user agent like this (changes based on operating system and version of cURL):</p>
<pre>curl/7.15.5 (i686-redhat-linux-gnu) libcurl/7.15.5 OpenSSL/0.9.8b zlib/1.2.3 libidn/0.6.5</pre>
<p>If a serveradmin sees that in their logs, they might freak out&#8230; so  I like these user agent strings for sneaky data pulls:</p>
<pre>Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)
Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_2) AppleWebKit/535.7 (KHTML, like Gecko) Chrome/16.0.912.77 Safari/535.7</pre>
<h2>Audience participation</h2>
<p>How do you use cURL and phpQuery? Any useful scripts or resources to point people to other than their respective documentation sites?</p>
<img src="http://feeds.feedburner.com/~r/skookum/blog/~4/PsQGUMG7J6Q" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://skookum.com/blog/scraping-poorly-formatted-data-with-curl-and-phpquery/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://skookum.com/blog/scraping-poorly-formatted-data-with-curl-and-phpquery/</feedburner:origLink></item>
		<item>
		<title>Charlotte Programming Company Helps Business Clients Go Digital</title>
		<link>http://feedproxy.google.com/~r/skookum/blog/~3/O3Z3EHs4Le4/</link>
		<comments>http://skookum.com/blog/charlotte-programming-company-helps-business-clients-go-digital/#comments</comments>
		<pubDate>Mon, 30 Jan 2012 20:17:08 +0000</pubDate>
		<dc:creator>josh</dc:creator>
				<category><![CDATA[Announcements]]></category>
		<category><![CDATA[Business]]></category>
		<category><![CDATA[Culture]]></category>

		<guid isPermaLink="false">http://skookum.com/?p=1693</guid>
		<description><![CDATA[Along with being ranked one of the Best Places to Work in Charlotte, North Carolina, James Hartsell—SDW&#8217;s co-founder and CEO ,was recently profiled by the Charlotte Business Journal. The Q&#038;A is reprinted below. Tell us a little about what Skookum Digital Works does and how it was founded? Skookum Digital Works is a technical partner [...]]]></description>
			<content:encoded><![CDATA[<p><em>Along with being ranked one of the <a href="http://www.bizjournals.com/charlotte/print-edition/2011/11/11/best-places-to-work-top-ranked-small.html?page=all">Best Places to Work in Charlotte, North Carolina</a>, James Hartsell—SDW&#8217;s co-founder and CEO ,was recently profiled by the <a href="http://www.bizjournals.com/charlotte/print-edition/2012/01/27/helping-business-clients-go-digital.html">Charlotte Business Journal</a>. The Q&#038;A is reprinted below.</em></p>
<p><img src="http://skookum.com/wp-content/uploads/2012/01/james_headshot_wide.jpg" alt="Charlotte, North Carolina computer software mobile programming" title="James Hartsell, CEO of Skookum Digital Works" width="620" height="423" class="aligncenter size-full wp-image-1695" /></p>
<p><strong>Tell us a little about what Skookum Digital Works does and how it was founded?</strong><br />
Skookum Digital Works is a technical partner for anyone with a startup dream. We mainly work with entrepreneurs—building out their products or customizing software for businesses. </p>
<p>My co-founder and I, Bryan Delaney, founded Skookum in 2005. We were roommates at UNC Charlotte, both graduated with computer science degrees, and both went to work for the Department of Defense for a few years before deciding we had a better mousetrap. </p>
<p>Bryan and I are Charlotte natives, and we&#8217;re happy to have located our office Uptown. </p>
<p><strong>Do you specialize in any particular types of apps or client base?</strong><br />
I don&#8217;t think its crass of me to say we like to work with <em>funded</em> startups. Our typical client is the non-technical entrepreneur; someone with business skills and ideas but with no programming background. We allow a non-technical entrepreneur to get started on their digital product without having to find a technical co-founder or trying to hire engineers they are not qualified to vet. </p>
<p>Our clients have often heard the word &#8220;No&#8221; elsewhere. We have expertise in the mobile web, complicated software integrations, and real-time web collaboration. </p>
<p><strong>What are some examples of apps Skookum has created?</strong><br />
A publishing company wanted a marketing tool to promote their books. SDW gave them a <a href="http://itunes.apple.com/us/app/mascot-talk/id420673475?mt=8">digital revenue stream</a>.</p>
<p>Some D.C. folks knew independent voters were eager to take collective action. <a href="http://ruck.us">SDW built them a data mining and people matching system</a>.</p>
<p>A group of investors-and-avid-golfers hated the 100+ scoring apps already available. <a href="http://gtgapp.com/">We made players&#8217; phones talk to each other</a>. (!)</p>
<p>A neighborhood of New York businesses disliked Groupon keeping their margins. We created a <a href="http://www.inbundles.com/">localized model they collectively controlled</a>. </p>
<p><strong>What do you think will be the next innovation in smartphone applications?</strong><br />
Mobile apps are going to be easier to download and live outside the walls of the Apple iTunes store and the Android Marketplace. <a href="http://vimeo.com/35539107">Companies can now place their applications on iPhones and iPads without Apple taking 30% of the cut</a>. </p>
<p>Mobile applications are also slowing making their way into retail. Most stores know they can use smartphones and tablet devices to enhance their store experience, but the smaller chains (and certainly the local guys) are waiting to see what the big guys do before making the investment. </p>
<p><strong>Charlotte isn’t really seen as a tech town. Will that ever change?</strong><br />
It&#8217;s fundamentally a marketing problem and one that <a href="http://www.flickr.com/photos/skookumdigitalworks/sets/72157627684737754/">we and 70+ other Charlotte tech leaders have addressed face to face with Mayor Foxx</a>. Aside from numerous <a href="http://www.quora.com/What-are-the-top-startups-in-the-Charlotte-NC-area">local startups</a> and technical partners like ourselves, all of the banks are essentially technology companies. </p>
<p>For just one example, If you took all the programmers out of Bank of America, they would comprise the tenth largest tech company in the world. BoA has technology needs that make engineers at IBM cry. </p>
<p>We like to think we&#8217;re doing our part recruiting talent to the area and flying the flag in front of national entrepreneurs. We have clients all over the place happy to come see us and come visit Charlotte. </p>
<p>Charlotte is already a tech hub, but the city definitely needs to get better about spreading that message. </p>
<img src="http://feeds.feedburner.com/~r/skookum/blog/~4/O3Z3EHs4Le4" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://skookum.com/blog/charlotte-programming-company-helps-business-clients-go-digital/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://skookum.com/blog/charlotte-programming-company-helps-business-clients-go-digital/</feedburner:origLink></item>
		<item>
		<title>Debugging with the Weinre</title>
		<link>http://feedproxy.google.com/~r/skookum/blog/~3/ZrXHrm7nBNE/</link>
		<comments>http://skookum.com/blog/debugging-with-the-weinre/#comments</comments>
		<pubDate>Wed, 11 Jan 2012 17:24:04 +0000</pubDate>
		<dc:creator>dustan</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Mobile]]></category>
		<category><![CDATA[debugging]]></category>
		<category><![CDATA[mobile]]></category>
		<category><![CDATA[remote]]></category>
		<category><![CDATA[strange library names]]></category>

		<guid isPermaLink="false">http://skookum.com/?p=1645</guid>
		<description><![CDATA[weinre. A rather odd accronym indeed. It could be pronounced why • ner • ree. Or wee • ner (which my training of the English language biases me towards). weinre. Web Inspector Remote. This is what happens when developers make and market a product. weinre. Weinre is a tool for remotely debugging your web pages. [...]]]></description>
			<content:encoded><![CDATA[<p><strong>weinre</strong>. A rather odd accronym indeed. It could be pronounced <code>why • ner • ree</code>.<br />
Or <code>wee • ner</code> (which my training of the English language biases me towards).</p>
<p><strong>weinre.</strong> Web Inspector Remote. This is what happens when developers make and market a product.</p>
<h2>weinre.</h2>
<p>Weinre is a tool for remotely debugging your web pages. Let’s say you’re building a responsive web site or a mobile web app. iOS’s Debug Console certainly can’t be the most helpful option for peeking behind the curtain. This is where weinre comes in.</p>
<p>Recently being brought into the Phonegap fold (and therefore Apache and the Apache Incubator), weinre is undergoing active development. You can learn about weinre at<br />
<a href="https://phonegap.github.com/weinre/Home.html">phonegap.github.com/weinre/Home.html</a> or <a href="https://callback.github.com/callback-weinre">callback.github.com/callback-weiner</a> (callback is the Apache Incubator github account).</p>
<blockquote class="float-right">
<p style="margin-top: 0;">Watch a demo<br />
on <a href="http://www.youtube.com/watch?v=gaAI29UkVCc">Youtube</a></p>
</blockquote>
<p>Here, you’ll learn that if you’re on OSX there is <a href="https://nodeload.github.com/pmuellr/weinre/zipball/1.4.0">an app</a> to get you up and running fast. You’ll learn that it’s a javascript-only implementation of the Webkit Inspector. You’ll learn that there are three parts (each with the word “Debug” in it’s name). But what you won’t learn is how to open up your localhost development server to outside devices. For that you came here.</p>
<p>To begin using weinre to remotely debug your projects, simply follow this six step program.</p>
<ol>
<li>Download the mac package from <a href="https://github.com/callback/callback-weinre/archives/master">https://github.com/callback/callback-weinre/archives/master</a></li>
<li>Create the directory and file
<pre>~/.weinre/server.properties</pre>
<p>with the following content:</p>
<pre>boundHost:  -all-</pre>
</li>
<li>Grab this bookmarklet <a href="javascript: (function(d,t,a){ var g=d.createElement(t),s=d.getElementsByTagName(t)[0]; g.src=a.protocol+"//"+a.host+':8080/target/target-script-min.js'; s.parentNode.insertBefore(g,s) })(document, 'script', location);"> Weinrize it!</a></li>
<li>Launch weinre</li>
<li>Run local server and weinre on the same machine while opening the website on your remote device.</li>
<li>Bask in the glory of Webkit Inspector and iOS Development.</li>
</ol>
<p style="font-size: .875em; color: #777;">Disclaimer: Opening up your computer with all boundHosts has security implications.</p>
<p>Happy debugging.</p>
<img src="http://feeds.feedburner.com/~r/skookum/blog/~4/ZrXHrm7nBNE" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://skookum.com/blog/debugging-with-the-weinre/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://skookum.com/blog/debugging-with-the-weinre/</feedburner:origLink></item>
		<item>
		<title>Automated WordPress Plugin Deployment</title>
		<link>http://feedproxy.google.com/~r/skookum/blog/~3/LhyTfROJJlw/</link>
		<comments>http://skookum.com/blog/automated-wordpress-plugin-deployment/#comments</comments>
		<pubDate>Thu, 05 Jan 2012 16:43:30 +0000</pubDate>
		<dc:creator>Mark</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[automation]]></category>
		<category><![CDATA[deploy]]></category>
		<category><![CDATA[git]]></category>
		<category><![CDATA[plugins]]></category>
		<category><![CDATA[scm]]></category>
		<category><![CDATA[svn]]></category>
		<category><![CDATA[wordpress]]></category>

		<guid isPermaLink="false">http://skookum.com/?p=1618</guid>
		<description><![CDATA[Have you ever found a tool that made things so much easier you had to tell as many people about it as soon as possible? Yeah, that just happened to me. A little back story: I wrote a pretty neat WordPress plugin and had it hosted on GitHub. Basically, it takes an iTunes App Store [...]]]></description>
			<content:encoded><![CDATA[<p>Have you ever found a tool that made things so much easier you had to tell as many people about it as soon as possible? Yeah, that just happened to me.</p>
<p><img class="aligncenter size-full wp-image-1636" title="sdw_spacer" src="http://skookum.com/wp-content/uploads/2012/01/sdw_spacer.jpg" alt="" width="600" height="15" /></p>
<h2>A little back story:</h2>
<p>I wrote a pretty neat WordPress plugin and had it <a href="https://github.com/markrickert/App-Display-Page">hosted on GitHub</a>. Basically, it takes an iTunes App Store application ID and fetches all the data about it and displays it on a WordPress site (while caching it for you in the WordPress database).</p>
<p>So I wanted to release it to the world using the WordPress plugin directory&#8230; the go-to location for finding plugins. If it didn&#8217;t live there, it basically had zero chance of getting any usage whatsoever. Nobody goes <a href="https://github.com/search?type=Everything&amp;language=PHP&amp;q=wordpress+plugin">searching GitHub</a> for WordPress plugins.</p>
<p><img class="aligncenter size-full wp-image-1636" title="sdw_spacer" src="http://skookum.com/wp-content/uploads/2012/01/sdw_spacer.jpg" alt="" width="600" height="15" /></p>
<h2>There was <em>one</em> problem&#8230;</h2>
<p>WordPress uses SVN as the required source code management tool for publishing plugins. You <s>clone</s> check out the repository, make your changes, commit them and then tag the new version and the WordPress plugin directory detects the change and within a few minutes, your updated plugin is released to the world and every site that is using your plugin gets a little message at the top of the admin bar asking them to update their version of the plugin.</p>
<p>Except I haven&#8217;t used SVN <a href="http://www.ear-fung.us/2009/11/20/git-versioning-system-just-blew-my-mind/" target="_blank">in about 4 years</a>. Basically the whole world has moved to GIT. There&#8217;s been a exodus from SVN, CVS, Perforce, Mercurial, etc. because of GIT&#8217;s <a href="http://whygitisbetterthanx.com/" target="_blank">ease of use and distributed model</a>.</p>
<p><img class="aligncenter size-full wp-image-1636" title="sdw_spacer" src="http://skookum.com/wp-content/uploads/2012/01/sdw_spacer.jpg" alt="" width="600" height="15" /></p>
<h2>GIT to the rescue</h2>
<p>Recent versions of GIT have really focused on integrating SVN as much as possible. The git-svn command is powerful enough to clone an entire SVN repository and allow you to work on it like it&#8217;s a GIT repository, then commit your history back to the SVN server, and the SVN server is none the wiser.</p>
<p>So I <em>knew</em> there had to be an easy and/or automated way to publish and then submit subsequent updates to my application.</p>
<p><img class="aligncenter size-full wp-image-1636" title="sdw_spacer" src="http://skookum.com/wp-content/uploads/2012/01/sdw_spacer.jpg" alt="" width="600" height="15" /></p>
<h2>tl;dr bro</h2>
<p>I know, I know&#8230;</p>
<p><img class="aligncenter size-full wp-image-1636" title="sdw_spacer" src="http://skookum.com/wp-content/uploads/2012/01/sdw_spacer.jpg" alt="" width="600" height="15" /></p>
<h2>Which brings me to my point:</h2>
<p>With a little Google-fu, I found <a href="http://find.brentshepherd.com/" target="_blank">Brent Shepherd&#8217;s</a> blog post about his <a href="http://thereforei.am/2011/04/21/git-to-svn-automated-wordpress-plugin-deployment/" target="_blank">Automated WordPress Plugin Deployment script</a>. Basically, it&#8217;s a bash script that you download and put into every plugin repos and change a few variables. When you&#8217;re don&#8217;e working on some features, just run ./deploy.sh and it automatically, checks out the SVN plugin, updates it with all your changes, making sure to ignore your GitHub &#8220;README.md&#8221; and the deploy script itself. Then it tags the new version and commits everything back to the WordPress server. It even aborts if it detects your readme.txt file stable version number doesn&#8217;t match your plugin&#8217;s declared version.</p>
<p>Thanks, Brent, for the fantastic deploy script. It worked flawlessly on the first try and my new plugin <a href="http://wordpress.org/extend/plugins/app-display-page/" target="_blank">has been published</a>.</p>
<p>Octocat to the rescue.<br />
<a href="https://github.com/thenbrent/multisite-user-management/blob/master/deploy.sh"><img class="size-thumbnail wp-image-1623 alignnone" title="Well, technically, the Octocat only has 5 arms in the image, but I'm assuming that the rest are perfectly in line with the front legs." src="http://skookum.com/wp-content/uploads/2012/01/github-150x150.png" alt="Well, technically, the Octocat only has 5 arms in the image, but I'm assuming that the rest are perfectly in line with the front legs." width="150" height="150" /></a></p>
<img src="http://feeds.feedburner.com/~r/skookum/blog/~4/LhyTfROJJlw" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://skookum.com/blog/automated-wordpress-plugin-deployment/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://skookum.com/blog/automated-wordpress-plugin-deployment/</feedburner:origLink></item>
		<item>
		<title>Open an iOS App from an Email</title>
		<link>http://feedproxy.google.com/~r/skookum/blog/~3/ho-k7ye12TE/</link>
		<comments>http://skookum.com/blog/open-an-ios-app-from-an-email/#comments</comments>
		<pubDate>Thu, 22 Dec 2011 15:33:49 +0000</pubDate>
		<dc:creator>Mark</dc:creator>
				<category><![CDATA[Code Samples]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[Mobile]]></category>
		<category><![CDATA[apple]]></category>
		<category><![CDATA[ios]]></category>
		<category><![CDATA[objective-c]]></category>
		<category><![CDATA[xcode]]></category>

		<guid isPermaLink="false">http://skookum.com/?p=1585</guid>
		<description><![CDATA[Apple has allowed iOS apps to register their own URL schemes on your devices for a while now, but I&#8217;ve never used this functionality in-depth &#8217;till just recently. Having your app register a URL scheme on a device means that you can open an installed application on a user&#8217;s iPhone or iPad in ONE CLICK from their email (or [...]]]></description>
			<content:encoded><![CDATA[<p>Apple has allowed iOS apps to register their own URL schemes on your devices for a while now, but I&#8217;ve never used this functionality in-depth &#8217;till just recently.</p>
<p>Having your app register a URL scheme on a device means that you can open an installed application on a user&#8217;s iPhone or iPad in ONE CLICK from their email (or the web, or another application). There are all sorts of apps <a href="http://wiki.akosma.com/IPhone_URL_Schemes" target="_blank">already using this functionality</a>.</p>
<h2>Use Case</h2>
<p>We just used this for a project where the client would send confirmation emails to the user after signup. The email would contain an link to a URL. The URL opens in mobile Safari, then launches the app and seamlessly logs the user into the app.</p>
<p>That&#8217;s one use case; there&#8217;s probably others (let us know yours). Another one could be a URL embeded in text—say someone is reading on their iPad and the content could prompt them to hop over to the app.</p>
<h2>Try It Out</h2>
<p>If a user has your app installed on their device, all you have to do is send them to my-great-app://whatever/ and Safari will resign to the background and your app will open. Why don&#8217;t you try it? I <em>know</em> you&#8217;ve got the Facebook app installed on your iPhone. Just clear your address bar and type (or click the link): <a href="fb://profile" target="_blank">fb://profile</a></p>
<p>Go ahead, I&#8217;ll wait.</p>
<p>It opened the Facebook app and took you to your profile page (or gave you a big fat cryptic error message if you don&#8217;t have the Facebook app installed). Facebook allows <a href="http://wiki.akosma.com/IPhone_URL_Schemes#Facebook" target="_blank">a LOT of options</a> that you can pass to the application to take you into various parts of the app.</p>
<h2>Process</h2>
<p>So enough about the Facebook app. What does a developer do if they want to pass a bunch of data to the app—without actually defining what needs to be passed using a bunch of if/else or switch statements?</p>
<p>It&#8217;s fairly trivial to add url scheme to your application&#8217;s Info.plist:</p>
<ol>
<li>Register the url scheme in your Info.plist. Lets say: my-great-app://</li>
<li>In the application delegate, implement this method and return YES:
<pre><a href="http://developer.apple.com/library/ios/#documentation/uikit/reference/UIApplicationDelegate_Protocol/Reference/Reference.html" target="_blank">application:openURL:sourceApplication:annotation:</a></pre>
</li>
<li>That&#8217;s it!</li>
</ol>
<p>I wrote a method you can add to your application that allows the passing of data through the url with key/pair values like so:</p>
<p>my-great-app://user_id/27/token/really9385long5892data/email/user@yourservice.com/</p>
<p>When the user clicks a link like that, or you auto-redirect them from your site to that URL, you can parse the URL into an NSDictionary with this code. Here&#8217;s the method and an example implementation along with some pretty badass comments so you know what the heck is going on:</p>
<script src="https://gist.github.com/1507673.js"></script><noscript><p>View the code on <a href="https://gist.github.com/1507673">Gist</a>.</p></noscript>
<p>Let me know in the comments if you find this useful at all or if you make changes to it.</p>
<img src="http://feeds.feedburner.com/~r/skookum/blog/~4/ho-k7ye12TE" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://skookum.com/blog/open-an-ios-app-from-an-email/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		<feedburner:origLink>http://skookum.com/blog/open-an-ios-app-from-an-email/</feedburner:origLink></item>
		<item>
		<title>Who Says Speed Kills?</title>
		<link>http://feedproxy.google.com/~r/skookum/blog/~3/OKY4l1akgcw/</link>
		<comments>http://skookum.com/blog/who-says-speed-kills/#comments</comments>
		<pubDate>Wed, 21 Dec 2011 18:20:05 +0000</pubDate>
		<dc:creator>steve</dc:creator>
				<category><![CDATA[Business]]></category>
		<category><![CDATA[Culture]]></category>
		<category><![CDATA[Development]]></category>

		<guid isPermaLink="false">http://skookum.com/?p=1550</guid>
		<description><![CDATA[Skookum Digital Works is wicked fast. Speed to market. Speed to prototype. Speed to minimum viable product. Never is developmental speed more apparent than when I think back to my pre-SDW sales life. I ran a software company. Same industry. Same clients. Same challenges. And two completely different approaches to solving those same business needs. [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://skookum.com/blog/who-says-speed-kills/speedkills_web/" rel="attachment wp-att-1556"><img src="http://skookum.com/wp-content/uploads/2011/12/speedkills_web.jpg" alt="" title="speedkills_web" width="600" height="339" class="aligncenter size-full wp-image-1556" /></a><br />
Skookum Digital Works is wicked fast. <strong>Speed to market. Speed to prototype. Speed to minimum viable product.</strong> </p>
<p>Never is developmental speed more apparent than when I think back to my pre-SDW sales life. </p>
<p>I ran a software company. </p>
<p>Same industry.<br />
Same clients.<br />
Same challenges.<br />
And two <strong>completely different approaches</strong> to solving those same business needs. </p>
<p><a href="http://skookum.com/blog/who-says-speed-kills/nun_web/" rel="attachment wp-att-1560"><img src="http://skookum.com/wp-content/uploads/2011/12/nun_web.jpg" alt="" title="nun_web" width="77" height="83" class="alignright size-full wp-image-1560" /></a>Perhaps my impressionable years of growing up in a Parochial school operated by nuns armed with wooden rulers lead to habits that played a role in my partiality for an inflexible, doctrinaire approach to application development.</p>
<p>I thought our 350+ page specifications documents were awesome. I thought our inflexible system produced predictable results. I thought our lumbering process equated thoroughness.</p>
<p>That all changed when I fell in love with Skookum. SDW was the company I always <em>envisioned</em> building. </p>
<p>SDW was nimble.<br />
SDW was able to change course and turn on a dime.<br />
SDW was fast, unfussy, AND thorough.  </p>
<p>Importantly, <strong>SDW also had a full toolbox.</strong> At my .NET shop, we had one hammer, so every problem looked like a nail. </p>
<p>Skookum has its own creative department. Instead of waiting for innovation to come from Microsoft, SDW makes their own. Gone are the square buttons and pull downs of the .NET environment (and expensive licensees), and instead, I can now give clients, chic, state-of-the art solutions emphasizing <strong>intuitive design</strong> and <strong>natural functionality</strong>. </p>
<p>I admit it, I&#8217;ve become an <strong>Agile convert</strong> and enjoy nothing more than winning over clients both former and new. I like showing how they too can be better, faster, and more nimble. Ahead of schedule, and under budget. No fuss, just <strong>shipped code</strong>. </p>
<p>I used to think complex web-based application development meant one thing—mass. </p>
<p>Now I know I was wrong. Whoever said “Speed Kills…” has obviously never worked with Skookum Digital Works before.</p>
<img src="http://feeds.feedburner.com/~r/skookum/blog/~4/OKY4l1akgcw" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://skookum.com/blog/who-says-speed-kills/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		<feedburner:origLink>http://skookum.com/blog/who-says-speed-kills/</feedburner:origLink></item>
		<item>
		<title>Don’t Let String Sanitization Slow You Down</title>
		<link>http://feedproxy.google.com/~r/skookum/blog/~3/tQpZPJZQKcE/</link>
		<comments>http://skookum.com/blog/dont-let-string-sanitization-slow-you-down/#comments</comments>
		<pubDate>Wed, 14 Dec 2011 13:48:10 +0000</pubDate>
		<dc:creator>Corey Ballou</dc:creator>
				<category><![CDATA[Code Samples]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[Experimental Dev]]></category>

		<guid isPermaLink="false">http://skookum.com/?p=1518</guid>
		<description><![CDATA[If you&#8217;ve ever taken a gander at a string sanitization class or library, you&#8217;ve probably noticed the amount of code necessary to keep the script kiddies at bay. We&#8217;re talking about slow string manipulations, i.e. string replacements and regular expressions. Most MVC Frameworks today come with some form of sanitization or input filtering class built [...]]]></description>
			<content:encoded><![CDATA[<p>If you&#8217;ve ever taken a gander at a string sanitization class or library, you&#8217;ve probably noticed the amount of code necessary to keep the <a href="http://en.wikipedia.org/wiki/Script_kiddie" target="_blank">script kiddies</a> at bay. We&#8217;re talking about slow string manipulations, i.e. <em>string replacements</em> and <em>regular expressions</em>.</p>
<p>Most <a href="http://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller" target="_blank">MVC </a>Frameworks today come with some form of sanitization or input filtering class built in. The problem with many of these libraries is that they fail to clean some of the more creative attack vectors. To combat this, some people use drop in libraries like <a href="https://www.owasp.org/index.php/Category:OWASP_AntiSamy_Project" target="_blank">OWASP AntiSamy</a> or <a href="http://htmlpurifier.org/" target="_blank">HTML Purifier</a> to ensure their data is getting scrubbed clean. HTMLPurifier, for instance, uses a Smoke Test via the <a href="http://ha.ckers.org/xss.html" target="_blank">ha.ckers.org</a> XSS attack list (the de-facto standard for finding attack vectors to test, might I add) to ensure they&#8217;re cleaning anything and everything.<span id="more-1518"></span></p>
<h2 style="margin-top:30px">So What&#8217;s The Problem?</h2>
<p>Cleaning a string is slow, to say the least. A slow load time is the bane of your site&#8217;s existence. Customers and visitors hate waiting. The tools mentioned above, as well as any equivalent unmentioned tools, accomplish the task via brute force stripping of characters and numerous regular expressions. Here are a few examples of some common XSS filters out there:</p>
<ul style="margin-bottom: 20px">
<li><a href="http://api.drupal.org/api/drupal/includes--common.inc/function/filter_xss/7" target="_blank">Drupal: filter_xss</a></li>
<li><a href="http://kohanaframework.org/3.0/guide/api/Security#xss" target="_blank">Kohana 3: Security::xss</a></li>
<li><a href="https://github.com/chriso/node-validator/blob/master/lib/xss.js" target="_blank">node-validator: xss.js</a></li>
<li><a href="http://api.rubyonrails.org/classes/ActionView/Helpers/SanitizeHelper.html" target="_blank">Rails 3: SanitizeHelper</a>
</ul>
<p>To optimize these libraries, we need to step back a minute and think about what it is we&#8217;re trying to accomplish. In this case, <em>how can we go about skipping all of the string manipulations and pattern matching with no loss in security?</em></p>
<h2 style="margin-top:30px">So What&#8217;s The Solution?</h2>
<p>There is no catch-all solution, especially if you&#8217;re trying to sanitize HTML coming in from a WYSIWYG editor. There is, however, a very worth-while tweak you can use to make your site&#8217;s sanitization much, much faster under most circumstances. The simple solution is to start your sanitization with a conditional statement which checks to see if the string is already clean of tom-foolery, and return it if so. Grunt work avoided. The reason such a simple trick works is because 99.9% of user input is going to be alpha-numeric with a few sprinkles of punctuation. Don&#8217;t quote me on that.</p>
<script src="https://gist.github.com/1476491.js"></script><noscript><p>View the code on <a href="https://gist.github.com/1476491">Gist</a>.</p></noscript>
<h2 style="margin-top:30px">The Wrap-Up</h2>
<p>It&#8217;s debatable as to what additional characters you can add to this without overly complicating the solution and potentially introducing security holes. I&#8217;ll leave it up to you as the reader to suggest alternative whitelist regexes or punch holes in the solution (like <em><strong>hey guy, how do you know if the character set is in utf-8?</strong></em>). </p>
<img src="http://feeds.feedburner.com/~r/skookum/blog/~4/tQpZPJZQKcE" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://skookum.com/blog/dont-let-string-sanitization-slow-you-down/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		<feedburner:origLink>http://skookum.com/blog/dont-let-string-sanitization-slow-you-down/</feedburner:origLink></item>
	</channel>
</rss>

