Archive for the ‘Programming’ Category

PHP equivalent of Django Admin?

Wednesday, August 20th, 2008

So … where is the PHP equivalent of Django Admin? Or the multitude of Rails Admin plugins?

I don’t care what framework it sits on as long as the out-of-the-box functionality is awesome.

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.

Miscellany

Monday, March 10th, 2008

I used to have a lot more time for blogging. Now it’s all steam ahead with the actual paying work. I’ve actually had to turn down some projects recently.

My latest project is live and generating a lot of traffic. I built the promotional site for the latest Gillette product -  The Gillette Fusion Power Phantom. Very tight deadline, but I made it on time and under budget.

I’ve also been involved with some work on Hotel.com.au, which is actually old-school MS Access and Visual Basic. I am quite enjoying it. Sure beats the hell out of PHP.

Melbourne Facebook Developer Garage Presentation

Sunday, February 24th, 2008

On Friday I had the privilege of presenting at the Melbourne Facebook Developer Garage.

I’ve uploaded the slides for my Introduction to Facebook Development talk.  I had to leave early due to some client commitments, but the talks were excellent and I met some very interesting people working in the Facebook space.

There is also a Melbourne Facebook Developer Group - I am keen to get another event organised really soon.

CodeIgniter: I Don’t Hate It

Thursday, February 14th, 2008

The unfortunate tragedy of my life is that I don’t get to develop in Ruby on Rails all the time. No, unfortunately for me, a large number of my clients need work done in PHP.

Which, as already indicated in several previous nuanced discussions, I hate.

I mean, really really HATE.

But that’s not the point of this post.

After being seriously burnt by the twin miseries of CakePHP’s poor documentation and desperately misguided attempt to mimic Rails I went looking for a new PHP MVC framework for a recent project.

Crucial requirements:

  • lack of opinion
  • simplicity
  • good documentation
  • understands PHP is not Ruby

I really wanted something that was pure VC, leaving out the M.

Views, Controllers and Models can go to hell.

PHP’s complete lack of dynamicism (and yes, I know PHP 5 has a crack at it, but whatever) means any attempt at Hibernate or Rails-style ORM is doomed to failure. And after screaming at CakePHP every time a finder returns an array of nested hashes of arrays of hashes and you can never work out how to just iterate through the records I’ve gone back to ADODB. You run a query and are returned a Record Set. I know this just reveals how long I spent in the late 90s hacking ASP, but if any language was still living in the late 90s, it’s PHP. And it’s actually quite good at it.

Where was I?

Right. Clean View/Controller mechanism. No Models.

Enter CodeIgniter.

It’s incredibly simple, the only assumption it makes is that you may never need most of the stuff it includes, so everything is an option, and it has great documentation.

CodeIgniter: I Don’t Hate It.

If you really have to use PHP, it’s worth a look.

Dear PHP and CakePHP

Friday, January 11th, 2008

I hate you.

That is all.

Why Rails is better than whatever it is you use: ToDo List in 5 Lines

Tuesday, December 18th, 2007

Rob Mayhew prepared this ToDo List Tutorial

  1. rails todo
  2. cd todo
  3. rake db:create:all
  4. script/generate scaffold Todo title:string body:text done:boolean due:datetime
  5. rake db:migrate

Update: This code pretty much also provides you with a REST API.

Facebook How-To: scheduling profile updates

Monday, December 10th, 2007

Several of the Facebook Applications I have developed have required scheduling updates to Facebook User Profiles.

The process for scheduling updates is a little involved, but basically involves using a Session Key to push data to each User’s Profile.

  • Store the user’s Session Key.
  • Schedule an update with Cron
  • User the User ID and Session Key to create a Facebook Client Object make a Facebook API call.

The following samples are from a CakePHP project I recently completed and use the Facebook PHP Library. I’ve expanded the SQL so you have a better idea of what is happening behind the scenes.

Store the Session Key:

function beforeFilter() {
$this->facebook_user_id = $this->facebook->require_login();
$this->sessionKey = $this->facebook->api_client->session_key;
$this->Settings->query("UPDATE settings SET sessionKey = '{$this->sessionKey}' WHERE id = '{$this->facebook_user_id}'");
}

Each time the user hits the application I generally refresh the Session Key in my normal login/authentication process.

Make the API Call:

$data = $this->Settings->query("SELECT * FROM settings WHERE lastUpdated <= DATE_SUB( NOW(), INTERVAL 1 DAY) ORDER BY lastUpdated ASC LIMIT 1");
$id = $data[0]["settings"]["id"];
$sessionKey = $data[0]["settings"]["sessionKey"];
$this->facebook = new Facebook(FB_API_KEY, FB_SECRET);
$this->facebook->set_user($id, $sessionKey);
$this->facebook_user_id = $id;
$this->facebook->api_client->profile_setFBML($fbml);

This code grabs the first Faccbook User from the database who last updated a day ago and then creates a Facebook Client using the Facebook User Id and Session Key to make an API Call.

Note: When scheduling updates I generally use Cron to call a URL on my application with wget or Curl. Using this technique you can leverage the existing logic of your app and don’t have to write a standalone script.

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.

Converting a FaceBook App to use Amazon S3

Friday, November 16th, 2007

I’ve just completed work on another Facebook application: Songbook.

This was a relatively straight forward conversion of the existing application to use S3 for data storage. Songbook allows users to upload and display a song in their Facebook Profile. The original development stored the files on disk and hit limits really fast … hosting large numbers of files becomes very expensive very quickly, not to mention performance issues.

I converted the whole thing to S3 very quickly - it’s actually easier in some respects to handle storing files in S3 than to disk. The application now has essentially limitless and very cost-effective storage capacity.

S3 really is incredible.