Sunday, March 6, 2016

Useful PHP Tips Revisited Link Day 3

3. Shortcut the else Link

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.
NOTE FURTHER DETAILS: 
  • PHP TRAINING IN KATHMANDU
  • PHP TRAINING IN LALITPUR
  • 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.

    Saturday, March 5, 2016

    Useful PHP Tips Revisited Link Day 2

    2. Know the Difference Between Comparison Operators Link

    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.';
    }
     
    ?>
    Further more details:
  • PHP TRAINING IN KATHMANDU
  • PHP TRAINING IN LALITPUR
  • Friday, March 4, 2016

    Useful PHP Tips Revisited Link Day 1

    1. Use an SQL Injection Cheat Sheet Link

    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']}'";
     
    ?>

    Further more: 
    PHP TRAINING IN KATHMANDU
    PHP TRAINING IN LALITPUR

    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.

    Thursday, March 3, 2016

    Top 10 PHP Tips for Developers

    I have always wanted to write an article like this, because I think about it all the time - what 10 things would I deem the most important to pass on to someone else? Well, after literally years of thought I think I have come up with the best list that I can think of. So, without further a do, let's get to it.

  • PHP TRAINING IN KATHMANDU
  • PHP TRAINING IN LALITPUR
  • 1) Go OOP

    If you have not yet entered the realm of Object Oriented Programming, then you are at a disadvantage, and you are falling behind fast.
    OOP is essentially a method of programming with the use of classes, or Objects, which tie like things together, remove the need for repetition of code and perform the basic tasks of production very simply. Objects are essentially classes that collect a bunch of functions together and wrap them in a wrapper that can be reused over and over again without the need to rewrite functionality or procedures every time you need to do something.
    Procedural Programming works by following a routine from the top to the bottom of each page as the server reads every file on your server. With OOP, there could be one or two objects being instantiated, which, in turn could instantiate a few, a hundred or a thousand other objects which could all perform certain tasks depending on variables passed into the objects. OOP is faster, simpler, easier to debug, uses less server resources, less code, is faster loading and more logical to work with once you figure out the basic principles. Go OOP - It changed my development style forever.

    2) Stay Away from Anything Ending With _once()

    We all know that include() simply gives us a warning if it fails, while require() kills the script with a fatal error when it fails. What we don't forget is that include_once() and require_once() is extremely hard on server resources. There is nothing we can do about it, it's how PHP is set up. Just remember that these things kill your server resources, specially on a huge framework, and if you plan your code properly you won't even need it anyway.

    3) Develop With Error Reporting On

    The very first thing you do when starting a new project is to turn error reporting to E_ALL, and you should only turn it off ten seconds before going to production mode. I do this with every project that I build and there is nothing better than running a project in full production mode and not even getting one error. Besides that, with error reporting on, you pick up any small errors that will eventually grow up to bite you in the... well, you get my point.

    4) Use A Framework If You Need One

    Ok, so Rasmus Lerdorf says you shouldn't use a framework because he could quite conclusively prove that a framework is much slower than normal PHP code when it came to printing a simple "Hello World" application. Two things to mention here though: you are not Rasmus Lerdorf and I bet you won't be building a "Hello World" application every time you program something. Frameworks that help you do the tedious things can help, although you will have to learn how the frameworks function first in order to make things simple, but that's the only real trade-off. Plus you stand less chance of writing bad code when someone else has written most of it for you, but let's pretend I didn't say that.

    5) Use PHP's Inbuilt Functions

    Ok, you want to count the amount of keys in an array? You can loop through the array and simply increment a value for each iteration, right? Or you can just use the built in PHP function count(), which does just what it should. PHP has many built-in functions that can do what you need them to, so check out the manual to make sure you are doing it in the best way possible.

    6) Protect Your Database

    The best and safest way is to use mysql_real_escape_string() for all database before it is added to the database. This function makes all strings safe in terms of quotes and other functions that can harm your database or contain malicious code, so use it to be sure you have taken the first step against protection of your data. Another thing you can do is validate all POST and GET strings, never use $_REQUEST, and make sure all form submitted data is of the right type and value before adding it to a database query.

    7) Use POST Not GET

    Ok, this isn't always possible, but when its really not necessary, don't use GET, use POST. The reason is simple - GET is simple to emulate, all I need to do is add something to my address bar and I can hack your project. Obviously GET is the easy way to do pagination and permalinks, but when using form submission especially, stay with POST, it's safer.

    8) Draw Before You Code

    A good practice to get into is to wireframe your projects, even if you are just scribbling a few notes on a piece of paper. It is very important to actually give the mechanics of you application some thought before sitting down to start coding, because in the process of planning it you will actually iron out the difficulties in your head and avoid the major headache that comes with the facepalm when you realize that everything you just did is either wrong, not needed, or just silly.

    9) Understand Your Project

    An artist cannot draw something that he has not seen before. A singer cannot sing a song that he has not heard before. You cannot code a project that you do not fully understand. If you do not understand exactly what it needs to do, and how it needs to it, you cannot build it.

    10) Code Code Code

    If I could get one thing through to anyone reading this, this is it. You cannot become a good developer by reading. You cannot become a good developer by watching someone develop. The one and only tried and trusted method, is to actually write code. But - and here is the trick - build real things! Do not go and code something that you have no interest in, or will never use. Build what you like, and you will be excited and interested by it, and you will learn. Then, make it awesome, build upon it, and make it better.