Foo Hack » Freebie Isaac Schlueter on Web Development Tue, 03 Nov 2015 06:34:16 +0000 en CSS vs Tables: You’re Doing It Wrong Tue, 03 Feb 2009 07:40:22 +0000 Isaac ...Read More]]> Definitions first.


A specified set of columns and rows with cells that automatically and fairly smartly expand to fit their contents; cells can span rows or columns; the table as a whole can be treated as one block, and cells can contain tables. A table is a metaphor for visually laying out 2-dimensional content.


cascading style sheets; not floating divs, not any specific markup, but just the concept of the visual display of markup specified by a series of rules that are kept separate from the markup they operate on, generally in an external linked file or a style tag in the head of the document.

Talking Past Each Other

CSS is (for various reasons cited elsewhere ad nauseam), in most cases, the more optimal technological approach. That’s not to say that the existing state of the CSS language is perfect. In fact, even the most vocal CSS advocates regularly assert that there are deep problems with the existing spec and browser support.

Tables are (for various reasons cited elsewhere ad nauseam), in most cases, a more optimal metaphor than any of its rivals. There’s nothing inherently wonderful about the tags themselves. In fact, even the most vocal table advocates regularly assert that the markup is ugly.

Therein lies the crux of the problem. CSS is a great technological approach, and tables are a great metaphor. The question then usually becomes, Should I mark up my content using <div> tags or <table> tags?, which really means, Is the separation of style from content more or less important than using the optimal layout metaphor? The debate goes a little like this:


This layout metaphor is better, so you should use these tags. All you idealists are unrealistic! (Also, if you think markup matters, you believe in fairies. It so doesn’t!)


Metaphor shmetaphor! You don’t care about the sanctity of data or code quality. Think of the maintenance! (Also, if you can’t do it with divs, you’re stupid. It’s so easy!)

The Right Answer, it would seem, is to use the table metaphor with the CSS technology. In the ideal world, you’d always mark up your content using the tags that would communicate your meaning most clearly to your intended user agents. Then you’d tell user agents how to treat those tags visually. To describe this visual display, you should be able to use the table metaphor, or the float metaphor, or absolute and relative positioning, or anything else, but that should not be done by your markup.

Getting Real

In the real world, it’s not so nice. The CSS specification has a set of display values designed to mimic the table tags, but they aren’t well supported, and anyway, it’s an imperfect imitation of a hack that was not really intended to be used the way we all ended up using it.

In other words, CSS is not an ideal example of what CSS aims at, and the table/tr/td tags are not an ideal implementation of the table/grid metaphor. CSS tables, though they are clever and in some cases quite useful, take it from bad to worse.

The state of the CSS art is not at a point where you can realistically expect to make any significant stylistic changes to your pages without altering the markup. If you need to move the navigation bar from the right to the left, or re-skin the page with dropshadows instead of rounded corners, or convert your gradients from 2-tone to 3-tone, or make your boxes vertically centered instead of top-aligned, you’re probably going to have to change your markup, at least a little.

In theory, it’s possible. I know a handful of my colleagues will vehemently disagree and point at countless approaches to enable virtually any kind of reskinning using only CSS changes. (I’ve used Leslie Sommer’s CSS Mojo technique to great success in the past; we used it for pretty much everything on Yahoo! Buzz.) But let me tell you, from years of experience building production sites with CSS, most of the time, in reality it just doesn’t work that way.

And why should it? What kind of crazy lunatic writes all their HTML by hand in text files, anyhow? Clearly you have some kind of back-end engine spitting it out from templates, so you just change the template, and voilà!, the markup is changed everywhere.

A Very Blue Bike Shed

Working at Yahoo, I’ve met some webdevs with truly incredible CSS ability, who crank out live code under real deadlines to exacting standards. They use CSS, and not tables, and they Get Shit Done. There are a lot of them, more than I can list here, but Nate Koechley, Matt Sweeney, Hedger Wang, and Leslie Sommer all deserve a special mention. I came to Yahoo knowing CSS pretty well, but I became an expert largely as a result of working in such a highly skilled community of developers.

Also due to my time at Yahoo, I’ve seen some absolutely crazy debates about markup and coding standards on the devel-frontend mailing list. I mean, you think this little flare-up in the blogosphere is anything? You got no idea, buddy. Seriously. And these are coworkers who (for the most part) really like and respect one another.

You wanna know a secret? It makes no difference.

Language is as language does. If everyone uses the <table> tag for markup, guess what happens: <table> is now a semantically meaningless (or at least, semantically vague) tag, and any user agents that might care about navigating tabular data have to deal with that fact. It becomes just another <div>, for all intents and purposes, but a little less flexible, and with a default styling that makes it handy for layout.

The passion for the rants comes from the fact that it is meaningless! Of course it’s a fertile ground for bikeshedism!

That’s right: It doesn’t matter.

Use whatever tags work for you. I don’t care. You’ll still be a good person.

I can tell you from experience that a deep knowledge of CSS is essential for serious front-end development. (Most so-called DHTML is actually just manipulating CSS with Javascript, and the Javascript is pretty light.) CSS can do some things that table tags can’t, so you ought to learn it. The reverse is also true, so you should know how to use tables, too.

Write code that you can maintain, that is flexible enough to let you change it without sacrificing the stability of your product. Test it in the user agents that you expect to support. Stop debating the color of this bikeshed.

If there’s ever a good reason to go back and change your tables to divs, or vice versa, you can do that. Hell, plan for that, because whether you use CSS for layout or not, you’re going to need to touch your markup sometimes. It is much much harder to build a product people want than it is to build a product that works in Browser X.

Belorussian translation provided by fatcow

Programming Puzzles and Our Mismatch Problem Mon, 07 Jul 2008 17:00:46 +0000 Isaac ...Read More]]> In interviewing candidates for programming jobs, a common technique is to ask them to solve some programming puzzle. Makes sense, right? If the guy’s smart enough solve random silly questions, he’s probably good at programming, since that’s most of what programming is.

As it turns out, this bit of common sense is common bullshit. It’s just another mismatch problem, along with requiring elementary school teachers to have lots of formal education, cops to be big and strong, and law school applicants to have great grades in high school. It doesn’t predict success even a little.

A Tale of Two Coders

Feel free to skip to the fun stuff.

Let me tell you about two programmers I’ve worked with.

The first graduated from Stanford University in the top 10% of his class with a degree in Computer Science, and went on to get an Master of Science in the subject. He knew about B+ trees and maps. He could tell you what a directed acyclic graph was, and what it should be used for. He built an MVC system from scratch to design business cards in a web browser, 2 years before Ajax was “teh new hotness”. He interviewed well, and had a host of companies to choose from. He chose a job, and was one of the highest paid new hires in the history of the company.

The second graduated from high school, and had absolutely no intentions of ever taking classes again if he could help it. Not sure what to do with his life, he worked at a local electronics store (Circuit City, I believe) for a few years. He’d messed around with computers plenty, programmed a bit, but nothing serious. A friend of his worked at a software company, and managed to get him a job, despite his lack of experience and education, and despite the fact that he interviewed terribly. He came in at the low end of the pay scale.

Who was the better programmer?

Since I tipped my hand by talking about the mismatch problem, you’re probably guessing that the second one was better. You’d be right. But I doubt you’d realize just HOW right you are.

Despite the fact that I think he deserves any reputation his lack of skill earns him in life, it strikes me as being in poor taste to name him here. Let’s call the first programmer “X”.

Over a year after X left the company, one of the other guys found that he could reliably predict and fix crazy strange bugs by searching for the guy’s initials in the codebase. (There was a fairly strict rule about commenting changes in existing code, which, thankfully, X followed.) I’m talking real bone-headed stuff like:

If Len(".837") = 3 Then

When is “.837″ ever 3 characters?! To make matters worse, that If block was wrapping about 250 lines of code, some of it essential to our customers getting paid. X was clearly operating in some kind of alternate universe. Real DailyWTF type shit. And, he was the kind of asshat who was nearly impossible to work with. I mean, imagine any quality that a programmer needs to have, except for IQ, and he lacked it. He was arrogant, rude, passive aggressive, and lazy. He was a bully who would go out of his way to make people feel uncomfortable once he decided that he didn’t like them. Every design discussion was an Argument from Intimidation—either you agreed with his idea and stroked his ego, or you were an idiot, plain and simple. He was good at (useless) puzzles, but his attention to detail in real work was beyond terrible.

Within 2 years at the company, the second guy—the uneducated, inexperienced, bad interviewer—was one of the go-to architects who really grokked how everything was supposed to work. He picked up Visual Basic fast enough to pass by most of the existing team, some of whom had been writing code since he was in high school. He was responsible for designing and implementing a part of the software that was the primary killer feature. He redesigned a huge chunk of the program that never quite worked right. He was in databases, in the presentation layer, and in between. By any estimation, a very significant portion of the product’s value was entirely his doing.

After we’d both left that place, I referred him to Yahoo. Despite not having very much experience in front-end web development, and again interviewing terribly, the hiring manager was wise enough to heed my very strong recommendation. And good thing, because he very quickly became one of the most important members of the Yahoo Games team. (And he occasionally reads this blog and comments on stuff. Hi, Geoff.)

So, at this point, you might be thinking, Well, if the super educated brainiacs are bad programmers, and the lazy hobbyists are good programmers, then we just need to flip the test around, and use it in reverse. Then we’ll find the Geoffs, and avoid the Xes.

If only it was that easy.

You see, there actually are quite a few very good programmers that are very good at silly puzzles and have degrees in Computer Science. Almost every problem has some kind of mathematical component; a lot of the theories were discovered because they’re true and relevant. Some of X’s abilities are quite useful, so having both the will and the skill is best. The hobbyists eventually find that they have to hit the books and learn theory at some point, or else they get passed by.

But those skills aren’t nearly as useful or predictive of programming ability as we might think. Geoff has the attitude of a great hacker and a mind that is capable of learning quickly, which, as it turns out, is much more useful in the long run, and much harder to test for. X had a big brain and a bad attitude. Most of programming is not solving puzzles with algorithms. Most of programming is communication, attention to detail, and a relentless desire to build something beautiful.

Some Puzzles

Despite the fact that programming puzzles are almost 100% useless in the hiring process, they’re fun, and a good mental work-out to keep your thinking sharp. They’re a good part of a practice regimen. Here are a few that I’ve come across lately that were pretty interesting. (Sadly, my beliefs about the foolishness of puzzles-as-hiring-tool are not shared by all of my managers, and I learned about two of these because they are used in our interview process.)

I’ll edit this post to include solutions later. I didn’t make up any of these, but I did revise them somewhat. The goal in each of them is to devise a program or algorithm that will find a solution in the least number of steps/iterations/whatever.

Square the Sum

For all 6-digit numbers from 100000 to 999999, find the numbers that, if you add the top three digits to the bottom three digits, and square the result, it will equal the original number.

For example, for 123456, you’d add 123 and 456, which equals 579. Then, square that sum, which yields 579 * 579 = 335241. 335241 ≠ 123456, so 123456 is not in the set.

Dropping Eggs

Let’s say that you have 2 eggs, and a building that is 100 floors tall. You need to figure out how high up you have to drop the egg to have it break when it hits the pavement. Assume that the egg either breaks completely or is completely undamaged. That is, repeatedly dropping from the second floor will not make it more likely to break. (Hypothetical eggs are very hard, but when they break, they really BREAK.)

For example, if you drop the egg from floor #50 or below, it won’t break. But if you drop it from floor #51 or above, it will break.

What is the optimal approach to testing floors? Assuming that you take that approach, and the egg breaks on the last floor you test, how many times did you have to drop it?

Part 2

As the number of floors n increases to a very large number (millions, billions, whatever—since it’s really not floors and eggs but a sorted database of records or something), how does your solution scale?

Let’s say that you have 3 eggs. What’s the value now?

As the number of eggs increases, how does the worst-case number of tests change? If you had an unlimited supply of eggs, is there a better solution?

I heard this one at work, and it sounded kind of familiar, but I didn’t remember the solution right away. I dug up my textbook from “CSC212: Data Structures and Algorithm Analysis”, and sure enough, it was one of the examples Dr. Sayed used to teach us big-O notation.

Non-Repeating Digits (Cedric’s Challenge, slightly revised)

Find the count of all natural numbers below a certain number of digits that have no repeated digits. For example, for length=2, the following numbers all satisfy: 10, 12, 21, 23, 32, 34; but these don’t: 11, 22, 33. For length=3, 97 and 102 are valid, but 99, 100, and 101 are not.

Additionally, find the two consecutive numbers that are furthest from one another, and the difference between them. For example, in the length=3 case, the greatest difference between two consecutive numbers is 4, between 98 and 102.

For example, in length=2, there are 90 matches. (1-99, except for 11,22,33,44,55,66,77,88,99.) The biggest jump between two consecutive numbers is 2, between 10 and 12.

Part 2

In addition to specifying the length in digits, also make the base variable. For example, in the (base=3,length=3) set, the following numbers are valid: 10, 12, 20, 21, 102, 201.

Compute the values for length=100,base=1000. Speed matters.

Part 3 (Cedric’s Challenge + arbitrary bases)

Print all the numbers in order before printing the count and difference. (Hint: if this doesn’t make it any more complicated, then you didn’t do parts 1 and 2 properly.)

Since the base can be arbitrarily high, express numbers in bases greater than 10 as a comma-delimited tuple rather than using character digits, optionally with a trailing comma. For example, the base-16 number normally written as “FA9″ could be printed as either “15,10,9,” or “15,10,9″.

Hacking the Google Favicon Sat, 07 Jun 2008 01:36:37 +0000 Isaac ...Read More]]> There’s been a lot of nerd rage about the new google favicon. I joined in with a rationalization for my distaste for their new design. After a few days of the lower-case “g” on a gray background, I decided today that I just couldn’t take it. Here’s how I fixed it, so my Mac shows the old logo.

Certainly, any company ought to think long and hard about any branding change so fundamental and wide-reaching as a change in logo. If you’re a web company, then your favicon IS your logo, and everything else is secondary. For Google’s sake, I sure hope they understand just how significant this change was, and weighed the pros and cons carefully.

While I recognize my position deep in peanut-gallery territory, I simply cannot accept that it was a good move. A favicon needs to be:

  1. Far from gray. Browser tabs are gray, and the purpose of a favicon is to let the faster right-brain processes identify your site in a list of tabs or bookmarks. If I can’t see it, it’s useless. FAIL
  2. Mostly not transparent. If you’re going to use a gray logo, fine. Put it on a white background, so you know it will stand out. A small logo in a transparent background is invisible. FAIL
  3. Evoke your corporate branding. I should be able to associate your favicon with your brand without thinking about it. If, for example, your corporate branding is focused on lots of bright colors on a white background, your favicon should echo this. FAIL
  4. Use big, simple shapes. Fine details (like those in the double-curl style of lower-case “g”) get lost at 16×16 size. FAIL

Poor contrast.  Not enough pixels.  Not "google" enough.  Prettier - Who cares?  FAIL

Yahoo and Google are effectively equivalent in terms of the objective quality of their search results. Scores of user-studies have shown that our perception in SERP quality is due primarily to brand loyalty and nothing else. If you’re a Yahoo searcher, and you see a red Y, your comfort filter tells you it’s good, no matter where the results actually came from. You can’t tell the difference, because, for the most part, there isn’t one. Most of the time, Yahoo and Google search pull up exactly the same sites, or close to it. They’re both very very good, and search is a case where there is a right answer, even if the method of finding it is a bit fuzzy.

For some searches, it seems that Yahoo is even significantly better than Google. Compare for yourself. Somewhat humorously, the results for “yahoo is better than google” seems to yield much better results on Yahoo. I tried the reverse search, expecting to see some kind of amusing self-bias, but actually Yahoo did that better, too. From my cursory non-scientific view, it seems like Yahoo puts a bit more weight on the title, and there are probably other slight differences. But the point is, the differences are slight enough to be overlooked. They’re both pretty damn good at finding what you ask for.

I work at Yahoo. But I use Google for search. I perhaps ought to bleed a little more purple than I do. I also own stock in Yahoo, so in a small way, using Google for search is not a financially rational move. So why do I do it?

Brand loyalty. I was using Google ever since it’s been around, and I’ll probably keep using it for a long time. I imprinted early on that big G in the white square, and some very low-level neural systems tell me loud and proud that, when it comes to searching, that G means Good. Frankly, rewiring all that stuff isn’t worth the effort.

I think that brand loyalty explains a lot of the nerd rage over the new favicon. Yes, it doesn’t affect the results. Yes, it’s just a case of cheese moving, and not even a very relevant one. And, face it, you’re not going to stop using Google over it if you’re already a Google user. But you may be consistently annoyed for several months while the brain circuits rewire themselves to imprint on the new design.

Unacceptable. I’m a web geek. I’m a hacker. There is no way in hell that I should have to put up with something I find even slightly distasteful in my regular internet experience. I refuse to be subjected to some marketing exec’s idea of what is best for me, when I clearly know my needs better. I don’t even care if he went to Stanford AND coded a rocket ship in Python.


If you use any Google services that require a login (such as GMail, Groups, Orkut, or pretty much anything other than Search), then you’ll need Apache 2. I tried really hard to make it work with Apache 1.3, but no dice.

The good news is, Apache 2 comes standard with Leopard. The bad news is, it doesn’t come standard with Tiger.

Since I was using Tiger, and Apache 1.3, this was a much more involved hack than I’d anticipated going in. Luckily, it’s just a matter of change one line in the /etc/hosts file to turn it off, which is good, because I had other things to do before I could fix it. I use MacPorts for a bunch of stuff, so I figured I’d just install Apache 2 that way.

Easier said than done, at least in my case.

I already had PHP and MySQL running a local copy of this site, and some other stuff. MacPorts really shines if you use it for everything—try to run Apache on MacPorts and run PHP and MySQL from some other location, and you’re in for a world of hurt. It took a lot of SFTW and learning about reconfiguring to get it all working properly.

I’m not the best guy in the world to critique package management systems, but I’ve got some end-user experience. I use apt-get on my web server, MacPorts on my laptop, and of course, yinst on all the Yahoo! machines I work on. Of course, that’s not counting the Registry and Add/Remove programs dialog from Windows Land (which is hell), and the much more user-friendly “Applications” folder on the Mac (which is lovely, but not really a full-featured package manager). Of these, yinst is the best, hands down. Powerful, simple, effective, and sadly, 100% closed-source and proprietary. If you’re not at Yahoo, you’re not using yinst.

But enough about installing stuff. Long story short, you need Apache 2, or don’t go any further. If you primarily use Firefox, you can just follow Paul’s advice, and install this Greasemonkey script.

I still recommend doing this, especially if you write code for the web, and you’re not normally a “back end guy”. It’s good to tinker with this stuff, and even break it once in a while in your own little sandbox. Unless you tinker, you never learn anything new. Newton did revolutionary work in optics, largely motivated by his need for a better telescope to look at the planets. It’s good to have a working knowledge of the tools of your trade, even if they’re just a means to an end.

So, fixing the G favicon…

mod_proxy to the rescue!

The premise of this hack is pretty simple:

  1. Edit the /etc/hosts file to point “” to your local machine.
  2. Use mod_proxy to transparently send all requests for “” on to Google’s actual IP address, except for /favicon.ico
  3. Point /favicon.ico at the old favicon file, sitting on your local machine.

The interesting thing is that you can do this for any file or url out there that you want to swap in your local machine. Don’t like the favicon that a given site uses? Change it! You have the power! That’s the beauty of the web.


For this hack, you’ll need:

Apache 2 with mod_proxy, mod_ssl, and mod_rewrite

If you have a Mac with Leopard and the developer tools stuff on it, you probably already have this, and might just need to enable them. I’ll tell you how.

If you don’t already have Apache 2 and/or mod_proxy installed, then that’s outside the scope of this post, like I said above. Sorry.

About 15 30 minutes

Yes, it’s really that easy. It’s fairly easy, but a bit trickier than I’d originally thought.

I use a Mac, and these instructions are fairly mac-centric. If you use a Linux or Unix machine, then most of it will still make sense. If you use a Windows machine, then a lot of it won’t apply, but the basic idea should still be possible if you use Apache and install mod_proxy.

Some Apache setups install the Apache Control script as apache2ctl, and others call it apachectl. Since I used MacPorts, I’ve got apachectl on my machine. Substitute as required for your setup.

If you run into any sticky points you can’t get out of, post a comment. I’d like to hear it. If you run into any sticky points and DO get out of it, then definitely post a comment! I’ll update this post with your info.

Get the old favicon

I couldn’t find the actual ico file, but I found some screenshots on the internet talking about the favicon change. I got a pretty good png, and lifted out just the 16×16 piece from the address bar in the screenshot.

Then, I used png2ico to convert that png to an ico file. It’s a great tool that I use all the time to make favicons. It lets you embed multiple pngs into the ico, but in this case, all that I really care about is the 16×16 that shows up in my address bar and on the tabs in Firefox and Safari.

All in all, that took probably less than 10 minutes. But you can do this step even faster by just downloading the Old Google Favicon. Extract it in Terminal or iTerm by doing this:

tar -xzvf old-google-favicon.tgz

You’ll get a file called old-google-favicon.ico. Put that under the “Sites” folder in your home directory. If you just un-tarred it using the command above, then it would be:

mv old-google-favicon.ico ~/Sites/

Turn on Apache

If you already run web pages and whatnot on your local machine, then you are already set. Skip to the next step.

To see if Apache is running, fire up a web browser and go to localhost. If you see the default Apache startup screen, then you’re all set. If it redirects to or a web search, or you get a “could not connect to server” message, then you need to enable Apache.

If you’re running Leopard, open up System Preferences, and click on Sharing. Click the little lock in the lower-left corner, and enter your password. Check “Personal Web Sharing”.

Try hitting localhost again. If it still doesn’t work, then do this in a terminal:

sudo apachectl graceful

If that doesn’t work, try:

sudo apache2ctl graceful

If it’s still not working, sorry, don’t know what to tell ya. Good luck.


At this point, you should be able to see the desired favicon at http://localhost/~YOUR_USER_NAME/old-google-favicon.ico, where YOUR_USER_NAME is the username that you log in with. (If you’re not sure what that is, open up a terminal, and type whoami, and it’ll tell you.)

If you’ve configured Apache to have some different document root, then adjust the path accordingly. For example, since my Mac is effectively a single-user machine, I just have the default document root pointed at /Users/isaacs/Sites/, so the favicon is at http://localhost/old-google-favicon.ico. Your setup may vary.

Ultimately, it doesn’t much matter where you put it, since we’ll be telling Apache exactly where to find it later.

Enable Apache Modules

Fire up your favorite text editor, and open your httpd.conf. By default, this file is in /etc/httpd/ or /etc/apache2/; if you installed with MacPorts, then it’s in /opt/local/etc/apache2/. (You’ll have to save it as the super-user, since it’s a root-owned file, so that means vi and emacs users will have to open it with sudo. GUI editors will usually prompt for your password when you try to save the file.)

Each of these lines have to be in there somewhere. If they’re missing, add them. If they’re commented-out, un-comment them.

LoadModule proxy_module modules/
LoadModule proxy_connect_module modules/
LoadModule proxy_http_module modules/
LoadModule ssl_module modules/
LoadModule proxy_balancer_module modules/
LoadModule rewrite_module modules/

If you notice that these rules look “out of place” for the stuff that’s already there, then modify to match. For example, if the other rules are all loading the .so files out of “libexec”, then change “modules” to “libexec”.

Restart apache by running this command in a terminal:

sudo apachectl graceful

If it tells you that the server couldn’t be restarted, try this to get a more helpful error message:

sudo apachectl configtest

If it’s not working, sorry, don’t know what to tell ya. You may need to install some of the required modules using the apxs utility.


Because we’ll be proxying an SSL (ie, https://…) connection, your server will have to be able to do SSL so that it can maintain the level of encryption.

I followed these instructions to create SSL keys. It directs you towards a script, and finding that was a bit tricky. For your convenience, I’ve provided it here.

Also, I put the ssl.key folder in the same folder as the other Apache stuff, the location of the ServerRoot directive. That way, I can refer to it by a relative path. If you prefer to have it in a separate location, that’s fine, but you’ll need to refer to it by the complete path in the configs below.

Get Google’s IP Addresses

In a terminal, run this:


You’re looking for the “Address” lines, not the “Server” line. In my bash profile, I have a handy shortcut for this, so I just type getip to see the results from both nslookup and ping.

Make a note of those IP addresses. As of this writing, from my location, I got these:

We’re actually going to define a load balancer to distribute your requests between these three. While that’s probably overkill, part of the benefit of this is educational, and that’s what a proxy would normally do.

Host File

Open up your /etc/hosts file in a text editor, and add this line:

Then, in a terminal, run this command to refresh your IP caches:

lookupd -flushcache

Bring up in a web browser, and you should be looking at that default Apache page again. If so, you’re on track. If not, figure out what went wrong. You can see if Apache is in trouble by running this command and then hitting the url again:

tail -f /var/log/apache2/error_log

MacPorts users: tail -f /opt/local/apache2/logs/error_log

You may need to comment that line out with a # and do the lookupd -flushcache if you want to search google while doing this. Or you could just use Yahoo! Search temporarily. Maybe in the process, you’ll get used to Yahoo search and even find that you like it better. (See? I’m a good little purple-blooded corporate monkey!)

Set up mod_proxy

So, now let’s take your new and un-improved, and turn it into a proxy for the actual

If you have a separate conf file where you keep your Apache customizations (which I highly recommend), then add this stuff in there. If you don’t, then you can just add it to /etc/httpd/httpd.conf or /etc/apache2/httpd.conf or /opt/local/apache2/conf/httpd.conf. Either way should work, as long as Apache finds out about it somehow.

Stuff that you may need to change wrapped in strong tags.

#google proxy stuff
Listen 443
SSLPassPhraseDialog builtin
SSLSessionCache dbm:/var/run/ssl_scache
SSLMutex file:/var/run/ssl_mutex
SSLRandomSeed startup builtin
<VirtualHost *:80>
# the place where you put the .ico file.
DocumentRoot /Users/isaacs/Sites/
ProxyPreserveHost On
ProxyRequests Off
<LocationMatch .*>
Order deny,allow
Allow from
SSLProtocol all -SSLv2
SSLSessionCacheTimeout 300
AllowCONNECT 443 563 80
SSLEngine on
# enable SSLv3 but not SSLv2
SSLProtocol all -SSLv2
SSLCertificateFile ssl.key/server.crt
SSLCertificateKeyFile ssl.key/server.key
# correction for browsers that don’t always handle SSL connections well
# You don’t really use MSIE on your own machine, though, do you??
SetEnvIf User-Agent “.*MSIE.*” \
nokeepalive ssl-unclean-shutdown \
downgrade-1.0 force-response-1.0
SSLProxyEngine on
<Proxy balancer://googlecluster>
# the IP addresses you fetched before.
# Browsing History seemed broken unless it proxies back to https.
# This is probably safer anyhow, for privacy.
ProxyPass /history
ProxyPassReverse /history
RewriteEngine On
RewriteRule /favicon.ico /old-google-favicon.ico [L]
ProxyPass / balancer://googlecluster/
<VirtualHost *:443>
# the place where you put the .ico file.
DocumentRoot /Users/isaacs/Sites/
ProxyPreserveHost On
ProxyRequests Off
<LocationMatch .*>
Order deny,allow
Allow from
<Proxy balancer://googlecluster>
# the IP addresses you fetched before.
# note the “https” on these ones.
SSLProtocol all -SSLv2
SSLSessionCacheTimeout 300
AllowCONNECT 443 563 80
SSLEngine on
# enable SSLv3 but not SSLv2
SSLProtocol all -SSLv2
SSLCertificateFile ssl.key/server.crt
SSLCertificateKeyFile ssl.key/server.key
# correction for browsers that don’t always handle SSL connections well
# You don’t really use MSIE on your own machine, though, do you??
SetEnvIf User-Agent “.*MSIE.*” \
nokeepalive ssl-unclean-shutdown \
downgrade-1.0 force-response-1.0
SSLProxyEngine on
RewriteEngine On
RewriteRule /favicon.ico /old-google-favicon.ico [L]
ProxyPass / balancer://googlecluster/

Save the file, and then restart Apache:

sudo apachectl graceful

Again, if it doesn’t work, try this to figure out what’s wrong:

sudo apachectl configtest


Now, go to You should see the google home page, complete with the old lovable [G] favicon. If you see google, but not the old favicon, go directly to the favicon.ico and refresh a whole bunch. Clear your cache, etc.

If you get the new favicon, try running some tests. Search, go to your account. Make sure everything works.

When you hit an https address, you’ll get a prompt that the certificate is issued by an untrusted authority. This is good! Check the cert details, and make sure that they’re what you typed when you created the certificate. Now, the question, do you trust yourself? (I’d already added myself as a trusted authority, so didn’t get this problem in Firefox, but I did see it in Safari.)

If it doesn’t show you the new favicon, then you might have put the virtual host config someplace where it doesn’t belong, or where it won’t be picked up. Tail the error_log file and see if Apache tells you anything is wrong. Note that some Apache configurations use “apache.conf” instead of “httpd.conf”, so maybe try that.

If it doesn’t load at all, tail the apache logs again, and see if anything is barfing.


You may now resume your google usage as normal, before the disruptive new favicon appeared.

Note: The Google Notifier won’t work, because it checks the certificate, and doesn’t give you the option to trust another authority, which is, in my opinion, very bad design. Also, the Google Notifier sends your password and username out in clear text by default, so it’s very insecure. You shouldn’t be using it in the first place.

Instead, you can use the RSS feed to get inbox alerts without exposing your info.

Steal My Bash Profile Wed, 07 May 2008 03:32:22 +0000 Isaac ...Read More]]> Feel free to skip the monologue and just get the goodies.

I am in love with the Bourne Again Shell. Bash is a fantastic terminal environment, and a very interesting programming language in its own right.

I grew up using DOS. Unix shells always seemed scary and foreign, for some reason. I think a big part of the reason that I stayed on Windows for as long as I did was that I knew DOS, and could always resort to it in times of need. As a support tech in college, I got very familiar with DOS. It was comfortable and handy.

When I got into web programming, I had no choice but to learn at least the rudimentary basics of a unix-style environment. At that time, I was as a support tech at a software company whose product uses VisualBasic ASP over IIS, and had started playing around in that environment. However, I had no money, and web hosts that support ASP cost money.

By some stroke of luck or persistence, I managed to find a host that was free, Beigetower. That link doesn’t work any more, of course. I don’t know how long that server’s been down. Cuong Nghiem’s still listed as the owner on whois, though.) On top of that, they provided shell access. Not being able to resist the temptation to tinker with a real live web server, I learned enough Bash to poke around. As I learned more PHP, I picked up more bits and pieces along the way.

When I started at Yahoo, it was sink or swim to some extent. I was issued a FreeBSD dev box, and a windows desktop. I did most of my development in my safe windows world, but there are *a lot* of things you have to do on your dev box as an engineer at Yahoo that simply can’t be done in any other way. Bash was a regular part of my daily routine almost from the first day.

Eventually, I fell so head over heels in love with Bash that I had to say goodbye to Windows and get a Mac.

There are many good reasons to get a Mac instead of a PC. They’re easier and more intuitive in a lot of ways. They certainly look a lot nicer on almost every level. But I’d be lying if I said that having Bash right there all the time wasn’t the ultimate dealmaker.

One of the best things about Bash, in my opinion, is the fact that you can add shortcuts to your .profile (or .bash_profile or .bashrc, of course) that will be loaded every time you log in. As soon as I learned this, I started adding stuff.

Eventually, I had my profile so tricked out that it was hideously painful to have to work on a machine that didn’t have my shortcuts. Without my customized prompt, I’d get really confused about which directory I was currently in, and have to type pwd every three seconds just to not get lost. The sequence would usually go like this:

$ la
-bash: la: command not found
$ la
-bash: la: command not found
$ la
-bash: la: command not found
$ alias la="ls -laF"

Those first few entries of la were accompanied by plenty of growling and confusion, every. single. time.

So, I got into the habit of using scp or rsync to send my bash profile to any machine that I’d have to work on. However, some machines have vi, and some don’t. I’d make a change on the profile on my mac, and forget to sync it to my dev box. Machines that I didn’t log into often would be so far out of date that it was the “la” situation all over again. What’s worse, I put some stuff in other shell script files that were called by the profile to do other things, so it was no longer straightforward to keep them in sync. I’d send half the package, and then log in, and be inundated with errors all over the place.

When I switched from FreeBSD to a Red Hat Linux box, half my stuff didn’t work quite the same way. Also, I moved Foo Hack to a great new host, which is running Ubuntu. On the Mac, I use MacPorts, and the Ubuntu slice uses apt-get, and the RHEL of course uses yinst, the Yahoo! package management tool that quite simply makes all others look like crap by comparison. (Sadly, yinst is not open source. There’s this hack to simulate yinst on top of apt, though.) The Ubuntu and RHEL environments used vi as the default editor, but I’d changed that on the Mac to point to mate, the command-line interface to TextMate.

To say the least, a simple sync wasn’t cutting it even a little.

I re-wrote all my bash profile goodies to fit in a single file. Shell scripts were replaced with functions so that they could all live together. The edit command was defined to use the first available editor from a list of alternatives. Then, I put it in a file that was external from the main .profile or .bashrc file, so that it could be synced without overwriting anything that the OS placed in there by default. The only thing to do on a new server was to add . ~/.extra.bashrc to the bottom of whatever profile script it was already using.

I had already added a command called editprof that would bring my profile up in an editor. All that was needed then was a pushprof command that would rsync the .extra.bashrc file to a given host.

I’m releasing it under the WTFPL. There are actually a few files, since some stuff simply didn’t make any sense to have in certain environments. The copy here on on github is symlinked from my home directory updated frequently, so it’ll stay pretty up to date. Feel free to copy, learn, fork, or, like the license says, just do wtf you like with it.

A word of warning: like government regulation, this file increases in size but rarely gets revised. Some stuff may be completely useless or pointless. Some of it I hardly ever use any more. Figuring out better solutions to these problems is left as an exercise for the reader.

Get my bash extras.