Pages

This is default featured slide 1 title

Go to Blogger edit html and find these sentences.Now replace these sentences with your own descriptions.

This is default featured slide 2 title

Go to Blogger edit html and find these sentences.Now replace these sentences with your own descriptions.

This is default featured slide 3 title

Go to Blogger edit html and find these sentences.Now replace these sentences with your own descriptions.

This is default featured slide 4 title

Go to Blogger edit html and find these sentences.Now replace these sentences with your own descriptions.

This is default featured slide 5 title

Go to Blogger edit html and find these sentences.Now replace these sentences with your own descriptions.

Thursday, July 5, 2012

Shortcut the else

This tip accidentally stumbles upon a useful practice, which is to always initialize variables before you use them. Consider a conditional statement that determines whether a user is an administrator based on the username:
<?php
 
if (auth($username) == 'admin') {
    $admin = TRUE;
} else {
    $admin = FALSE;
}
 
?>
This seems safe enough, because it’s easy to comprehend at a glance. Imagine a slightly more elaborate example that sets variables for name and email as well, for convenience:
<?php
 
if (auth($username) == 'admin') {
    $name = 'Administrator';
    $email = 'admin@example.org';
    $admin = TRUE;
} else {
    /* Get the name and email from the database. */
    $query = $db->prepare('SELECT name, email
                           FROM   users
                           WHERE  username = :username');
    $query->execute(array('username' => $clean['username']));
    $result = $query->fetch(PDO::FETCH_ASSOC);
    $name = $result['name'];
    $email = $result['email']; 
    $admin = FALSE;
}
 
?>
Because $admin is still always explicitly set to either TRUE or FALSE, all is well, but if a developer later adds an elseif, there’s an opportunity to forget:
<?php
 
if (auth($username) == 'admin') {
    $name = 'Administrator';
    $email = 'admin@example.org';
    $admin = TRUE;
} elseif (auth($username) == 'mod') {
    $name = 'Moderator';
    $email = 'mod@example.org';
    $moderator = TRUE;
} else {
    /* Get the name and email. */
    $query = $db->prepare('SELECT name, email
                           FROM   users
                           WHERE  username = :username');
    $query->execute(array('username' => $clean['username']));
    $result = $query->fetch(PDO::FETCH_ASSOC);
    $name = $result['name'];
    $email = $result['email']; 
    $admin = FALSE;
    $moderator = FALSE;
}
 
?>
If a user provides a username that triggers the elseif condition, $admin is not initialized. This can lead to unwanted behavior, or worse, a security vulnerability. Additionally, a similar situation now exists for $moderator, which is not initialized in the first condition.
By first initializing $admin and $moderator, it’s easy to avoid this scenario altogether:
<?php
 
$admin = FALSE;
$moderator = FALSE;
 
if (auth($username) == 'admin') {
    $name = 'Administrator';
    $email = 'admin@example.org';
    $admin = TRUE;
} elseif (auth($username) == 'mod') {
    $name = 'Moderator';
    $email = 'mod@example.org';
    $moderator = TRUE;
} else {
    /* Get the name and email. */
    $query = $db->prepare('SELECT name, email
                           FROM   users
                           WHERE  username = :username');
    $query->execute(array('username' => $clean['username']));
    $result = $query->fetch(PDO::FETCH_ASSOC);
    $name = $result['name'];
    $email = $result['email'];
}
 
?>
Regardless of what the rest of the code does, it’s now clear that $admin is FALSE unless it is explicitly set to something else, and the same is true for $moderator. This also hints at another good security practice, which is to fail safely. The worst that can happen as a result of not modifying $admin or $moderator in any of the conditions is that someone who is an administrator or moderator is not treated as one.
If you want to shortcut something, and you’re feeling a little disappointed that our example includes an else, we have a bonus tip that might interest you. We’re not certain it can be considered a shortcut, but we hope it’s helpful nonetheless.
Consider a function that determines whether a user is authorized to view a particular page:
<?php
 
function authorized($username, $page) {
    if (!isBlacklisted($username)) {
        if (isAdmin($username)) {
            return TRUE;
        } elseif (isAllowed($username, $page)) {
            return TRUE;
        } else {
            return FALSE;
        }
    } else {
        return FALSE;
    }
}
 
?>
This example is actually pretty simple, because there are only three rules to consider: administrators are always allowed access; those who are blacklisted are never allowed access; and isAllowed() determines whether anyone else has access. (A special case exists when an administrator is blacklisted, but that is an unlikely possibility, so we’re ignoring it here.) We use functions for the rules to keep the code simple and to focus on the logical structure.
There are numerous ways this example can be improved. If you want to reduce the number of lines, a compound conditional can help:
<?php
 
function authorized($username, $page) {
    if (!isBlacklisted($username)) {
        if (isAdmin($username) || isAllowed($username, $page)) {
            return TRUE;
        } else {
            return FALSE;
        }
    } else {
        return FALSE;
    }
}
 
?>
In fact, you can reduce the entire function to a single compound conditional:
<?php
 
function authorized($username, $page) {
    if (!isBlacklisted($username) && (isAdmin($username) || isAllowed($username, $page)) {
        return TRUE;
    } else {
        return FALSE;
    }
}
 
?>
Finally, this can be reduced to a single return:
<?php
 
function authorized($username, $page) {
    return (!isBlacklisted($username) && (isAdmin($username) || isAllowed($username, $page));
}
 
?>
If your goal is to reduce the number of lines, you’re done. However, note that we’re using isBlacklisted(), isAdmin(), and isAllowed() as placeholders. Depending on what’s involved in making these determinations, reducing everything to a compound conditional may not be as attractive.
This brings us to our tip. A return immediately exits the function, so if you return as soon as possible, you can express these rules very simply:
<?php
 
function authorized($username, $page) {
 
    if (isBlacklisted($username)) {
        return FALSE;
    }
 
    if (isAdmin($username)) {
        return TRUE;
    }
 
    return isAllowed($username, $page);
}
 
?>
This uses more lines of code, but it’s very simple and unimpressive (we’re proudest of our code when it’s the least impressive). More importantly, this approach reduces the amount of context you must keep up with. For example, as soon as you’ve determined whether the user is blacklisted, you can safely forget about it. This is particularly helpful when your logic is more complicated.

Know the Difference Between Comparison Operators


This is a good tip, but it is missing a practical example that demonstrates when a non-strict comparison can cause problems.
If you use strpos() to determine whether a substring exists within a string (it returns FALSE if the substring is not found), the results can be misleading:
<?php
 
$authors = 'Chris & Sean';
 
if (strpos($authors, 'Chris')) {
    echo 'Chris is an author.';
} else {
    echo 'Chris is not an author.';
}
 
?>
Because the substring Chris occurs at the very beginning of Chris & Sean, strpos() correctly returns 0, indicating the first position in the string. Because the conditional statement treats this as a Boolean, it evaluates to FALSE, and the condition fails. In other words, it looks like Chris is not an author, but he is!
This can be corrected with a strict comparison:
<?php
 
if (strpos($authors, 'Chris') !== FALSE) {
    echo 'Chris is an author.';
} else {
    echo 'Chris is not an author.';
}
 
?>

Use an SQL Injection Cheat Sheet


This particular tip is just a link to a useful resource with no discussion on how to use it. Studying various permutations of one specific attack can be useful, but your time is better spent learning how to safeguard against it. Additionally, there is much more to Web app security than SQL injection. XSS (Cross-Site Scripting) and CSRF (Cross-Site Request Forgeries), for example, are at least as common and at least as dangerous.
We can provide some much-needed context, but because we don’t want to focus too much on one attack, we’ll first take a step back. Every developer should be familiar with good security practices, and apps should be designed with these practices in mind. A fundamental rule is to never trust data you receive from somewhere else. Another rule is to escape data before you send it somewhere else. Combined, these rules can be simplified to make up a basic tenet of security: filter input, escape output (FIEO).
The root cause of SQL injection is a failure to escape output. More specifically, it is when the distinction between the format of an SQL query and the data used by the SQL query is not carefully maintained. This is common in PHP apps that construct queries as follows:
<?php
 
$query = "SELECT *
          FROM   users
          WHERE  name = '{$_GET['name']}'";
          
?>
In this case, the value of $_GET['name'] is provided by another source, the user, but it is neither filtered nor escaped.
Escaping preserves data in a new context. The emphasis on escaping output is a reminder that data used outside of your Web app needs to be escaped, else it might be misinterpreted. By contrast, filtering ensures that data is valid before it’s used. The emphasis on filtering input is a reminder that data originating outside of your Web app needs to be filtered, because it cannot be trusted.
Assuming we're using MySQL, the SQL injection vulnerability can be mitigated by escaping the name with mysql_real_escape_string(). If the name is also filtered, there is an additional layer of security. (Implementing multiple layers of security is called "defense in depth" and is a very good security practice.) The following example demonstrates filtering input and escaping output, with naming conventions used for code clarity:
<?php
 
// Initialize arrays for filtered and escaped data, respectively.
$clean = array();
$sql = array();
 
// Filter the name. (For simplicity, we require alphabetic names.)
if (ctype_alpha($_GET['name'])) {
    $clean['name'] = $_GET['name'];
} else {
    // The name is invalid. Do something here.
}
 
// Escape the name.
$sql['name'] = mysql_real_escape_string($clean['name']); 
 
// Construct the query.
$query = "SELECT *
          FROM   users
          WHERE  name = '{$sql['name']}'";
 
?>
Although the use of naming conventions can help you keep up with what has and hasn't been filtered, as well as what has and hasn't been escaped, a much better approach is to use prepared statements. Luckily, with PDO, PHP developers have a universal API for data access that supports prepared statements, even if the underlying database does not.
Remember, SQL injection vulnerabilities exist when the distinction between the format of an SQL query and the data used by the SQL query is not carefully maintained. With prepared statements, you can push this responsibility to the database by providing the query format and data in distinct steps:
<?php
 
// Provide the query format.
$query = $db->prepare('SELECT *
                       FROM   users
                       WHERE  name = :name');
 
// Provide the query data and execute the query.
$query->execute(array('name' => $clean['name']));
 
?>
The PDO manual page provides more information and examples. Prepared statements offer the strongest protection against SQL injection.

MySQL Server Crashed – Site was still online!

You don’t hear this often… MySQL server crashed and the sites hosted in that server went offline for hours together. But, when a similar thing happened to my VPS, it wasn’t the case. My site was still online, while I was troubleshooting the issue with MySQL server. Ultimately, I could not figure out the issue and I had to purge the entire MySQL installation. However, I was still cool during the entire process. You may ask how. Here is what happened and how you can prevent the same for your own VPS too…

First Things First

As part of regular tweaking of MySQL, I changed a few things in my.cnf, then restarted the mysqld. Bump! It didn’t start. I reverted the changes. Still it didn’t budge. Immediately I knew that MySQL server has crashed for unknown reason. Upon checking the log, here is what I found…


120525 06:54:11 mysqld_safe Starting mysqld daemon with databases from /var/lib/mysql
120525  6:54:11 [Note] Plugin 'FEDERATED' is disabled.
06:54:11 UTC - mysqld got signal 11 ;
This could be because you hit a bug. It is also possible that this binary
or one of the libraries it was linked against is corrupt, improperly built,
or misconfigured. This error can also be caused by malfunctioning hardware.
We will try our best to scrape up some info that will hopefully help
diagnose the problem, but since we have already crashed,
something is definitely wrong and this may fail.

key_buffer_size=31457280
read_buffer_size=524288
max_used_connections=0
max_threads=100
thread_count=0
connection_count=0
It is possible that mysqld could use up to
key_buffer_size + (read_buffer_size + sort_buffer_size)*max_threads = 133850 K  bytes of memory
Hope that's ok; if not, decrease some variables in the equation.

Thread pointer: 0xffffffffbfb01d80
Attempting backtrace. You can use the following information to find out
where mysqld died. If you see no messages after this, something went
terribly wrong...
stack_bottom = ffffffffbfb03ab8 thread_stack 0x20000
/usr/libexec/mysqld(my_print_stacktrace+0x2d)[0x83b70e2]
/usr/libexec/mysqld(handle_fatal_signal+0x4a2)[0x829d156]
[0xb777c400]
/usr/libexec/mysqld(_Z18ha_resolve_by_nameP3THDPK19st_mysql_lex_string+0xad)[0x82a104c]
/usr/libexec/mysqld(_Z14open_table_defP3THDP11TABLE_SHAREj+0x1822)[0x82213c2]
/usr/libexec/mysqld(_Z15get_table_shareP3THDP10TABLE_LISTPcjjPij+0x197)[0x8169869]
/usr/libexec/mysqld(_Z10open_tableP3THDP10TABLE_LISTP11st_mem_rootP18Open_table_context+0x545)[0x817010a]
/usr/libexec/mysqld(_Z11open_tablesP3THDPP10TABLE_LISTPjjP19Prelocking_strategy+0x456)[0x8171683]
/usr/libexec/mysqld(_Z20open_and_lock_tablesP3THDP10TABLE_LISTbjP19Prelocking_strategy+0x54)[0x8171f86]
/usr/libexec/mysqld[0x81adf41]
/usr/libexec/mysqld(_Z11plugin_initPiPPci+0x8dc)[0x81b0db9]
/usr/libexec/mysqld[0x8133a34]
/usr/libexec/mysqld(_Z11mysqld_mainiPPc+0x42a)[0x8136cc8]
/usr/libexec/mysqld(main+0x27)[0x812ce33]
/lib/i686/nosegneg/libc.so.6(__libc_start_main+0xe6)[0xb7288ce6]
/usr/libexec/mysqld[0x812cd95]

Trying to get some variables.
Some pointers may be invalid and cause the dump to abort.
Query (0): is an invalid pointer
Connection ID (thread ID): 0
Status: NOT_KILLED

The manual page at http://dev.mysql.com/doc/mysql/en/crashing.html contains
information that should help you find out what is causing the crash.
120525 06:54:11 mysqld_safe mysqld from pid file /var/run/mysqld/mysqld.pid ended
I tried everything I could, for about 90 minutes. Then I gave up and purged the entire MySQL installation and installed it again. Viola! It started fine! Then it was only a matter of taking the latest database backup and putting it back.