Sunday, December 13, 2009

Signature verification does NOT work with Facebooker and Rails 2.3

I've been working on a Facebook application called My Trips (http://apps.facebook.com/my_trips/) for several months now in my free time. I am using the Facebooker gem for this project. If you are interesting in developing Facebook applications with Rails, I would highly recommend reading Developing Facebook Platform Applications With Rails, about developing Facebook applications with Facebooker.

At some point I'm going to do a comprehensive write up of my experiences developing a Facebook application with Rails and Facebooker. But until then, I figured I should share one important thing I found.

Facebook passes signatures to your application on every request. The checksum of all signature parameters, plus your "secret key" (a key assigned to your application when it's installed, and never sent in HTTP requests) must equal the signature parameter sent to you by Facebook in params. This ensures that the request actually came from Facebook and not from a third party spoofing Facebook. This is a great security feature. Facebooker automatically checks the signature on every request from Facebook, and throws an exception if the signature doesn't match before your controller code is hit. At least that's how it works with Rails 2.2 and earlier.

With Rails 2.3, Facebooker adds the Rack::Facebook rack extension that is supposed to do this signature verification one level above Facebooker, among other things. However, Rack::Facebook didn't actually verify signatures in my application. I made requests by spoofing Facebook, and just manually typing in URLs without even attempting to spoof, and my requests were processed. They should not have been.

I couldn't really figure out why Rack::Facebook wasn't doing this. Since the signature verification code is in Facebooker and works in Rails 2.2 and earlier, I decided to modify the Facebooker code to do this check explicitly. To do this, edit the facebooker/lib/facebooker/rails/controller.rb file, find the verify_signature method, and comment out the first 3 lines that does a check to see if Rack::Facebook is loaded. When you restart your application, Facebooker goes back to verifying the signature itself. After doing this, my spoofed and manual requests were correctly caught.

Saturday, November 21, 2009

My Trips Facebook application online

I've been working on developing a Facebook application in my free time for the past 6 months. It's finally online! The application is called My Trips. It allows you to post trips/vacations that you are going on, and a notice will be published on your wall automatically when you leave for the trip if you choose. You can see trips that all of your friends are going on, and see where everyone is right now. Maps are displayed everywhere showing trips. Check it out at http://apps.facebook.com/my_trips/.

Saturday, September 19, 2009

Firebug 1.4 shows "The resource from this URL is not text"

After I upgraded to Firebug 1.4, I could no longer debug Javascript from pages served by my local development server. I got the message "The resource from this URL is not text" on the script tab for each file. However, I could successfully debug Javascript on pages served by the production server.

So I went back to Firebug 1.3.3 thinking that this was just a Firebug bug that they'll fix soon. When Firefox 3.5 was released, I had to go up to 1.4 again, since Firebug 1.3 is not compatible with Firefox 3.5. To my disappointment, Firebug was still displaying this error.

After looking in to this error more, I found out that it's because Webrick serves javascript files with a mime type of application/octet-stream. This is causing Firebug to think that it can't read the files. Webrick should probably be fixed to serve Javascript files as text. Firebug should definitely be fixed to read javascript files, since it did in previous versions and Firefox still reads the files fine. However, it doesn't look like they're going to fix Firebug.

So, what's the solution? Run mongrel instead of webrick. Mongrel serves javascript files with a valid mime type. Just do a "gem install mongrel", and mongrel will load up instead of webrick.

Sunday, July 26, 2009

Javascript Bind: Making Me Hate Javascript A Little Less

I've been working on a Javascript intensive section of my web app lately, and it's reminding me of how much I hate Javascript. Everything seems so haphazard and chaotic compared to writing Ruby code. The Prototype effort has made things less painful but it's still not fun.

One area of Javascript in particular that's always given me trouble is dynamically creating elements that have event handlers. Let me give an example. Say you want to generate 5 links, each with a different value.

  <div id="buttons">
<input type="button" value="Generate links" onclick="generateLinks()" />
<script type="text/javascript">
function generateLinks() {
for (var i=0; i < 5; i++) {
var a = document.createElement('a');
a.linkNum = i;
a.onclick = function() { alert("i is " + i + ", linkNum is " + this.linkNum); };
a.href = "javascript:void(0)";
a.innerHTML = "Link " + i;
document.getElementById('buttons').appendChild(a);
}
}
</script>
</div>

When you run the code, the value of the variable i inside the function is always the same. That's because it essentially becomes a global variable. So when the event occurs and the function is run, the current value of i is reported. One hackish way around this is to assign a custom property to the element that you are creating. When the function is run, the keyword "this" refers to the element that the event occurs on, so you can easily access the custom property of the element, which was assigned when the element was created.

However, in more complex Javascript, you may want to access the object that you're generating the event handler code in. Let me give an example:

  <div id="buttons">
<input type="button" value="Generate links" onclick="generateLinks()" />
<script type="text/javascript">
var linkGenerator;
function generateLinks() {
linkGenerator = new Object();
linkGenerator.val = "Hello from link generator";
linkGenerator.showAlert = function(index) {
alert(this.val + " " + index);
};
linkGenerator.generateLink = function(index) {
var a = document.createElement('a');
a.linkNum = index;
a.onclick = function() { this.showAlert(index); };
a.href = "javascript:void(0)";
a.innerHTML = "Link " + index;
document.getElementById('buttons').appendChild(a);
};
for (var i=0; i < 5; i++) {
linkGenerator.generateLink(i);
}
}
</script>
</div>

If you run this code, you'll see an error in Firebug: "this.showAlert is not a function". That's because when the event handler function gets run, "this" does not refer to the linkGenerator object. this refers to the a element. So there is no "this.showAlert" property of the a object.


This is where the Prototype bind function comes to the rescue! Simply add .bind() to the end of any function, and pass the object that you want "this" to be when the function is called. Example:

  <div id="buttons">
<input type="button" value="Generate links" onclick="generateLinks()" />
<script type="text/javascript">
var linkGenerator;
function generateLinks() {
linkGenerator = new Object();
linkGenerator.val = "Hello from link generator";
linkGenerator.showAlert = function(index) {
alert(this.val + " " + index);
};
linkGenerator.generateLink = function(index) {
var a = document.createElement('a');
a.linkNum = index;
a.onclick = function() { this.showAlert(index); }.bind(this);
a.href = "javascript:void(0)";
a.innerHTML = "Link " + index;
document.getElementById('buttons').appendChild(a);
};
for (var i=0; i < 5; i++) {
linkGenerator.generateLink(i);
}
}
</script>
</div>

Now, when you generate the links, the "this" inside of the function will refer to linkGenerator and display the correct thing.

In addition to specifying the context for this, you can also pass other variables in to the function. Remember our first example, where we were using the variable i in the event handler, and it was always showing the last value? Well, guess what, bind can help us here too. Simply pass a list of variables in to bind after the this reference, and these variables will be available in the function, set to the values that they were at the time the function is generated, not run. Example:

  <div id="buttons">
<input type="button" value="Generate links" onclick="generateLinks()" />
<script type="text/javascript">
var linkGenerator;
function generateLinks() {
linkGenerator = new Object();
linkGenerator.val = "Hello from link generator";
linkGenerator.showAlert = function(index) {
alert(this.val + " " + index);
};
linkGenerator.generateLink = function(index) {
var a = document.createElement('a');
a.linkNum = index;
a.onclick = function(myI) { this.showAlert(index); alert("i is " + myI); }.bind(this, i);
a.href = "javascript:void(0)";
a.innerHTML = "Link " + index;
document.getElementById('buttons').appendChild(a);
};
for (var i=0; i < 5; i++) {
linkGenerator.generateLink(i);
}
}
</script>
</div>

If i is not passed in to bind and taken as a parameter to the function, i will always report as 5, like it did in the first example. By passing it in to bind, the value at that time gets preserved. Very useful stuff!

One more thing that bind does. If you want to get the event that triggered the function call, put bindAsEventListener instead of bind after the function. This will always pass event as the first parameter.

Wednesday, May 27, 2009

Exception notifier plugin causing internal server error

I am using the exception notifier plugin to send me emails on the details of all unhandled exceptions in my web app (read about this plugin on my earlier blog posting, Exception notification plugin).  I recently put my web app on a new server, and when an unhandled exception occurred, Internal Server Error was displayed to the user, and no email was sent.  After digging in to this, I found that the exception notification code itself was generating an exception.  The offending file is views/exception_notification/_environment.rhtml.  Turns out there is a syntax error in that file when using Ruby 1.8.6 patch level 110 or higher.  The plugin was fixed in November 2007, but I had downloaded the plugin before that time.  

The fix is described at http://dev.rubyonrails.org/ticket/9940.  Simply edit the plugsin/exception_notification/views/exception_notification/_environment.rhtml file, and change the third line to:
* <%= "%-*s: %s" % [max.length, key, filter_sensitive_post_data_from_env(key, @request.env[key].to_s.strip)] %>



The only difference is that the first *- is changed to -*.

Wednesday, May 13, 2009

Running the same rake task more than once

While writing some rake tasks, I found out that you cannot run another task more than once in your task.  Example:
task :test do |t|
Rake::Task["log:clear"].invoke
# do something to add to the log file
Rake::Task["log:clear"].invoke
end

No errors will occur, but the second log:clear will not get run. All rake tasks work like this. I'm not really sure of the reason why this capability was put in rake, but rake keeps track of when each task gets run and only allows a task to be run once within the same rake call. But, to get around this, you can call reenable on the task after it's invoked, and then the task can be used again. Example -
task :test do |t|
Rake::Task["log:clear"].invoke
Rake::Task["log:clear"].reenable
# do something to add to the log file
Rake::Task["log:clear"].invoke
end

The second log:clear will now run correctly. Another wonderfully documented feature of Ruby....

Thursday, April 23, 2009

brentsowers.com registered

I now have my own domain name for this blog, brentsowers.com. You can get to the blog at http://www.brentsowers.com.  I'll be making sub domains for my other blogs.  

Thursday, April 16, 2009

Converting a string to a time in Ruby

I had a really hard time finding information on how to convert a string in your own custom format into a Time object in Ruby. Turns out it's pretty easy but poorly documented. Use the method DateTime.strptime. Documentation on that is hard to come by, but you pass in the string containing the time as the first parameter, then the second parameter is the format string. This returns a DateTime object, call .to_time on it to get a Time object. Example:
DateTime.strptime("2009/04/16 19:52:30", "%Y/%m/%d %H:%M:%S").to_time

The format uses the same syntax as what you pass in to strftime to print out a date. The page http://snippets.dzone.com/posts/show/2255 has a complete listing of all format types.

Friday, January 9, 2009

How to debug Javascript in Internet Explorer

Firebug for Firefox is an invaluable tool for debugging Javascript. And when you're writing code that uses the Prototype library, the code usually works the same in both Firefox and Internet Explorer, so can use Firebug to debug your Javascript. But for regular, non-Prototype Javascript code, and the occasional Prototype function that isn't completely browser independent, you may need to debug Javascript code from Internet Explorer to get it to work correctly. Fortunately it's pretty simple to do this, although it's not easy to find how to do this.

For Internet Explorer 8, Microsoft has bundled some developer tools. Click Tools then Developer Tools. Functionality is somewhat similar to Firebug, more similar to Chrome's developer tools, but not quite as good.

For Internet Explorer 6 or 7, you must install other tools to debug. Before you can start debugging, you will need either Visual Studio or Microsoft Script Editor. If you don't have Visual Studio, you can download the Microsoft Script Editor from Microsoft at http://www.microsoft.com/downloads/details.aspx?FamilyID=2f465be0-94fd-4569-b3c4-dffdf19ccd99&displaylang=en. From Script Editor, you can do just about everything that you can from Visual Studio, including viewing the call stack, setting break points, stepping through code, setting variables to watch, etc.


Once you have Visual Studio or Script Editor installed, from Internet Explorer, click Tools, then Internet Options. (if you're using IE7 and the menu bar is hidden, press ALT to show it). From this window, click the Advanced tab, and then uncheck "Disable script debugging (Internet Explorer".


Once you click OK here, go to the page that you wish to debug from. Then click View, Script Debugger, Open (again if you're using IE7 and the menu bar is hidden, press ALT to bring it up).

After this another window will open up asking which debugger you wish to use. Click on the one you wish to use (either Script Editor or Visual Studio), and click Yes.


If you use Script Editor, the HTML for the page you are on will be displayed. This typically doesn't help you debug the Javascript because your Javascript is probably in another file. But by default there is no window to select other files! To show the file selection window, simply click Debug, Windows, then Running Documents.

This will open up a window on the left listing all of the loaded Javascript and HTML files. Just double click on the file that your code that you wish to debug is in. Now you can set a breakpoint on a line by clicking in the gray area directly to the left of the code (or click Debug, New Breakpoint), and when you do something from the web page that will cause this Javascript to run, the Script Editor will pause execution from that line, allowing you to inspect values, view the call stack, step through code, etc. If you want to debug code that runs when your document loads, you can add the line debugger; to your Javascript, which will cause the debugger to automatically open up when the page is loaded.

While this capability isn't as comprehensive as Firebug (no viewing of requests, times, etc.), it certainly serves the purpose of allowing you to debug Javascript code from within Internet Explorer.