View Sidebar

Archive for category: Projects

Thomas Friedman Op-Ed Generator

Thomas Friedman Op-Ed Generator

This is exactly what it sounds like. After about 5 hours of work, I think I’ve made what has to be the best Thomas Friedman op-ed generator that exists on the market today. I can’t give enough credit to Michael Ward whose post inspired the project (and whose work I use liberally in the generator, but not exclusively).

Screen Shot 2012-12-19 at 8.59.10 PM

December 19, 20123 commentsRead More
Defeating Chrome’s Content-Security-Policy Header via a Chrome Extension

Defeating Chrome’s Content-Security-Policy Header via a Chrome Extension

This one was fun. While working on Feedhound, we suddenly started getting this error:

Refused to connect to 'https://feedhound.co/' because it violates the following Content Security Policy directive: "connect-src https://*.facebook.com http://*.facebook.com https://*.fbcdn.net http://*.fbcdn.net *.facebook.net *.spotilocal.com:* https://*.akamaihd.net ws://*.facebook.com:* http://*.akamaihd.net".

We were wondering what this message was. It turns out, apparently, that Facebook just started implementing the new HTML5 Content Security Policy standard in Chrome and Safari. While designed to prevent cross-site-scripting (XSS) attacks and enhance security, the new CSP policy is a huge problem for Chrome extensions, which often rely on the ability to create and call external scripts in order for the extension to, ahem, work properly. Since this is a new protocol, it isn’t turned on in Firefox yet, but it soon will be.

So we freaked out for a bit, and then remembered that Chrome has the chrome.webRequest API that lets you intercept headers and rewrite them. A couple hacks later, and voila:

chrome.webRequest.onHeadersReceived.addListener(function (details)
{
	for (i = 0; i < details.responseHeaders.length; i++) {
		if (details.responseHeaders[i].name.toUpperCase() == "X-WEBKIT-CSP") {
			details.responseHeaders[i].value = "default-src *;script-src https://*.feedhound.co https://*.facebook.com http://*.facebook.com https://*.fbcdn.net http://*.fbcdn.net *.facebook.net *.google-analytics.com *.virtualearth.net *.google.com 127.0.0.1:* *.spotilocal.com:* chrome-extension://lifbcibllhkdhoafpjfnlhfpfgnpldfl 'unsafe-inline' 'unsafe-eval' https://*.akamaihd.net http://*.akamaihd.net;style-src * 'unsafe-inline';connect-src https://*.facebook.com http://*.facebook.com https://*.fbcdn.net http://*.fbcdn.net *.facebook.net *.spotilocal.com:* https://*.akamaihd.net ws://*.facebook.com:* http://*.akamaihd.net https://*.feedhound.co";
		}
	}
	return {
		responseHeaders : details.responseHeaders
	};
}, {
	urls : ["*://*.facebook.com/*"],
	types : ["main_frame", "sub_frame", "stylesheet", "script", "image", "object", "xmlhttprequest", "other"]
},
	["blocking", "responseHeaders"]
);

Problem solved! The above listener needs to be added to the local extension resources and run as a background script. Also, the above is to modify the Facebook CSP to include our scripts at feedhound.co only for people who have installed our extension, and we have made sure to not overrite Facebook's carefully considered CSP in order to avoid leaving our users vulnerable to the same sort of XSS attacks that the CSP is designed to prevent.

In other news, we are super close to launching and I'm excited for that to happen!

December 17, 20121 commentRead More
Building a Chrome Extension that Connects to a Facebook App

Building a Chrome Extension that Connects to a Facebook App

While working on Feedhound, we ran into an unexpected problem where we were having trouble loading the Facebook SDK from our extension onto the target page. Since our app depends on being able to run custom social searches based on the users’ feeds, needless to say this was a deal breaker.

The first hurdle was the fact that the window.fbAsyncInit() method will not fire if the site page does not have the same URL as your Facebook app URL. This restriction will hold even if you use a content script to call the JS from your app URL–it reads the domain of the page the script is run on, not the domain of the script source. So even though we could append the SDK to any page we wanted, it never initiated the FB connection. This will be a problem for anyone who is trying to authenticate a Facebook user via a Chrome extension.

The workaround is pretty easy, it just involves inserting an invisible iFrame into the target page, running the Facebook SDK from the iFrame (whose source is your app URL), then using the window.postMessage API to send a message from your iFrame to the parent page, where your content script is running to pick up the message.

Here’s the source for the <YOUR_FACEBOOK_APP_URL>/iframe.html page (replace “<YOUR_APP_ID>” and “<PARENT_PAGE_URL>”):

<!doctype html>
<html lang="en">
<head>
 <meta charset="utf-8">
</head>
<body>
<div id="fb-root"></div>
<script>
 window.fbAsyncInit = function () {
 // init the FB JS SDK
 FB.init({
 appId:'YOUR_APP_ID', // App ID from the App Dashboard
 status:true, // check the login status upon init?
 cookie:true, // set sessions cookies to allow your server to access the session?
 xfbml:true // parse XFBML tags on this page?
 });
FB.getLoginStatus(function (response) {
 if (response.status === 'connected') {
 // the user is logged in and has authenticated your
 // app, and response.authResponse supplies
 // the user's ID, a valid access token, a signed
 // request, and the time the access token
 // and signed request each expire
 var uid = response.authResponse.userID;
 var at = response.authResponse.accessToken;
 // This is your messaging to the parent of the iFrame
 parent.postMessage({connectStatus:"" + response.status + "", userID:"" + uid + "", accessToken:"" + at + ""}, "https://www.<PARENT_PAGE_DOMAIN>"); //This MUST match the root domain where the iFrame will be inserted, or the message won't get passed
 } else if (response.status === 'not_authorized') {
 // the user is logged in to Facebook,
 // but has not authenticated your app
 } else {
 // the user isn't logged in to Facebook.
 }
 });
};
 // Load the SDK's source Asynchronously
 // Note that the debug version is being actively developed and might
 // contain some type checks that are overly strict.
 // Please report such bugs using the bugs tool.
 (function (d, debug) {
 var js, id = 'facebook-jssdk', ref = d.getElementsByTagName('script')[0];
 if (d.getElementById(id)) {
 return;
 }
 js = d.createElement('script');
 js.id = id;
 js.async = true;
 js.src = "https://connect.facebook.net/en_US/all" + (debug ? "/debug" : "") + ".js";
 ref.parentNode.insertBefore(js, ref);
 }(document, /*debug*/ true));
</script>
</body>
</html>

Here’s the source for your manifest.JSON file:

{
 "name": "Chrome Extension that Connects to a Facebook App",
 "version": "0.1",
 "description": "To connect a Chrome extension to a Facebook app!",
 "content_scripts": [
 {
 "matches": ["*://*.<PARENT_PAGE_DOMAIN>/*"], //The page(s) where your content scripts will fire, which has to match the message passing param in iframe.html
 "css" : ["main.css"],
 "js" : ["main.js"],
 "run_at" : "document_start",
 "all_frames" : false
 }
 ],
 "manifest_version": 2,
 "minimum_chrome_version": "17"
}

Here’s the source for your main.js file:

window.onload = function(){ // this could be done faster with the livequery() plugin for jquery
elt = document.createElement('iframe');
elt.id = 'facebook_load_frame';
elt.src = 'https://<YOUR_FACEBOOK_APP_URL>/iframe.html';
document.getElementsByTagName('body')[0].appendChild(elt);
};
// Message passing API from David Walsh at http://davidwalsh.name/window-iframe
// Create IE + others compatible event handler
var eventMethod = window.addEventListener ? "addEventListener" : "attachEvent";
var eventer = window[eventMethod];
var messageEvent = eventMethod == "attachEvent" ? "onmessage" : "message";
// Listen to message from child window
eventer(messageEvent,function(e) {
 console.log("Connection status: "+e.data.connectStatus+"; UserID: "+e.data.userID+"; AccessToken: "+e.data.accessToken);
 //This is the data from the Facebook SDK
},false);

And, to top it off, the main.css file (to be derived via a content script to avoid potential FOUC issues):

#facebook_load_frame {
 width:1px;
 height:1px;
 border:0;
 position:absolute;
 top:0;
 left:0;
 display:none;
}

Finally, make sure that whether you are using a https:// or http:// protocol, that your protocol is consistent throughout. Your iFrame should have the same protocol as the parent page (to avoid “insecure content” warnings) and the Facebook SDK will throw an error if there’s a protocol mismatch as well.

Enjoy!

December 4, 2012Comments are DisabledRead More
Fast Anagrammer (A Magma Transfer)

Fast Anagrammer (A Magma Transfer)

This was a fun coding project. Using Bootstrap.js and some simple PHP, I coded an anagrammer that performs much, much faster than existing anagram sites. I don’t know what they are using to anagram (or de-anagram), but execution is taking forever with sites like wordsmith.org and anagrammer.com; in addition, sites like wineverygame.com have a 12-character limit on their anagrammer. Mine has a 60-character limit.

Basically, the way it works is, after accessing the dictionary which is stored on the server, the anagrammer immediately eliminates all words that are too long (which could be 50% or more of the words). Then it starts a while loop and runs through each word, which is then broken down using str_split into its component letters. The magic is in a two-step elimination process:

if(strpos($input,$letter) === false){
 return false;
}

if(substr_count($word,$letter)>substr_count($input,$letter)){
 return false;
}

The first, checks to see if the component letter is even part of the input string; if not, it is thrown out. The second checks to see if the component letter appears more in the dictionary word than it does in the input. If so, it is thrown out.

After that, it’s just a question of stacking an array and sorting by string length.

This uses a standard TWL dictionary which has 178,691 words.

November 12, 2012Comments are DisabledRead More
Broadcast for Friends for iPhone

Broadcast for Friends for iPhone

The reason I was in Budapest for the summer was to work on a new iPhone app, Broadcast for Friends, which we announced last night in an awesome launch party at Ustream.  Check out some of the awesome press we got.

Broadcast for Friends (or BFF for short) is a brand new app that allows anyone with an iPhone to broadcast live video direct to their friends on Facebook. It’s so dead simple and easy to use, yet this is the first time our live streaming technology has been used like this, and as far as we know, no one else has done it like this, either.

Here’s how it works. Anyone can download Broadcast for Friends from the app store. Once you load the app, you can connect directly to your Facebook account in order to start broadcasting. You don’t need a Ustream account to broadcast, and best of all, it’s absolutely free!

   

BFF not only has a high quality camera, we also have 10 Hollywood-inspired filters to make your video pop.  Favorites around the office are Maltese (film noir style) and Vendetta (graphic novel style).  We also have a “Curiosity” filter inspired by the recent expedition to Mars.

You can change filters by swiping or by selecting a filter on the bottom.  You can also choose your camera.  When you are ready to broadcast, it’s fast and easy.  We ask you how you want to share your broadcast first.  We have three options right now: Public, Friends, or Only Me.  Then you can go live.

   

Here’s the coolest thing about BFF:  As soon as you are live, you are live right on Facebook.  That means your friends will see your video in their news feeds, and you can find your videos right on your Facebook timeline.

As you know, Ustream has always been at the forefront of live video streaming technology, and BFF is no exception.  There’s a ton of engineering power behind this simple app that allows us to get live video streaming on 3G and WiFi to our servers and back to Facebook instantaneously.  The result is an experience that doesn’t exist anywhere else.  That’s right, we’re the only app that allows you to send live video right to your Facebook Timeline.

Here’s the best part:  When you are done broadcasting, your video is saved automatically on your Timeline so it can be viewed by any of your friends even if they missed the event.  Your videos can also be viewed from the app itself.

Here’s a cool video showing how the app works.

August 17, 2012Comments are DisabledRead More
Shame Alarm for iPhone

Shame Alarm for iPhone

After about a month of development and testing, I am really excited to launch Shame Alarm in the iTunes store.  It’s an alarm clock that not only wakes you up, but if you fail to turn it off in time it will send a message to your Facebook and Twitter friends telling them you couldn’t get up.  Silly, yes.  A little negative incentive grounded in solid economic theory?  Definitely.  From the app store:

Have trouble getting out of bed? What better way to motivate you than knowledge that if you fail to get up, everyone from your parents to your co workers to your Twitter followers in Indonesia will know that you lack the ability to perform one of the most basic of bodily functions?

Trust us, when this little alarm clock goes off, you’ll move quickly to get to the dresser, because if you don’t, someone will know about it.

Shame Alarm is guaranteed to increase your morning productivity! Simply log in to Facebook and/or Twitter, and you’ll never fail to wake up again!

Features:

  • 8 classic wake up ringtones
  • Add vibrate for some extra buzz
  • Set alarm to repeat on select days
  • Dark interface for perfect night time usage
  • Remember, like all third party alarm clock apps, you must leave the app running overnight. Make sure it’s plugged in!

Scientifically Verified

Recent findings in behavioral economics have proved that shame is the most motivating emotion for humans. It is so persuasive, that humans can be shamed into doing almost about anything better. We have found that 9 out of every 10 people are more likely to do something if shamed into doing it–more than would do it for money. Now that’s powerful!

Download the app here:  http://shamealarm.com/download/

May 25, 2011Comments are DisabledRead More
GEarth Flightsim Package Release

GEarth Flightsim Package Release

So I’ve been spending some time on Google Earth’s Flight Simulator, a little easter egg which was packaged in version 4.2.  I found that it was difficult, once airborne, to fly to locations and find runways to land on (the resolution of the runways isn’t good enough until you’re too close to be able to land smoothly), so I decided to create a set of runway outlines and flight paths to serve as guides for getting from Point A to Point B.

In this package, runways are denoted in red, and flight paths are yellow.  Flight paths start at the beginning of the takeoff runway and end at the end of the landing runway (so red and yellow markers overlap), and can be flown in either direction.

The package can be downloaded here, and it contains 239 runways in 94 cities around the globe, in Europe, North America, South Asia, Oceania, Southeast Asia, Africa, East Asia, Middle East, and South America.  It also contains 24 flight paths with typical routes such as New York – Chicago, and atypical routes such as Santiago, Chile to Xian, China – the longest major city to major city route possible on Google Earth.  Routes are designed to provide entertainment for serious long-distance fliers and impatient ones as well (some routes can be flown in under twenty minutes).

I hope to release more runway paths and routes in the future.  For now, hope this provides GEarth Flightsim buffs with something to go off of.

If you missed the download link above, here is another.  Enjoy!

July 24, 2008Comments are DisabledRead More
Risk Odds Battle Outcome Simulator

Risk Odds Battle Outcome Simulator

I had a bit of fun and slapped together a program that simulates odds for the board game Risk.  Fascinatingly enough, the point at which a territory attacking a territory with the same number of armies starts losing is at 12.  So if you’re 10 vs. 10, you’re favored to win, but if you’re 13 vs. 13, you’re favored to lose.

Anyway, it’s a bit silly, but it’s been fun to play with.  It comes up with results based on running simulations, about 10k per submission.  Click here or below to go to RiskOdds.com.

June 2, 2008Comments are DisabledRead More