A Brief Introduction

I’m a married Software Engineer living in Seattle who is originally from Chicago’s western suburbs. I’m a 2007 graduate of MSOE‘s Software Engineering program and recently began a new job on Microsoft’s Exchange team and am working specifically on Outlook Web App. I’m currently working primarily with C#, HTML, CSS, and some JavaScript, but in the past, I’ve also worked significantly with Java applications built on Oracle databases. In my free time, I enjoy photography and more web development with PHP, MySQL, HTML, CSS, Javascript, and jQuery; my largest personal project has been for my dad’s business, DDM Garage Doors.

One of the authors of the Bible, Paul, writes, “If anyone speaks, let him speak as the oracles of God. If anyone ministers, let him do it as with the ability which God supplies, that in all things God may be glorified through Jesus Christ, to whom belong the glory and the dominion forever and ever” (1 Peter 4:11 NKJV). Though this web site is about me and who I am, my greatest desire is not that I look good but that it act as an instrument through whose music God uses me to proclaim Christ, His death and resurrection for the sins of the world, and the truths of His Word. My greatest desire is that my life would say with Paul, “For to me, to live is Christ, and to die is gain.” To learn more, I’d encourage you to read The Only thing in Life that Really Matters.

Please keep in mind that all content on my site reflects my own personal opinions, not those of my employer, Microsoft.

Below you’ll find my blog for posting updates in my life, changes to my web site, or just random thoughts going through my head. All posts since March 3, 2001 are available here. Enjoy!

Xenon bulb replacement on 2002 BMW 330ci (e46)

I noticed recently that one of the headlights on my 2002 BMW 330ci (e46) was dimmer than the other:

Remembering back to reading I’d done years ago, I initially was apprehensive about attempting a repair myself. The whole system is more complicated than a normal halogen setup, so I wasn’t even certain what the root cause was. Rather than repairing myself, I planned to have my mechanic take care of it for me. But, when I saw that the list price on GetBmwParts.com for the replacement bulbs was around $200 each, I feared I’d spend somewhere close to $500 for the repair, that is, if the bulbs were the issue. Absolutely absurd, especially considering replacing headlights on any other car has never cost me more than around $50 for the pair. In fact, on my Civic, the last time I replaced a bulb, it was $10.

So, I set out to figure out if I could troubleshoot the problem and fix it myself. One of the advantages of having a car that’s more than 15 years old is the abundance of content available online. I found a helpful thread on E46 Fanantics with troubleshooting instructions. The first step: swap the left and right bulbs to see if the problem followed.

But before I could do this, I had to figure out how to get at the bulb. I tried removing it without removing the whole headlight assembly but there wasn’t enough space to get the rear cap off the back of the bulb. So, I found a pair of videos on YouTube. First, for removing the headlight assembly:

And then for replacing the bulb:

When I removed the bulb from the side which was discolored / dimmer, I noticed a small crack and figured that the issue was, indeed, the bulb:

I swapped the driver’s side and passenger’s side bulbs to confirm, and the problem followed. Conclusion: the bulb needed to be replaced.

From my reading online (especially the E46 Fanantics post), I gathered that it’s ideal to replace the bulbs together to ensure consistent brightness – I guess the bulbs lose a little bit of intensity over time. So, I picked up a pair of new Philips D2S Xenon HID bulbs.

After installing them, everything looked great:

But then, as I was writing this post, I discovered that counterfeit bulbs are prevalent. I went to Philip’s web site to verify the authenticity of the bulbs. Although I had ordered both from Amazon, one of them registered as fake. But, I forgot on which side I placed each of the bulbs! Incredible! I tried to inspect the bulbs to discern for obvious signs of counterfeiting but nothing stood out. Reviewers on Amazon suggested that fake bulbs had caused them issues with the rest of the system, so I decided to return both and try again. Fortunately, Amazon’s return policy is extremely generous and I was able to return both bulbs. Replacements are on the way; pending authenticity verification, I’ll hopefully get these installed soon!

As a side note: A friend shared a helpful tip for re-installing the headlight assembly. There’s one screw that is particularly difficult to reach (the one Zach, from the video, uses a socket extension to reach). I don’t have a magnet in my socket set, so I was worried about dropping the screw into the ether. I used a small dab of liquid super glue on either side of the screw head, attached it to the socket, and let it dry. In my first couple attempts, one of the socket extensions released but left the socket attached. I removed the screw again and then wiggled it just enough so it could break free from the socket with a little force once it was screwed in. This did the trick, and I was able to reassemble without dropping the screw somewhere unreachable.

Road Bike Inner Tube Replacement

Last weekend while I was out enjoying Seattle’s beautiful weather, speeding down hills on my road bike, I had the inevitable misfortune of getting a flat tire. So, this week, for the first time in my life (at age 30!), I set out to learn how to change my bike tire.

There is certainly an abundance of tutorials for how to change your bike tire and inner tube, so I do not intend to reiterate existing material. Rather, I wanted to highlight some of the questions I had and share the answers I discovered in the hopes that, if you’re doing this for the first time, too, I may just save you a little bit of time.

I referred to the following two tutorials while changing my inner tube:

  1. Replacing bike tire and tube at Instructables.com
  2. Replacing bicycle tire at WikiHow.com

What tube should I buy?

The following factors are important in choosing a tube:

  1. Size (more on that later)
  2. Valve type – presta vs. schrader. I assume if you own a bike pump, you’ve already figured out the difference. Schrader is the type on my car, Presta was engineered to facilitate pumping tires to higher pressures and is the one I have on my bike.
  3. Valve length – based on the depth of your wheel. Unless you’ve got crazy deep rims, I expect 42mm is sufficient.

Tube Size

Bike Tire

The size of the tube you need depends on the size of your tire. You can find the tire size listed somewhere on the sidewall, just as you would on your car. As is depicted above, my tires indicate 700x25c, so I found a tube that fits tires size 20-25. According to customer input on Amazon, it’s preferable to buy a tube whose range is smaller rather than larger (i.e. 20-25 would be preferable to 25-32).

Of course, as with anything I buy from Amazon, I take a look at the customer reviews to make a final decision between competing options. There wasn’t an obvious choice, so I just ended up purchasing the Continental 42mm Presta Valve Tube, size 700 x 20-25.

Do I need to replace the tire too?

The general guidance as to whether your tire must be replaced seems to be based on the wear on your current tire. If you can see the threads in the tire, or if there are a lot of nicks in the rubber, it seems it would be time to change it. I decided not to change my tire; I had only about 600-700 miles on it, and it didn’t seem to be worn significantly, nor was there much damage to it. After removing it, I inspected it from the inside and concluded that I made the right decision. Once I need new tires, I intend to take a closer look at the Continental GatorSkin DuraSkin Tire, which appears to last a long time and protect the tube quite well.

Removing the tire

I found removing the tire to be the most difficult part of the job. One of the tutorials suggests using a screwdriver; I prefer to avoid using tools that have the opportunity to inflict permanent damage. (Same goes for removing those panels in the car interior). Plus, I already had two types of bike tire levers on hand.

The method I used was the two lever approach. I inserted the first lever and used its “hook” to attach it to one of the spokes and hold it in place.

The "other end" of the lever has a hook you can use to attach to one of your spokes.

I tried using another of these same levers, but I either had too much difficulty getting it underneath the tire, or else I could not slide it along the rim. I found the lever on the Topeak Alien II to have a slightly slimmer edge that was more effective at prying the tire from the rim.

Compare the two levers; the second is the Topeak.

Bike Tire Lever

Topeak Alien II Bike Tire Lever

Best wishes on your repair, and happy riding!

git push

I’ve spent some time recently messing around with (learning) git. I needed a better solution for tracking changes to the work I do for DDM Garage Doors, Inc., and git seems to be the leading choice these days.

As part of this exercise, I also moved my C++ Examples from high school over to Github. I’m not convinced there’s much value in keeping this code up online, other than nostalgia. In addition to the rather rudimentary nature of most of the assignments, I saw several optimizations I could make to the code and realized that most of my interview questions at Microsoft and Google required more complex solutions. In any case, as the first code I ever wrote in a strongly typed OO language, it holds a special place in my heart.

PayPal Fraud and Poor Customer Service

After several months of inactivity on PayPal, I logged in to my account today to confirm that my address was correct. I noticed that a second address had been added to my profile, one that has not been used in any payment I’ve transacted.

So, I called PayPal support and chose the “fraud” option. The first lady I spoke with was able to identify when the address was added, and that it was added as a gift address, but told me not to worry about it … that I must have added it when making a payment. I explained to her that it was not related to either of my *two* PayPal transactions (the most recent of which was in January). I eventually was able to speak with someone with further insight into my account, who explained that someone had gained access to my account, added the address, tried to make a payment, and they had detected it as fraud. I was advised to change my password and security questions.

Contrast this with the fraud against my Discover Card this past spring. My CC was first denied, they locked down my whole account, and I had to get a new one. The card was denied before Discover had a chance to reach out to me, but I did receive a delayed phone call AND email notification that I needed to contact them about my account, after I had already called in to address the issue.

PayPal, you failed on four counts:

  1. You didn’t notify me that there was fraud against my account, and that I should change my password to avoid it in the future. Instead, I had to notice the issue two months later, and call you.
  2. You let the fraudulent address remain in my account profile.
  3. You blocked the email notification I should have normally received indicating that an address was added to my account.
  4. Your customer service rep … the one I reached when I said I was calling about fraud … told me not to worry about it.

Uploading .htaccess with FileZilla and Zero-Byte Files

I’m running FileZilla at the moment, and just ran into an issue uploading an htaccess file. Every time I uploaded it, it would appear to transfer successfully, but then the server would report a zero-byte file. I tried renaming the file, no luck. Finally, I got the file to transfer by switching my connection mode to Active instead of Passive. Go figure.

FileZilla FTP Settings Dialog

Looks like there’s a FileZilla update. I’ll install that in the hopes of avoiding the issue in the future.

Edit >> Same issue with 3.7.3. Oh well. Active it is. I’d switch to SFTP; Fluid Hosting sent us a note awhile back stating that SFTP was now enabled but every time I’ve tried it, I’ve gotten a connection failure.

Working around Litespeed’s mod_rewrite intermittent 404 Issue

I use mod_rewrite all over the place. Who doesn’t these days? IIS 7 even has a URL rewriting module that will convert your mod_rewrite rules. But I digress.

I noticed a few months back that I’d get an occasional 404 error for a page that I know exists and is handled by a mod_rewrite rule. Within a few seconds, the access logs reported a URL matching the same rewrite rule with a 200 OK response. If I hit the URL myself after receiving notification of the failure, it would work. I concluded there’s some sort of bug in Litespeed and escalated to the Fluid Hosting support folks. They suggested that they are “pretty sure that Litespeed developers are aware of the issue” and that it is a known issue because a Google Search for “htaccess rewrite problem litespeed” yields lots of results. Not so convinced myself; most of those results are people confused about how to configure mod_rewrite. In any case, my problem is still not resolved, and I continue to receive emails when these 404s occur. Probably a few each day. Not only would I like to reduce some of the noise, but I also want to avoid losing business if someone happens across a 404 error. So, this evening, I set out to create a workaround.

The hypothesis I’m testing with this solution is that the 404 error resolves itself automatically within about a second. The gist of the solution is to add a custom 404 error handler that spits out some Javascript that retries the request and, if it receives a 200 response, replaces the body of the page with that content. After a threshold is reached, it will stop trying and display an error message.

I initially tried implementing this retry on the server side to keep the client unaware of what was going on. Although I had a way around it, the risk of infinite recursion (and consuming all the server’s threads) was greater than I wanted to accept. (I.e. 404 error handler calls the target page, which calls my 404 error handler again. Certainly adding a header or query param to the request could help avert this.)

So … I’d share the entire code for this solution but it’s embedded in all the rest of my error handling mess that I’d rather keep to myself for now. I dream of polishing off every little pet project I’ve got, but in reality, I can’t see it happening anytime soon. So, I’ll give you an outline of what I did and hopefully you can adapt the solution to work for your needs. I did this with PHP but these concepts should transfer to any language.

Configure a Handler for 404 Errors

This is as simple as adding the following line to your .htaccess file. If you don’t know what htaccess is, this solution isn’t for you … because you couldn’t have really gotten in this mess without it … unless WordPress or some other tool configured the problematic mod_rewrite for you.

ErrorDocument 404 /404.php

Determine your retry criteria

I don’t want to retry every request. I decided to restrict retries to GET requests matching a certain set of URL patterns that I know are handled by mod_rewrite rules.

function ShouldRetryRequest()
	$retryPatterns = array(

	// Only retry GET requests. Is REQUEST_METHOD ever not set?
		return false;

	// Only retry if it matches our pattern
	foreach ($retryPatterns as $pattern) {
		if (preg_match( $pattern, $_SERVER['REQUEST_URI'] )) {
			return true;

	return false;

Return 200 OK from your error handler

When you’ve decided you want to retry the request, you’ll want to be sure you return 200 OK from your script. Many modern browsers, when they see a 404 response, will return a “friendly” error message that tries to give the user an idea of what happened but probably only confuses him further. If you’re not retrying this particular request, go ahead and return 404. Returning 200 OK ensures your content will be displayed and executed. The other advantage to returning 200 OK is that if the search engine is the “user” who happens to hit this scenario, it won’t remove the page from its index … then again, it will have totally different content associated with that page, unless it evaluates and execute the Javascript I provide a little further on, so maybe we don’t really gain anything there.

You’ll notice that my Javascript retry code expects an error condition in order to retry; once it sees a 200 OK, it will simply display that content. If that content again is our error page with the retry script, you’ll get stuck in an infinite loop. So, be sure to continue to return a 404 for requests coming from the retry script. I’m simply returning 200 OK only when the attempt query param, added by the retry script, is not present. The web server, because it has reached my script through ErrorDocument, takes care of returning the 404 when the following condition does not match.

$retry = ShouldRetryRequest();

// Original GET/POST params are not passed to the error document, so can't use $_REQUEST
if ($retry && strpos($_SERVER['REQUEST_URI'], "attempt=") === false) {
	header('HTTP/1.0 200 OK');

Hide your <body> at page load

I’d recommend putting display:none on your <body> tag. The code below will either replace the content if the 404 issue resolves itself, or remove the display:none to show the error text if the maximum number of retry attempts is reached.

Return the script that will do the retry

Your error document needs to return the code that will do the retry. This is the bit of code I whipped up this evening. Whereas I typically prefer to put my scripts toward the end of the document, I wanted to get the first retry fired off as quickly as possible, so I put this near the top of my <head> tag.

I decided to use jQuery to take advantage of its friendly AJAX APIs, so you’ll want to be sure to include the jQuery script ahead of this one.

var retryCount = 0;
var maxRetries = 5;
// How long to wait between retries, in milliseconds
var retryFrequencyMS = 200;

var theUrl = window.location.href;
var params = { 
	attempt: retryCount, 
	log404: false // This tells my error handler not to do what it would normally do with this particular request

function retry() {
	  url: theUrl,
	  data: params,
	  success: function(html) {
		var newDoc = document.open("text/html", "replace");
	  error: function(jqXHR, status) {
		if (retryCount == maxRetries) {
			params['log404'] = true;
		if (retryCount <= maxRetries) {
			params['attempt'] = retryCount;
			setTimeout(retry, retryFrequencyMS);
		else {
			// Ensure body has loaded
			$(document).ready(function() {
	  dataType: 'html',

Testing the retry logic

I put together a second simple PHP file that simulates the intermittent 404 error. The first time it is hit, it returns our error handling code. Subsequent requests, it will respond with a 404 header, until a threshold is reached.


Finally, hit the simulated 404 script from your browser. Change the attempt threshold from 2 to a value above your retry count to simulate the behavior in which the server persists in returning 404s for all retry attempts.


So … there it is. I’ve still got to put this code into production; it will be interesting to see if the volume of 404 error reports from this issue go down. I’m also interested in how long it takes for Litespeed to recover from this issue. I’ll provide updates if I find better values for the retry interval and/or maximum number of attempts.

Let me know how this works for you, if I can answer any questions, or if you spot any errors.

An Update…

Saturday, 2:20 pm PST – So, an hour or two after implementing the solution I described above, I got a report about one of these 404 errors. The script retried the page, but the server persisted in ignoring the mod_rewrite rule. Certainly I could introduce a greater delay between retries. But then it struck me … since this issue is occurring really with rules targeting a single script, why not use my error handler to forward requests to the script internally, instead of with a HTTP request. The script exists on the file system, so fake the PATH_INFO server variable, I include the script, and I’m in business.

Will continue to keep an eye on this and see how it works out.

Mt. Rainier at Midnight

Ellen recently suggested I take a picture of Mt. Rainier from our rooftop every day. (Or, on a cloudy day, where Mt. Rainier would normally be visible.) A few nights ago, I was going through the first months’ worth of photos and noticed that I can spot a faint shadow of Mt. Rainier in this shot I took around midnight on July 23rd.

Mt. Rainier is visible even at night ... if you look carefully

Transfer Angry Birds data from iPod Touch to iPhone

I recently (finally?) upgraded to a smartphone. I had been using a basic phone for quite some time and got the additional functionality offered by a smartphone by carrying my iPod Touch with me at all times … after all, I reasoned, WiFi is offered nearly everywhere. Anyway … it’s great to be carrying around a single device (the iPhone 5) that is thinner, faster, lighter, and all around way cooler than my LG EnV + iPod Touch combo. Plus, the iPhone’s GPS and 4G network will be helpful when we move out to Seattle later this month.

But, I was bummed to find that my Angry Birds game data got lost in the transition from the iPod Touch to the iPhone. I had both devices syncing application data to iCloud, but when I loaded up Angry Birds for the first time on the iPhone, it appeared I’d have to start from scratch. When I first got the iPod Touch, I played the series of games quite frequently, so starting over then wouldn’t have been a problem. But now my relationship with the game is more casual, so I didn’t want to have to redo all those levels again. So, today, I set out to find a solution.

After a little research, I learned about a few tools that will allow you to access the iOS device’s file system and transfer data to your computer. After quickly following Angry Birds Nest’s tutorial on transferring game progress, I’ve got all my Angry Birds data on my iPhone.