Javascript Error with Mootools, IE 7 and Google Adsense

I use firefox for the vast majority of my web browsing, with IE and Chrome occasionally thrown in. While using IE 7 the other day, I opened up this very site, and to my dismay, discovered a javascript error: Line 89, Object doesn't support this action.


I was surprised, since I tested the site on IE 7 not too long ago and am not using any plugins or 3rd party code (i.e. this isn't a wordpress site). At first, it appeared the Core MooTools was the culprit, as removing that file stopped the error. But that didn't explain why there was no error when I tested it on my development box, which had the MooTools JavaScript included. After a little more head scratching I realized the only difference between the site on my dev box and production box was the fact that I have Google Adsense ads on the live site, but not on the dev site.


Sure enough, removing the ads caused the error to go away. Trying to be a good web developer, I was loading my MooTools scripts at the bottom of the page to prevent locking the browser while rendering the page. When I moved the Core MooTools script into the head tag at the top of the page, the error went away. Not sure the exact details of the problem, but loading MooTools after Google Adsense was causing errors in IE 7...

Posted In: JavaScript | 8 comments

Authenticating A User With Zend_Auth

One of the nice things about the Zend Framework is being able to use it all, or only use individual parts that appeal to you. The Zend_Auth component is no exception, and makes it very easy to authenticate users. An important distinction needs to be made between authentication and authorization. Authentication is determining whether someone is who they say they are - in other words, assigning an identity to an end user. Authorization revolves around determining what actions a user can perform, and is typically handled by Zend_Acl.

Authenticate Against a Database

While using a 3rd party such as Facebook, Google, Twitter or OpenId is starting to gain a lot of traction, authenticating against a database is still one of the most common ways to authenticate a user. At it's most simplest (read the last paragraph to learn why you should never use this code), assuming we had a table called userTable with a field username for the username, and password for the password, we would have something like:

<?php
        $auth 
Zend_Auth::getInstance();
        
$db = new Zend_Db_Adapter_Pdo_Mysql(array(
            
'host' => 'localhost',
            
'username' => 'username',
            
'password' => 'password',
            
'dbname' => 'mydb'
        
));
         
$authAdapter Zend_Auth_Adapter_DbTable($db,'userTable','username','password');
        
$authAdapter->setIdentity($_POST['user'])->setCredential($_POST['password']);
        
$result $auth->authenticate($authAdapter);
        if(
$result->isValid()) {
            die(
'user authenticated');
        } else {
            die(
'user not authenticated');
        }
?>

In this example, we get the Zend_Auth instance using the static function getInstance. Zend_Auth is a singleton, meaning there should only be one instance of the class during request execution. The reason for this becomes apparent when you use Zend_Auth to get a user's identity. You want to ensure you are always accessing the same instance of Zend_Auth in your code.


We then set up the database connection with the variable $db, and set up the adapter used by Zend_Auth, referenced by the variable $authAdapter. $authAdapter takes the database adapter, then the name of the table that holds end users' credentials, then the field name of said table that has the username, and finally the field name of said table that stores the password. Finally, we set the identity and credential via a $_POST variable that would be supplied on a login form, and call authenticate on Zend_Auth while passing in the adapter and check if the result is valid. All in all, pretty straightforward.

Get My Identity


Once an end user has successfully logged in, we can get the end user's identity via Zend_Auth:


<?php
        $auth 
Zend_Auth::getInstance();
        if (
$auth->hasIdentity()) {
            
$identity $auth->getIdentity();
            
print_r($identity); // $authAdapter->setIdentity($_POST['user']);
        
}
?>

First, we grab the singleton Zend_Auth and then check if the user has an identity. If she does, then we get the identity. I can see the question bouncing around in your head - what is the identity. By default, when you log in with the code above, it will use the value from the setIdentity method, which is typically the user name. You can now tell whether a user is logged in, and you have their user name stored in a session.


What happens if you want to store something else besides a string as the identity? For example, you may be using Zend_Acl, and want to know the role of the user - let's create an object and store that as the identity. We have a couple of options to accomplish this, but first let's understand what Zend_Auth is doing when you call the authenticate method. Zend_Auth takes the identity returned by the Adapter (which in the case of the db adapter is a string) , and persists the identity in a session. Therefore, we could create our own adapter and return an object instead of a string, or we can interact directly with the db adapter and bypass Zend_Auth. The second option seems easiest to explain, so let's roll with that (subclassing db adapter would make a nice blog post...).

<?php
        $db 
= new Zend_Db_Adapter_Pdo_Mysql(array(
            
'host' => 'localhost',
            
'username' => 'root',
            
'password' => '',
            
'dbname' => 'bf'
        
));
        
$authAdapter = new Zend_Auth_Adapter_DbTable($db,'userTable','username','password');
        
$authAdapter->setIdentity($_POST['user'])->setCredential($_POST['password']);
        
$result $authAdapter->authenticate();
        if(
$result->isValid()) {
            echo 
'user authenticated<br />';
        } else {
            echo 
'user not authenticated<br />';
        }
        
$auth Zend_Auth::getInstance();
        
var_dump($auth->hasIdentity());
?>

We have similar code as before, except we are calling authenticate on the adapter. If you run this code in a browser, you would see that we authenticated the user (assuming you put in the right username and password), but we get false when calling $auth->hasIdentity(). Since we didn't use Zend_Auth to authenticate, the identity is not “saved.

To remedy this, we can update our code with the following lines:

<?php
        $auth 
Zend_Auth::getInstance();
        
$db = new Zend_Db_Adapter_Pdo_Mysql(array(
            
'host' => 'localhost',
            
'username' => 'root',
            
'password' => '',
            
'dbname' => 'bf'
        
));
        
$authAdapter = new Zend_Auth_Adapter_DbTable($db,'member','username','password');
        
$authAdapter->setIdentity($_POST['user'])->setCredential($_POST['password']);
        
$result $authAdapter->authenticate();
        if(
$result->isValid()) {
            echo 
'user authenticated<br />';
            
$auth->getStorage()->write($authAdapter->getResultRowObject(array(
                
'username''role'
            
)));
        } else {
            echo 
'user not authenticated<br />';
        }
        
        
var_dump($auth->hasIdentity()); //true
        
var_dump($auth->getIdentity()); // object(stdClass)#67 (2) { ["username"]=> string(3) "rob" ["role"]=> string(5) "admin" }
?>

Once the result is valid, we are getting the storage mechanism (usually a session) and telling the storage to save the result from the database as a standard object. The array of username and role are the fields we want to save. Notice we left out the password field, as that should not be persisted. For my applications, I actually have a user object that implements Zend_Acl_Role_Interface, so I instantiate my user object, and grab the values from the stdClass object that is returned from getResultRowObject.

Can You Say Insecure

What's so horrible about the above code? We are storing an end user's password in plain text within the database. If someone gains access to the database, that person now has access to all your users' password. Maybe that's not a big deal because you don't store any sensitive information like credit cards, but it's still a very bad idea. Not only will your street cred be ruined as the entire internet laughs at your folly of storing unencrypted passwords, but if you happen to store email addressees, a cracker would now have your user's email address and the password for your site. A decent percentage of your users will likely have the same password for your site and for their email account (who can remember unique passwords for every site...). You get the picture...

At a minimum, you need to encrypt the password stored in your database and add a salt to the password. You can read this article to brush up on the problems with storing passwords in a database. My next blog post will cover how to use a one way hash and a salt to make it more difficult for passwords to be cracked in the event your database is compromised.


Posted In: PHP, Zend Framework | 3 comments

How to Handle a date in PHP

Handling dates is an important part of many applications, and fortunately, it is relatively easy to work with dates in PHP.

Set the Timezone

Before jumping into how to handle dates, it is worth noting that PHP by default will use the date and time from the server. If the time zone of your server differs from your timezone, or the people using your website, you can have some unexpected results. To determine what your time zone is, you can use:

<?php
    
echo date_default_timezone_get();  // America/Los_Angeles for Western
?>

There are a couple of options available if you want to change the time zone. If you want to change the time zone in just your current PHP script, find your time zone, and then use:

<?php
    date_default_timezone_set
('America/Los_Angeles');
?>

If you would like to change it for all PHP scripts on the server, you can edit the php configuration file (php.ini) :


[Date]
; Defines the default timezone used by the date functions
date.timezone = America/New_York

Get the Current Date


Now that we have your time zone set correctly, let's look at the simple use case of echo'ing out the current date. To do this, you can use the date function.

<?php
    
echo date('m/d/y');  // 02/01/11
?>

It's easy to apply a different format to the date, just replace the characters in the above example with any of the following:


Important Full Date and Time:

  • r: Displays the full date, time and timezone offset. It is equivalent to manually entering date("D, d M Y H:i:s O")


Time:

  • a: am or pm depending on the time

  • A: AM or PM depending on the time

  • g: Hour without leading zeroes. Values are 1 through 12.

  • G: Hour in 24-hour format without leading zeroes. Values are 0 through 23.

  • h: Hour with leading zeroes. Values 01 through 12.

  • H: Hour in 24-hour format with leading zeroes. Values 00 through 23.

  • i: Minute with leading zeroes. Values 00 through 59.

  • s: Seconds with leading zeroes. Values 00 through 59.



Day:

  • d: Day of the month with leading zeroes. Values are 01 through 31.

  • j: Day of the month without leading zeroes. Values 1 through 31

  • D: Day of the week abbreviations. Sun through Sat

  • l: Day of the week. Values Sunday through Saturday

  • w: Day of the week without leading zeroes. Values 0 through 6.

  • z: Day of the year without leading zeroes. Values 0 through 365.



Month:

  • m: Month number with leading zeroes. Values 01 through 12

  • n: Month number without leading zeroes. Values 1 through 12

  • M: Abbreviation for the month. Values Jan through Dec

  • F: Normal month representation. Values January through December.

  • t: The number of days in the month. Values 28 through 31.



Year:

  • L: 1 if it's a leap year and 0 if it isn't.

  • Y: A four digit year format

  • y: A two digit year format. Values 00 through 99.




Other Formatting:

  • U: The number of seconds since the Unix Epoch (January 1, 1970)

  • O: This represents the Timezone offset, which is the difference from Greenwich Meridian Time (GMT). 100 = 1 hour, -600 = -6 hours


Timestamps and Dates

Echo'ing the current date is easy, but how about calculating dates in the future or past? In the above examples, we simply provided the formatting as the first parameter and the date function spit out the current date/time. If you want to work with dates other than the current one, you will need to use the second parameter of the date function, which is a timestamp.

A timestamp is UNIX speak for the number of seconds that have passed since January 1, 1970. To generate the current date and time via a timestamp, you can use the mktime function. When you call the date function, it is grabbing the current timestamp by default and you don't need to provide the timestamp:

<?php
    
echo date('m/d/y');
    echo 
date('m/d/y'mktime()); 
?>

Manipulating Dates

Manipulating dates is hard until you get the basics of timestamps. There are a couple of ways to generate dates in the part or future. One way is to simply add or subtract the number of seconds for a given duration. For example, there are 86,400 seconds in a day, so if we wanted to display the date for tomorrow, you could simply use the below code to generate the current timestamp, then add 86,400 seconds (a day) to the timestamp, which gives us the timestamp for tomorrow:

<?php
    
echo date('m/d/y', (mktime() + 86400));
?>

Calculating the number of seconds in a month or year can be a bit laborious, so let's take a look at some other functions to help with manipulating and calculating dates. First up is the strtotime function, which expects to be given a string containing an English date format and will return the timestamp for the given string. To get the date for tomorrow, and next month, and next year, we could use:

<?php
        
echo date('m/d/y'strtotime("+1 day")) . '<br />';
        echo 
date('m/d/y'strtotime("+1 month")). '<br />';
        echo 
date('m/d/y'strtotime("+1 year")). '<br />';
?>

The strtotime function can also come in handy if you are dealing with a date column from MySQL (e.g. it is formatted as YYYY-MM-DD):

<?php
     $mysqlDate 
'2011-01-20';
    echo 
date('F j, Y'strtotime($mysqlDate));
?>

Validating Dates

I can't believe you've made it this far... Since you have, let's look at validating a date that could come from a user. As any good coder knows, we never trust input that comes from 3rd parties, whether that is an end user entering a value into an HTML form, or data coming from a web service.

With that in mind, how do we validate that an end user entered in a correct date into a form field? If we use the strtotime function with an invalid date, it will return false. So it strtotime can’t parse the date, we know it is not a valid date!

<?php
        
if(!strtotime('2011-13-20')) {
            echo 
'That is a bad date';
        }
?>

In Conclusion

Hopefully, you know a bit more about how to work with dates in PHP. We've only scratched the surface, and there are a lot of other functions available, so keep on learning!

Posted In: PHP | No Comments

Mysql Error 1064 (4200) - Using BTREE

Trying to move a database from my development machine which is running MySQL 5.1.41 on Ubuntu to my server, which is Ubuntu but runs MySQL 5.0.51a and I keep getting an error:
ERROR 1064 (42000) at line 122: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'USING BTREE, KEY `FrtTP_Feature` (`featureId`), CONSTRAINT `FrtTP_Feature` F' at line 4

On my development machine, I can dump and upload the database just fine, but it won't import all the tables to MySQL on my production box. Obviously the differing MySQL versions are causing problems. I searched on the internets, but nothing much useful came up, as that error seems to be used for everything. I'm finding out that MySQL's errors are anything but informative.

After some digging on MySQL's site, I found the syntax USING BTREE has moved to after the key description in versions greater than 5.1. After changing my database dump file, I can now upload all my tables and data to my production server. You would think they would wait until major version numbers to choke on the placement of that syntax.... Below are the changes I made to get 5.1.41 to work with 5.0.51a:
UNIQUE KEY `url_unique` (`url`,`memberId`) USING BTREE becomes UNIQUE KEY `url_unique` USING BTREE (`url`,`memberId`) and
PRIMARY KEY (`memberId`,`tripreportPhotoId`) USING BTREE becomes PRIMARY KEY USING BTREE (`memberId`,`tripreportPhotoId`)

Posted In: mysql | 5 comments

Mysql Error 1005 - Foreign Key Contraint Woes

If you are trying to set up foreign key constraints in MySQL InnoDb table, and run into Error 1005, open up a mysql client on the command line and type show engine innodb status. Then scroll through the output until you reach:
------------------------
LATEST FOREIGN KEY ERROR
------------------------

This will give you more information about the error. The foreign key names have to be unique, so if you use something generic for the name, you may run into issues when setting up constraints on other tables. The other error I have experienced was trying to set the on delete action to set the field null, but null was not allowed on that field.

Posted In: mysql | No Comments

View more posts