<?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>Curtis Tasker &#187; Programming</title>
	<atom:link href="http://curtistasker.com/blog/programming/feed" rel="self" type="application/rss+xml" />
	<link>http://curtistasker.com</link>
	<description>&#99;&#117;&#114;&#116;&#105;&#115; (at) &#116;&#97;&#115;&#107;&#101;&#114; (dot) &#110;&#101;&#116;</description>
	<lastBuildDate>Sat, 24 Jul 2010 22:42:25 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.1</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Input Driven</title>
		<link>http://curtistasker.com/blog/technology/256/input-driven</link>
		<comments>http://curtistasker.com/blog/technology/256/input-driven#comments</comments>
		<pubDate>Thu, 18 Dec 2008 21:04:23 +0000</pubDate>
		<dc:creator>Curtis</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[apple]]></category>
		<category><![CDATA[keyboard]]></category>
		<category><![CDATA[mouse]]></category>
		<category><![CDATA[scancode]]></category>

		<guid isPermaLink="false">http://curtistasker.com/?p=256</guid>
		<description><![CDATA[I seem to chew through and spit out peripherals yearly. I suppose when you spend as much time as I do in front of a computer, you feel compelled to have the perfect input devices.

Finding Perfection
I started out with a standard IBM PC keyboard, one of those giant clackers, and a dreary old grey mouse with [...]]]></description>
			<content:encoded><![CDATA[<p>I seem to chew through and spit out peripherals yearly. I suppose when you spend as much time as I do in front of a computer, you feel compelled to have the perfect input devices.<br />
<span id="more-256"></span></p>
<h2>Finding Perfection</h2>
<p>I started out with a standard IBM PC keyboard, one of those giant clackers, and a dreary old grey mouse with my first computer.  Since then I&#8217;ve gone through literally dozens of upgrades. Ball mice gave way to optical mice, which in turn gave way to laser mice. In the past few years I&#8217;ve gone through half a dozen gaming mice, before finally settling on a <a href="http://en.wikipedia.org/wiki/Logitech_G9">Logitech G9</a>. Most of my relatives have a castoff mouse that once graced my desk, but my right hand is finally happy.</p>
<p>My keyboard churn has followed the same breakneck pace. I&#8217;ve gone through keyboards with built in <a href="http://en.wikipedia.org/wiki/Trackpoint">trackpoints</a>, purportedly ergonomic split keyboards, a dozen near-disposable $10 keyboards, a <a href="http://www.daskeyboard.com/">Das Keyboard</a> (100% blank, of course), and two backlit keyboards. I started with loud clicky keys, moved to silent soft keys, then back to clicky, then back to soft. I never did find one I was happy with.</p>
<p>That changed when the aluminum <a href="http://www.apple.com/keyboard/">Apple Keyboard</a> caught my eye. After a trek to an Apple Store and half an hour coding away on it (to the mild amusement of the staff), I brought one home. I&#8217;ve since moved to the wireless version, and aside from my occasional lapses when I try to use the nonexistent Numpad or Home/End PgUp/PgDn keys, I&#8217;m happy. In fact, the quality of the typing experience was so good that it factored in heavily to my MacBook Air purchase.</p>
<h2>Windows Support</h2>
<p>Despite both the wired and wireless keyboards being fairly fantastic as far as the hardware goes, the software support for Windows is severely lacking. The default <a href="http://support.apple.com/kb/HT1167">mapping</a> isn&#8217;t ideal.  The software offered by Apple for bootcamp is difficult to find for a Windows user, and once found is just not up to the task. When I first bought the wired keyboard, I spent hours putting together a melange of hacks to turn the keyboard into a usable device on Windows.</p>
<h3>A few of the problems:</h3>
<ul>
<li>Media &amp; Volume keys are nonfunctional</li>
<li>Command key where Alt key should be, but acts like Windows key</li>
<li>Option key where Windows key should be, but acts like Alt key</li>
<li>Right Control key acts like Right Alt key</li>
<li>Fn key where Insert key should be (wired keyboard only)</li>
<li>Clear key where NumLock key should be (wired keyboard only)</li>
</ul>
<p>That covers most of the big issues, but the list of minor issues can go on for some time.  I used <a href="http://sharpkeys.codeplex.com/">SharpKeys</a> to remap the F7-F12 <a href="http://en.wikipedia.org/wiki/Scan_codes">scancodes</a> to the windows media keyboard equivalents, turn F13-F15 into the PrintScreen, Scroll Lock, and Pause keys, and make the Ctrl and Alt keys work properly.  This proved to be an adequate solution at the time.</p>
<p>After I got my Macbook Air, I wanted more parity between how the keyboard on my laptop and desktop worked. Since I had upgraded to the wireless Apple Keyboard around the same time, I particularly needed shortcuts to replicate the lost buttons.  Again using scancodes, I turned the Command key into Ctrl, to make cut/copy/paste use the same gesture as the Mac. I used a scripting language called <a href="http://www.autohotkey.com/">AutoHotkey</a> to add some additional functionality, namely Ctrl+ArrowKeys shortcuts for Home/End/PgUp/PgDn, and Fn+Backspace for Delete. </p>
<h3>More Problems Arise</h3>
<p>All was well until I started beta testing new program, and my mapping fell apart. You see, this program bypassed the standard Windows keyboard device driver, and used their own instead. This made things problematic as my scancode mappings were thus ignored. The program used Ctrl + # and Alt + # heavily, and the Ctrl and Alt keys were just not where my fingers expected them to be. In addition, Command started acting like the Windows key again, launching the start menu when pressed. Words cannot adequately express how highly annoying this all was.</p>
<p>I tried to code my way out of this problem with more scripting, and ended up realizing that scancodes just weren&#8217;t doing the job anymore. I decided the only viable solution was to replicate all the key mapping functionality in my script instead.</p>
<h2>An Easy Solution</h2>
<p>Before I got too involved in this project, I did a little digging on the net, and a program called <a href="http://code.google.com/p/uawks/">UAWKS</a> caught my eye. It had been released just weeks prior, and it basically does everything my scancode remapping and scripting did, with a slick bit of user interface thrown on top. I swapped over entirely to this program, with minimal tweaks to the underlying code to suit my needs.</p>
<p>There are a few lingering issues, but I wholeheartedly recommend <a href="http://code.google.com/p/uawks/">UAWKS</a> to anybody running an Apple keyboard under Windows.  It is a requirement to get the proper Windows behavior out of the keyboard.</p>
<p>Of course, all this is going to be a moot point once I replace my desktop with a Mac.  At least I&#8217;ll be able to use the same mouse and keyboard, without all the hassle.  At this point, my lust for new input devices is sated.  Of course, who can say what the next year&#8217;s product line will bring?</p>
<p><strong>Update (03/25/2009):</strong>  Just spent an hour on the Wacom Intuos4. <em>*sigh*</em> With a little willpower, perhaps I can keep the tablet consumption rate down to something reasonable.</p>
]]></content:encoded>
			<wfw:commentRss>http://curtistasker.com/blog/technology/256/input-driven/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Basic access control in Apache</title>
		<link>http://curtistasker.com/blog/programming/153/basic-access-control-in-apahce</link>
		<comments>http://curtistasker.com/blog/programming/153/basic-access-control-in-apahce#comments</comments>
		<pubDate>Wed, 23 Jul 2008 16:23:41 +0000</pubDate>
		<dc:creator>Curtis</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[apache]]></category>
		<category><![CDATA[htaccess]]></category>
		<category><![CDATA[password]]></category>
		<category><![CDATA[protect]]></category>
		<category><![CDATA[wordpress]]></category>

		<guid isPermaLink="false">http://curtistasker.com/?p=153</guid>
		<description><![CDATA[Apache .htaccess files can be used to block access to specific resources, or to provide minimal security through user name and password authentication.
You can use a .htaccess file in any folder of your website, and it will apply to any subfolders.  A single .htaccess file placed in the root of your domain can apply [...]]]></description>
			<content:encoded><![CDATA[<p>Apache <a href="http://httpd.apache.org/docs/2.2/howto/htaccess.html">.htaccess files</a> can be used to block access to specific resources, or to provide minimal security through user name and password authentication.</p>
<p>You can use a .htaccess file in any folder of your website, and it will apply to any subfolders.  A single .htaccess file placed in the root of your domain can apply to the entire website.  While this is advantageous for blocking access to files, you&#8217;re going to need a seperate .htaccess in each subfolder that you want to password protect.</p>
<p><span id="more-153"></span></p>
<h2>Blocking access to resources</h2>
<pre># block access to all .ht* files
&lt;files ~ "^\.ht"&gt;
    Order allow,deny
    Deny from all
&lt;/files&gt;

# block access to wp-config
&lt;files wp-config.php&gt;
	Order allow,deny
	Deny from all
&lt;/files&gt;</pre>
<p>This blocks access to all files that begin with .ht, as well as the wp-config.php file.  You can use this type of definition to block access to any file or folder of your choosing.</p>
<p>If you&#8217;re running Wordpress, ideally you should move your wp-config.php file to a location on your server that is above the root of your domain; It contains security information that you really don&#8217;t want somebody getting access to.</p>
<h2>Password protecting files and directories</h2>
<p>This is not a terribly good method of protecting your content, as none of the data is encrypted as you access it.  In addition, unless you use digest mode, your user name and password are sent in the clear every time you type them in.</p>
<h3>Creating users and passwords</h3>
<p>First, you need to create some user names and passwords and store them in a .htaccess file.</p>
<pre>% cd /home/username/webapps/www.example.com/
  htpasswd -c .htpasswd user1
  Adding password for user1.
  New password:  pass
  Re-type new password:  pass

% chmod a+r .htpasswd</pre>
<p>Switch to the root folder of your domain, and run the <a href="http://httpd.apache.org/docs/2.2/programs/htpasswd.html"><code>htpasswd</code></a> command with <code>-c</code> to create a new password file, with <code>user1</code> as a user.  Then type in a password for that user.  Finally you chmod the file to ensure it has the proper permissions.</p>
<p>You can add additional users to the file by simply using the above command without the <code>-c</code> option.  You can also create groups of users, by creating a file called .htgroup and that looks like so:</p>
<pre>my-users: user1 user2 user3 user4</pre>
<p>You should ideally put your .htpasswd file in a location that isn&#8217;t accessible from your website, such as your home directory.</p>
<h3>Setting up the authentication (Basic)</h3>
<pre>AuthType Basic
AuthName "My Protected Folder"
AuthUserFile /home/username/webapps/www.example.com/.htpasswd
AuthGroupFile /dev/null
Require valid-user</pre>
<p>AuthType we&#8217;re using is Basic (password sent in the clear).</p>
<p>AuthName is an arbitrary name you assign to your protected content.  If you protect multiple directories, and give each directory the same AuthName, then the user will only be required to entire their information once;  They will then be granted access to all the directories.</p>
<p>AuthUserFile is the location of the .htpasswd file, which grants users listed in this file access.</p>
<p>AuthGroupFile is the location of the .htgroup file, if you wish to grant a group of users access.  In this case I&#8217;m defining a null group.</p>
<p>Require can list either specific user names group names, or any valid user or group from the Auth files.</p>
<h3>Setting up authentication (Digest)</h3>
<p>This is slightly more secure than Basic mode, as your password is sent as an md5 hash rather than in the clear.  To use Digest mode, use the following code:</p>
<pre>AuthType Digest
AuthDigestDomain /
AuthDigestProvider file
AuthUserFile /home/username/webapps/www.example.com/.htdigest
AuthName "My Protected Folder"
Require valid-user</pre>
<p>You will need a new password file, which can be created using <a href="http://httpd.apache.org/docs/2.2/programs/htdigest.html"><code>htdigest</code></a>.   Follow the same steps used when creating the .htpasswd file, the syntax for the command is the same.</p>
]]></content:encoded>
			<wfw:commentRss>http://curtistasker.com/blog/programming/153/basic-access-control-in-apahce/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>URL rewriting using Apache</title>
		<link>http://curtistasker.com/blog/programming/109/url-rewriting-using-apache</link>
		<comments>http://curtistasker.com/blog/programming/109/url-rewriting-using-apache#comments</comments>
		<pubDate>Sun, 20 Jul 2008 21:26:00 +0000</pubDate>
		<dc:creator>Curtis</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[apache]]></category>
		<category><![CDATA[htaccess]]></category>
		<category><![CDATA[regex]]></category>
		<category><![CDATA[url rewriting]]></category>
		<category><![CDATA[wordpress]]></category>

		<guid isPermaLink="false">http://curtistasker.com/?p=109</guid>
		<description><![CDATA[Several years ago, you made the grave error of putting an overly specific URL in some advertising (example.com/fall_2005_news.html).  You&#8217;ve come to your senses and are re-organizing your website&#8217;s structure, and you really want to get rid of that html file.  You&#8217;d like any user attempting to visit that ancient URL to instead be [...]]]></description>
			<content:encoded><![CDATA[<p>Several years ago, you made the grave error of putting an overly specific URL in some advertising (<code>example.com/fall_2005_news.html</code>).  You&#8217;ve come to your senses and are re-organizing your website&#8217;s structure, and you really want to get rid of that html file.  You&#8217;d like any user attempting to visit that ancient URL to instead be shunted to <code>example.com/news</code>.</p>
<p>Well, such a procedure is relatively easy.  Apache <a href="http://httpd.apache.org/docs/2.2/howto/htaccess.html">.htaccess files</a> can be used in any folder of your website, and will apply to any subfolders.  Thus, a single .htaccess file in the root of your domain can apply to the entire website.</p>
<p>The aforementioned example is fairly simple, but URL rewriting of extreme complexity is possible once you know the rules.  Generally, instead of simply changing <code>file1.html</code> to <code>folder/file1.html</code> using a single rule, you will instead change every file fitting the form <code>fileX.html</code> to <code>folder/fileX.html</code>.  That is to say, any request for a file that matches a specific pattern will be rewritten to a new URL.</p>
<p><span id="more-109"></span></p>
<h2>Regular Expressions</h2>
<div class="infobox alignright">
<h3><abbr title="Regular Expressions">Regex</abbr> Pointers</h3>
<table border="0">
<tbody>
<tr>
<td>^</td>
<td>start of line anchor</td>
</tr>
<tr>
<td>$</td>
<td>end of line anchor</td>
</tr>
<tr>
<td>.</td>
<td>match any character</td>
</tr>
<tr>
<td>?</td>
<td>match 0 to 1 of the preceding elements</td>
</tr>
<tr>
<td>*</td>
<td>match 0 to N of the preceding elements</td>
</tr>
<tr>
<td>+</td>
<td>match 1 to N of the preceding elements</td>
</tr>
<tr>
<td>[abc]</td>
<td>matches any 1 character from the list abc</td>
</tr>
<tr>
<td>[^ab]</td>
<td>matches any characters except a and b</td>
</tr>
<tr>
<td>\.</td>
<td>match the character period</td>
</tr>
<tr>
<td>(.*)</td>
<td>backreference that matches all characters</td>
</tr>
<tr>
<td>!</td>
<td>negate the match</td>
</tr>
</tbody>
</table>
</div>
<p>It&#8217;s a bit beyond the scope of this post to teach <abbr title="Regular Expressions">regex</abbr> in depth, but here&#8217;s a few pointers to help decipher the code in the next section.</p>
<p>As a mildly complex example, consider <code>^www\.([^\.]+\.[^\.]+)$</code>.  This starts at the beginning of the line, matches the character string <code>www</code>, followed by a period, followed by 1 to N characters that are not period, followed by a period, followed by 1 to N characters that are not a period, followed by the end of the line.</p>
<p>It matches any URL that fits the form: <code>www.example.com</code>.  It then stores a backreference for the <code>example.com</code> portion of the match.  Think of a backreference as a saved variable containing the text that was matched inside a pair of parenthesis.  Multiple backreferences can be made per block of <abbr title="Regular Expressions">regex</abbr>, and they can be used later on in your code.</p>
<h2>URL Rewriting</h2>
<p>Apache defines a few simple commands that allow you to use <abbr title="Regular Expressions">regex</abbr> to dynamically alter a URL.  The <a href="http://httpd.apache.org/docs/1.3/mod/mod_rewrite.html">official documentation</a> is a great help, but the <a href="http://www.google.com/search?q=RewriteRule">examples on the web</a> are of much greater instructional value.  Generally you begin URL rewriting like so:</p>
<pre>&lt;IfModule mod_rewrite.c&gt;
RewriteEngine on
RewriteBase /</pre>
<p>and ends like so:</p>
<pre>&lt;/IfModule&gt;</pre>
<p>It uses an if..then block to enclose all URL rewriting commands, and will only evaluate the block if the correct Apache module is installed.  It begins by turning on the rewrite engine, and setting the base of all rewriting to the root directory.</p>
<p>RewriteCond and RewriteRule control how a URL is rewritten.  Generally you write 0 to N RewriteCond statements followed by a single RewriteRule statement.  The RewriteRule will only be executed if every RewriteCond statement preceding it matches something.</p>
<p>RewriteCond takes two arguments:  the string to match against, followed by the pattern to match.  RewriteRule takes two arguments: the pattern to match, followed by the rewritten URL.  RewriteRule always uses the REQUEST_URI variable as its string to match against;  If the URL was <code>http://www.example.com/folder1/file1.html</code>, it would match against the string <code>folder1/file1.html</code>.</p>
<h3>Strip off the www subdomain</h3>
<pre>RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC]
RewriteRule ^(.*)$ http://%1/$1 [R=301,L]</pre>
<div class="infobox alignright">
<h3>Backreferences</h3>
<table border="0">
<tbody>
<tr>
<td>%1</td>
<td>the first backreference from RewriteCond</td>
</tr>
<tr>
<td>$1</td>
<td>the first backreference from RewriteRule</td>
</tr>
<tr>
<td>$2</td>
<td>the second backreference from RewriteRule</td>
</tr>
</tbody>
</table>
</div>
<p>This starts with the HTTP_HOST variable, which contains just the www.example.com portion of the incoming URL.  It then matches <code>www.</code>, and stores a backreference to all characters that come after that.</p>
<p>Assuming that the URL did indeed contain a <code>www.</code>, then the RewriteRule comes into play.  The pattern <code>^(.*)$</code> will match everything in the REQUEST_URI, and store a backreference to the string.  The URL is then rewritten using the two backreferences.</p>
<h3>Map subdomains to subfolders</h3>
<pre>RewriteCond %{HTTP_HOST} ^([^.]+)\.([^.]+\.[^.])$
RewriteRule ^(.*)$ http://%2/%1/$1 [R=301,L]</pre>
<p>This starts with the HTTP_HOST variable, which contains <code>subdomain.example.com</code>.  It finds the subdomain using <code>([^.]+)\.</code> to match 1..N characters that is not periods until it reaches a period.  A backreference is stored as %1.</p>
<p>Next, it finds the domain using <code>([^.]+\.[^.])$ to match 1..N of characters that are not periods (</code><code>example</code>) followed by a period followed by 1..N characters that are not periods (<code>com</code>).  It stores the domain in the backreference %2.</p>
<p>Finally, the RewriteRule uses the pattern <code>^(.*)$</code> tomatch everything in the REQUEST_URI, and stores a backreference as $1.  The URL is then rewritten using the three backreferences.  So, <code>subdomain.example.com</code> now becomes<code> example.com/subdomain</code>.</p>
<h3>Prevent image hotlinking</h3>
<p>If you host images on your website, you may want to prevent other websites from stealing your bandwidth by hotlinking to your images.</p>
<pre>#RewriteCond %{HTTP_REFERER} !^$
#RewriteCond %{HTTP_REFERER} !^http://(www\.)?example.com/.*$ [NC]
#RewriteRule \.(gif|jpg|png)$ - [F]</pre>
<p>The first RewriteCond will match any request where the referring site is not empty.  The second will match any request where the referring site is any site except your own site (<code>example.com</code> or <code>www.example.com</code>).</p>
<p>If either of those conditions are met, the RewriteRule kicks in, and matches any file that ends in gif, jpg, or png.  So, if any outside website links to any file on your website that ends in those 3 file extensions, it will return a forbidden response.</p>
<h2>Wordpress URL Rewriting</h2>
<p>If you use Wordpress, when you customize your permalinks through the admin interface, Wordpress will attempt to alter your .htaccess file to add the following lines:</p>
<pre>RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]</pre>
<p>What this does is check to see if a requested file or directory exists (<code>example.com/directory</code>).  If the file or directory exists, nothing happens, and you are able to access the resource as usual.  If it does not exist (<code>example.com/postname</code>), the RewriteRule activates, sending the request to the Wordpress index.php.  From here, the Wordpress permalink php code takes over, translating your request into the Wordpress resource you requested.</p>
]]></content:encoded>
			<wfw:commentRss>http://curtistasker.com/blog/programming/109/url-rewriting-using-apache/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>
