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

<channel>
	<title>Hot Koehl &#187; For techies</title>
	<atom:link href="http://frankkoehl.com/category/for-techies/feed/" rel="self" type="application/rss+xml" />
	<link>http://frankkoehl.com</link>
	<description>The more you know, the more you don't know</description>
	<lastBuildDate>Mon, 16 Jan 2012 22:52:04 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
<xhtml:meta xmlns:xhtml="http://www.w3.org/1999/xhtml" name="robots" content="noindex" />
		<item>
		<title>Fix WordPress &#8220;Fatal error: Allowed memory size&#8221; messages</title>
		<link>http://frankkoehl.com/2011/10/fix-wordpress-fatal-error-allowed-memory-size-messages/</link>
		<comments>http://frankkoehl.com/2011/10/fix-wordpress-fatal-error-allowed-memory-size-messages/#comments</comments>
		<pubDate>Thu, 27 Oct 2011 04:38:51 +0000</pubDate>
		<dc:creator>Frank</dc:creator>
				<category><![CDATA[For techies]]></category>

		<guid isPermaLink="false">http://frankkoehl.com/?p=1391</guid>
		<description><![CDATA[You may (or may not) have noticed this site was down for the past few days, displaying a blank page no matter what URL was entered. After recalling that I had turned off PHP error onscreen outputting, I was presented with this lovely message: Fatal error: Allowed memory size of 33554432 bytes exhausted (tried to [...]]]></description>
			<content:encoded><![CDATA[<p>You may (or may not) have noticed this site was down for the past few days, displaying a blank page no matter what URL was entered. After recalling that I had turned off PHP error onscreen outputting, I was presented with this lovely message:</p>
<pre>
Fatal error: Allowed memory size of 33554432 bytes exhausted
(tried to allocate XX bytes) in /some/file on line XX
</pre>
<p>This is a general PHP error, but the exact amount (<code>33554432 bytes</code>) occurs very frequently on WordPress sites. Here&#8217;s what&#8217;s happening, and how to fix it.</p>
<p>Every installation of PHP has an ini value called <code>memory_limit</code>, which hardcaps how much memory PHP may use on any given request. There are other ini settings that dictate the memory usage for specific actions, like <code>post_max_size</code>, but this one is universally applied; you can&#8217;t load anymore than what this value dictates.</p>
<p>I do a lot of stuff with files in PHP, so I blow this value out from it&#8217;s default of 128 MB up to 2 GB. I set this globally in my <code>php.ini</code> file like so:</p>
<pre>memory_limit = 2G</pre>
<p>I could also set this value from inside an .htaccess file:</p>
<pre>php_value memory_limit 2G</pre>
<p>Since this value was set before the site even loads, imagine my surprise when PHP is telling me that the limit is now 33554432 bytes, or 32 MB. The limit was changed by a define in WordPress called <code>WP_MEMORY_LIMIT</code>. </p>
<p>Here&#8217;s where things go awry. WordPress tries to check the existing <code>memory_limit</code> before applying it&#8217;s own terms, however <strong>the value must be set in terms of MB</strong>. Look back at my example settings; the PHP memory shorthand allows me to set in gigabytes using a &#8220;<code>G</code>&#8220;. But WordPress does a straight integer comparison to figure out if the existing setting is more/less than 32 MB. Here&#8217;s the offending code, a portion of an if statement on line 42 in <code>wp-includes/default-constants.php</code></p>
<pre>( (int) @ini_get('memory_limit') < abs(intval(WP_MEMORY_LIMIT)) ) )</pre>
<p>What you end with in that sample is essentially <code>if (2 < 32)</code>, which resolves true and thus WordPress applies it's own default limits.</p>
<p>You have three options to rectify the situation: two easy fixes, plus one badass "server-baller" fix. First the easy ones. As WordPress <a href="http://codex.wordpress.org/Editing_wp-config.php#Increasing_memory_allocated_to_PHP">outlines in the article on increasing memory</a>, simply define <code>WP_MEMORY_LIMIT</code> in <code>wp-config.php</code> using MB syntax. If I wanted to set it to 2 GB, it would look like this:</p>
<pre>define('WP_MEMORY_LIMIT', '2048M');</pre>
<p>Your value will be honored as long as it is an integer value greater than 32, but could break if WordPress changes it's memory size comparison calculation.</p>
<p>Alternatively, I could change my the <code>memory_limit</code> setting directly in <code>php.ini</code> or <code>.htaccess</code> to use MB syntax:</p>
<pre>

memory_limit = 2048M

[.htaccess]
php_value memory_limit 2048M
</pre>
<p>Realistically I would probably edit php.ini. Well, that is, I <strong>would</strong>, if I didn't know about the badass server-baller third option, which overrides <code>php.ini</code> AND prevents WordPress (or any other site for that matter) from making any changes to the value.</p>
<p>Look back at my <code>.htaccess</code> setting, and notice that I set the value using the command <code>php_value</code>. PHP has a similar command called <code>php_<span class='red'>admin</span>_value</code>, which you can use for setting all the same stuff as <code>php_value</code>. </p>
<p>The difference: <code>php_admin_value</code> can only be set within Apache configurations, i.e. it <strong>cannot</strong> be used inside of <code>.htaccess</code> files. Furthermore, any value set using <code>php_admin_value</code> cannot be overridden by any later calls to <code>php_value</code> or <code>ini_set</code>. You can override <code>php.ini</code> defaults, and lock that value in for the remainder of the request.</p>
<p>So back to our WordPress example, I opened the <code>VirtualHost</code> for frankkoehl.com and entered this line:</p>
<pre>php_admin_value memory_limit 2G</pre>
<p>Now the site will always allow a memory limit of 2 GB, no matter what. WordPress can try and set whatever value it likes, it will never be recognized.</p>
<p>Note that this function requires that you have access to Apache configurations, at least the ones running your site. Most shared hosting packages won't offer this level of access.</p>
<p>It's worth mentioning that WordPress sets a default value of 32 MB, lower than PHP's own default of 128 MB. I disagree that such a low limit is necessary, but they are trying to be good stewards to servers everywhere, so I can see where they're coming from. </p>
<p>I still have no idea why this memory issue popped up in the first place, but it gave me an excuse to share a cool configuration option that has saved me from having to scour code on several bloated, crappy sites to find obscure ini settings. I have a recent <a href="http://stackoverflow.com/questions/5628148/disable-e-deprecated-in-php-error-log">real-world example you can read about on Stack Overflow</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://frankkoehl.com/2011/10/fix-wordpress-fatal-error-allowed-memory-size-messages/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Using hashmarks for URL anchors in Apache rewrites</title>
		<link>http://frankkoehl.com/2011/05/using-hashmarks-for-url-anchors-in-apache-rewrites/</link>
		<comments>http://frankkoehl.com/2011/05/using-hashmarks-for-url-anchors-in-apache-rewrites/#comments</comments>
		<pubDate>Wed, 04 May 2011 18:09:13 +0000</pubDate>
		<dc:creator>Frank</dc:creator>
				<category><![CDATA[For techies]]></category>

		<guid isPermaLink="false">http://frankkoehl.com/?p=1338</guid>
		<description><![CDATA[Today I had to make an Apache rewrite that redirected a custom URL not only to a different page, but also to a specific anchor link on the destination page. In other words, /foobar had to actually load /some/other/url#foobar. However, by default Apache rewrites will escape the hash (#) symbol, converting to its hexcode equivalent [...]]]></description>
			<content:encoded><![CDATA[<p>Today I had to make an Apache rewrite that redirected a custom URL not only to a different page, but also to a specific anchor link on the destination page. In other words, <code>/foobar</code> had to actually load <code>/some/other/url#foobar</code>.</p>
<p>However, by default Apache rewrites will escape the hash <code>(#)</code> symbol, converting to its hexcode equivalent <code>%23</code>. </p>
<p>So this rewrite&#8230;</p>
<pre>RewriteRule ^/foobar/?$ /some/other/url#foobar/ [R=301,L]</pre>
<p>will produce this URL&#8230;</p>
<pre>http://example.com/some/other/url%23foobar</pre>
<p>In order to make this rewrite work, we must <strong>prevent Apache from escaping the hash mark</strong> by using the <code>noescape</code> flag. A little tweak to the rewrite, and we&#8217;re good to go&#8230;</p>
<pre>RewriteRule ^/foobar/?$ /some/other/url#foobar/ [R=301,L,NE]</pre>
<p>See that little <code>NE</code> on the end? That&#8217;s all we need to make rewrite anchors work.</p>
<p>Documentation on all the rewrite flags can be found in the <a href="http://httpd.apache.org/docs/2.0/mod/mod_rewrite.html#rewriterule">Apache docs for the RewriteRule Directive</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://frankkoehl.com/2011/05/using-hashmarks-for-url-anchors-in-apache-rewrites/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Remove parent directories from tar archives</title>
		<link>http://frankkoehl.com/2011/04/remove-parent-directories-from-tar-archives/</link>
		<comments>http://frankkoehl.com/2011/04/remove-parent-directories-from-tar-archives/#comments</comments>
		<pubDate>Sun, 10 Apr 2011 18:43:52 +0000</pubDate>
		<dc:creator>Frank</dc:creator>
				<category><![CDATA[For techies]]></category>

		<guid isPermaLink="false">http://frankkoehl.com/?p=1335</guid>
		<description><![CDATA[You run a Linux web server, and have painstakingly crafted custom backup processes for all your important data. Undoubtedly, the backup copies end up being stored in the form of a tar archive. Everything works great &#8212; copies are made, compressed, and sent off-site. There&#8217;s just one naggy little issue: whenever you open one of [...]]]></description>
			<content:encoded><![CDATA[<p>You run a Linux web server, and have painstakingly crafted custom backup processes for all your important data. Undoubtedly, the backup copies end up being stored in the form of a <a href="http://www.computerhope.com/unix/utar.htm">tar archive</a>. Everything works great &#8212; copies are made, compressed, and sent off-site. There&#8217;s just one naggy little issue: whenever you open one of those tar backups, it includes the entire directory tree above the folder you actually need. </p>
<p>This problem always drove me nuts when creating MySQL database backups. I want to make a tar backup of <code>/var/lib/mysql/database_name</code> and call it <code>database_name.tar.gz</code>. If I then unpack the tar under <code>/root</code>, I&#8217;ll have a bunch of worthless subfolders to drill down through: <code>/root<strong color="red">/var/lib/mysql/</strong>database_name</code>. All I really want is the <code>database_name</code> folder, the <code>/var/lib/mysql/</code> parent directories can all go away.</p>
<p>Here&#8217;s how to get rid of those pesky parent folders once and for all. Before running your tar command, you must first use <code>cd</code> to move into the parent directory that contains the folder you want. Then, within your call to tar, leave the parent folders off your target files/folders.</p>
<p>Here&#8217;s the command sequence for previous example:</p>
<pre>
cd /var/lib/mysql
tar -czf /any/folder/you/want/database_name.tar.gz database_name
</pre>
<p>The resulting file will unpack directly into a single subfolder called <code>database_name</code>.</p>
<p>If you run your tar process as part of a larger scripting event, your script might not run/maintain a shell interface. In these cases, the <code>cd</code> command will be executed in a vacuum, and won&#8217;t have any effect. I run into this problem when I try to perform shell magic inside of PHP scripts. </p>
<p>Fortunately, there&#8217;s an easy workaround: you can append multiple shell commands together using <code>&#038;&#038;</code>. With <code>&#038;&#038;</code>, each command will be executed and completed before the next one begins, mimicking a person typing out commands one line at a time. </p>
<p>Here&#8217;s what our MySQL example looks like as a single line:</p>
<pre>
cd /var/lib/mysql &#038;&#038; tar -czf /any/folder/you/want/database_name.tar.gz database_name
</pre>
<p>Enjoy your tar backups sans worthless parent directories!</p>
]]></content:encoded>
			<wfw:commentRss>http://frankkoehl.com/2011/04/remove-parent-directories-from-tar-archives/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Key-based logins for SSH</title>
		<link>http://frankkoehl.com/2011/04/key-based-logins-for-ssh/</link>
		<comments>http://frankkoehl.com/2011/04/key-based-logins-for-ssh/#comments</comments>
		<pubDate>Fri, 08 Apr 2011 18:11:21 +0000</pubDate>
		<dc:creator>Frank</dc:creator>
				<category><![CDATA[For techies]]></category>

		<guid isPermaLink="false">http://frankkoehl.com/?p=1317</guid>
		<description><![CDATA[Here&#8217;s the scenario: You have a remote-hosted Linux server that you currently access via SSH by entering a username and password. You would like to use a public/private key pair so that you don&#8217;t have to enter a password every time you log in. You do most of your work from a Windows/Mac client, where [...]]]></description>
			<content:encoded><![CDATA[<p>Here&#8217;s the scenario: You have a remote-hosted Linux server that you currently access via SSH by entering a username and password. You would like to use a public/private key pair so that you don&#8217;t have to enter a password every time you log in. You do most of your work from a Windows/Mac client, where you generally don&#8217;t mess with the command line and would rather not bother to learn. </p>
<p>Here&#8217;s how to enable key authentication for the root user on your remote Linux server. Once you&#8217;ve gone through the process you&#8217;ll be able to easily replicate it for any other user accounts that require SSH access.</p>
<p><strong>1. Create the key pair from your server</strong><br />
I don&#8217;t know what your local system looks like, nor do I care. We know the server has everything you need since it already has SSH installed, so let&#8217;s just do the heavy lifting from there! </p>
<p>SSH into your server as root, and run the following commands:</p>
<pre>
cd ~
mkdir ~/.ssh
chmod 700 ~/.ssh
ssh-keygen -t rsa
</pre>
<p>Your output from the call too <code><a href="http://www.manpagez.com/man/1/ssh-keygen/">ssh-keygen</a></code> will look something like this:</p>
<pre>
Generating public/private rsa key pair.
Enter file in which to save the key (/root/.ssh/id_rsa):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /root/.ssh/id_rsa.
Your public key has been saved in /root/.ssh/id_rsa.pub.
</pre>
<p>You may enter a passphrase to encrypt the key, but keep in mind you&#8217;ll have to enter that passphrase every time you wish to connect, effectively defeating our purposes for using keys in the first place. Just leave the password lines blank when prompted.</p>
<p>[Sidebar]<br />
In practice, the connection procedure for passphrase&#8217;d SSH keys and standard username/password combo look exactly the same: connect to server > enter password > get access. However, using keys with a passphrase is far more secure than a simple username/password challenge. A would-be attacker needs the key file AND the passphrase in order to get in. This extra layer of connection requirements raises the security bar significantly, especially if you&#8217;re careful about where/how you store the file and passphrase.<br />
[/Sidebar]</p>
<p><strong>2. Which keys go where?</strong><br />
If you navigate to <code>/root/.ssh</code>, you&#8217;ll find 2 files: <code>id_rsa</code> (the private key) and <code>id_rsa.pub</code> (the public key). Here&#8217;s the part that causes the most confusion for newcomers to key-based authentication:</p>
<h4>The <strong class="red">public key (id_rsa.pub)</strong> belongs on your <strong class="red">remote server</strong>.</h4>
<h4>The <strong class="blue">private key (id_rsa)</strong> resides on your <strong class="blue">local client</strong>, or whatever machine is connecting <strong>to</strong> the remote server.</h4>
<p>It seems counter-intuitive for some people, espcially if you&#8217;re familiar with SSL. The SSH connection process has the remote server giving offering up the public key for every connection request, placing the onus on the client (i.e. you) to respond with the proper private information.</p>
<p><strong>3. Install the public key on the server</strong><br />
The public key is on the server, but not in the right place yet. We need to place it where SSH will look for it when a key-based connection is made.</p>
<pre>
cd ~/.ssh
cat id_rsa.pub >> authorized_keys2
</pre>
<p>SSH looks for potential public key matches in the file <code>authorized_keys2</code>. The file might be called <code>authorized_keys</code> (no number two) on some systems. The cat command appends the entire key to that file, or creates it if it doesn&#8217;t already exist. </p>
<p>At this point the file <code>id_dsa.pub</code> is no longer needed. For the sake of security, you may tuck it away somewhere for safe-keeping, and delete the server copy.</p>
<p><strong>4. Install the private key on your local client</strong><br />
Pull <code>id_rsa</code> (without the &#8220;.pub&#8221;) down to your local machine using your file transfer method of choice. Once you have a local copy, you should remove the one located on the server, and throw another copy in a dark corner somewhere for safe keeping. This is especially important when setting up key-based authentication for the root user: if you lose the key and disable password logins (discussed below), you will be unable to connect to your server via root. No bueno.</p>
<p>At this point you need to add the key to the SSH connection details of whatever SSH client you use. This fairly straightforward with nearly any SSH client, save one: <a href="http://www.chiark.greenend.org.uk/~sgtatham/putty/">PuTTY</a>. For whatever reason, the PuTTY team uses a special format for SSH keys, and we need to convert your private key to that format before we can connect.</p>
<p><strong>5. Convert SSH private key for PuTTY on Windows</strong></p>
<ol>
<li>Open the PuTTY Key Generator. The executable is called <code>puttygen.exe</code></li>
<li>From the Menu select <strong>Conversions > Import key</strong></li>
<li>Browse to your local copy of <code>id_rsa</code> and choose <em>Open</em>.</li>
<li>Click the <strong>Save private key</strong> button, listed under Actions on the lower portion of the window.</li>
<li>Save the resulting .ppk file in a permanent location (PuTTY will look for the file in this location every time you connect)</li>
<li>Open PuTTY, and load the saved session for your server</li>
<li>Navigate to configuration menu to <strong>Connection > SSH > Auth</strong></li>
<li>Click the <strong>Browse</strong> button under <strong>Private key file for authentication</strong>, find your new .ppk file, and click <strong>Open</strong></li>
<li>Be sure to save the changes made to your PuTTY session!</li>
</ol>
<p>There are plenty of tutorials on PuTTY around the web should you require more information.</p>
<p><strong>6. Harden SSH by disabling password authentication</strong><br />
Using keys-based authentication allows you to enforce better protection on your server from SSH-based attacks. <strong class="red">Test your connection before completing going any further.</strong></p>
<p>Connect to your server using your fancy new SSH key, and open <code>/etc/ssh/sshd_config</code> in your favorite editor. Find the entry for <code>PasswordAuthentication</code>, or add the line as follows:</p>
<pre>
PasswordAuthentication no
</pre>
<p>Save and close the file, then restart SSH (on Debian/Ubuntu systems the command will be <code>/etc/init.d/ssh restart</code>). That will prohibit all SSH connections allow you to still connect as root, but only using your key. Again, make sure your key-based authentication is working properly before applying this change.</p>
]]></content:encoded>
			<wfw:commentRss>http://frankkoehl.com/2011/04/key-based-logins-for-ssh/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PHP IDS website down</title>
		<link>http://frankkoehl.com/2011/02/php-ids-website-down/</link>
		<comments>http://frankkoehl.com/2011/02/php-ids-website-down/#comments</comments>
		<pubDate>Wed, 09 Feb 2011 18:33:42 +0000</pubDate>
		<dc:creator>Frank</dc:creator>
				<category><![CDATA[For techies]]></category>

		<guid isPermaLink="false">http://frankkoehl.com/?p=1309</guid>
		<description><![CDATA[PHP IDS is an intrusion detection system written in PHP. It allows developers to incorporate security analysis directly into their systems. Since it&#8217;s written in PHP, it can go wherever the site goes, and has minimal server requirements. Plus, since it works at the site level, a developer can pick and choose how and when [...]]]></description>
			<content:encoded><![CDATA[<p>PHP IDS is an intrusion detection system written in PHP. It allows developers to incorporate security analysis directly into their systems. Since it&#8217;s written in PHP, it can go wherever the site goes, and has minimal server requirements. Plus, since it works at the site level, a developer can pick and choose how and when to apply it to site actions. I love it.</p>
<p>Unfortunately, I went to <a href="http://php-ids.org">the PHP IDS site</a> today to grab the latest version, only to discover the site is either temporarily down or closed entirely. The error message is in German, but Google Translate gives the following translation:</p>
<blockquote><p>This server is no longer in operation.</p>
<p>Please tell the operator that the DNS on the new IP 46.4.40.248 convert their.</p>
<p>schokokeks.org </p></blockquote>
<p>Anyone know what&#8217;s going on?</p>
<p><strong>Update April 4, 2011</strong><br />
Looks like they had some domain issues, and are now back at <a href="http://phpids.org">phpids.org</a>. The lead developer of PHPIDS, .mario, has <a href="http://phpids.org/2011/03/30/we-are-back">a post detailing the shutdown and return</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://frankkoehl.com/2011/02/php-ids-website-down/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Require site visitors to enable Javascript</title>
		<link>http://frankkoehl.com/2010/04/require-site-visitors-to-enable-javascript/</link>
		<comments>http://frankkoehl.com/2010/04/require-site-visitors-to-enable-javascript/#comments</comments>
		<pubDate>Mon, 19 Apr 2010 17:05:56 +0000</pubDate>
		<dc:creator>Frank</dc:creator>
				<category><![CDATA[For techies]]></category>

		<guid isPermaLink="false">http://frankkoehl.com/?p=1231</guid>
		<description><![CDATA[This one has dogged me for quite some time, but I finally figured out how to force users to turn on Javascript when using sites with a lot of mission critical Javascript logic. Let me first begin by acknowledging that, yes, requiring Javascript flies in the face of site accessibility. Policy wonks for this sort [...]]]></description>
			<content:encoded><![CDATA[<p>This one has dogged me for quite some time, but I finally figured out how to force users to turn on Javascript when using sites with a lot of mission critical Javascript logic.</p>
<p>Let me first begin by acknowledging that, yes, requiring Javascript flies in the face of site accessibility. Policy wonks for this sort of thing will tell you that Javascript should never be a necessity, that a page should &#8220;degrade gracefully&#8221; when Javascript isn&#8217;t enabled. This mindset is complete crap, in my opinion. Every site has a minimum browser requirement, and Javascript is built into every modern browser. I fail to see why we are still separating the two, and can make a darn good case for expecting Javascript on the user&#8217;s end. But that argument&#8217;s for another day. If you agree with me, read on.</p>
<p><strong>The example</strong><br />
This example assumes you understand HTML, CSS, and Javascript, and makes use of <a href="http://jquery.com">jQuery</a>, so you may have to adapt it to fit your Javascript framework of choice.</p>
<p>This technique could be applied across the board to an entire site, but let&#8217;s start with a single page. A login or account registration is a great choice, since they are already gateway pages to your site. Start by adding the following CSS definition to your page or stylesheet:</p>

<div class="wp_syntax"><div class="code"><pre class="css" style="font-family:monospace;">.enable-javascript<span style="color: #00AA00;">&#123;</span>
  <span style="color: #000000; font-weight: bold;">display</span><span style="color: #00AA00;">:</span><span style="color: #993333;">none</span>
<span style="color: #00AA00;">&#125;</span></pre></div></div>

<p>Next, open the HTML for your page and add the <code>enable-javascript</code> CSS class to the top level container containing the <strong>body</strong> of your page. You should try to leave the header and footer (and their accompanying navigation links) visible and accessible. For example, after my header DIV, the body of my pages are typically wrapped in something like this:</p>

<div class="wp_syntax"><div class="code"><pre class="html" style="font-family:monospace;">&lt;div id=&quot;content&quot; class=&quot;enable-javascript&quot;&gt;
  [...]
  &lt;div class=&quot;base&quot;&gt;&lt;/div&gt;
&lt;/div&gt;</pre></div></div>

<p>At this point, you&#8217;re looking at a blank page. Now let&#8217;s give our non-JS users something to look at. Place a <a href="http://www.w3schools.com/tags/tag_noscript.asp"><code>&lt;noscript&gt;</code></a> code block <strong>outside</strong> and <strong>above</strong> the body that you just hid. You can use CSS and elaborate HTML inside a <code>&lt;noscript&gt;</code> block, so feel free to make it look good. I actually duplicate my body wrap HTML so the look is similar:</p>

<div class="wp_syntax"><div class="code"><pre class="html" style="font-family:monospace;">&lt;noscript&gt;
  &lt;div id=&quot;content&quot; class=&quot;enable-javascript&quot;&gt;
    Javascript is not currently enabled in your browser. &lt;a href=&quot;http://www.google.com/support/bin/answer.py?answer=23852&quot;&gt;You must enable Javascript&lt;/a&gt; in order for this site to work properly.
    &lt;div class=&quot;base&quot;&gt;&lt;/div&gt;
  &lt;/div&gt;
&lt;/noscript&gt;</pre></div></div>

<p>Finally, make sure the jQuery library is loaded, and add this bit of code to the Javascript for your page:</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;">$<span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
  $<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'.enable-javascript'</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">show</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p><strong>What&#8217;s happening</strong><br />
We&#8217;re using the <strong>absence</strong> of Javascript to halt the user&#8217;s access to a page. By default, page content is hidden via CSS, and we use Javascript to reveal it. If the user&#8217;s browser does not have Javascript enabled, the reveal never happens. Visibility for the <code>&lt;noscript&gt;</code> block is handled automatically by the browser, depending on whether Javascript is running or not.</p>
<p><strong>A live example</strong><br />
I&#8217;m using this technique on the <a href="https://fwdvault.com/signin">Fwd:Vault login page</a>. In order to see it in action, you obviously have to disable Javascript. You can use the <a href="http://www.google.com/support/bin/answer.py?answer=23852">Google support link to turn Javascript on</a>, and Firefox users can use the <a href="https://addons.mozilla.org/en-US/firefox/addon/60">Web Developer toolbar add-on</a> to do this a little more efficiently.</p>
<p><strong>A couple caveats</strong><br />
Javascript is a client-side language; it actually lives inside the user&#8217;s browser, and runs from the user&#8217;s machine. Javascript code essentially tells the browser to manipulate the static HTML of the page, and the server isn&#8217;t involved in the process at all (AJAX is something of an exception). This means that there is absolutely no way for us to look for Javascript on the server side using PHP or other server-side technologies.</p>
<p>In addition, since Javascript control is firmly in the hands of the user, you cannot trust Javascript for security. Your average user will be stopped dead with this technique, but hackers and code monkeys can easily circumvent it. This is the case with all Javascript effects, and all have the same countermeasure: scrub all incoming data regardless of Javascript rules enforcement.</p>
<p>Feel free to post comments or questions, and please link your own examples if you put this technique to use!</p>
]]></content:encoded>
			<wfw:commentRss>http://frankkoehl.com/2010/04/require-site-visitors-to-enable-javascript/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Building a complex system? Take easy steps.</title>
		<link>http://frankkoehl.com/2010/03/building-complex-system-take-easy-steps/</link>
		<comments>http://frankkoehl.com/2010/03/building-complex-system-take-easy-steps/#comments</comments>
		<pubDate>Sun, 21 Mar 2010 20:28:08 +0000</pubDate>
		<dc:creator>Frank</dc:creator>
				<category><![CDATA[For techies]]></category>
		<category><![CDATA[coding theory]]></category>
		<category><![CDATA[crappy coding]]></category>
		<category><![CDATA[software development]]></category>
		<category><![CDATA[standards]]></category>

		<guid isPermaLink="false">http://frankkoehl.com/?p=1192</guid>
		<description><![CDATA[After launching Fwd:Vault last month, it&#8217;s been a race to add the necessary features and functions to take the service broader. First on the list was more subscription tiers. I launched with just two: free and &#8220;unlimited everything.&#8221; I did this because, well, it was easy. Your instinct may be to dismiss my decision as [...]]]></description>
			<content:encoded><![CDATA[<p>After <a href="/2010/02/celebrate-the-little-victories">launching Fwd:Vault last month</a>, it&#8217;s been a race to add the necessary features and functions to take the service broader. First on the list was more subscription tiers. I launched with just two: free and &#8220;unlimited everything.&#8221; I did this because, well, it was easy.</p>
<p>Your instinct may be to dismiss my decision as laziness, but hear me out. I built most of the base site with just 1 state: free (remember that unlimited free beta period last year?). That allowed me to &mdash; rightly &mdash; focus purely on features, functions, bugs, etc. Dealing with subscription tiers at the same time would have clouded everything, slowing everything down and likely leading to more rewriting. Staying focused allowed me to get the cornerstone stuff right before building on top of it. </p>
<p>I applied the same thought process when it came time to offer paid options. The game plan has always been to have three paid options, plus the free account. However instead of initially coding four possible user states, I started with just two: free or paid.</p>
<p>This makes my job as a developer much more focused. There&#8217;s a LOT of logic in a service like Fwd:Vault focused explicitly on subscriptions: access permissions, showing/hiding upgrade options, setting quota restrictions, security checks to prevent hackarounds from unscrupulous users. The functionality of almost every page is affected by the user&#8217;s free/paying status, and don&#8217;t even get me started on the work it takes to process credit cards. You have to be <del>doubly</del> triply careful when dealing with people&#8217;s personal data like that. On and on. Getting the basics in place takes a lot of forethought and coding.</p>
<p>So instead of thinking about all this stuff in four dimensions &mdash; free, option 1, option 2, option 3 &mdash; I can cover most everything in just two &mdash; free or paid &mdash; and then come back later to fill in the holes for the other tiers.</p>
<p>Complexity is your enemy as a developer. Each task must be as tightly focused as possible. The tighter your focus, the less chance you&#8217;ll have to introduce bugs. Adding more later may require rewrites, but they are far far easier than rewriting the big sloppy mess you get when biting off more than you can chew.</p>
<p>With the basic subscription and tier logic in place, it&#8217;s a far simpler matter to expand the options out to infinity (though we&#8217;ll start with four). Expect to see the new pricing options in a few weeks.</p>
<p>Looking for more to read? There&#8217;s a new post on the Fwd:Vault Blog that details the <a href="http://blog.fwdvault.com/2010/03/always-forgetting-to-defrag-use-your-screensaver/">most unobtrusive disk defragmenting process</a> I&#8217;ve seen (that I also use for my own systems).</p>
]]></content:encoded>
			<wfw:commentRss>http://frankkoehl.com/2010/03/building-complex-system-take-easy-steps/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Toyota&#8217;s new logo</title>
		<link>http://frankkoehl.com/2010/03/toyotas-new-logo/</link>
		<comments>http://frankkoehl.com/2010/03/toyotas-new-logo/#comments</comments>
		<pubDate>Thu, 11 Mar 2010 21:03:12 +0000</pubDate>
		<dc:creator>Frank</dc:creator>
				<category><![CDATA[For entrepreneurs]]></category>
		<category><![CDATA[For everyone]]></category>
		<category><![CDATA[For techies]]></category>
		<category><![CDATA[humor]]></category>
		<category><![CDATA[Twitter]]></category>
		<category><![CDATA[usability fail]]></category>

		<guid isPermaLink="false">http://frankkoehl.com/?p=1183</guid>
		<description><![CDATA[I hear Toyota is contemplating a quick makeover to their current logo and tagline&#8230; Wish I could take credit for it, but at least it comes complements of fellow PSL member Eight Eleven. Update: I complimented the author Aaron, and the following conversation ensued&#8230; Aaron: I&#8217;m going to end up in a lawsuit with Toyota [...]]]></description>
			<content:encoded><![CDATA[<p>I hear Toyota is contemplating a quick makeover to their current logo and tagline&#8230;</p>
<p><a href="http://twitpic.com/17ye23"><img src="http://frankkoehl.com/wp-content/uploads/toyota_logo.jpg" alt="moving forward unexpectedly" title="Toyota logo" width="336" height="114" class="alignnone size-full wp-image-1184" /></a></p>
<p>Wish I could take credit for it, but at least it comes complements of fellow <a href="http://phillystartupleaders.org/">PSL</a> member <a href="http://twitter.com/eighteleveninc">Eight Eleven</a>.</p>
<p><strong>Update:</strong> I complimented the author Aaron, and the following conversation ensued&#8230;</p>
<blockquote><p><strong>Aaron:</strong><br />
I&#8217;m going to end up in a lawsuit with Toyota for sure on this one.</p>
<p><strong>Frank:</strong><br />
As a design firm, what a boon for business THAT would be!</p>
<p><strong>Aaron:</strong><br />
Yeah, I can see the headlines already: &#8220;Japanese automaker Toyota files lawsuit against New Jersey based Advertising and Marketing Agency, Eight Eleven Inc., then mid-suit, hires them to execute a new branding campaign.&#8221;
</p></blockquote>
<p>Fantastic.</p>
]]></content:encoded>
			<wfw:commentRss>http://frankkoehl.com/2010/03/toyotas-new-logo/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Running the show: A day in the life</title>
		<link>http://frankkoehl.com/2010/02/running-the-show-a-day-in-the-life/</link>
		<comments>http://frankkoehl.com/2010/02/running-the-show-a-day-in-the-life/#comments</comments>
		<pubDate>Tue, 16 Feb 2010 21:03:46 +0000</pubDate>
		<dc:creator>Frank</dc:creator>
				<category><![CDATA[For entrepreneurs]]></category>
		<category><![CDATA[For everyone]]></category>
		<category><![CDATA[For techies]]></category>
		<category><![CDATA[Academia]]></category>
		<category><![CDATA[business support]]></category>
		<category><![CDATA[customer service]]></category>
		<category><![CDATA[entrepreneur]]></category>

		<guid isPermaLink="false">http://frankkoehl.com/?p=1167</guid>
		<description><![CDATA[We all know most TV is pretty banal, but every now and then something comes along that provides insight, makes you think. So if you ever wondered what it&#8217;s really like to be the boss, you need to watch the latest episode of House. They&#8217;ve done an excellent job (based on my experience, anyway) capturing [...]]]></description>
			<content:encoded><![CDATA[<p>We all know most TV is pretty banal, but every now and then something comes along that provides insight, makes you think. So if you ever wondered what it&#8217;s <strong>really</strong> like to be the boss, you need to watch the latest episode of House. They&#8217;ve done an excellent job (based on my experience, anyway) capturing the reality of being in charge. Everyone looks to you to fix problems they can&#8217;t handle, and everything that goes wrong is ultimately your fault. It also gets really lonely at times. If you&#8217;re one of those people who think that the boss just sits at his/her desk and collects a big paycheck, this is a must-see.</p>
<p>The show&#8217;s writers and producers get extra bonus points from me for taking on the issue of healthcare, and having the stones to come right and say, &#8220;This is a business, and we need to make money.&#8221; They even couch the message in a scenario that most people should be able to appreciate from both sides. Very timely given all the discourse surrounding healthcare reform.</p>
<p>44 minutes, well worth it.</p>
<p><object width="512" height="296 "><param name="movie" value="http://www.hulu.com/embed/C9j6xa2eBAuhqoD0k_syPw"></param><param name="allowFullScreen" value="true"></param><embed src="http://www.hulu.com/embed/C9j6xa2eBAuhqoD0k_syPw" type="application/x-shockwave-flash" allowFullScreen="true"  width="512" height="296"></embed></object></p>
]]></content:encoded>
			<wfw:commentRss>http://frankkoehl.com/2010/02/running-the-show-a-day-in-the-life/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Preventing Firefox memory, processor bloat</title>
		<link>http://frankkoehl.com/2010/02/preventing-firefox-memory-processor-bloat/</link>
		<comments>http://frankkoehl.com/2010/02/preventing-firefox-memory-processor-bloat/#comments</comments>
		<pubDate>Tue, 09 Feb 2010 20:03:13 +0000</pubDate>
		<dc:creator>Frank</dc:creator>
				<category><![CDATA[For techies]]></category>
		<category><![CDATA[browsers]]></category>
		<category><![CDATA[desktop tips]]></category>
		<category><![CDATA[open source]]></category>

		<guid isPermaLink="false">http://frankkoehl.com/?p=1159</guid>
		<description><![CDATA[If you&#8217;ve read this blog before, you know I&#8217;m a big Firefox fan. But the one problem that has dogged me is the inevitable bloat that Firefox suffers when open for long periods of time. I work in my browser all day, and after 8 hours it has usually gobbled up all the available RAM, [...]]]></description>
			<content:encoded><![CDATA[<p>If you&#8217;ve read this blog before, you know I&#8217;m a big Firefox fan. But the one problem that has dogged me is the inevitable bloat that Firefox suffers when open for long periods of time. I work in my browser all day, and after 8 hours it has usually gobbled up all the available RAM, and sucks processor cycles like a Dyson. Fortunately I&#8217;ve finally pinpointed the cause and several solutions.</p>
<p>Let&#8217;s start at the source. The Firefox team made a crucial usability decision, which is at the heart of the problem. They wanted to allow the user to recover any page that may have recently opened. So by default, Firefox keeps navigation history for all your open tabs, plus the last 10 tabs that you closed. The navigation history for each of those tabs &mdash; both open and closed &mdash; can hold up to a maximum of 50 pages (i.e. the number of URLs you can traverse purely through the Back/Forward buttons)</p>
<p>With no limit to the number of open tabs, plus the high limit on the Back/Forward navigation, it&#8217;s easy to see why Firefox slows to a crawl. If you do a lot of browsing in a lot of tabs, your memory disappears in a hurry. Managing all that extra memory causes the processor to work overtime to keep Fire<del>fox</del> hippo moving.</p>
<p>There are two ways to fix this issue in a pinch. First you can simply restart the browser, making sure that it doesn&#8217;t save your tabs (you are prompted to save tabs at close by default). Second, you can clear the Recently Closed Tabs to eliminate a portion of the tab history bloat (History > Recently Closed Tabs > Clear Closed Tabs List).</p>
<p>For a more long-term solution, we need to mess with the system settings. Type <code>about:config</code> in the address bar to bring up Firefox&#8217;s complete configurations list. The latest Firefox versions present you with a warning before opening the page.</p>
<p>A warning: this page handles everything in your browser. Everything. Don&#8217;t mess with stuff if you don&#8217;t know what you&#8217;re doing.</p>
<p>In the &#8220;Filter&#8221; textbox at the top, enter </p>
<pre>browser.sessionstore.max_tabs_undo</pre>
<p>This setting controls how many closed tabs to track. Less old tabs =  less memory usage. Double click the lone entry in the list and change the value from &#8220;10&#8243; to &#8220;5.&#8221;</p>
<p>Back to the filter box, enter </p>
<pre>browser.sessionhistory.max_entries</pre>
<p>This setting controls the navigation history limit. Double click the entry and drop the value from &#8220;50&#8243; down to &#8220;25&#8243;.</p>
<p>Close the <code>about:config</code> tab and restart your browser.</p>
<p>Your mileage on these tweaks will vary depending on your system specs. If you can go a day of heavy browsing without hitting the creep, slowly increment the settings back up, until you hit the sweet spot.</p>
]]></content:encoded>
			<wfw:commentRss>http://frankkoehl.com/2010/02/preventing-firefox-memory-processor-bloat/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

