Fresh paint

I just pushed a new design for this site. Despite my infrequent posting, I’m still getting decent traffic every day from Google. The makeover was long overdue as the previous design from 2007 was starting to feel quite dated.

My goal was to design something that felt more modern and works better on mobile. Clean and simple. Focus on the content. I’m still running on WordPress, but I hacked up a new theme that uses Twitter Bootstrap to make it responsive and the Lato font to make it pretty.

I’ve switched the comments over to Facebook. Requiring commenters to use their real identity is the best way I know to deal with spam. I can’t import old comments into Facebook, so I’ll be using Disqus for historical posts.

Enjoy.

Want to be more disciplined?

I love this quote from the founder of Dropbox, Drew Houston:

The hardest-working people don’t work hard because they’re disciplined. They work hard because working on an exciting problem is fun.

Want to be more disciplined? How about finding something you truly care about instead?

Prison

I’ve written before about the injustice of our prison system in the United States. I continue to be horrified by the racism and unfairness shown in the enforcement of our laws. The deprivation of anyone’s liberty is not something that should be taken lightly, and certainly never for the sake of financial gain. It should go without saying, but neither should rape ever be the punchline of a joke.

I’ve been really impressed with John Oliver’s Last Week Tonight. He’s hilarious, but more importantly, he’s not scared to tackle hard but important issues head on. This episode about prison is no exception.

Introducing my latest startup, Forage

I’ve always hated going to the grocery store. It’s such a pain to figure out what to make, how to get to the store and then find everything I need. I’m sick of throwing away food that I don’t eat in time. And why do I need to buy a $8 container of cumin when I only need 1 tsp!?!

I’m stoked to finally share what I’ve been working on for the last few months. Today we’re launching Forage — delicious meals that you can cook at home in 20 mins or less. All the ingredients are pre-measured so you can explore new types of dishes without all the waste.

I’d love to have you check it out. If nothing else, sign up to take advantage of some free food!

Inalienable rights

When I visited Hiroshima and the Peace museum there, I was blown away by the forgiveness exhibited by the Japanese people. Walking around that museum was one of the most moving experiences of my life. We called it the “cry museum”. There’s something wrong with you if you can walk through that museum without shedding a tear. The museum is a memorial for the atomic bomb victims and it shows the price of war in a very up-close and uncomfortable way.

Today I stumbled on this TED talk by George Takei on Why I love a country that once betrayed me:

Once again, I found myself blown away by the unbelievable amount of forgiveness by the Japanese people.

I was also reminded of how much I appreciate the ideals on which the United States was founded — the idea that all people are created equal. The idea that all people have an inalienable right to life, liberty and the pursuit of happiness.

Today there are countless examples of inequality in our country. It’s so easy to be discouraged. Takei’s story is certainly a solemn reminder of how easily we can slip away from these founding principles. Bono likes to talk about the “blind spots of our age”. We look back on the injustice we displayed to Japanese Americans with horror and disgrace. What are the things we’re accepting today that history will judge us for?

Those inalienable right are still worth defending.

The security hole I found on Amazon.com

I found a security hole on Amazon last August. While looking at their HTTP headers, I happened to notice that the entire amazon.com domain was susceptible to clickjacking attacks. If I could trick you into clicking anywhere on a webpage I controlled, I could get you to buy any product that’s available for sale on Amazon. By the way, that includes any fake products that I added to Amazon myself. For the hack to work, you needed to be signed into your Amazon account and have one-click purchasing turned on. I created a working proof-of-concept that looked like this:

amazon-clickjacking

Clicking either button caused an instant purchase of the movie Click (get it?). I resisted the temptation to use the exploit to send myself a million dollars worth of free Amazon gift cards, and instead responsibly disclosed it to the Amazon security team. It took them months to fix it, but the security hole has finally been closed using the x-frame-options header that I recommended.

This hack is classic clickjacking. I created a transparent iframe containing a product page on amazon.com that had been carefully positioned so when you think you’re clicking on my page, you’re actually clicking the “Buy now” button on their site instead. Here’s the link to the code for the no longer working proof of concept.

Habits > Willpower

In the book The Willpower Instinct, Kelly McGonigal explains how your willpower is just like any other muscle. It gets tired. If you’re relying on your willpower to make the changes you want in your life, you’re likely going to fail. In the book Foodist, Darya Rose talks about the secret to eating better and the answer is not to go on another diet. It’s to build positive eating habits into your life. Positive habits beat willpower every time.

They say it takes 21 days to build a new habit.

It’s never to late to start building new habits into your life. I’m ashamed to say this, but it wasn’t until last year that I started flossing daily. Now it’s a daily routine for me. This month, I started doing the 7-min workout every morning. Now I roll out of bed and start doing jumping jacks. 7 minutes isn’t much, but that’s kinda the point. Overcoming inertia is the hard part. If you can’t find 7 minutes a day, it’s time you loosen up your schedule.

And there are plenty of tricks to help you get started. I found I was happiest when I biked to work instead of sitting in traffic and dealing with parking tickets. So I sold my car and treated my bike to a tune-up from the Bike Doctor (highly recommended service by the way).

I’m happier than I’ve been in a long time. For me the secret has been as simple as being intentional about finding what makes me happy and then turning those things into daily habits.

Taking a peek inside __VIEWSTATE

If you’ve ever viewed-source on a website that uses Microsoft technology like ASP or .NET, you may have noticed a massive blob of unintelligible text stored in a input field called __VIEWSTATE. What you’re seeing is actually a bunch of Base64 encoded data that gets passed back and forth between the server and the client. I don’t understand how anyone ever thought this was a good idea, but there are a ton of sites that still use this technique. Just check out some old enterprise applications or any Microsoft website and you’ll see what I mean. The United and US Airways websites are a couple other good examples. Unless the __VIEWSTATE is encrypted, you’ll be able to take a look inside using this simple bookmarklet:

javascript:xmp=document.createElement("xmp");
txt=document.createTextNode(atob(document.getElementsByName("__VIEWSTATE")[0].value));
xmp.appendChild(txt);
document.body.insertBefore(xmp,document.body.firstChild);

Drag this link to your toolbar to try it: Decode ViewState

Pinterest’s 25 edge cases

I was snooping around the JavaScript that Pinterest uses for their “Pin It” button. No real reason. I’m just nosy.

Most of the code is what you would expect, but what jumped out at me were the 25 websites that get special treatment. In fact, Pinterest’s JavaScript is riddled with special handling for edge-cases on third-party sites. As a developer, I have the tendency to always search for the universal solution – one piece of code that works everywhere. While universal code is arguably “better”, this more often than not is what code looks like in the “real world”.

lookup: {
        artsy: {
            page: {
                seek: [/^https?:\/\/(.*?\.|)artsy\.net\/artwork\//,
                    /^https?:\/\/(.*?\.|)artsy\.net\/post\//
                ]
            },
            img: {
                seek: [/^https?:\/\/(.*?\.|)artsy\.net\//],
                act: "lookup"
            }
        },
        behance: {
            img: {
                seek: [/^http:\/\/behance\.vo\.llnwd\.net\//],
                act: "lookup"
            }
        },
        dasauge: {
            img: {
                seek: [/^https?:\/\/cdn?[0-9]\.dasauge\.net\//],
                act: "lookup"
            }
        },
        dailymotion: {
            page: {
                seek: [/^https?:\/\/.*?\.dailymotion\.com\//],
                act: "lookup",
                via: "id",
                multimedia: true,
                doNotCrawl: true
            }
        },
        dreamstime: {
            img: {
                seek: [/(.*?)\.dreamstime\.com\//],
                act: "lookup"
            }
        },
        etsy: {
            page: {
                seek: [/^https?:\/\/.*?\.etsy\.com\/listing\//],
                patch: {
                    img: function (g) {
                        return g.replace(/il_(.*?)\./,
                            "il_570xN.")
                    }
                }
            },
            img: {
                seek: [/^https?:\/\/.*?\.etsystatic\.com\//],
                patch: function (g) {
                    return g.replace(/il_(.*?)\./, "il_570xN.")
                },
                act: "lookup"
            }
        },
        fivehundredpx: {
            page: {
                seek: [/^https?:\/\/500px\.com\/photo\//],
                act: "lookup",
                via: "id",
                doNotCrawl: true
            },
            img: {
                seek: [/pcdn\.500px\.net\//],
                act: "lookup"
            }
        },
        facebook: {
            page: {
                seek: [/^https?:\/\/(.*?\.|)facebook\.com\//],
                act: "close",
                msg: "privateDomain",
                patch: function (g) {
                    return g.replace(/%privateDomain%/, "Facebook")
                }
            }
        },
        flickr: {
            page: {
                seek: [/^https?:\/\/www\.flickr\.com\//],
                act: "lookup",
                via: "id",
                doNotCrawl: true
            },
            img: {
                seek: [/staticflickr.com\//, /static.flickr.com\//],
                act: "lookup"
            }
        },
        geograph: {
            img: {
                seek: [/^https?:\/\/(.*?)\.geograph\.org\./],
                act: "lookup"
            }
        },
        googleReader: {
            page: {
                seek: [/^https?:\/\/.*?\.google\.com\/reader\//],
                act: "close",
                msg: "privateDomain",
                patch: function (g) {
                    return g.replace(/%privateDomain%/, "Google Reader")
                }
            }
        },
        googleList: {
            page: {
                seek: [/^https?:\/\/www\.google\.com\/search(.*&tbm=isch.*)/],
                patch: function (g) {
                    g.f.debug("patching Google Image Search results");
                    var i, j, a, b, c, d;
                    if (i = g.d.getElementById("ires")) {
                        i = i.getElementsByTagName("A");
                        j = 0;
                        for (a = i.length; j < a; j += 1) {
                            d = c = "";
                            if (i[j].href) {
                                b = i[j].href.split("imgrefurl=");
                                if (b[1]) c = b[1].split("&")[0];
                                b = i[j].href.split("imgurl=");
                                if (b[1]) d = b[1].split("&")[0]
                            }
                            if (c && d) {
                                b = i[j].getElementsByTagName("IMG");
                                if (b[0]) {
                                    g.f.set(b[0], "data-pin-url", decodeURIComponent(c));
                                    g.f.set(b[0], "data-pin-media", decodeURIComponent(d))
                                }
                            }
                        }
                    }
                }
            }
        },
        imdb: {
            img: {
                seek: [/^https?:\/\/(.*?)\.media-imdb\.com\/images\//],
                patch: function (g) {
                    return g.replace(/@@(.*)/,
                        "@@._V1_SX800.jpg")
                }
            }
        },
        kickstarter: {
            page: {
                seek: [/^https?:\/\/.*?\.kickstarter\.com\/projects\//],
                act: "lookup",
                via: "id",
                multimedia: true
            }
        },
        pinterest: {
            page: {
                seek: [/^https?:\/\/(.*?\.|)pinterest\.com\//],
                act: "close",
                msg: "installed"
            }
        },
        polyvore: {
            page: {
                seek: [/^https?:\/\/(.*?\.|)polyvore\.com\//],
                act: "lookup",
                via: "id",
                doNotCrawl: true
            },
            img: {
                seek: [/^https?:\/\/(.*?)\.polyvoreimg\.com\//],
                act: "lookup"
            }
        },
        shutterstock: {
            img: {
                seek: [/^https?:\/\/image.shutterstock\.com\//, /^https?:\/\/thumb(.*?).shutterstock\.com\//],
                act: "lookup"
            }
        },
        slideshare: {
            page: {
                seek: [/^https?:\/\/.*?\.slideshare\.net\//],
                act: "lookup",
                via: "id",
                multimedia: true,
                doNotCrawl: true
            }
        },
        soundcloud: {
            page: {
                seek: [/^https?:\/\/soundcloud\.com\//],
                act: "lookup",
                via: "id",
                multimedia: true,
                doNotCrawl: true
            }
        },
        stumbleuponFrame: {
            page: {
                seek: [/^https?:\/\/(.*?\.|)stumbleupon\.com\/su/],
                act: "bustFrame",
                serviceName: "StumbleUpon",
                frameId: ["tb-stumble-frame", "stumbleFrame"]
            }
        },
        ted: {
            page: {
                seek: [/^https?:\/\/(.*?)\.ted\.com\/talks\//],
                act: "lookup",
                via: "id",
                multimedia: true,
                doNotCrawl: true
            },
            img: {
                seek: [/^https?:\/\/(.*?)\.ted\.com\//],
                act: "lookup"
            },
            iframe: {
                seek: [/^https?:\/\/(.*?)\.ted\.com\//],
                act: "lookup",
                via: "id"
            }
        },
        tumblr: {
            img: {
                seek: [/^https?:\/\/.*?\.media\.tumblr\.com\//],
                patch: function (g) {
                    return g.replace(/_(\d+)\.jpg$/, "_1280.jpg")
                }
            }
        },
        tumblrList: {
            page: {
                seek: [/^https?:\/\/www\.tumblr\.com\/tagged/, /^https?:\/\/www\.tumblr\.com\/dashboard/],
                patch: function (g) {
                    g.f.debug("patching Tumblr search or index");
                    var i, j, a, b, c, d, e, h;
                    i = g.d.getElementsByTagName("LI");
                    j = 0;
                    for (a =
                        i.length; j < a; j += 1) {
                        h = g.f.get(i[j], "data-tumblelog-content-rating");
                        b = i[j].getElementsByTagName("A");
                        e = "";
                        c = 0;
                        for (d = b.length; c < d; c += 1)
                            if (b[c].id && b[c].id.split("permalink_")[1]) {
                                e = b[c].href;
                                break
                            }
                        if (e) {
                            b = i[j].getElementsByTagName("IMG");
                            c = 0;
                            for (d = b.length; c < d; c += 1)
                                if (h === "adult") {
                                    g.f.set(b[c], "data-pin-nopin", true);
                                    g.f.debug("do not pin per Tumblr content rating: " + b[c].src);
                                    g.f.log("nsfw_per_domain", b[c].src, e)
                                } else g.f.set(b[c], "data-pin-url", e)
                        }
                    }
                }
            }
        },
        vimeo: {
            page: {
                seek: [/^https?:\/\/vimeo\.com\//],
                act: "lookup",
                via: "link",
                patch: function (g) {
                    g.f.debug("patching Vimeo page");
                    var i, j, a, b, c, d;
                    i = g.d.getElementsByTagName("LI");
                    j = 0;
                    for (a = i.length; j < a; j += 1) {
                        if (i[j].id && i[j].id.match(/^clip/)) {
                            b = i[j].id.split("clip");
                            if (b[1]) {
                                b[1] = b[1].replace(/_/, "");
                                g.f.thumbMedia("http://vimeo.com/" + b[1], "vimeo", "link")
                            }
                        } else {
                            b = i[j].getElementsByTagName("A");
                            if (b[0])(b = g.f.get(b[0], "data-id")) && g.f.thumbMedia("http://vimeo.com/" + b, "vimeo", "link")
                        }
                        b = i[j].getElementsByTagName("IMG");
                        c = 0;
                        for (d = b.length; c < d; c += 1) g.f.set(b[c],
                            "data-pin-nopin", true)
                    }
                }
            },
            iframe: {
                seek: [/^http?s:\/\/vimeo\.com\/(\d+)/, /^http:\/\/player\.vimeo\.com\/video\/(\d+)/],
                act: "lookup",
                via: "link",
                patch: function (g) {
                    var i = null;
                    g = g.split("#")[0].split("?")[0].split("/").pop();
                    if (g > 1E3) i = "http://vimeo.com/" + g;
                    return i
                },
                att: "src"
            }
        },
        youtube: {
            page: {
                seek: [/^https?:\/\/www\.youtube\.com\/watch/],
                act: "lookup",
                via: "link",
                multimedia: true,
                extended: true
            },
            video: {
                seek: [/^https?:\/\/(.*?\.|)youtube\.com\/videoplayback/],
                act: "lookup",
                via: "link",
                att: "data-youtube-id",
                patch: function (g) {
                    var i = null;
                    if (g) i = "http://www.youtube.com/embed/" + g;
                    return i
                }
            },
            iframe: {
                seek: [/^https?:\/\/(.*?\.|)youtube\.com\/embed\//],
                act: "lookup",
                via: "link"
            },
            embed: {
                seek: [/^http:\/\/s\.ytimg\.com\/yt\//],
                patch: function (g) {
                    var i = null;
                    g = g.split("video_id=");
                    if (g[1]) {
                        i = g[1].split("&")[0];
                        i = "http://www.youtube.com/embed/" + i
                    }
                    return i
                },
                att: "flashvars"
            },
            img: {
                seek: [/^https?:\/\/(.*?\.|)ytimg\.com\/(vi|li)\//, /img.youtube.com\/vi\//],
                act: "lookup"
            }
        }
    }

The big choices in life

A great quote from Steve Jobs:

Remembering that I’ll be dead soon is the most important tool I’ve ever encountered to help me make the big choices in life.

Almost everything–all external expectations, all pride, all fear of embarrassment or failure–these things just fall away in the face of death, leaving only what is truly important.

Remembering that you are going to die is the best way I know to avoid the trap of thinking you have something to lose. You are already naked. There is no reason not to follow your heart.