<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <title>KuchtaBlog</title>
    <link rel="alternate" type="text/html" href="http://kevinkuchta.webfactional.com/blog/" />
    <link rel="self" type="application/atom+xml" href="http://kevinkuchta.webfactional.com/blog/atom.xml" />
    <id>tag:kevinkuchta.webfactional.com,2009-12-24:/blog/1</id>
    <updated>2012-01-17T19:44:46Z</updated>
    
    <generator uri="http://www.sixapart.com/movabletype/">Movable Type 4.32-en</generator>

<entry>
    <title>Basic Authentication with JSONP</title>
    <link rel="alternate" type="text/html" href="http://kevinkuchta.webfactional.com/blog/2012/01/basic-authentication-with-jsonp.html" />
    <id>tag:kevinkuchta.webfactional.com,2012:/blog//1.24</id>

    <published>2012-01-17T19:03:09Z</published>
    <updated>2012-01-17T19:44:46Z</updated>

    <summary>JSONP background JSONP is the name for a technique to get around the same-origin policy. It works pretty well when you&#8217;re trying to make a cross-domain request- for example, to some service&#8217;s api, without using a server proxy. In my...</summary>
    <author>
        <name>Kevin</name>
        <uri>http://www.kevinkuchta.com</uri>
    </author>
    
    <category term="jsonpajaxauthentication" label="jsonp ajax authentication" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en-US" xml:base="http://kevinkuchta.webfactional.com/blog/">
        <![CDATA[<h2>JSONP background</h2>

<p><a href="http://en.wikipedia.org/wiki/JSONP">JSONP</a> is the name for a technique to get around the <a href="http://en.wikipedia.org/wiki/Same_origin_policy">same-origin policy</a>.  It works pretty well when you&#8217;re trying to make a cross-domain request- for example, to some service&#8217;s api, without using a server proxy.  In my case, I was trying to build a tool that would work from a flat file.</p>

<h2>The problem</h2>

<p>JSONP <a href="http://stackoverflow.com/questions/1640391/how-do-i-make-a-jsonp-call-with-jquery-with-basic-authentication">doesn&#8217;t work</a> with basic authentication.  We can verify this by skipping the jquery shortcuts and trying a very simple jsonp request by hand:</p>

<pre><code> function makeRequest(username,password){
    var url = "https://" + username + ":" + password + "@api.github.com/user?callback=jsonpCallback";
    var scriptToAdd = $('&lt;script type="text/javascript" src=""&gt;&lt;/script&gt;');
    scriptToAdd.attr('src',url);
    $('body').append(scriptToAdd);
}
function jsonpCallback(response){
    console.log( "response=",response );
}
</code></pre>

<p>The above code attempts to make an authenticated request by appending a script tag with an src of &#8220;user:pass@host.com/path.&#8221;  Test it out by adding that (and jquery) to a page running <code>makeRequest( 'kkuchta', 'hunter2' );</code>, substituting your username and password, of course.  Inspect the resulting object, and you&#8217;ll see that the authentication failed.</p>

<h2>The solution</h2>

<p>Script tags may not like authentication in the url, but image tags don&#8217;t mind it.  Furthermore, basic authentication will get cached.  As such, all we need to do it add an image element whose src is our url with basic auth, then wait for it to load:</p>

<pre><code>function makeRequest(username,password){
    var imgUrl = "https://" + username + ":" + password + "@api.github.com/user";
    var scriptUrl = "https://api.github.com/user?callback=jsonpCallback";

    // Attach image to cache auth
    var img = $('&lt;img /&gt;').attr( "src", imgUrl );
    $('body').append(img);
    img.remove();

    // Let the image load, then do the jsonp request
    setTimeout(function(){
        var scriptToAdd = $('&lt;script type="text/javascript"&gt;&lt;/script&gt;');
        scriptToAdd.attr('src',scriptUrl);
        $('body').append(scriptToAdd);
    },1000);
}
function jsonpCallback(response){
    console.log( "response=",response );
}
</code></pre>

<p>Again, try <code>makeRequest( 'someGithubUser', 'someGithubPass' )</code>.  This time, the resulting object should the correct, authenticated response.  Jsonp with basic auth, woo!  You should only have to do this once per session- all jsonp requests thereafter should be go right past the authentication.  This also works fine with at least jQuery&#8217;s jsonp- presumably any other jsonp wrapper as well.</p>
]]>
        

    </content>
</entry>

<entry>
    <title>Mac shell script to toggle socks proxy</title>
    <link rel="alternate" type="text/html" href="http://kevinkuchta.webfactional.com/blog/2011/08/mac-shell-script-to-toggle-socks-proxy.html" />
    <id>tag:kevinkuchta.webfactional.com,2011:/blog//1.23</id>

    <published>2011-08-05T19:57:40Z</published>
    <updated>2011-08-05T20:06:46Z</updated>

    <summary>What A simple script that&#8217;ll toggle your System Preferences proxy settings on a Mac. It takes one argument- the name of the interface on which to toggle the proxy (eg, &#8216;Airport&#8217; or &#8216;Ethernet&#8217;). You can easily wrap this with an...</summary>
    <author>
        <name>Kevin</name>
        <uri>http://www.kevinkuchta.com</uri>
    </author>
    
    
    <content type="html" xml:lang="en-US" xml:base="http://kevinkuchta.webfactional.com/blog/">
        <![CDATA[<h3>What</h3>

<p>A simple script that&#8217;ll toggle your System Preferences proxy settings on a Mac.  It takes one argument- the name of the interface on which to toggle the proxy (eg, &#8216;Airport&#8217; or &#8216;Ethernet&#8217;).  You can easily wrap this with an automator script using the &#8220;Get specified text&#8221; action to provide the argument and the &#8216;Shell Script&#8217; action to run the script.</p>

<p>Uses growl to notify you of what it&#8217;s done.  That can be removed if you want- just delete the end of the script below the relavent comment.</p>

<h3>How</h3>

<p>Nothing too complex here- uses the mac command line &#8216;networksetup&#8217; tool, which allows command-line modification of network setting, to get and set the proxy state.  Then it uses the mac command line &#8216;osascript&#8217; tool, which runs apple script, to notify growl.  The applescript in question just registers itself, then sends the message.</p>

<h3>Code</h3>

<pre><code># Get current status
interface=$1
status=`networksetup -getsocksfirewallproxy $interface | grep "^Enabled: [a-zA-z]*$"`
echo "status=$status"
if [ "`echo $status | grep "No"`" ]; then
    newState="on"
else
    newState="off"
fi

# Set new state
networksetup -setsocksfirewallproxystate Airport $newState

# Print message (delete after here to remove growl notification)
if [ "$status" ]; then
    message="$interface socks proxy is now $newState"
else
    message="Error toggling socks proxy on interface:'$interface'"
fi
osascript -e 'tell application "GrowlHelperApp"' -e 'set the allNotificationsList to {"Toggled"}' -e 'set the enabledNotificationsList to {"Toggled"}' -e 'register as application "Proxy Toggler" all notifications allNotificationsList default notifications enabledNotificationsList' -e "notify with name \"Toggled\" title \"Toggled\" description \"$message\" application name \"Proxy Toggler\"" -e 'end tell'
</code></pre>
]]>
        

    </content>
</entry>

<entry>
    <title>Matching PHP and JS Encryption</title>
    <link rel="alternate" type="text/html" href="http://kevinkuchta.webfactional.com/blog/2011/08/matching-php-and-js-encryption.html" />
    <id>tag:kevinkuchta.webfactional.com,2011:/blog//1.22</id>

    <published>2011-08-02T04:05:25Z</published>
    <updated>2011-08-02T04:19:51Z</updated>

    <summary>Problem You&#8217;d think that encryption is in encryption- AES is AES, DES is DES, etc. Encrypt with scheme X, decrypt with scheme X, and it comes out clean. Turns out, though, that it&#8217;s not that easy. Or rather, it is,...</summary>
    <author>
        <name>Kevin</name>
        <uri>http://www.kevinkuchta.com</uri>
    </author>
    
    
    <content type="html" xml:lang="en-US" xml:base="http://kevinkuchta.webfactional.com/blog/">
        <![CDATA[<h2>Problem</h2>

<p>You&#8217;d think that encryption is in encryption- AES is AES, DES is DES, etc.  Encrypt with scheme X, decrypt with scheme X, and it comes out clean.  Turns out, though, that it&#8217;s not that easy.  Or rather, it is, but the relevant libraries on different platforms like to do things different.  Consider that to encrypt/decrypt something with AES you need:</p>

<ul>
<li>To use the same mode (CBC, EBC, etc)</li>
<li>The same block type for block cipher modes</li>
<li>The same key size (128 bit, 256 bit, etc)</li>
<li>The same key (of course)</li>
<li>The same initialization vector</li>
<li>To know whether the library pads/truncates your key</li>
<li>To know whether/how the library hashes your key</li>
<li>To know whether the library includes necessary extra information (plaintext size and IV) in its output or whether you need to keep track of that yourself</li>
<li>To know whether your ciphertext output it hex, base64 encoded, UTF8, or whatever.</li>
</ul>

<p>In further fun, the libraries you&#8217;re looking at may only expose half of these variables and just pick their own numbers for the other half.</p>

<p>So, when you need to encrypt something client-side and decrypt it in, say, PHP, it&#8217;s not as simple as you&#8217;d like.</p>

<h4>Quick Aside</h4>

<p>Why would you want to encrypt client-side!  That&#8217;s insane!  Well, the short version is that I&#8217;m not hiding data from bad guys- I&#8217;m hiding it from my own system.  What&#8217;s happening is that the user is entering credential information for an external system.  That includes a username + password, plus some variable other stuff.  The variable other stuff (VOS for now) is what needs to get encrypted.  The username and password are already treated with kid gloves in our system- they&#8217;re not saved, they&#8217;re blocked out if a dev tries to log them, etc.  The VOS, though, is new, and we&#8217;re passing it back as part of a complex data object that <em>isn&#8217;t</em> treated carefully- it could end up in analytics, logs, dump files, emails, etc.  As such, we&#8217;re encrypting it client-side with the user&#8217;s password and decrypting it just before we need to send it to the external system (a point at which we also have the user&#8217;s password).  As such, if it accidentally gets logged or something, it&#8217;s not stored in the clear.</p>

<h2>Solution time</h2>

<p>Not that complex, just putting it here because there didn&#8217;t seem to be a good ready-made recommendation anywhere I google.</p>

<p>I ended up using <a href="http://code.google.com/p/slowaes/">SlowAES</a>, which is fast enough for many purposes.  It comes with parallel implementations in PHP, JS, Python and Ruby.  They each take the same parameters and use the same utilities, so it&#8217;s easy to get them to line up.  To save you some time, here&#8217;s a simple use example for PHP and JS (not thoroughly tested because we decided to go for another solution before this made it to that point, but anyway):</p>

<p><strong>encrypt.php</strong></p>

<pre><code>&lt;?php
require( 'slowaes/php/aes_fast.php');
require( 'slowaes/php/cryptoHelpers.php');

/*
 * Encrypts and decrypts plaintext with a given key.  Written to be compatible
 * with it's counterpart in js.  Uses AES.  Uses the slowAES encryption lib,
 * which is more than fast enough for our purposes; using it here because it
 * has several parallel versions in different languages (mainly php and js).
 *
 * Usage: Encrypt takes any string as the plaintext and any string as the key.
 *      Decrypt takes the output of encrypt and the same key used to encrypt.
 *
 * Details you might care about:
 *      The encryption output is really 3 space-seperated strings: 
 *      - The length of the original plaintext string as an integer
 *      - The Initialization Vector (iv).  This is just a random string that
 *        will be different each encryption, and can be sent in the clear
 *        with the ciphertext.  This is a hex string.
 *      - The ciphertext itself, as a hex string.
 *
 * Crypto details you won't care about unless you're setting up another set of
 * methods to match these ones:
 *      - AES (Rijndael, or very close, I think)
 *      - 256 bit key
 *      - 128 bit IV
 *      - CBC mode
 *
 **/
function encrypt( $plaintext, $key ){

    // Set up encryption parameters.
    $plaintext_utf8 = utf8_encode($plaintext);
    $inputData = cryptoHelpers::convertStringToByteArray($plaintext);
    $keyAsNumbers = cryptoHelpers::toNumbers(bin2hex($key));
    $keyLength = count($keyAsNumbers);
    $iv = cryptoHelpers::generateSharedKey(16);

    $encrypted = AES::encrypt(
        $inputData,
        AES::modeOfOperation_CBC,
        $keyAsNumbers,
        $keyLength,
        $iv
    );

    // Set up output format (space delimeted "plaintextsize iv cipher")
    $retVal = $encrypted['originalsize'] . " "
        . cryptoHelpers::toHex($iv) . " "
        . cryptoHelpers::toHex($encrypted['cipher']);

    return $retVal;
}

function decrypt( $input, $key ){

    // Split the input into its parts
    $cipherSplit = explode( " ", $input);
    $originalSize = intval($cipherSplit[0]);
    $iv = cryptoHelpers::toNumbers($cipherSplit[1]);
    $cipherText = $cipherSplit[2];

    // Set up encryption parameters
    $cipherIn = cryptoHelpers::toNumbers($cipherText);
    $keyAsNumbers = cryptoHelpers::toNumbers(bin2hex($key));
    $keyLength = count($keyAsNumbers);

    $decrypted = AES::decrypt(
        $cipherIn,
        $originalSize,
        AES::modeOfOperation_CBC,
        $keyAsNumbers,
        $keyLength,
        $iv
    );

    // Byte-array to text.
    $hexDecrypted = cryptoHelpers::toHex($decrypted);
    $retVal = pack("H*" , $hexDecrypted);

    return $retVal;
}

/**
 * Some simple testing code
 **/

$plaintext = "Testing the php encryption/decryption. Unicode LOD: ಠ_ಠ!";
$key = "multipass!";
$cipherText = encrypt($plaintext,$key);
$result = decrypt($cipherText,$key);
?&gt;
&lt;!doctype html&gt;
&lt;html lang="en"&gt;&lt;head&gt;&lt;meta charset="UTF-8"&gt;&lt;/head&gt;&lt;body&gt;
    &lt;h1&gt;Encrypting&lt;/h1&gt;
    &lt;b&gt;plaintext:&lt;/b&gt; &lt;?= $plaintext ?&gt; &lt;br&gt;
    &lt;b&gt;key:&lt;/b&gt; &lt;?= $key ?&gt; &lt;br&gt;
    &lt;b&gt;raw cipherText:&lt;/b&gt; &lt;?= $cipherText ?&gt; &lt;br&gt;
    &lt;h1&gt;Decrypting&lt;/h1&gt;
    &lt;b&gt;result:&lt;/b&gt;&lt;?= $result ?&gt;
&lt;/body&gt;&lt;/html&gt;
</code></pre>

<p><strong>encrypt.js.html</strong></p>

<pre><code>/**
 * An encryption setup to match our server-side one; see there for
 * documentation on it.
 **/
function decrypt(input, key){

    // Split the input into its compontents
    var inputSplit = input.split(" ");
    var originalSize = parseInt(inputSplit[0]);
    var iv = cryptoHelpers.toNumbers(inputSplit[1]);
    var cipherIn = cryptoHelpers.toNumbers(inputSplit[2]);

    // Set up encryption parameters
    var keyAsNumbers = cryptoHelpers.toNumbers( bin2hex( key ) );

    var decrypted = slowAES.decrypt(
        cipherIn,
        slowAES.modeOfOperation.CBC,
        keyAsNumbers,
        iv
    );

    // Byte-array to text
    var retVal = hex2bin(cryptoHelpers.toHex(decrypted));
    retVal = cryptoHelpers.decode_utf8(retVal);

    return retVal;
}

function encrypt( plaintext, key ){

    // Set up encryption parameters
    plaintext = cryptoHelpers.encode_utf8(plaintext);
    var inputData = cryptoHelpers.convertStringToByteArray(plaintext);
    var keyAsNumber = cryptoHelpers.toNumbers(bin2hex(key));
    var iv = cryptoHelpers.generateSharedKey(16);

    var encrypted = slowAES.encrypt(
        inputData,
        slowAES.modeOfOperation.CBC,
        keyAsNumber,
        iv
    );

    // Set up output format (space delimeted "plaintextsize iv cipher")
    var retVal = plaintext.length + " "
        + cryptoHelpers.toHex(iv) + " "
        + cryptoHelpers.toHex(encrypted);

    return retVal;
}

// Equivilent to PHP bin2hex
function bin2hex (s) {
    var i, f = 0,
        a = [];

    s += '';
    f = s.length;

    for (i = 0; i &lt; f; i++) {
        a[i] = s.charCodeAt(i).toString(16).replace(/^([\da-f])$/, "0$1");
    }

    return a.join('');
}

// Equivilent to PHP hex2bin
function hex2bin(hex) {
    var str = '';
    for (var i = 0; i &lt; hex.length; i += 2)
        str += String.fromCharCode(parseInt(hex.substr(i, 2), 16));
    return str;
}

/**
 * Some simple testing code
 **/
$(function(){
    var key = "multipass!";
    var plaintext = "Testing the php encryption/decryption. Unicode LOD: ಠ_ಠ!";
    var output = "";
    var cipherText = encrypt(plaintext,key);
    var newPlaintext = decrypt(cipherText,key);
    output += ("&lt;br&gt;plaintext=" + plaintext);
    output += ("&lt;br&gt;cipherText=" + cipherText);
    output += ("&lt;br&gt;newPlaintext=" + newPlaintext);

    $('#output').html(output);
});
</code></pre>

<p>Remember that this is probably neither efficient nor elegant.  It hasn&#8217;t been tested extensively, so use at your own risk.  Should do the job, though.  The full code is zipped up here: <a href="http://kevinkuchta.webfactional.com/blog/JS_PHP_Encryption%202.zip">JS<em>PHP</em>Encryption 2.zip</a></p>
]]>
        

    </content>
</entry>

<entry>
    <title>Converting State Plane Coordinates in Ruby</title>
    <link rel="alternate" type="text/html" href="http://kevinkuchta.webfactional.com/blog/2011/04/converting-state-plane-coordinates-in-ruby.html" />
    <id>tag:kevinkuchta.webfactional.com,2011:/blog//1.21</id>

    <published>2011-04-09T18:59:36Z</published>
    <updated>2011-04-09T19:22:19Z</updated>

    <summary>I got a pile of data with coordinates last night. The coordinates were in State Plane NY West format, which is a semi-state specific coordinate system that needs to be translated before you can use it like latitude/longitude. There are...</summary>
    <author>
        <name>Kevin</name>
        <uri>http://www.kevinkuchta.com</uri>
    </author>
    
    
    <content type="html" xml:lang="en-US" xml:base="http://kevinkuchta.webfactional.com/blog/">
        <![CDATA[<p>I got a pile of data with coordinates last night.  The coordinates were in State Plane NY West format, which is a <a href="http://en.wikipedia.org/wiki/State_Plane_Coordinate_System">semi-state specific</a> coordinate system that needs to be translated before you can use it like latitude/longitude.  There are better references out there if you want a thorough treatise on the subject, but I thought I&#8217;d give the concrete solutions I came up with in case you, like me, just want to get lat/lon and could hardly care less about 80&#8217;s era cartography.</p>

<ol>
<li><p>Install <a href="http://trac.osgeo.org/proj/">proj4</a>, the 80&#8217;s-era c library that everything relating to geospatial coordinate transformations seems to be built on.  This is <em>related to</em> and possibly the basis for, but not actually the same thing as <a href="http://gdal.org/">gdal</a>.  Gdal has some handy command-line tools in case you don&#8217;t need to do this programmatically.  Further, it takes similar projection strings as proj4.</p>

<p>Anyway, build it from source.  I had no trouble on Mac OS 10.6.</p></li>
<li><p>Install the <a href="https://rubyforge.org/projects/proj4rb/">ruby bindings</a>.  I had to build from source here (ruby 1.9.2) too- their build instructions were pretty handy.  Just go through the configure/make/make install stuff, then rake as a gem, then gem install that local gem.</p></li>
<li><p>Code it up:</p>

<pre><code>require 'proj4'
proj = Proj4::Projection.new '+proj=tmerc +lat_0=40 +lon_0=-78.58333333333333 +k=0.9999375 +x_0=350000 +y_0=0 +ellps=GRS80 +units=ft +no_defs'
geox = 1394144.401
geoy = 1165107.387
latlon = proj.inverse Proj4::Point.new(geox,geoy)
converter = (180 / Math::PI)
puts "lat = " + (latlon.lat * converter).to_s
puts "lon = " + (latlon.lon * converter).to_s
</code></pre></li>
</ol>

<p>Note that geox and geoy are the inputs.  The string of parameters in the call to Projection.new is what defines the initial projection (that is, the state plane) that the input is on.  You&#8217;ll want to replace that with the one for your state.  To get that info:</p>

<ol>
<li>Go to http://home.comcast.net/~rickking04/gis/spc.htm and look up your FIPS zone.  Mine is 3103, since my data is for Monroe county, NY.</li>
<li>Go to http://spatialreference.org/ref/esri/ and enter your state.  There should be a short list of results, one of which has your FIPS zone in it.  Mine is &#8220;ESRI:102317: NAD 1983 HARN StatePlane New York West FIPS 3103&#8221;.  Click on it.</li>
<li>Click on the &#8220;Proj4&#8221; link, which should take you to the string you want.  Mine is &#8220;+proj=tmerc +lat<em>0=40 +lon</em>0=-78.58333333333333 +k=0.9999375 +x<em>0=350000 +y</em>0=0 +ellps=GRS80 +units=m +no_defs&#8221;.  Note that you may need to change the &#8216;units&#8217; element in that string- mine was in feet, which is &#8216;ft&#8217;.</li>
</ol>
]]>
        

    </content>
</entry>

<entry>
    <title>Facebook iFrame Authorization</title>
    <link rel="alternate" type="text/html" href="http://kevinkuchta.webfactional.com/blog/2011/02/facebook-iframe-authorization.html" />
    <id>tag:kevinkuchta.webfactional.com,2011:/blog//1.20</id>

    <published>2011-02-01T06:18:31Z</published>
    <updated>2011-02-01T06:56:31Z</updated>

    <summary>So, it turns out that any facebook page, when loaded in an iframe, will explode. That is, it&#8217;ll display the facebook logo and nothing else. It&#8217;d say it&#8217;s an anti-clickjacking measure, if I had to guess. The problem is that...</summary>
    <author>
        <name>Kevin</name>
        <uri>http://www.kevinkuchta.com</uri>
    </author>
    
    <category term="facebook" label="Facebook" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="oauth" label="OAuth" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="rails" label="Rails" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="seniorproject" label="SeniorProject" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en-US" xml:base="http://kevinkuchta.webfactional.com/blog/">
        <![CDATA[<p>So, it turns out that any facebook page, when loaded in an iframe, will explode. That is, it&#8217;ll display the facebook logo and nothing else. It&#8217;d say it&#8217;s an anti-clickjacking measure, if I had to guess.</p>

<p>The problem is that this applies to /any/ iframe, including facebook&#8217;s own. This presents a problem when trying to load facebook&#8217;s authorization page in a facebook iframe-based app. This was a problem as of Jan 1, 2011, but facebook changes things so fast that it may be resolved by now. If not, here&#8217;s how to fix it.</p>

<h4>How it should work:</h4>

<ol>
<li>User loads apps.facebook.com/myapp, which loads myserver.com/fb_content/start in an iframe, which, upon detecting that the user has not authorized the app, will redirect to-</li>
<li>Facebook&#8217;s authorization page (still in the iframe).  If the user clicks &#8220;Allow&#8221;, it&#8217;ll redirect to whatever url you passed in the redirect, such as-</li>
<li>myserver.com/fb<em>content/cool</em>authorized/stuff (still in the iframe)</li>
</ol>

<p>Of course, as stated, step 2 blows up.</p>

<h4>How to make it work</h4>

<ol>
<li>User loades apps.facebook.com/myapp, which loads myserver.com/fb_content/start in an iframe, which, upon detecting that the user has not authorized the app, will <em>javascript</em> redirect (busting out of the frame) to:</li>
<li>Facebook&#8217;s authorization page (<em>not</em> in an iframe).  If the user clicks &#8220;Allow&#8221;, it&#8217;ll redirect to the url passed, which gets you back to-</li>
<li>myserver.com/fb_content/start (<em>not</em> in an iframe), since facebook authorization won&#8217;t redirect to a domain that&#8217;s not yours (eg, can&#8217;t do apps.facebook.com), so you need to first redirect to a page you control, detect that you&#8217;re not in an iframe, and so redirect to-</li>
<li>apps.facebook.com/myapp, which loads myserver.com/fb_content/start in an iframe, which, upon detecting that the user <em>has</em> authorized your app, will redirect to-</li>
<li>myserver.com/fb<em>content/cool</em>authorized/stuff (still in the iframe)</li>
</ol>

<p>Luckily, this all looks like &#8220;How it should work&#8221; to the user if the redirects are fast.</p>

<h4>Rails code to do it</h4>

<p>In app/controllers/oauth_controller:</p>

<pre><code>def start
    require 'uri'
    escaped_callback_url = URI.escape(FB_CONFIG['callback_url'], Regexp.new("[^#{URI::PATTERN::UNRESERVED}]"))
    signed_request_data = decode_signed_request(FB_CONFIG['app_secret'],params[:signed_request])

    if(signed_request_data)
        if(signed_request_data["user_id"] != nil)
            # User has already or just accepted the app
            session['auth_token'] = signed_request_data['oauth_token']
            redirect_to "wherever you want to go after authentication"
        else
            # User hasn't accepted our app
            @redirect_url = "https://graph.facebook.com/oauth/authorize?client_id=#{FB_CONFIG['app_id']}&amp;redirect_uri=#{escaped_callback_url}&amp;display=page&amp;scope=publish_stream,user_photo_video_tags&amp;type=user_agent&amp;display=page"
        end
    else        
        #We're not in a facebook iframe
        redirect_to FB_CONFIG['app_url']
    end
end

private
    require 'base64'
    def base64_url_decode(str)
      str += '=' * (4 - str.length.modulo(4))
      Base64.decode64(str.gsub("-", "+").gsub("_", "/"))
    end

    require 'hmac-sha2'
    # used to validate signed requests from facebook http://developers.facebook.com/docs/authentication/canvas
    def decode_signed_request(facebook_secret, signed_request)
        if(signed_request==nil)
            return nil
        end
        if(facebook_secret==nil)
            raise "Facebook secret not set."
        end
      encoded_sig, encoded_data = signed_request.split(".")
      decoded_data = base64_url_decode(encoded_data)
      decoded_sig = base64_url_decode(encoded_sig)
        logger.info "Decoded data = " + decoded_data.inspect
        logger.info "Json parsed decoded data = " + ActiveSupport::JSON.decode(decoded_data).inspect
        expected_sig = HMAC::SHA256.digest(facebook_secret, encoded_data)
      return decoded_sig==expected_sig ? ActiveSupport::JSON.decode(decoded_data) : nil
    end
</code></pre>

<p>In app/views/oauth:</p>

<pre><code>&lt;% if @redirect_url %&gt;
    &lt;script type='text/javascript'&gt;top.location.href = '&lt;%= raw @redirect_url %&gt;';&lt;/script&gt;
&lt;% end %&gt;
</code></pre>

<p>In config/initializers/load_config:</p>

<pre><code>FB_CONFIG = YAML.load_file("#{RAILS_ROOT}/config/facebook.yml")[RAILS_ENV]
</code></pre>

<p>In config/facebook.yml:</p>

<pre><code>production:
    app_id: '1234your_app_id'
    api_key: '1234your_app_key'
    app_secret: '1234your_app_secret'
    callback_url: "myserver.com/fb_content/start"
    app_url: http://apps.facebook.com/myapp
</code></pre>

<p>In Gemfile:</p>

<pre><code>gem 'json'
gem 'ruby-hmac'
</code></pre>
]]>
        

    </content>
</entry>

<entry>
    <title>How to analyze global functions from a Chrome content script</title>
    <link rel="alternate" type="text/html" href="http://kevinkuchta.webfactional.com/blog/2010/12/how-to-analyze-global-functions-from-a-chrome-content-script.html" />
    <id>tag:kevinkuchta.webfactional.com,2010:/blog//1.18</id>

    <published>2010-12-17T23:12:07Z</published>
    <updated>2010-12-24T20:44:48Z</updated>

    <summary><![CDATA[So, it turns out that the code run in chrome content scripts run in their own context. As such, I can&#8217;t access global variables set by in-page code. However, chrome content scripts do use the same DOM. Further, when &lt;script>...]]></summary>
    <author>
        <name>Kevin</name>
        <uri>http://www.kevinkuchta.com</uri>
    </author>
    
    
    <content type="html" xml:lang="en-US" xml:base="http://kevinkuchta.webfactional.com/blog/">
        <![CDATA[<p>So, it turns out that the code run in chrome content scripts run in their own context.  As such, I can&#8217;t access global variables set by in-page code.  However, chrome content scripts do use the same DOM.  Further, when  &lt;script> elements are inserted into the DOM dynamically, they&#8217;re run using the page&#8217;s context, and can access those global variables/functions.</p>

<p>In this example, insertToDOM just adds the code as the content of a script element to the <head> element (this code uses JQeury, but you could easily do it without.</p>

<pre><code>function insertToDOM(code){
    $("head").append( $('&lt;script language="javascript"&gt;' + code + '&lt;/script&gt;'));
}
</code></pre>

<p>Now, to get all user-defined functions, we need to filter out all the normal javascript functions.  In this case, we&#8217;re analyzing the function bodies- built-in functions will have bodies containing &#8220;[native code]&#8221;, so we can just get rid of those.  Everything that reaches the <code>console.log(window[f].toString());</code> line will be a user-defined function.  Note that the toString method called on a function object will return its body.</p>

<pre><code>insertToDOM(
    'for (var f in window){'+
        'bodyString = window[f]!=null ? window[f].toString() : "";'+
        'if(bodyString.indexOf != null &amp;&amp; bodyString.indexOf("[native code]")==-1 &amp;&amp; bodyString.indexOf("function ")!=-1 ){'+
            'console.log(window[f].toString());'+
        '}'+
    '}'
);
</code></pre>

<h3>Irrelevant background</h3>

<p>This code is part of an ongoing christmas javascript war I&#8217;m having with the webmaster of a forum I frequent.  He annually covers his site with christmas themed decorations and obnoxious mouse-following reindeer.  I wrote a chrome plugin to revert it.  He wrote a script to detect my code and redirect to internet shock sites if it&#8217;s found.  We&#8217;ve been going back and forth recently- he&#8217;ll fix his code, I&#8217;ll fix mine.  This is my latest blow- a variant on this detects if the function body contains redirect code and kills the function if it does.  I could just fix my code following his next move and then just stop publishing my code, but where&#8217; the fun in that?  :D</p>

<p>Code for the above plugin, if anyone&#8217;s interested, can be found at https://sse.se.rit.edu/hg-manage/kmk3817</p>

<p><strong>Edit:</strong> For a later version of this I threw together an insertToDom function that takes a function object, chops out the body, and inserts that.  So, passing in &#8220;function(){alert(&#8220;test&#8221;);}&#8221; will add &#8220;alert(&#8220;test&#8221;)&#8221; to the DOM in a script element.</p>

<pre><code>function insertToDOM(func){
    //everything between the first and last brackets.
    funcString = func.toString();
    funcStringArray1 = funcString.split("}");
    funcStringArray1.pop();
    funcString = funcStringArray1.join("}");
    funcStringArray2 = funcString.split("{");
    funcStringArray2.shift();
    funcBody = funcStringArray2.join("{");
    $("head").append( $('&lt;script language="javascript"&gt;' + funcBody + '&lt;/script&gt;'));
}
</code></pre>
]]>
        

    </content>
</entry>

<entry>
    <title>Engineer&apos;d</title>
    <link rel="alternate" type="text/html" href="http://kevinkuchta.webfactional.com/blog/2010/10/engineerd.html" />
    <id>tag:kevinkuchta.webfactional.com,2010:/blog//1.17</id>

    <published>2010-10-18T02:52:03Z</published>
    <updated>2010-10-18T03:45:10Z</updated>

    <summary>I&#8217;m sick of Facebook&#8217;s liking system. I can see their idea, but it&#8217;s become complete crap. 99% of &#8220;likes&#8221; that show up in my feed are either thoroughly inane our outright malicious (seriously, I never thought I&#8217;d see this much...</summary>
    <author>
        <name>Kevin</name>
        <uri>http://www.kevinkuchta.com</uri>
    </author>
    
    <category term="facebookjavascriptchrome" label="facebook javascript chrome" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en-US" xml:base="http://kevinkuchta.webfactional.com/blog/">
        <![CDATA[<p>I&#8217;m sick of Facebook&#8217;s liking system.  I can see their idea, but it&#8217;s become complete crap.  99% of &#8220;likes&#8221; that show up in my feed are either thoroughly inane our outright malicious (seriously, I never thought I&#8217;d see this much clickjacking in the wild).</p>

<p>So, here&#8217;s a prototype of a script to remove them from the front page:</p>

<p><strong>Edit:</strong> Newer version, now with 50% less fail (lots of false positives).</p>

<pre><code>var likeRegex = /.*likes &lt;a.*/;
var timerFct = function(){
    $(".storyContent").filter(function(){
        console.log(2);
        return likeRegex.test( $(this).html() );
    }).hide();
    setTimeout(timerFct,10000);
}
setTimeout(timerFct,3000);
</code></pre>

<p>It&#8217;s meant as part of a chrome plugin- once I package it as such (assuming there&#8217;s no pitfalls there- haven&#8217;t tried it yet), I&#8217;ll post it here.  For you firefox users, throw it into Greasemonkey and you should be good.</p>

<p>To be clear, this is not guaranteed to work.  The regex will hit plenty of false positives, and I&#8217;ll refine this if I get around to it later.</p>

<p><strong>Edit</strong>: Chrome extension.  Works for me- let me know if you have trouble: <a href="http://kevinkuchta.webfactional.com/blog/fbdeliker_1_0/fbdeliker.crx">fbdeliker.crx</a></p>
]]>
        

    </content>
</entry>

<entry>
    <title>Wrttn.in Quine</title>
    <link rel="alternate" type="text/html" href="http://kevinkuchta.webfactional.com/blog/2010/07/wrttnin-quine.html" />
    <id>tag:kevinkuchta.webfactional.com,2010:/blog//1.16</id>

    <published>2010-07-22T03:41:39Z</published>
    <updated>2010-08-02T23:29:03Z</updated>

    <summary>Because I got bored and my javascript is rusty, I put together what I&#8217;m calling a Wrttn.in quine. Edit: Does not appear to be working in Chrome (my main browser). I&#8217;d only tested it in Firefox so far because A)...</summary>
    <author>
        <name>Kevin</name>
        <uri>http://www.kevinkuchta.com</uri>
    </author>
    
    <category term="webjavascriptajaxwrttnin" label="web javascript ajax &quot;wrttn.in&quot;" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en-US" xml:base="http://kevinkuchta.webfactional.com/blog/">
        <![CDATA[<p>Because I got bored and my javascript is rusty, I put together what I&#8217;m calling a Wrttn.in quine.</p>

<p><strong>Edit:</strong> Does not appear to be working in Chrome (my main browser).  I&#8217;d only tested it in Firefox so far because A) firebug rocks and B) I&#8217;m too lazy to care about cross-browser compatibility in my free time.  I&#8217;ll take a look at the problem sometime soon when it&#8217;s not after midnight on a workday.</p>

<h4>Wrttn.in</h4>

<p>Wrttn.in is just a notepad-type site.  It&#8217;s similar to a.longreply.com.  You enter some text, hit save, and it gives you two urls: a public one that shows that text (eg, wrttn.in/323f1) and a private one that allows you to administer it (eg. wrttn.in/admin/46feb701xda).  Now, as it happens, the text you enter will not be sanitized for html or javascript&#8230; :D</p>

<h4>Quine</h4>

<p>A <a href="http://en.wikipedia.org/wiki/Quine_(computing">quine</a>) is a programmer toy.  It&#8217;s a program that outputs a copy of it&#8217;s source code.  What I&#8217;ve written is a hunk of javascript that, when placed in a wrttn.in page, will put a button on the page.  Pressing that button will ajax up a new wrttn.in page, populate it with the same code as the initial page, and redirect to it.  Not a traditional quine, of course, but it&#8217;s the same spirit.  :)</p>

<h4>Explanations</h4>

<p>A few things to explain in the following code:</p>

<ul>
<li>It&#8217;s possible to pass in content on a wrttn.in create call, but that content will be stripped of it&#8217;s javascript.  That&#8217;s why we have a subsequent edit call- edit does not strip it.</li>
<li>This may not work long since we&#8217;re not using an api or anything stable- the calls were just reverse engineered from the pages.  It&#8217;d be pretty easy for the wrttn.in creator to shut down this code he decides to.  Just has to sanitize his edit inputs.</li>
<li>Content type has to be markdown.  Textile encodes the quote marks.</li>
<li>This is a quick hack- nothing more.  Don&#8217;t expect great code.</li>
</ul>

<h4>Code</h4>

<pre><code>&lt;div id="vcms_whole"&gt;
    &lt;div id="vcms_content"&gt;&lt;input type="button" id="btnCreateNew" value="Create New!"/&gt;&lt;/div&gt;
    &lt;script type="text/javascript" src="http://code.jquery.com/jquery-1.4.2.js" charset="utf-8"&gt;
    &lt;/script&gt;
    &lt;script type="text/javascript" charset="utf-8"&gt;
        function createNewPage(){
            var wcms_wholeElement = document.getElementById("vcms_whole");
            var outerDiv = document.createElement("div");
            outerDiv.appendChild(wcms_wholeElement);
            wholeHTML = outerDiv.innerHTML;
            var publicId = "none";
            $.ajax({
                async: false,
                url: 'http://wrttn.in/create',
                dataType: 'html',
                type: 'POST',
                data: {content:wholeHTML,parser:'markdown'},
                success: onCreateSuccess,
                cache: false
            });
            var fullEditUrl = "http://wrttn.in"+editUrl;

            //Send edit request because 'create' filters out the javascript, but edit does not.
            $.ajax({
                url: fullEditUrl,
                dataType: 'html',
                async: false,
                type: 'POST',
                data: {content:wholeHTML},
                success: onEditSuccess,
                cache: false
            });
        }

        function onCreateSuccess(data, status, request){
            var dataEl = $(data).filter("title");
            var titleText = dataEl.text()
            adminId = titleText.replace("wrttn admin:","");
            var idLink = document.createElement("a");
            var something = $(data);
            var editEl = $("#edit",something);
            var formEl = editEl.children("form")[0];
            editUrl = formEl.attributes.getNamedItem("action").value;
            var editUrlSections = editUrl.split("/");
            publicId=editUrlSections[editUrlSections.length-2];
        }

        function onEditSuccess(data, status, request){
            window.location='http://wrttn.in/admin/'+adminId;
        }

        function setup(){
            $("#btnCreateNew").bind('click',createNewPage);
        }

        setup();
    &lt;/script&gt;
&lt;/div&gt;
</code></pre>

<p>I have a slightly more interesting application for this technique, but I&#8217;ll post about that when/if I actually get to it.</p>
]]>
        

    </content>
</entry>

<entry>
    <title>Cheap Tricks</title>
    <link rel="alternate" type="text/html" href="http://kevinkuchta.webfactional.com/blog/2010/06/cheap-tricks.html" />
    <id>tag:www.kevinkuchta.com,2010:/blog//1.15</id>

    <published>2010-06-09T00:12:33Z</published>
    <updated>2010-06-15T21:49:44Z</updated>

    <summary>I heard a fun statistic today: the average software development turnover rate is 20% annually. The Bureau of Labor Statistics says 33% for all departures in IT, and 15% for quits. Let&#8217;s say it&#8217;s 20%- that&#8217;s a whole new company...</summary>
    <author>
        <name>Kevin</name>
        <uri>http://www.kevinkuchta.com</uri>
    </author>
    
    
    <content type="html" xml:lang="en-US" xml:base="http://kevinkuchta.webfactional.com/blog/">
        <![CDATA[<p>I heard a fun statistic today: the average software development turnover rate is 20% annually.  The Bureau of Labor Statistics says 33% for all departures in IT, and 15% for quits.  Let&#8217;s say it&#8217;s 20%- that&#8217;s a whole new company every 5 years (not really, of course, but it&#8217;s still a significant chunk of your company gone in that period).  How can any company achieve consistent results when more than half their company is swapped out every 3 years?  Predictable budgets and schedules become hella-difficult, not even to mention the cost of training new employees and the lost production while that&#8217;s happening.</p>

<p>Of course, we all know that holding on to quality developers means keeping them challenged, paying them highly, throwing them cool technology, etc.  That said, we&#8217;re not all made of money, so here&#8217;s a few cheap tricks that buy a lot of developer love for not much money.</p>

<h2>Free food</h2>

<p>Give your employees a free dinner once every month or two.  Somewhere nice and a little highly-priced, but not someplace they have to dress up.  High-quality barbecue joints or steakhouses are decent choices.  A lot of the common-folk consider a meal around $50 a head to be too pricy to treat themselves, so it&#8217;s pretty great when it&#8217;s gifted from management.  Remember, you paid them 100 times that amount this month alone (assuming 60k a year).  It&#8217;s a gift you don&#8217;t even have to do on company time, and gets a lot of bang for a tiny cost.</p>

<h2>Dual Monitors</h2>

<p><a href="http://www.codinghorror.com/blog/2004/06/multiple-monitors-and-productivity.html">A</a> <a href="http://www.netlobo.com/dual_monitor_productivity.html">number</a> <a href="http://www.nytimes.com/2009/01/15/technology/personaltech/15basics.html?_r=3&amp;pagewanted=1&amp;em">of</a> sites and studies espouse the productivity virtues of multiple monitors- they easily make up for a $100 investment on that alone.  Further, though, developers <em>enjoy</em> using them.  Again, you&#8217;re paying them $60,000 a year- you can afford to give them a tool they love that&#8217;s been shown to increase productivity up to 44%, lasts 3+ years, and costs 0.16% of a developer&#8217;s annual pay.</p>

<h2>Free Coffee</h2>

<p>It may seem like a small thing, but one nicety I&#8217;ve heard programmers and IT workers complain about endlessly is the lack of free coffee.  It&#8217;s a little weird, considering how cheap home coffee-makers are (got mine for $12 at a thrift store), and how cheap making one&#8217;s self a cup is.  That said, developers seem to love having it on hand in the office, and I can hardly fault them- they get up early, come in, and sit without much movement for the next 4 hours.  Anyway, you can get a high-end office-oriented single-cup maker for $500, or $17 a head in a 30-person office.  Hell, even a cheap home-oriented brewer (<$50) kept well supplied will do the job (though the wasted time for high-paid developers to set up and brew pots may not be worth the savings).</p>

<h2>Decent Chairs</h2>

<p>A rower notices the rowboat.  A pilot notices his cockpit.  When I tour a potential job, I notice the chair I&#8217;m going to spend 40 hours a week in.  Yes, good chairs are stupidly expensive ($750 for the famous Aeron chair), but quality chairs stand out.  There&#8217;s talk about improved back health, productivity, etc, but the biggest advantage is their attractiveness to new and old developers.  They signal that the people in management care about the day-to-day physical needs of developers (even though we all know you just want more work out of us). At a dollar a week (assuming a 10 year lifespan), that Aeron chair is a solid investment- cheaper than (as <a href="http://www.joelonsoftware.com/articles/FieldGuidetoDevelopers.html">Joel Spolsky</a> points out) your average toilet paper expenditure.</p>

<p>There, that wasn&#8217;t so bad, was it?  I didn&#8217;t suggest that everyone get private offices, litter the place with beanbags, or have catered sushi every day.  These are simple things, and you can do them without really high-level approval.  They&#8217;ll reduce turnover, increase productivity, and attract brighter minds- in short, they&#8217;ll pay for themselves.</p>
]]>
        

    </content>
</entry>

<entry>
    <title>FulStack, empty coffee cup</title>
    <link rel="alternate" type="text/html" href="http://kevinkuchta.webfactional.com/blog/2010/04/fulstack-empty-coffee-cup.html" />
    <id>tag:www.kevinkuchta.com,2010:/blog//1.14</id>

    <published>2010-04-10T01:47:40Z</published>
    <updated>2011-02-01T07:40:09Z</updated>

    <summary>I recently undertook participation in RIT48 with my good friends Chris &#8216;Cap&#8217; Tosswill (a fellow software engineer) and Meghan Manders (a designer). RIT48 is a competition to create a web business in 48 hours, with mixed emphasis on business plan...</summary>
    <author>
        <name>Kevin</name>
        <uri>http://www.kevinkuchta.com</uri>
    </author>
    
    <category term="fulstack" label="FulStack" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en-US" xml:base="http://kevinkuchta.webfactional.com/blog/">
        <![CDATA[<p>I recently undertook participation in <a href="http://rit48.com">RIT48</a> with my good friends <a href="http://tosswill.net/">Chris &#8216;Cap&#8217; Tosswill</a> (a fellow software engineer) and <a href="http://meghanmanders.com/">Meghan Manders</a> (a designer).  RIT48 is a competition to create a web business in 48 hours, with mixed emphasis on business plan and implementation.  Our team got a working prototype of our product (<a href="http://fulstack.com">FulStack.com</a>) up and running, and we won second place (+ $400)!  More details in <a href="http://www.kevinkuchta.com/blog/projects/fulstack.html">the project page</a>.</p>
]]>
        

    </content>
</entry>

<entry>
    <title>No Comment</title>
    <link rel="alternate" type="text/html" href="http://kevinkuchta.webfactional.com/blog/2010/02/no-comment.html" />
    <id>tag:www.kevinkuchta.com,2010:/blog//1.12</id>

    <published>2010-03-01T03:05:22Z</published>
    <updated>2010-03-01T03:06:36Z</updated>

    <summary>Much like throwing a kitten into a pit of rottweilers, there are a few questions you can throw into any group of developers that&#8217;ll have them at each other&#8217;s throats in moments. One fun one I discovered recently was: &#8220;When...</summary>
    <author>
        <name>Kevin</name>
        <uri>http://www.kevinkuchta.com</uri>
    </author>
    
    
    <content type="html" xml:lang="en-US" xml:base="http://kevinkuchta.webfactional.com/blog/">
        <![CDATA[<p>Much like throwing a kitten into a pit of rottweilers, there are a few questions you can throw into any group of developers that&#8217;ll have them at each other&#8217;s throats in moments.  One fun one I discovered recently was:</p>

<p>&#8220;When do you comment?&#8221;</p>

<p>Most opinions I&#8217;ve seen have fallen into one of a few categories:</p>

<ol>
<li>Real men don&#8217;t need comments</li>
<li>The code should be self-documenting</li>
<li>Comment on design decisions (the &#8216;whys&#8217; of code blocks)</li>
<li>Comment on the what blocks of code are doing (the &#8216;whats&#8217; of code blocks)</li>
<li>COMMENT EVERYTHING!!!!1!!1ONE11!1!!</li>
</ol>

<p>Few reasonable people hold position 5, and the people holding position 1 aren&#8217;t likely to turn away from their <a href="http://www.pbm.com/~lindahl/mel.html">RPC-4000</a> to care what some wet-behind-the-ears, object-oriented, virtualizing, abstracting, greenhorn youngin&#8217; like me has to say.</p>

<h4>Self Documenting Code</h4>

<p>The general argument is that clear method/parameter/variable/etc names, clean well-formatted code, and well structured source are sufficient for the sort of low-level documentation you see.</p>

<p>The Pros are pretty clear- less commenting means less stuff to keep up to date and in sync with the code.</p>

<blockquote>
  <p>Commenting just makes the source file twice as long.</p>
</blockquote>

<p>However, no one is perfect.  Your code is never ultimately well structured, named, and formatted.  If you think it is and I have to deal with your code later, I want to track you down and light your face on fire.  Unless you&#8217;re the perfect lovechild of Steve McConnell and Erich Gamma, then your naming, structure, and formatting will be incomplete, and I will hate you.  You&#8217;re better off assuming you suck and commenting as such.</p>

<h4>Comment on design decisions</h4>

<p>The idea here is that you&#8217;d comment on how a method or block of code fits in with the rest of system.  Obviously you don&#8217;t want a complete design document in the comments for every method, but you might want to point out specific gotcha&#8217;s and the code&#8217;s general role in the system.</p>

<p>The Pro&#8217;s to this are that it helps someone going through the code understand the possible ramifications of changes, especially if they&#8217;re non-obvious.</p>

<p>The problem with this approach is that it&#8217;s hard to keep up to date.  That&#8217;s true of any documentation, but comments are supposed to be the closest thing to the code itself.  Comments that reflect not just changes to the code at hand but also the rest of the system are difficult to keep current.  If code in modules A, B, and C all discuss what module D does (in relation to how they interact with it), then they all have to be updated when module D is changed or repurposed.</p>

<h4>Comment on function</h4>

<p>Pretty simple - comment on what a block of code or method does.  You see this formalized in Javadocs.</p>

<p>The main argument against this tact is that it should be unnecessary.  Programmers can read code, why do we need text to tell us what code does?</p>

<p>I would argue that we don&#8217;t want to take the time to read your code and figure out what it does.  If I&#8217;m skimming through a dozen foreign thousand-line class files, I don&#8217;t want to have to read every line in them just to find the one block that modifies X; it&#8217;d be nice to be able to skim through comments to find &#8220;//This section deals with X.&#8221;</p>

<p>In another case, your code may just be too dense to be read quickly.  I can figure out what your line-noise regex does, but unless you deal with it constantly it&#8217;ll take a minute- it&#8217;d save me some time if you took 20 seconds to give dense code a brief description.  The same can go for any unusually clever or cryptic piece of code: yes I can read it, but I&#8217;m looking at this source to find information, not marvel at how clever you thought you could be.</p>

<h4>Whaddaya say?</h4>

<p>So which style&#8217;s best?  It really depends on how you and your development team work.  Some things to consider:</p>

<ul>
<li>How good is your external documentation?</li>
<li>How big is your codebase?</li>
<li>Is your architecture clear enough that the consequences of most changes are obvious?</li>
</ul>

<p>Personally, I try to err on the side of more commenting- while I&#8217;ve seen some egregious examples of over-commenting, those are few and far between.  Under-commenting, though, I&#8217;d bet we&#8217;ve almost all been burnt by.</p>
]]>
        

    </content>
</entry>

<entry>
    <title>Autotune the project</title>
    <link rel="alternate" type="text/html" href="http://kevinkuchta.webfactional.com/blog/2010/02/autotune-the-project.html" />
    <id>tag:www.kevinkuchta.com,2010:/blog//1.11</id>

    <published>2010-02-05T01:18:04Z</published>
    <updated>2010-02-07T00:22:10Z</updated>

    <summary>Hell is shiny objects I don&apos;t know about you, but I often suffer from a lack of motivation on personal projects. Usually it goes something like this: Be sitting at my computer and thing &quot;Hey, I&apos;ve got a half hour;...</summary>
    <author>
        <name>Kevin</name>
        <uri>http://www.kevinkuchta.com</uri>
    </author>
    
    <category term="spdb" label="spdb" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en-US" xml:base="http://kevinkuchta.webfactional.com/blog/">
        <![CDATA[<h3>Hell is shiny objects</h3>

<p>I don't know about you, but I often suffer from a lack of motivation on personal projects.  Usually it goes something like this:</p>

<ol>
<li>Be sitting at my computer and thing "Hey, I've got a half hour; I could try to fix that bug in the FPA event model."</li>
<li>Launch Textmate, open the relevant directory in it, and wait for that to load.</li>
<li>Launch MAMP and wait for it to spool up it's isolated MySQL and Apache servers</li>
<li>Start up the Fixx issue tracker server and wait for that to load.</li>
<li>Go to the production and staging sites for reference, and wait for those to load</li>
<li>Go to the site on localhost, as well as the bug tracker page, and wait for those to load.</li>
<li>Open Cyberduck (my sftp client of choice) and wait for it to load + make it's connection</li>
<li>Load up the terminal and navigate to the right directory</li>
<li>Switch back to Textmate and get to work.</li>
</ol>

<p>Of course there's usually some point in there where, while waiting for something to load, I get distracted.  Stumbleupon is just a keystroke or two away.  Cmd-T, Ctrl-Shift-S and I'm reading about baby elephants in Asia.  30 minutes later, I'm out of time, and no work got done.</p>

<p>While this isn't a huge problem when I'm being payed to work or any project that I'm working on for large contiguous blocks of time, it used to come up all time with personal projects.  Further, even without the distraction factor, the amount of effort required to get down to work can be off-putting.  Once I'm working, I'm focused like a racehorse (assuming racehorses are really focused- I really have no idea).  Getting to that point can be an issue, though.</p>

<h3>Make the robot do it</h3>

<p>We automate every other aspect of our projects, why not this?  Continuous integration severs, build scripts, unit tests- we script our way past any monotonous task, so how 'bout setup?</p>

<p>I have one button on my dock to load up all the tools I need to code, run, test, and deploy my work for <a href="http://www.kevinkuchta.com/blog/projects/SPDB">SPDB</a>, and slightly less involved but increasingly automated processes for my other tool-intensive projects.  These tend to be some amalgomation of Automator, AppleScript, and Bash.  They're not especially elegant, but they're not ment to be- spending too much time developing tools to organize tools to do actual work starts bogging down your ability to actually do work.</p>

<h3>Time is an illusion</h3>

<p>Like most labor-saving labor, this seemed like more work than it was worth right up until I started using it.  That seems to be a common theme on automation- ever heard any of these?</p>

<ul>
<li>"Automated Unit testing takes too much time to write- time we could use to develop"</li>
<li>"Version Control is too much effort to be worth the small amount of time it save."</li>
<li>"We don't need to script our deployment process- we don't do it /that/ often."</li>
</ul>

<p>But once these tasks are completed, you immediately start to see the benefit.  Saving even 30 to 60 seconds every time I launch my dev environment setup script builds up pretty fast.</p>

<h3>Housing Prices</h3>

<p>Automating a task is like buying a house.  Before that, you're just renting.  Every month you pay your rent, and have nothing to show for it other than living in your flat for that month.  Every time you do a task by hand, you pay the time it takes and have nothing to show for it other than completing it once.</p>

<p>When you buy a house, you start building equity.  Yes, you had an up-front cost, but now every house payment is building up benefit to you, instead of just being thrown away.  Likewise, a scripted task takes time to set up up front, but thereafter saves you time every time you do that task at a fraction of the effort.</p>

<p>Further, what's more fun- launching, spooling, loading and opening?  Or just coding?</p>

<p>Whenever and whereever it's practical: automate it.  It's usually worth the time.</p>
]]>
        

    </content>
</entry>

<entry>
    <title>&quot;Modern Font Embedding&quot; or &quot;How I learned to hate IE all over again&quot;</title>
    <link rel="alternate" type="text/html" href="http://kevinkuchta.webfactional.com/blog/2010/01/modern-font-embedding-or-how-i-learned-to-hate-ie-all-over-again.html" />
    <id>tag:www.kevinkuchta.com,2010:/blog//1.9</id>

    <published>2010-01-24T20:41:52Z</published>
    <updated>2010-01-31T01:21:49Z</updated>

    <summary>A New Hope Since the dawn of time, man has yearned for full control of fonts on his website. For many years, though, we&#8217;ve been stuck using just the fonts that we can reliably expect every user to have installed...</summary>
    <author>
        <name>Kevin</name>
        <uri>http://www.kevinkuchta.com</uri>
    </author>
    
    <category term="css" label="css" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="kevinkuchtacom" label="kevinkuchta.com" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="web" label="web" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en-US" xml:base="http://kevinkuchta.webfactional.com/blog/">
        <![CDATA[<h3>A New Hope</h3>

<p>Since the dawn of time, man has yearned for full control of fonts on his website.  For many years, though, we&#8217;ve been stuck using just the fonts that we can reliably expect every user to have installed on their machines.</p>

<p>However, hope has come at last; no longer must we toil in typographic mediocrity.  As of summer-ish of 2009, most major browsers (Safari, Firefox, IE) support it (in anticipation of the CSS 3.0 spec).  We are now free from the shackles of conformist font faces!</p>

<p>Given all this, I decided to have a go of playing with embedded fonts on www.kevinkuchta.com.  It&#8217;s easy, what could go wrong?</p>

<h3>Fail and You</h3>

<p>Of course, it&#8217;s not that simple (it never is).  IE&#8217;s been doing font embedding since it was put in the CSS 2.0 specification (then subsequently removed in CSS 2.1).  As such, they do it entirely different from everyone else (and, for that matter, the spec).</p>

<p>There are plenty of other references on <a href="http://www.qodo.co.uk/blog/re-introducing-font-face-css-rules/">font embedding </a>, but I thought I&#8217;d focus specifically on the weird things IE does, since that&#8217;s what&#8217;s been giving me some fun headaches.  Hopefully this will save some people some trouble in the future.</p>

<h3>Things IE Doesn&#8217;t do</h3>

<h4>Multiple Font Sources</h4>

<p>In an ideal world, your font list could look something like this:</p>

<pre><code>src: url("/fonts/HelNuBold.ttf"), url("/fonts/HelNuBold.eot")
</code></pre>

<p>If any given source failed for whatever reason, it&#8217;d fail over to the next on on the list, and this is exactly what Firefox et. al will do.  IE, on the other hand, will fail entirely if it sees multiple source declarations on one line like that.  It tries to load the font entitled: <code>"/fonts/HelNuBold.ttf"), url("/fonts/HelNuBold.eot"</code></p>

<h4>Local Font Sources</h4>

<p>Ideally, you could declare a font-face that would look first to a local source:</p>

<pre><code>src: local("Helvetica Neue Italic")
</code></pre>

<p>This would be especially useful in conjunction with multiple font sources.  IE doesn&#8217;t like the &#8220;local&#8221; syntax, though, and will ignore a line with local in it.  This is actually useful if you want to set up a source list that IE will ignore, but Firefox et al. will read.</p>

<h4>Font Weights</h4>

<p>Some fonts have different actual font files for bold text- it&#8217;d be nice if we could set up a set of fonts to automatically switch to the correct font whenever a section of text in a certain embedded font was bolded.  It&#8217;d work something like this:</p>

<pre><code>@font-face{
    font-family: "somefont";
    src: "url("/fonts/HelveticaNeueBold.ttf")"
    font-weight: 700;
}
@font-face{
    font-family: "somefont";
    src: "url("/fonts/HelveticaNeueRegular.ttf")"
    font-weight: 400;
}
</code></pre>

<p>This is even more useful when dealing with a font (like Helvetica Neue) that has half a dozen different font-weights, from UltraLight to Black.  Of course, true to form, IE fails and Firefox/Safari work fine.  What&#8217;s interesting about this one, though, is that it fails non-deterministically.  It will decide to render bold/regular fonts with random fonts, weights, and variously condensed/expanded.</p>

<p>It makes for a cool party trick to switch fonts randomly on different reloads from static css/html.  If you have access to IE, you can check out a <a href="http://www.kevinkuchta.com/ietest-static/ftest.html">live demo</a>, in which I&#8217;ve assigned several very different fonts to the same font-family but different font-weights; try reloading a few times.  If you don&#8217;t have IE, you can see the effect using the excellent IE testing tool <a href="http://ipinfo.info/netrenderer/index.php">Netrender</a> and reloading a few times.</p>

<h4>Font Styles</h4>

<p>Very similar to how you&#8217;d use font-weights- italicized text would automatically use the italicized font, rather than just being slanted by some browser algorithm.  It&#8217;d look like:</p>

<pre><code>@font-face{
    font-family: "somefont";
    src: "url("/fonts/HelveticaNeueRegular.ttf")"
    font-style: normal;
}
@font-face{
    font-family: "somefont";
    src: "url("/fonts/HelveticaNeueItalic.ttf")"
    font-style: italic;
}
</code></pre>

<p>But, of course, IE reacts non-deterministically to this.  Firefox/Safari work fine.</p>

<h4>TTFs</h4>

<p>Everyone&#8217;s gotta have their own font format, of course.  Firefox/Safari take, among others, .ttf (TrueType Font) files, whereas IE takes .eot &#8220;Embedded Open Type&#8221; files.  The technical differences between these two are a topic for another post, but for the purposes of embedding, they can be treated the same.  For those starting out with ttf&#8217;s or otf&#8217;s, I cannot recommend highly enough the font generator by <a href="http://www.fontsquirrel.com/fontface/generator">Font Squirrel</a>.  It&#8217;ll output the necessary eot&#8217;s as well as the correct CSS to work in both IE and Firefox.</p>

<div class="metapost">&#8216;Cause I got mad styles / I got money in piles.  This web shizzle is rockin&#8217; some mad minimalistic style.  I&#8217;m a fan of minimalism in webdesign because, well, it&#8217;s harder for me to screw up.  Clean lines and lots of whitespace.  Anyway, we now have a much prettier site.  I&#8217;ve killed a lot of the default Moveable Type widgets and played around with a those that are left.  I also spent a lot of time trying to get the typography right (or at least the way I want it- I&#8217;m not a graphics designer), and had some fun with IE (for certain values of &#8216;fun&#8217;).</div>
]]>
        

    </content>
</entry>

<entry>
    <title>Why not roll my own?</title>
    <link rel="alternate" type="text/html" href="http://kevinkuchta.webfactional.com/blog/2010/01/why-not-roll-my-own.html" />
    <id>tag:www.kevinkuchta.com,2010:/blog//1.5</id>

    <published>2010-01-13T03:16:05Z</published>
    <updated>2010-01-18T01:37:53Z</updated>

    <summary><![CDATA[Writing a blog engine is a right of passage for young developers.&nbsp; It is the web equivalent of printing Fibonacci numbers or calculating the sides of a triangle- step number two after Hello World.&nbsp; As such, the question is raised:Why...]]></summary>
    <author>
        <name>Administrator</name>
        
    </author>
    
    
    <content type="html" xml:lang="en-US" xml:base="http://kevinkuchta.webfactional.com/blog/">
        <![CDATA[Writing a blog engine is a right of passage for young developers.&nbsp; It is the web equivalent of printing Fibonacci numbers or calculating the sides of a triangle- step number two after Hello World.&nbsp; As such, the question is raised:<br /><br />Why don't I roll my own?<br /><br />The first answer to that is that there's not much more to be gained from it.&nbsp; It was useful when I was first learning HTML, then CSS, then PHP, the Rails, as a project with some practical application that also has enough technical requirements to flex the tool being learnt a little.<br /><br />Further, it scaled well to various tools (when learning HTML, I could do a simple static-page blog; when learning rails, I could do a dynamic mvc blog engine with tests and a db).&nbsp; Now, though, I know enough about the principle web tools (HTML/CSS) and a smattering of languages + frameworks (CodeIgniter, Rails, etc) that building another blog engine in them just isn't that useful to me.<br /><br />Secondly, the need for this project to be done outweighs my need to learn from it.&nbsp; I've gone through half a dozen iterations of my personal site- each time better and more complex.&nbsp; The problem is that when using a project as a learning tool, it never gets done.<br /><br />By the time I finished building one of the first versions of my site with table based layouts, I'd figured out that css layouts were much better.&nbsp; By the time I finished a static css-layout site, I realized that even a little php could make modifications much easier, etc, etc.&nbsp; I always want to rewrite it in light of the flaws I learnt while writing it.&nbsp; At this point, <a href="http://www.kevinkuchta.com/blog/2009/12/kevin-kuchtas-blog.html">I need a solid web presence</a> that isn't constantly changing.<br /><br />Thirdly, I want the sort of features that a mature product gives.&nbsp; I can roll a basic blog engine with post and paginated archives in 20 minutes in Rails (less using generators), but then what?&nbsp; Then I want comments on that, so I write comments in another 20.&nbsp; Then I realize that I want formatting for my comments and blog posts, so I spend some time putting in markdown.&nbsp; Then I get a spammer in the comments, so I put in captchas.&nbsp; Then I decide that I upload enough images that I'd like a way to do that through the ui, rather than ftp-ing to the server.&nbsp; Then I need... and so on.<br /><br />Role-based authentication, searching, skins, analytics, performance optimiziation, OpenId, RSS/Atom, etc.&nbsp; These are all things I can or can learn to do, but it often means I have to choose between living without the feature or putting all my other pojects (and the writing itself) on hold to do it.&nbsp; Having a well thought out platform like MovableType, with the features I'm likely to need already there, allows me to focus on other things.<br /><br />So, why not roll my own? Because it's no longer educational, I need this site for itself, and I want a full-featured system.&nbsp; Good enough reasons for me.<br /><br /><div class="metapost">This chunk of text here is what I'm going to call a metapost, in the sense that it talks about the current state of the site, rather than presenting actual content.  My plan is to use these to discuss changes to the site while keeping them seperate from the actual posts.  Since a post along the lines of "Sorry the site was down last night" won't be at all relevant in a year, this will allow me to programatically remove these comments later.</div>
]]>
        
    </content>
</entry>

<entry>
    <title>Kevin Kuchta&apos;s Blog</title>
    <link rel="alternate" type="text/html" href="http://kevinkuchta.webfactional.com/blog/2009/12/kevin-kuchtas-blog.html" />
    <id>tag:www.kk.knothere.net,2009:/blog//1.2</id>

    <published>2009-12-24T02:46:29Z</published>
    <updated>2009-12-24T02:56:17Z</updated>

    <summary><![CDATA["A man's domain is his castle"I've been kicking around the internet since I was a kid, and I've owned various websites about as long.&nbsp; From the HTML course I took over the summer in elementary school to the rails system...]]></summary>
    <author>
        <name>Administrator</name>
        
    </author>
    
    
    <content type="html" xml:lang="en-US" xml:base="http://kevinkuchta.webfactional.com/blog/">
        <![CDATA[<blockquote>"A man's domain is his castle"<br /></blockquote>I've been kicking around the internet since I was a kid, and I've owned various websites about as long.&nbsp; From the HTML course I took over the summer in elementary school to the rails system I put together a couple years back, I've always had some online representation, often tied to various user names and interests.&nbsp; I've made Starcraft fan pages, webcomics, rough cms's, collections of written work- everything but the standard blog.<br /><br />What I've lacked until now, though, has been a place directly associated with Kevin Michael Kuchta.&nbsp; The closest thing to that is my facebook page, which isn't the front I want to show the world.&nbsp; To this end, I'm getting my hair combed, buying a respectable domain name, and putting a decent blog there.&nbsp; That's this thing.<br /><br />I'll get into the decisions I've made concerning this site, the history of my online presence, my current place in life, etc in future posts- this is just to say why this site exists: to be a stable repository for all things Kevin Kuchta.<br />]]>
        
    </content>
</entry>

</feed>

