Crayon Physics

erich January 14th, 2009

This has got to be one of the coolest games I have ever seen.

I’ve always been a fan of puzzle games, but in this particular game, the puzzle of how to connect a ball to a star separated by distances and objects, is as dynamic as your imagination.

Players are presented with more than 70 different puzzles and its brilliance is found in the way it challenges you to use your imagination to envision and then implement your own unique solutions to each one.

In the PC version, players use the mouse to draw shapes and objects that react to the laws of physics. For example, if you draw a box in the air, it will fall because of gravity.

What’s particularly clever about this game (as you’ll see in the video below) is that you can be as creative as you want. Simple levers and inclined planes work, but then again, so will rockets, dragons, and trebuchets.

Watch the video to see what I’m talking about… Other really interesting demonstrations can be seen here and here.

tags: , , ,

New Drupal Module Released

erich January 11th, 2009

Back in October, I released my first module for Drupal, the open-source content management system. These days, I seem to be developing exclusively for Drupal, and with a robust API and thriving community, I can only say how much fun it is to work with.

However, like any platforms, there are pieces missing. Fortunately, Drupal is one of those platforms that is very easily extended through modules. I came across one of those missing pieces while working on a project. I do all of my development in a sandbox, and when the work is complete, I QA the product in a staging environment before pushing the code and database changes to a production environment. I found that there was no way to manage user/role permissions in code; all management was a manual process via the web interface.

Having to repeat manual tasks like this across different environments increases the odds of errors. Steps can be omitted or performed improperly. In the case of permissions, I decided to correct that by writing a module called Permissions API. What this module allows you to do is to grant and revoke permissions to roles in code.

This is probably most useful in the context of programmatically creating CCK content types. The ability to import CCK content types through code is great until you decide that you want members of specific roles to be able to do something with this content type. Currently, the only way to grant the permissions is to navigate through the access control page in the admin interface, which is completely unusable if you have a lot of roles and a lot of modules. This module addresses that problem by providing two functions:

permissions_grant_permissions()
permissions_revoke_permissions()

Each function accepts a role id and an array of permissions. Sample usage would be:

PHP:
  1. <?php
  2. function mymodule_update_1(){
  3.   // Handle roles and permissions
  4.   $rid = db_result(db_query('SELECT r.rid FROM {role} r WHERE r.name = \'some custom role\''));
  5.   if($rid> 0){
  6.     $permissions = array(
  7.       'create some_content_type content',
  8.       'edit some_content_type content',
  9.       'edit own some_content_type content',
  10.     );
  11.     permissions_grant_permissions($rid, $permissions)
  12.   }
  13. }
  14. ?>

This module also provides functions for granting all permissions defined by a given module to a given role, as well as granting all defined permissions to a given role, which is useful for creating admin-type roles. Sample usage would be:

PHP:
  1. <?php
  2. function mymodule_update_2(){
  3.   // Create a "super-admin" role by granting all permissions
  4.   $rid = db_result(db_query('SELECT r.rid FROM {role} r WHERE r.name = \'some custom role\''));
  5.   if($rid> 0){
  6.     permissions_grant_all_permissions($rid);
  7.   }
  8. }
  9. ?>

The next example shows how to grant all permissions defined by a specific module to a specific role:

PHP:
  1. <?php
  2. function mymodule_update_3(){
  3.   // Grant all permissions defined by a module's hook_perm implementation
  4.   $rid = db_result(db_query('SELECT r.rid FROM {role} r WHERE r.name = \'some custom role\''));
  5.   if($rid> 0){
  6.     permissions_grant_all_permissions_by_module($rid, 'some module')
  7.   }
  8. }
  9. ?>

tags: , , , ,

Drupal and Taxonomy Weights

erich November 25th, 2008

I recently worked on a project in Drupal that called for a large number of taxonomy terms. I needed to put the terms in a specific order, but unfortunately, I had more terms than Drupal's weight field supports, which is a range from -10 to +10.

I did a quick search on Drupal, and was horrified to see how many people are hacking core to add a greater range. This is pretty easy to do without hacking core. All you need to do is create your own module that implements hook_form_alter().

my_module.module

PHP:
  1. function my_module_form_alter($form_id, &$form) {
  2.   switch($form_id) {
  3.     case 'taxonomy_form_term':
  4.     $form['weight']['#delta'] = 100;
  5.     break;
  6.   }
  7. }

And that's it!

tags: , , , , , , ,

Get Firefox Ad

erich November 21st, 2008

This is a pretty cool ad for Firefox that just makes me laugh...

tags: , , , , , ,

Tradition vs. Technology

erich October 19th, 2008

Raking leavesI've lived in New England my entire life, and if there's one thing that Yankees treasure, it's tradition. I'm no different, and yet today, I grudgingly decided that one tradition is not worth keeping.

Ever since I was a child, my family engaged in one of the most time-honored New England traditions of the autumn: raking leaves. Raking leaves is a noble chore. You get exercise and fresh air, your lawn benefits from being dethatched by the tines of the rake, and it instills a solid work ethic in the young.

It's a chore that I have always cherished. This year, however, I was rather dreading it. I just purchased a new home in September, and it has a substantially larger yard than my previous home. I knew that it would take me weeks to rake the entire property, and with a full time job, young kids, a wife, and everything else that keeps a family busy, I was trying to figure out how I could squeeze an extra 12 hours into each day.

Mostly out of curiosity, I decided to try a leaf blower. I'll categorically state that I find this to be cheating, but in the face of weeks of raking, I saw little reason to not give it a try. I'll have to admit, I was highly skeptical of the tool. As I mentioned before, one of the benefits of raking by hand is that the lawn gets a good dethatching; that is, all the dead grass and other material that forms a carpet right at the level of the soil and blocks nutrients from reaching the roots of the grass gets pulled up by the tines of the rake. I didn't see how a leaf blower would help with this.

At this point, I have to concede that the idea for the leaf blower was not mine. The leaf blower was a gift to me from my father, who is much wiser than I am. When he first gave it to me, I had no intention of using the thing for the reasons I had mentioned above. I have the unfortunate tendency to forget about things that I dismiss as useless, even if my determination regarding the usefulness of a thing is based on little or no prior experience. I don't know what it was about today that made me rethink my position on the leaf blower, but I was pleasantly surprised by its effectiveness.

As I mentioned, I have a large yard. Nearly two acres of level lawn, ringed by a thick woods of maple, oak, birch, and sumac. I was able to completely clear my backyard of fallen leaves in under an hour, a chore that would have easily taken me six hours had I resorted to my traditional techniques. The leaf blower was powerful enough to scrub the lawn and underlying soil clean. However excited I was about my progress and the ease of clearing the leaves, I could not help but feel sadness.

You see, I'm addicted to technology. I work with it every day, and run my life with it. The use of technology, even simple technology like a leaf blower, has implications. Using a leaf blower is a one-man job, and the tool is so loud, there's no chance for discussion and conversation while working. Furthermore, when you use a tool that cuts your work time down to next to nothing, the issue of work ethic is not even worth mentioning.

I was left wondering how I will teach all of these things to my sons. How will I teach them the value of sweat equity, the importance of physical labor and the satisfaction of putting your body to work with fantastic results? How can they learn the fine art of Yankee conversation, which occurs in short bursts, layered on top of physical work? The great New Hampshire author Noel Perrin described this very thing in one of his essays.

Sure, I can choose to abandon the leaf blower and go back to traditional methods. But as much as I have this choice, my Yankee sense of frugality forbids me from doing something that takes so much time when I have at my disposal the tools to get the job done faster leaving room for other things. Would I rather rake or spend the extra time with my sons?

As my father always reminds me, there's no such thing as setting aside quality time with your kids. He points out that any time you spend with your kids is quality. Perhaps I'll take this to heart and take my kids for a walk in the woods instead of raking up the woods.

tags: , , , , , , , ,

Flex and Drupal Paths

erich October 10th, 2008

At CommonPlaces, each developer has his or her own sandbox to code in. Each sandbox can run n instances of a Drupal application, which all run out of subdirectories from the developer's web root. So, for example I have a structure like this:

  • /public_html
    • /drupal_site1
    • /drupal_site2

We have a similar staging environment for all of our QA, and then of course, we have the production servers.

When I develop Flex applications that need to connect to one of these instances, I run into fun with dynamic urls to the /services/amfphp gateway. Because Flex can interact with Javascript, it's trivial to build dynamic urls to whatever environment the Flex app is running in.

Step 1: Download and enable the JSTools module for Drupal. This module extends the Drupal javascript object and gives it extra properties.

Step 2: Construct your urls dynamically in Flex by utilizing the ExternalInterface object.


var protocol:String = ExternalInterface.call('location.protocol.toString');
var domain:String = ExternalInterface.call('location.hostname.toString');
var urlPath:String = ExternalInterface.call('eval', 'window.Drupal.settings.jstools.basePath');
var gatewayUrl:String = protocol + "//" + domain + urlPath + "services/amfphp";

Note that the protocol and domain strings are set via ExternalInterface calls to a javascript function. The urlPath string is set via a call to the eval() function, and I'm passing in an argument of the Drupal basepath property set by jstools.

Debugging this is also easy, if you use Firefox and the Firebug plugin. All you have to do is pass debug strings to the console:


ExternalInterface.call('console.info', 'protocol = ' + protocol);
ExternalInterface.call('console.info', 'domain = ' + domain);
ExternalInterface.call('console.info', 'path = ' + urlPath);
ExternalInterface.call('console.info', 'gateway url = ' + gatewayUrl);

With the dynamic url to your amfphp gateway set, you can be assured that your Flex client will be able to consume data from Drupal services, no matter where the Flex app is run.

tags: , , , , , , , , , ,

Hack-proof Your Drupal App - the Video

erich October 6th, 2008

I had the pleasure of presenting at DrupalCon in Szeged Hungary, and the topic of my presentation was Drupal security from the perspective of the application. I am pleased to be able to share the video of my presentation.

tags: , , , , , , ,

DrupalCon Experiences in Szeged, Hungary

erich August 29th, 2008

I have been attending DrupalCon this week, hosted in the beautiful Hungarian town of Szeged.

I was fortunate in that my company, CommonPlaces, was generous enough to become a silver sponsor for the conference. This gave me the opportunity to present a session on Drupal security, and a BoF session on cross-site request forgeries and mitigation strategies. The session on hack-proofing Drupal applications seems to have been well received; there was a mix of people in the audience in terms of skill levels and knowledge on the topic.

While the information I presented was well documented in various parts of drupal.org and other blogs, I think the practical demonstrations of attack strategies was eye-opening for many in the audience. There is a big difference, in my opinion, between knowing how to prevent a vulnerability and knowing the mechanics and practical application of a vulnerability. The practical demonstrations were handled by Arian Evans from WhiteHat Security, as my co-presenter.

There was a wide variety of sessions offered at DrupalCon, and one of my favorites by far was on the topic of attracting and retaining Drupal talent. This was a very candor look at how some of the larger Drupal shops (RainCity, Palantir, and Development Seed) run their businesses and profit from working with Drupal.

The huge presence of Acquia here at DrupalCon is very exciting, and I'm very excited to see what they are up to.

If you haven't gotten the chance to attend a DrupalCon before, I hope that you find a way to beg, borrow, or hitchhike your way to the next one.

DrupalCon, CommonPlaces, Drupal, security, sessions

Drupal and Sane Flash Remoting

erich July 7th, 2008

On my latest project, I was faced with a challenge: build Flash widgets that displayed dynamic data and could be embedded on any web page. Phase two of the widgets called for user interaction with the widget, as opposed to simply displaying content. It seemed that Flex would be the most logical technology to use for this project.

I used the Services and AMFPHP modules for Drupal to expose content via web services for my Flex widget to consume. However, I ran into a problem with the critical piece that Flex needs in order to get remote data. As a workaround to the browser security settings that prevent cross-site scripting, Adobe chose to implement an opt-in solution in the form of a file called crossdomain.xml. With crossdomain.xml, a site owner may allow a list of domains to read its data and the client, Flash in this case, is responsible for enforcement. As the business case for the project called for the widget to be embedded on any domain, I needed to use a promiscuous crossdomain policy, allowing access from all domains:

XML:
  1. <cross-domain-policy>
  2.   <allow-access-from domain="*"/>
  3. </cross-domain-policy>

Because of this policy, the widget was allowed to read all data on the site that the user has access to, including any (authenticated) content and (session) cookies. This could easily lead to privacy violations, account takeovers, theft of sensitive data, and bypassing of CSRF protections.

Other domains in a similar predicament have simply hosted their APIs on a different domain, thus preventing access to user data on the root domain. Unfortunately, the nature of Drupal doesn't allow for splitting the Services functionality out from the rest of the platform.

My solution was to write a forwarder, which is just a really simple PHP script, that is hosted on a subdomain. This subdomain hosts the promiscuous crossdomain policy, and the policy file on the root domain is configured to only accept requests from the subdomain. The forwarder does two things: it first makes sure that only requests to /services/amfphp are allowed; if allowed, the $HTTP_RAW_POST_DATA is sent to the root domain via cURL.

PHP:
  1. <?php
  2. // Configuration variables
  3. $server = 'http://mydomain.com/services/amfphp';
  4.  
  5. $request_uri = trim($_SERVER['REQUEST_URI']);
  6. if ($request_uri[0] === '/'){
  7.   $request_uri = substr($request_uri, 1);
  8. }
  9.  
  10. // Split the uri into components
  11. list($handler, $protocol) = split('/', $request_uri);
  12.  
  13. // Filter out unwanted requests
  14. if(($handler != 'services') && ($protocol != 'amfphp')){
  15.   exit();
  16. }
  17.  
  18. // Handle the post from the flash/flex client
  19. $xml = $HTTP_RAW_POST_DATA;
  20. if(strlen($xml) == 0){
  21.   exit();
  22. }
  23.  
  24. // Set the headers
  25. $header[] = "Content-type: text/xml";
  26. $header[] = "Content-length: ".strlen($xml);
  27.  
  28. $ch = curl_init($server);
  29. curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
  30. curl_setopt($ch, CURLOPT_TIMEOUT, 30);
  31. curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
  32. curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);
  33.  
  34. $response = curl_exec($ch);
  35.  
  36. if (curl_errno($ch)) {
  37.   exit();
  38. }
  39. else {
  40.   curl_close($ch);
  41.   if(strlen($response) == 0){
  42.     exit();
  43.   }
  44.   print $response;
  45. }
  46.  
  47. exit();
  48.  
  49. ?>

Because the subdomain doesn't host any data at all, the security risk has been removed. If you are working with Drupal and Flash remoting, you'll need to consider the risks associated with promiscuous crossdomain policy files. While my solution certainly isn't the only solution, it is pretty effective and simple.

tags: , , , , , , , , , , ,

Introduction to Young Talent

erich June 15th, 2008

My niece, Brynn Doughty, played a wonderful piano piece for a recital on June 12, 2008.


Next »