Tag Archives: web applications

Mouseover / Mouseout on Nested Elements

Did I mention I’m code-sprinting over the next three days?  Actually, next two days – I just finished my first day today.

What’s code-sprinting?  It’s a trendy term for sitting down with your team, and plowing through code en masse, trying to get as much done as possible.  8 hour days, cookies, coffee, whiteboards, pizza, crashes, bugs, tickets, fixes, etc.  We’re trying to cram 3 weeks of work into 3 days.  Cool.

In case you don’t remember, I’m working on a project called Checkmark (or OLM…still undecided on the name) – a tool for Professors/TAs to receive student code submissions, and to facilitate easy marking and annotating of the submitted code.

So here’s something I learned today while coding:

Say you have some nested DIV’s, and the parent DIV has a mouseout trigger.  Something like this:

<div id="parent" onMouseOut="alert('Mouseout triggered on parent');">
  <div id="child_1">This is some child</div>
  <div id="child_2">This is another child</div>
</div>

As you would expect, the mouseout event will get triggered if you move your mouse over the parent DIV, and then move the mouse back out again.

But it also gets triggered when you move your mouse OVER any of the child DIV’s.

Say what?  That’s right – even though you’re still inside the parent DIV, the mouseout event got triggered.  I found this out today when I was trying to code dropdown menus in Javascript/CSS using Prototype – I could get the dropdown menus to appear find when I clicked on the appropriate button, but they’d disappear again as soon as I put my mouse over any of the sub-elements of the DIV.

So how did I fix this?  I found this example code, and adapted it for my purposes.  This code assumes that you’re using the Prototype Javascript library.

$('some_dropdown').observe('mouseout',
  function(event) {
     //We could probably replace the following with Event.element(event), but oh well.
     var target = $('some_dropdown');
     var mouse_over_element;  //What the mouse is currently over...
     //So let's check to see what the mouse is now over, and assign it to mouse_over_element...
     if( event.toElement ) {
        mouse_over_element = event.toElement;
     }
     else if(event.relatedTarget) {
       mouse_over_element = event.relatedTarget;
     }
     //In the event that the mouse is over something outside the DOM (like an alert window)...
     if(mouse_over_element == null) {
        return;
     }
     //Now we just make sure that what the mouse is currently over is NOT a descendant of
     //the dropdown, and that the target is not the current mouse_over_element (I can't
     //remember which case this covers, but it's important)
     if(!mouse_over_element.descendantOf(target) && target != mouse_over_element) {
        target.hide();
     }
   }
 );

And it works.  Whew!  Just thought I’d share that little snippit.

SQL Injection Prevention in PHP – Tip 1

It’s amazing – I’ve been going around, Googling for anything with “index.php?id=”…and that’s really all it takes.  Now, granted, SQL Injection isn’t new, and a lot of the top hits have taken some steps to protect themselves, but if you go deep – like, Google search page 23 deep – you’ll find ones that break if you put a semi-colon after the id # – and if it breaks, it’s vulnerable.

So, here’s my first tip on preventing SQL Injection – when you’re asking for an ID number, make sure it’s a number, and nothing else. Also consider using prepared statements – database wrappers like MDB2 for PHP make this easy.

Check this out – this might be how I would have done it 3 years ago:

<?php
  //Assume we're already connected to a MySQL database...
  $id = $_GET['id'];

  $result = mysql_query('SELECT * from pages where id='.$id);
  if (!$result) {
     die('Invalid query: ' . mysql_error());
  }
  ... //Code to print out my result to the page
?>

I’d do it this way now:

Note: My use of MDB2 might be a little rusty – I haven’t tested this code, and I usually compose RowDataGateway objects with MDB2 to represent my data.  So pay more attention to the structure than the actual syntax.

<?php
  require 'View.php';
  require 'MDB2.php';  //An excellent DB layer from the PEAR libs

  //Code to set $mdb2 as our DB connection variable
  //See http://pear.php.net/package/MDB2 for details
  $id = $_GET['id'];

  try {
    if(!is_int($id)) {
      //ID wasn't an int, it's no good, let's bail
      throw new Exception('Could not recognize the id that you passed');
    }
    //ID was an int, let's see if we can find the record
    $sql = 'SELECT * from pages where id=:id";
    $statement = $mdb2->prepare($sql);
    $statement->bindParam('id', $id);
    $result = $statement->execute();
    if(PEAR::isError($result)) {
      //Uh oh - our result was an error on the PEAR library level
      throw new Exception('There was an error communicating with the database');
    }
    //Insert the database result into the view, render, and die.
    $content = new View('templates/page.tpl', array('page' => $result->fetchOne()));
    $content->render();
    die;
  }
  catch(Exception $e) {
    //We must have caught an exception - put this into our
    //error page template with the error message, render, die.
    $content = new View('templates/error.tpl', array('message' => $e->getMessage()));
    $content->render();
    die;
  }
?>

Yes, it’s quite a bit more code. But I feel safer just looking at it.
Did I miss anything on this? Please post a comment if you  notice that I’ve left a gaping hole.  Learning is good.

Preventing SQL Injection Attacks

Over the reading week, along with studying for various midterms and assignments, I’ve decided to brush up on preventing SQL Injection attacks in web applications.

Pretty scary/awesome stuff out there on this stuff.  Here’s a great place to get some SQL Injection training, and here’s an excellent SQL Injection cheat sheet.

I got hit with a pretty bad SQL Injection attack last summer on an application I had written 3 years ago (before I had any clue that SQL Injection attacks were possible).

Here’s the take home message:  never trust user input.  Ever. If you’re expecting an int, make sure it’s an int.  Never insert user input directly into an SQL string. Use prepared statements instead, or stored procedures.

Luckily, I just did a quick survey of all of my running apps, and I seem to be OK in terms of SQL Injection.  Still, it’s a common attack vector – and the consequences of being lazy on user input can be pretty awful.

Update: Want to see something awesome?  Check this out – a Debian box gets rooted through MySQL injection…killer soundtrack too.