Archive for the ‘Code’ Category

Bad things done well: accepting dangerous input with Rails

Wednesday, April 2nd, 2008

For various reasons I need to be able to be able to accept some script input from the client.

The basic requirement is to be able to accept some Ruby code from the client in order to allow customisation of the HTML output from an RSS feed.

This is obviously a rather dangerous thing. I essentially need to allow arbitrary Ruby to be executed with an eval

However, in Ruby, we can run code in SAFE mode.

At Level 4:

Ruby effectively partitions the running program in two. Nontainted objects may not be modified. Typically, this will be used to create a sandbox: the program sets up an environment using a lower $SAFE level, then resets $SAFE to 4 to prevent subsequent changes to that environment

The core of my approach is to create a new Thread, set the SAVE level to 4 and call a method.

feed = FeedNormalizer::FeedNormalizer.parse(open(self.url))
thread = Thread.start {
$SAFE = 4
html = safe_method(feed, script)}
}
thread.join #wait for the thread to finish

The safe_method itself does a sanity check on the safe level. The method takes a feed object and a script - the script is processed using eval and because the feed object is in the context, the script has access to it. However, the safe level prevents any malicious code from attempting to use Ruby magic and meta-programming to gain access to variables outside the thread or any globals

def safe_method(feed,script)
if ( $SAFE < 4 )
raise “SecurityException: attempting to execute UNSAFE script”
end

html = “”
eval(script)
return html
end

The user can then pass in code that looks like:

html << “<h2>#{feed.title}</h2>”
html << “<ul>”
feed.entries.each do |entry|
  html << “<li><a href=\”#{entry.urls.first}\”>#{entry.title}</a></li>”
end
html << “</ul>”

And the feed is processed without (too much) risk.

RailsCamp 2.0

Wednesday, November 21st, 2007

RailsCamp is on this weekend. 40 uber-geeks gathered to immerse themselves in Ruby On Rails.
It should be pretty cool.

I haven’t prepared any materials, but might present something on Amazon Web Services - I did this for the Melbourne Ruby User Group a little while ago.

Now Hiring!

Tuesday, October 2nd, 2007

Been very swamped with contract work, but I have managed to roll a Facebook App called Now Hiring into production for Taleo.

I had a list of updates, but the blog died a horrible and fatal death, and I can’t for the life of me remember what they where.

Except pagination in Rails with will_paginate is so good it’s terribly terribly frightening

Mock testing with mocha

Wednesday, September 12th, 2007

Mocha is a library designed to let you mock objects in your test environment. It’s very useful for testing around external dependencies

Inside one of my controllers I am calling a SOAP Service:

message_result = SOAPService.send_message(message)

This leaves me with a problem in my functional test - external dependencies are not conduive to self-contained test. Enter Mocha to the rescue!

Mocha lets me create a stub for a method on any instance of my object. This means that I can intercept the calls in my test, without needing to touch the code inside my controller.

SOAPService.any_instance.stubs(:send_message).returns( MessageResult.new )
get :respond
assert_match(/1<\/status>/, @response.body)

The get :respond call above would normally invoke a SOAP call, but using any_instance.stubs(:send_message).returns( MessageResult.new ) means that the SOAPService.send_message method now will return a new MessageResult. My controller doesn’t care and now my functional test is tight and focussed, and tests the controller logic without the external dependency being a factor.

Did you find this Ruby on Rails article useful? Why not recommend Toby at Working With Rails?

RailsRumble: distro decisions decisions

Friday, September 7th, 2007

I received my Linode account for the Rails Rumble.

I logged in and the first thing I have to do is pick the Linux distro I want to install and use for the Rumble.

There are far too many options!

The available distros are:

  • Arch 0.7.1
  • Debian 4.0 (Etch)
  • Finnix 86.1
  • Ubuntu 6.06
  • Ubuntu 7.04
  • CentOS 5.0 (RHEL rebuild)
  • Fedora Core 6 (FC6)
  • Slackware 12.0 (-new-)
  • Mandrake 9.1 (Bamboo)
  • Gentoo Linux 2006.1

I’m not really a systems person … I know my way around Linux, but I don’t have a whole lot of experience setting a machine up from scratch. I’ve been lucky that for the last several years I’ve worked with truly awesome sys admins who take care of all this stuff for us.

So what to use?

I am leaning toward Ubuntu 6.06 (Dapper Drake) because it looks like there are some good tutorials around (I even think the Peepcode guys have been using Ubuntu for some of their work - it might be time to subscribe).

Any ideas are appreciated. I am definitely going to learn a lot this weekend.

RailsRumble Notes - WoR! by self.Team

Saturday, September 1st, 2007

You can find all my notes for the RailsRumble in Backpack.

I changed my mind, I am going to keep my notes here in the blog.

Go self.Team!

How not to hire …

Friday, August 31st, 2007

37 Signals has a post about Writing Better Help Wanted Ads, which has some excellent advice and a summary of some ideas from around the blogospehere.

I have had some pretty bad (and sometimes actually rude) encounters recently as a Freelance Developer.

A fairly typical example was this response to my considered, thoughtful and detailed application for an advertised position:

I am looking for freelance web programmers who are proficient in the
following:
-HTML, CSS, JavaScript and Flash up to $20/hour
-with PHP, MySQL and Linux, and willing to learn Ruby on Rails up to
$22/hour
-with Ruby on Rails _experience_ up to $25/hour

I prefer programmers with Ruby on Rails experience, but will consider
you if you have _very_ strong skills in the first two items.

You must be able to work under tight deadlines. I prefer people who are
proactive and have a good design sense. You must be a proficient
programmer. You must be willing to take design direction, and work under
an established set of procedures. Work availability varies.

I read this as:

  1. You must be cheap
  2. You must have lots of experience
  3. You must not value that experience (see points 2 via 1)
  4. You must work really hard and under pressure
  5. You must do what we tell you
  6. You still may not get any actual work

There’s no mention of the types of work, the flavour of the projects, or why I might be interested.

On top of all this, it was instantly evident that the responder hadn’t read my application - I had actually detailed my most recent experience with Rails (and other relevant technologies) on several “real-world” projects.

The fact is:

If you are good at your job, you can choose the work you do.

Finding good people is hard, regardless of industry, but particularly in software development. The employment or negotiation process is as much about the potential employer selling the role as it is about me proving I am good at what I do.

I’m certainly not saying you need to treat me like a God of Code, but perhaps you should actually read my job application …

self.Team

Wednesday, August 29th, 2007

I’ve registered for the RailsRumble as a one-person team called, cunningly: self.Team

See what I did there?

I am going to be building a game - a browser-based, AJAXified wargame loosely based on the Roll Out The Gun Barrels ruleset. I’ll be posting a few design ideas over the next week.

Ready to Rumble

Monday, August 27th, 2007

Rails Rumble has been announced. 48 hours to build an application from scratch.

I am going to enter … as a solo developer. I think I will attempt to build the game I have been occasionally designing for the last couple of months. Or maybe my idea for a Google Adwords Landding Page Manager. I’ve already signed up for the AdWords API …

Snippets: dynamic CSS classes

Tuesday, August 14th, 2007

I found myself over the weekend needing to create CSS classes dynamically. Not just add a class to a DOM element, which is easy, but actually building a CSS class based on user input and attaching it to selected elements.

Proved to be harder than it sounds.

  var green = {
    color: "#00FF00"
  };

  Object.extend(Element.Methods, {
    setClass:function(element, className) {
      element = $(element);
      element.addClassName(className);
      klass = eval(className);
      for (var property in klass) {
        element.style[property] = klass[property];
      }
    }
  });
  Element.addMethods();

  function changeClass() {
    elements = document.getElementsByClassName("red");
    elements.each(function(e) {
      e.setClass("green");
    });
  }

This code lets you specify a “CSS Class” as a Javascript object. Then you can use the Element.setClass to add the properties to the element style. The changeClass() function finds all the “red” elements and sets them to use the “green” Virtual CSS class. I use addClassName to add the new class name, which may cause conflicts with existing CSS classes.

The name is added because I was thinking that I would need a way to remove the class. At the moment I don’t, but it wouldn’t be all that hard to implement. You would store the element’s original properties and remove the class name, and reset all the overridden styles. The disadvantage of what I am doing is overriding the styles at the element level - these will take precedence in CSS.

I am positive there is an easier way of doing this with Prototype and Scriptaculous, so let me know if find one. I looked at interacting with the styles directly using the DOM, but it’s pretty messy.