Showing posts with label example. Show all posts
Showing posts with label example. Show all posts

Accepting and Displaying User Data Giving Warnings for Links

Saturday, March 28, 2009

There is one final manipulation of user submitted data that is regularly done. If the script allows users to include URLs in their data, the user could make the link say something completely different from where the URL actually goes. This ends up being a blemish on your website. The common solution is to display beside the actual link, the host name that the link refers to. This gives the browser a visual indication whether the link is going where they think it is.

This can be done whether you are allowing HTML to be entered or BBCode. If BBCode, just call the function defined in the following code after it has been converted into HTML. This technique can be useful for other purposes as well, such as scanning HTML data and placing "offsite" links for any external link versus ones to your own website.

<?php
// A function to create warnings on any links:
function warn_links($string) {
    // First, find all the links in the string:
    preg_match_all('|<a\s+href\s*=\s*([\'"])(.*?)\1>|i',
        $string, $results, PREG_OFFSET_CAPTURE | PREG_SET_ORDER);

    // Now, loop over all results, BACKWARDS, to make replacements
    // Backwards so that our offsets don't start changing on us:
    foreach (array_reverse($results) as $r) {
        // [0][1] contains the offset position of the link & [2][0]
        //  contains the URL - So parse the URL to get it's host:
        $parsed = parse_url($r[2][0]);

        // Check the host - if it doesn't exist use this server's hostname:
        $host = isset($parsed['host']) ? $parsed['host'] :
            $_SERVER['HTTP_HOST'];

        // Now insert the 'host' warning:
        $string = substr_replace($string, " [{$host}] ", $r[0][1], 0);
    }

    return $string;
}

// If we had a POST, then output the data for reference:
if (count($_POST)) {
    echo "<p>The data, with link warnings:</p>\n";
    echo warn_links($_POST['data']);
}
?>
<form action="<?= $_SERVER['PHP_SELF'] ?>" method="post" name="f1">
<p>Enter some data:</p>
<p><textarea name="data" cols="80"
    rows="10"><?= @$_POST['data'] ?></textarea></p>
<p><input type="submit" /></p>
</form>


Hope it helps.

Forcing a User to Use SSL-Encrypted Pages

Friday, March 27, 2009

Here is a simple function to see if a user is connecting via SSL or not:

<?php
function is_SSL() {
    /* Checks to see whether the page is in secure mode */
    if ($_SERVER['SERVER_PORT'] == "443") { 
        return true;
    } else {
        return false;
    }
}
?>


This function works by checking the port through which the client connected to the server (SSL is port 443). If the access is not secure and it should be, you can use $_SERVER['PHP_SELF'] and the header() function to redirect to a secure version of the page.

Detailed Backtracing for Error Reporting in PHP

Thursday, March 26, 2009

It can be useful to have detailed error messages when you are trying to debug code. This can be used to display detailed messages to the screen when in your development environment.

Here's the code

<?php
// Define a custom error handler for more details
function detailed_err($errno, $errstr, $errfile, $errline, $errcontext) {
    // First of all, begin by noting that a fatal error occurred, and basic
    // details just like a normal error report:
    echo "<p>FATAL ERROR - {$errstr}</p>\n";

    // Now use debug_print_backtrace to give the function call list in
    // a compressed format easy for quick scanning:
    echo "<pre>\nFunction Call Tree:\n";
    debug_print_backtrace();

    // To finish off our 'extreme' debugging mode here, let's also give
    // a full backtrace dump, which will contain all variables that existed
    // and much much more.
    echo "\nFull Backtrace:\n";
    var_dump(debug_backtrace());

    // Close off that pre tag
    echo "</pre>\n";

    // That's it, time to make sure the script dies:
    die();
}

// Now go ahead and register this as the error handler:
set_error_handler('detailed_err', E_ERROR | E_USER_ERROR);
?>


This example makes full use of debug_bracktrace(), which gives you a full list (as an array) of all currently open function calls, variables, line numbers, and more. It also uses debug_print_backtrace(), which gives a smaller, simpler output to the backtrace to make it easier to just see the heart of the problem. Combined, this makes for as much detail as you could really care to have.

Of course, you would certainly want to make sure that this is enabled only on your development environment. You would not want this level of detail about your system to be displayed to the end user. However, you could modify this on your production server so that instead of outputting all this to the screen, it could send it as an email to you instead. That way if a fatal error happens on the website, you will be instantly notified and have all the information possible to go and debug it.

Hop it helps.

Making RSS Display Example

Sunday, March 22, 2009

RSS feeds are often used in nontraditional ways. Web browsers have various ways of displaying RSS feeds, separate RSS software exists to read them, and even email clients are starting to display the output of the RSS.

With all this, though, one thing is often overlooked: simply reading in the RSS feed from another website and displaying it on your own website. The followong code creates a basic function that reads in a remote RSS feed, specified by a URL, and generates an HTML definition list from it, making the title a link and including the description. It also includes the title of the feed as a paragraph first.

If you want to use this in a live web page, you can wrap it inside a <div> tag to control/apply additional formatting.

<?php
// Create a function that will turn an RSS feed, into a definition list:
function rss_dl($url) {
    // Begin by loading the RSS feed into SimpleXML:
    $rss = simplexml_load_file($url);

    // Ok, output the title of the feed just as a paragraph block.  People
    // can use stylesheets later to make it look as they wish:
    echo <<<EOSNIPPET
<p>
  <a href="{$rss->channel->link}">{$rss->channel->title}</a>
</p>
EOSNIPPET;

    // Now begin our definition list:
    echo "<dl>\n";

    // Loop through all items to make definition entries from them
    foreach ($rss->channel->item as $i) {
        // The title with link:
        echo "<dt><a href=\"{$i->link}\">{$i->title}</a></dt>\n";

        // The description as the dd
        echo "<dd>{$i->description}</dd>\n";
    }

    // End our list now, we are done
    echo "</dl>\n";
}

// Test this out:
rss_dl('http://acorn.atlantia.sca.org/calendar.xml');

// And try it again:
echo "<br /><br /><br />\n";
rss_dl('http://rss.cnn.com/rss/cnn_topstories.rss');
?>


Hope it helps.

Example Recursive Function in PHP

Thursday, March 5, 2009

A recursive function is defined simply as a function that calls itself. (Also falling under the definition would be any group of functions that loop among themselves, such as function A calling function B, which in turn calls A.) PHP supports recursive functions, and they are often an elegant solution instead of a lengthy, deep, set of static instructions. Let's look at a simple comparison of two functions that do the same thing, one written recursively, and the other not.

Recursive function example

<?php
function sum_up_to($number) {
    $result = 0;
    for ($i = 1; $i <= $number; $i++) {
        $result += $i;
    }
    return $result;
}

// The same function, written as a recursive function
function sum_up_recursive($number) {
    return ($number) ? ($number + sum_up_recursive($number - 1)) : 0;
}

// Try this in both cases, with the number 42, which should return: 903
echo 'Regular version = ', sum_up_to(42), "\n";
echo 'Recursive version = ', sum_up_recursive(42), "\n";
?>


Notice how even in this simple example of adding numbers, the code for the recursive version is much shorter and simpler. The only extra effort that must always go into recursive functions is ensuring that they exit. It is easy to write a function that will run forever. In this case, we are using the recursive function to count down, so we need to detect when we are at zero and return zero, ending the recursion.

When writing recursive functions, keep in mind two issues. The first issue is execution time.By default, PHP restricts the execution time of any script. This helps ensure that a script does not lock up a web server. Hence, you should make sure that any recursion will complete within the allotted time or modify the limit using set_time_limit().

The second issue is resources. With each call to a function, memory is allocated for all arguments passed by value and for all local variables created in a function. This memory is released on exit of that function call. Normally, this is not an issue because a function is called, does its job, and then exits. However, when a function is called recursively, this normal pattern is interrupted. When a function is called recursively, each call consumes whatever memory is needed until the recursion finally ends, when each recursive call starts returning. Normally this is not an issue. However, it is good practice to ensure that recursive functions do not create large arrays or use other "consumable" resources, such as opening files.

Finding how to end your recursion properly is the most important skill to learn in this regard. Hope it helps.

PHP: Generating Random Passwords Example

Sunday, March 1, 2009

Sometimes security dictates that users may not be allowed to choose their own passwords. In these cases you need some way to quickly generate them. Even if you do not have a requirement for random passwords, you will still often need to generate initial passwords for users, or use them when someone has lost his password and needs a new temporary one.

The following code gives an example of a function that lets you specify an arbitrary length of characters, and it generates a random password for you containing only lowercase letters, uppercase letters, and numbers.

<?php
// A function that accepts a parameter to specify a length, and then returns
// a random password with characters and letters
function random_password($length = 8) {
    // Declare a blank string to start from
    $pass = '';

    // Now loop for as many times as the length
    for ($i = 0; $i < $length; $i++) {
        // For this character, first give an equal chance of upper,lower,num
        switch (rand(0,2)) {
            case 0:
                // Generate a Number from 0 to 9
                $pass .= rand(0,9);
                break;
            case 1:
                // Generate a letter from A to Z via ascii values 65 to 90
                $pass .= chr(rand(65,90));
                break;
            default:
                // Instead use a letter from a to z, via ascii 97 to 122
                $pass .= chr(rand(97,122));
        }
    }

    // Return that password!
    return $pass;
}

// Test this, echo out a batch of 10 passwords, from 1 to 10 characters long
echo "<ol>\n";
foreach (range(1,10) as $l) {
    $tmp = random_password($l);
    echo "<li>{$tmp}</li>\n";
}
echo "</ol>\n";
?>


At the heart of this code is a switch statement that gives a random one-in-three chance of each character being lowercase, uppercase, or a number. It then randomly picks the appropriate type of character via generating ASCII values and converting them with chr(). By first randomly choosing which of the three types is used, we evenly distribute them throughout. Otherwise, because there are more letters than digits, digits would rarely appear.

Hope it helps.

Submitting a POST HTTP Request with cURL

Thursday, February 26, 2009

This may happen when in the middle of a PHP script you need to send data to another server and retrieve the response. This case is often when dealing with a third-party vendor, such as a payment company, data provider, and so on. Accomplishing this is easy to do with GET strings because you can just generate the string needed by hand and call it via file_get_contents() as a URL. (Or even using http_build_query() to help you create your data request.)

However, the situation is not as simple when you need to do a POST. POST commands go to a regular URL, but the data is sent separately as part of the request headers. The regular PHP URL wrappers cannot handle this. Therefore it is easiest to use the PHP cURL extension, which allows for complex interactions with Internet protocols.

Note
It is also possible to handle POST arguments via directly connecting to the server with sockets or an fopen() command and sending the POST data manually.

The following code shows a function that handles doing a POST for you, just by passing it the URL to contact, as well as the POST data. The POST data should be in the same format that http_build_query() produces, and therefore, we will make sure to use it.

<?php
// Create a function to handle the posting of data
function http_post($url, $post) {
 $c = curl_init();
 curl_setopt($c, CURLOPT_URL, $url);

 curl_setopt($c, CURLOPT_POST, true);
 curl_setopt($c, CURLOPT_POSTFIELDS, $post);

 curl_setopt ($c, CURLOPT_RETURNTRANSFER, true);
 return curl_exec($c);
}
$fields = array('data' => 'John Doe', 'idx' => 11321);

echo http_post('http://example.com/script.php', http_build_query($fields));
?>


cURL can handle many advanced Internet protocols and is extremely powerful. This is just a small taste of what it can do. To discover more, read the documentation at http://php.net/curl.

Note
cURL support in PHP relies on the libcurl library, which must be obtained and compiled into PHP, as well as enabling the extension, which does not exist by default either. More information on how to accomplish these tasks is available in the PHP documentation at http://php.net/curl.

PHP: Basic Web Server Example

Wednesday, February 25, 2009

Now, we will create a web server in PHP, serving only GET requests and basic file types. Given that it will be written in PHP, however, we will add an easy feature: Every file served through this web server will be treated as PHP and parsed for commands. After all, why else would you write a web server in PHP except to run PHP in it?

To make this web server, we'll start by creating our service on a specific port and IP address. It will be set to the local loopback address 127.0.0.1 and port 8088 to not conflict with any other web server on the same machine. We then listen for connections. To handle more than one client connection at a time, when a connection comes in, we will launch a new process using pcntl_fork(). This creates a new process that can handle the request and return the data, leaving the parent/server process to immediately be ready to accept another connection.

This setup will not scale well; someone could easily bring down your machine by rapidly connecting to the machine, causing you to spawn thousands of processes. If this server was ever put into production, it would at the very least need to have a limiting factor built into it, keeping the number of processes to a certain maximum. Of course, after that there are many other issues with this basic web server in terms of performance, features, and so on. However, it gives a good overview of how to write an Internet server.

<?php
$port = 8088;
$host = '127.0.0.1';
$docroot = '/html';

set_time_limit(0);

if (!($server = stream_socket_server("tcp://{$host}:{$port}",
        $err_num, $err_string))) {
    exit("ERROR: Failed to Open Server - {$err_num} - {$err_string}\n");
}


for (;;) {
    $client = stream_socket_accept($server, -1);

    if ($client) {
        $pid = pcntl_fork();

        if ($pid == -1) {
            exit("ERROR: Could not create new process!");
        }
        elseif (!$pid) {
            $command = fgets($client, 2048);

            while($line = fgets($client, 2048)) {
                if (trim($line) === '') { break; }
            }

            $request = explode(' ', $command);

            if ($request[0] != 'GET') {
                @fwrite($client, 
"HTTP/0.9 501 Not Implemented Server: Bare-Basic-PHP-WebServer Content-Type: text/html
<html><head><title>501 Not Implemented</title></head>
<body><h1>501 Not Implemented</h1>
<p>This is a very basic web server that only implements GET</p>
</body></html>");
                fclose($client);
                exit();
            }
            $parts = explode('?', $request[1]);
            if ($parts[0]{strlen($parts[0])-1} == '/') {
                $parts[0] .= 'index.php';
            }
            if (!is_file($docroot . $parts[0])) {
                @fwrite($client,
"HTTP/0.9 404 Not Found
Server: Bare-Basic-PHP-WebServer
Content-Type: text/html

<html><head><title>404 Not Found</title></head>
<body><h1>404 Not Found</h1>
<p>We looked, but the file you requested was nowhere to be found!</p>
</body></html>");
                fclose($client);
                exit();
            }

            $path = pathinfo($parts[0]);
            switch ($path['extension']) {
                case 'gif':
                case 'png':
                case 'jpg':
                    $mime = "image/{$path['extension']}";
                    break;
                case 'html':
                case 'xml':
                case 'css':
                    $mime = "text/{$path['extension']}";
                    break;
                case 'js':
                    $mime = 'application/x-javascript';
                    break;
                case 'php':
                    $mime = 'text/html';
                    break;
                default:
                    $mime = 'application/octet-stream';
            }

            if (isset($parts[1])) {
                parse_str($parts[1], $_GET);
            }

            ob_start();
            include "{$docroot}{$parts[0]}";
            $output = ob_get_contents();
            ob_end_clean();

            $length = strlen($output);
            @fwrite($client,
"HTTP/0.9 200 Ok
Server: Bare-Basic-PHP-WebServer
Content-Type: {$mime}
Content-Length: {$length}

{$output}");

            fclose($client);
            exit();
        }
    }
    @fclose($client);
}
?>


Note that this program as designed will run forever and will need to be manually killed off. When calling pcntl_fork(), your process splits into two identical copies with only a slight difference. In the parent, the call to pcntl_fork() returns the process id of the child. In the child, it returns 0. This allows you to then run different code depending on whether the current process is the parent or the child of the fork.

Caution
The pcntl (process control) functions of PHP are not available on Windows, because Windows has a different process model than UNIX. Also, even on UNIX they are not compiled into the server by default and must be specifically included upon compilation. To learn more about these functions and how to enable them, visit http://php.net/pcntl.

Hope it helps.

PHP: Example Using Sockets to Connect to an Internet Server

Tuesday, February 24, 2009

When you need to talk to an Internet service such as http, ftp, SOAP, and so on, you will need to directly access this service via TCP or UDP sockets. This is a raw connection to another server, and you must know the details of the protocol you will be dealing with to properly send commands and receive data from them.

PHP provides a number of ways to talk with Internet servers, including a fsockopen() function and an entire BSD sockets extension that can be used. However, as of PHP 5, the streams extension has been greatly enhanced and is the preferred way to talk with Internet servers because it is highly configurable and powerful.

The following code is a small application that uses stream_socket_client() to connect to the free Internet Time Service provided by NIST. The time service works as follows: A TCP connection is made to port 13 on one of the NIST servers. When a connection is successfully created, the server immediately sends the response back with the current time.

<?php
if (!($tp = stream_socket_client('tcp://time.nist.gov:13', $err, $str))) {
    exit("ERROR: Failed to connect - {$err} - {$str}\n");

    exit("ERROR: Failed to connect - {$err_num} - {$err_string}\n");
}

fgets($tp);

echo trim(fgets($tp));

fclose($tp);
?>
To find out more information about the stream functions, see http://php.net/stream.

Hope it helps.

PHP: Communicating with an LDAP Server Example

Monday, February 23, 2009

LDAP(Lightweight Directory Access Protocol) is used to talk with directory services for retrieving and modifying data. It is not a relational database system. LDAP is simply a system that provides a hierarchical organization of data. LDAP's most common use currently is for corporate address and email books, allowing for all information about each employee to be stored and retrieved as needed.

PHP provides commands to communicate to an LDAP server that are easy to use. A typical set of commands would be to connect to the server, bind (authenticate), search for some data, and then handle the data. The only problem is that the structure of each LDAP server is completely different based on how the administrator set it up, just like every database system is different. Therefore, you must understand the structure of the tree hierarchy of that LDAP server to work with it.

In the following code, we connect to a fictional LDAP server that just has three levels of hierarchy with the top one being c = Country Code, then under that o = Organization, and then below that un = User Name. (Nominally, of course, there would be more information beneath that level; however, this is all we need for our example.)

<?php
if (!($lc = ldap_connect('ldap.example.com'))) {
    die("ERROR: Can't connect to the LDAP server\n");
}

//Anonymous bind (read only access)
ldap_bind($lc);

// Search for anyone in the IT department
// with a username starting with 'e'
$res = ldap_search($lc, 'o=Information Technology, c=US', 'un=e*');

// Now, let's read all results from our search:
$data = ldap_get_entries($lc, $res);

// Loop over them all, echoing the data out:
for ($i=0; $i < $data['count']; $i++) {
    echo "Full entry (distinguished name - dn): {$data[$i]['dn']}
\n"; echo "Username: {$data[$i]['un'][0]}
\n"; } ?>


Like many other extensions of the language, LDAP support must be compiled into the server (or enabled on Windows) before you can use it. Also, we have only scratched the surface of what the full LDAP extension can do. To explore more, read the documentation at http://php.net/ldap.

Hope it helps.

PHP: Automatically Creating and Updating PHP Include Files

Sunday, February 22, 2009

There are times when you have some configuration data that your script needs to access, and the easiest way to store and use that is of course to just place it in a PHP file and include it. That way it is just part of your program, and the data is immediately ready to access.

Normally, this would involve you having to update that configuration file by hand whenever anything changes. This does not need to be the case, however, because PHP provides a function called var_export() that turns any PHP variable back into valid PHP code. Therefore by applying this you could update your configuration data, saving it back to the file. You could even use this to store other forms of data as a quick and easy method as shown in following example

<?php
// Include our file:
$data = array();
@include 'config.php';

// If we were asked to make changes, then do so:
if (count($_POST)) {
    // Just update/add the value to the 'data' array
    $data[$_POST['name']] = $_POST['val'];

    // Now save it to disk, create the 'full' file wrapping it in valid PHP
    $file = "\n";
    file_put_contents('config.php', $file, LOCK_EX);
}

// Echo out the current data
echo "<pre>Current Data is:\n\n";
print_r($data);
echo "</pre>\n";
?>
<form action="<?= $_SERVER['PHP_SELF'] ?>" method="post" name="myform">
<p>Key: <input type="text" name="name" value="" /></p>
<p>Value: <input type="text" name="val" value="" /></p>
<input value="Save Data" type="submit" />
</form>


This is very simplistic and only inserts single-dimensional strings. However, you can see the basic concept. Any PHP data can be re-created/stored in this manner, allowing for PHP files that "rewrite themselves" and all the power (and danger) that comes with that.

Hope it helps.

PHP: Creating a PHP-Based FTP Client Example

Saturday, February 21, 2009

The best way to accomplish tasks like getting directory listings, making directories, deleting files, putting multiple files at once on FTP in PHP is to use the FTP extension that is built into it. (Note that the FTP extension is enabled by default in Windows builds of PHP but must be specifically compiled into other versions.)

The following script is designed to be run from the command line, using the command-line version of PHP to execute it instead of through a web server.

<?php
$stdin = fopen('php://stdin', 'r');
$server = false;
$mode = FTP_ASCII;
$commands = array('open', 'close', 'quit', 'exit', 'cd', 'ls', 'dir',
    'pwd', 'get', 'put', 'ascii', 'binary', 'bin', 'delete', 'del');

if ($argc > 1) {
    // Remove the filename from the line
    array_shift($argv);
    // Now call the open function to handle this:
    _open($argv);
}

while (true) {
    echo 'phpftp> ';

    $line = trim(fgets($stdin));

    if ($line) {
        // Split the line into an array of space separated entries:
        $opts = explode(' ', $line);
        $cmd = strtolower(array_shift($opts));

        if (!in_array($cmd, $commands)) {
            echo "! Command not supported.\n";
        }
        // If server is false, only allow 'open'
        elseif (($server xor ($cmd != 'open')) && ($cmd != 'quit') && ($cmd != 'exit')) {
            echo "! Invalid server status for this command.\n";
        } else {
            // Otherwise, execute whatever command they gave 
            $func = "_{$cmd}";
            $func($opts);
        }
    }
}


// Open a connection:
function _open($opts) {
    global $server, $stdin;

    if (!isset($opts[0])) {
        echo '? Host: ';
        $opts[0] = trim(fgets($stdin));
    }


    if (!isset($opts[1])) {
        echo '? User: ';
        $opts[1] = trim(fgets($stdin));
    }


    if (!isset($opts[2])) {
        echo '? Pass: ';
        $opts[2] = trim(fgets($stdin));
    }


    if (!($server = @ftp_connect($opts[0]))) {
        echo "! Error, cannot connect to host!\n";
        $server = false;
    } else {
        if (!(@ftp_login($server, $opts[1], $opts[2]))) {
            echo "! Error, Username/Password not accepted!\n";
            ftp_close($server);
            $server = false;
        } else {

            echo "- Connected to {$opts[0]}\n";

            if ($type = ftp_systype($server)) {
                echo "- Server type: {$type}\n";
            }

            _ascii(0);
            _pwd(0);
        }
    }
}

// Close a connection:
function _close($opts) {
    @ftp_close($GLOBALS['server']);
    $GLOBALS['server'] = false;
    echo "- Connection Closed.\n";
}

// Change directories
function _cd($opts) {
    if (!(@ftp_chdir($GLOBALS['server'], @$opts[0]))) {
        echo "! Error, Failed to change directory\n";
    }
    _pwd(0);
}

// Quit the program!
function _exit($opts) {
    if ($GLOBALS['server']) {
        _close(0);
    }
    echo "- Goodbye!\n";
    exit();
}
function _quit($opts) {
    _exit($opts);
}

// To get a directory listing:
function _ls($opts) {
    $optstring = implode(' ', $opts);
    if ($res = ftp_rawlist($GLOBALS['server'], $optstring)) {
        foreach ($res as $r) { echo "{$r}\n"; }
    } else {
        echo "! Error, could not generate directory listing\n";
    }
}
function _dir($opts) {
    _ls($opts);
}

// Figure out what directory you are in:
function _pwd($opts) {
    $cwd = ftp_pwd($GLOBALS['server']);
    echo "- Current directory: {$cwd}\n";
}

// Get a file from the remote host, and save it locally.
function _get($opts) {
    // If we don't have any options, give an error
    if (!($opts)) {
        echo "! Error, no file specified\n";
    } else {
        // If we don't have a second option, assume a desire to
        // save the file into the current directory, with the same name
        if (!isset($opts[1])) {
            $opts[1] = basename($opts[0]);
        }

        // Now, attempt to save the file.
        if (!@ftp_get($GLOBALS['server'], $opts[1], $opts[0],
                $GLOBALS['mode'])) {
            echo "! Error - Could not download file\n";
        } else {
            echo "- Data saved to file: {$opts[1]}\n";
        }
    }
}

// Put a local file to the remote host:
function _put($opts) {
    if (!($opts)) {
        echo "! Error, no file specified\n";
    } else {
        if (!isset($opts[1])) {
            $opts[1] = basename($opts[0]);
        }

        if (!@ftp_put($GLOBALS['server'], $opts[1], $opts[0],
                $GLOBALS['mode'])) {
            echo "! Error - Could not upload file\n";
        } else {
            echo "- Data uploaded to file: {$opts[1]}\n";
        }
    }
}

// To Change the transfer mode to ASCII
function _ascii($opts) {
    $GLOBALS['mode'] = FTP_ASCII;
    echo "- Transfer mode: ASCII\n";
}

// Change the transfer mode to Binary
function _binary($opts) {
    $GLOBALS['mode'] = FTP_BINARY;
    echo "- Transfer mode: Binary\n";
}
function _bin($opts) {
    _binary($opts);
}

// Allow for deleting of files
function _delete($opts) {
    if (!($opts)) {
        echo "! Error, no file specified\n";
    } else {
        if (!@ftp_delete($GLOBALS['server'], $opts[0])) {
            echo "! Error - Could not delete file\n";
        } else {
            echo "- File Deleted: {$opts[0]}\n";
        }
    }
}
function _del($opts) {
    _delete($opts);
}
?>


To accomplish the task of creating a fully functional (though basic) FTP client in PHP, start by beginning to converse with the operating system's input by opening php://stdin. This is the equivalent in other languages of reading from stdin, and is how you accept input from the user. It then enters a loop waiting for input and doing some basic sanity checks on the command it was given, and then proceeds to perform the task requested of it.

It creates a set of its own internal functions to map to the various commands and is almost a direct one-for-one mapping for the functions provided in the FTP extension. The only difference is that the client does some extra error checking to give useful responses back to the user. Of note about the code itself: The use of a variable to hold function names, as discussed in Chapter 6, "Functions," is implemented.

In the end this creates a functional FTP client that has been written completely in PHP. It is missing some more advanced features, and even some basic ones (such as the creation and removal of directories), but gives a fairly complete example of how powerful the FTP extension for PHP is.

Hope it helps.

PHP: Connecting to an FTP Server Example

Friday, February 20, 2009

There are many ways to connect to an FTP server in PHP. One is using the cURL package, which not only handles the POST submissions talked about there but can do FTP as well. Another, is with the specific FTP extension that exists in PHP. However, the easiest way to connect to an FTP server, is to use PHP's basic file commands, such as file_get_contents() and file_put_contents(), and pass them a fully qualified ftp URL, just like would be used in a web browser. The format of this is as follows:

 ftp://user:password@example.com/directory/file.ext


where, of course, you replace the user and password with the ones that you need for your situation (or leave them off for anonymous access), replace example.com with the host you are connecting do, and then similarly change the directories and filename. This makes putting or receiving a file a simple one-line operation in PHP as shown below
<?php
 file_put_contents('ftp://user:pass@example.com/mydata.txt','Hi FTP!');
 $data = file_get_contents('ftp://user:pass@example.com/storage.txt');
 echo $data;
?>


Hope it helps.

PHP HTTP Authentication

Tuesday, February 17, 2009

HTTP authentication is the same method used by server-controlled access. The HTTP protocol specifies a method for requesting access information through WWW-Authenticate header request. When browser receives WWW-Authenticate header, it will display a dialog box requesting username andd password. PHP provides some global variables in the $_SERVER superglobal array as follows:

  • PHP_AUTH_USER contains the value of username field
  • PHP_AUTH_PW contains the value of password field
  • PHP_AUTH_TYPE either Basic or Digest, contains the type of authorization being used
Here's an example of a PHP script that presents HTTP username/password dialog box and then validates the given values.
<?php
if (!isset($_SERVER['PHP_AUTH_USER']) ||
        $_SERVER['PHP_AUTH_USER'] != 'username' ||
        $_SERVER['PHP_AUTH_PW'] != 'password' ) {
    //on failed
    header('WWW-Authenticate: Basic realm="For Your Eyes Only"');
    header('HTTP/1.0 401 Unauthorized');
    echo '<h1>401 Unauthorized!</h1><strong>Forbidden</strong>';
    exit;
}

//on success
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
                "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title>Authentication Test</title>
</head>
<body>
<h2>Hello <?= $_SERVER['PHP_AUTH_USER'] ?>:</h2>
<p>You entered <?= $_SERVER['PHP_AUTH_PW'] ?> as your password!</p>
</body></html>


Hope it helps.

PHP Simple CAPTCHA Example

Thursday, February 12, 2009

CAPTCHA stands for Completely Automated Public Turing Test to tell Computers and Humans Apart. It is mainly used to stop computer programs from submitting form on a web page automatically, sending automated email, and other tasks. Although the term can refer to a wide variety of methods like autio bites, riddles, etc, the typical method used by many applications is interpretation of a graphic, a graphic that contains text in it that has been altered/distorted/obscured in ways that should make it difficult for OCR proframs to actually try to parse the data out of the graphic, yet, uhman can still read it.

Many different types of distortions can be done like bending the text, rotating it, putting dots, lines, and so on. Here's an example of PHP with GD library to generate CAPTCHA graphic.

<?php
$w = 300;
$h = 50;
$gfx = imagecreatetruecolor($w, $h);

imageantialias($gfx, true);

$white = imagecolorallocate($gfx, 255, 255, 255);
imagefilledrectangle($gfx, 0, 0, $w-1, $h-1, $white);

$str = '';
foreach (range(0, rand(5,7)) as $r) {
    $str .= chr(rand(65,90));
}

$pos = $w / strlen($str);

foreach(range(0, strlen($str) - 1) as $s) {
    $shade = rand(0, 100);
    $tmpgray = imagecolorallocate($gfx, $shade, $shade, $shade);
    imagettftext($gfx,     
        rand($h/3, $h/2), 
        rand(-60, 60),     
        $s*$pos+($pos*.4), 
        rand($h*.5,$h*.7), 
        $tmpgray,         
        'arial',           
        $str{$s});         
}

foreach(range(-$h, $w, 5) as $x) {
    $shade = rand(50,254);
    $tmpgray = imagecolorallocate($gfx, $shade, $shade, $shade);
    imageline($gfx, $x, 0, $x+$h+rand(0,25), $h-1, $tmpgray);
    imageline($gfx, $x, $h-1, $x+$h+rand(0,25), 0, $tmpgray);
}

session_start();
$_SESSION['captcha'] = $str;
header('Content-type: image/png');
imagepng($gfx);
?>


Save the script as captcha.php. And here's the example of how to use it on a web page
<?php
session_start();
if (count($_POST)) {
   if (isset($_SESSION['captcha'])) {
        if ($_SESSION['captcha'] === strtoupper($_POST['check'])) {
            //on success
     unset($_SESSION['captcha']);
            echo "Congratulations, you typed it in correctly!";
        } else {
            //on failed
            echo "Sorry, that wasn't it, try again!";
        }
    } else {
   //on same session
        echo "Sorry, no spamming aloud!";
    }
}
?>
<form action="<?= $_SERVER['PHP_SELF'] ?>" method="post">
Please enter the text that you see in the following graphic:<br />
<img src="captcha.php" /><br />
<input name="check" type="text"><br />
<input name="Submit" type="submit">
</form>


Remember, after you have validated a user, you MUST destroy the session variable that held the CAPTCHA key. If you don't do this, it is possible for a user to submit the same form many times through a variation on session hijacking, providing the same session id and the same text that matches the key. Because the key wasn't destroyed, this will work and will continue to work until that session expires. Therefore, always destroy the key as soon as possible.

Hope it helps.

PHP: Encrypting Session Data

Wednesday, February 11, 2009

Usually, encrypting session data is not necessary, however, if te data that you store in sessions is sensisitive, or you're questioning the security in your database, here's an example on how to do it.

The idea is simple, you'll just have to modify your functions that store and retrieve data to encrypt and decrypt the data.$sess_db is the database sesion.

<?php
 function get_sess_data($id)
    {
      global $_sess_db;

      $algorithm = MCRYPT_BLOWFISH;
      $mode = MCRYPT_MODE_CBC;

      $id = mysql_real_escape_string($id);

      $sql = "SELECT data FROM sessions
              WHERE  id = '$id'";

      if ($result = mysql_query($sql, $_sess_db))
      {
          $record = mysql_fetch_assoc($result);
          $data = base64_decode($record['data']);
          $iv_size = mcrypt_get_iv_size($algorithm, $mode);
          $ciphertext = substr($data, $iv_size);
          $iv = substr($data, 0, $iv_size);
          $crypt = new crypt();
          $crypt->iv = $iv;
          $crypt->ciphertext = $ciphertext;
          $crypt->decrypt();
          return $crypt->cleartext;
      }
      return '';
    }

    function _write($id, $data)
    {
      global $_sess_db;
      $access = time();
      $crypt = new crypt();
      $crypt->cleartext = $data;
      $crypt->generate_iv();
      $crypt->encrypt();
      $ciphertext = $crypt->ciphertext;
      $iv = $crypt->iv;
      $data = base64_encode($iv . $ciphertext);
      $id = mysql_real_escape_string($id);
      $access = mysql_real_escape_string($access);
      $data = mysql_real_escape_string($data);
      $sql = "REPLACE INTO  sessions
              VALUES ('$id', '$access', '$data')";
      return mysql_query($sql, $_sess_db);
     }
?>


Hope it helps.

Request Data from Amazon.com Using PHP and SOAP

Tuesday, February 10, 2009

Though the letter S on SOAP stands for 'Simple', SOAP is far from simple. The idea is to place all input and output detail of a web service into Web Services Description Language(WSDL) document, making it easy for programmer to generate programming interface and call a web service just like creating method or function. No more mess around wit cURL, building queries, or any of that stuff, just create your requested object, make an interface with PHP, call the method, and you get an object containing what you need. As easy as that.

PHP5 has a collection of built-in SOAP classes, including SoapClient class that will be used often. But typically, classes aren't built by default, you need to include the --enable-soap parameter whenconfiguring and building PHP5.

Here's an example based on Amazon's web service that offers to help you sell its good from your website. Just apply for an access key ID, and you can access it for free. See below

<?php
 $sClient = new SoapClient('http://webservices.amazon.com/AWSECommerceService/
AWSECommerceService.wsdl');


Now, set up an object for the request you want to send.
 $search->AWSAccessKeyId = "yourKeyId";
 $search->Request->SearchIndex = "Music";
 $search->Request->Keywords = "Van Halen";


To perform search, run itemSearch() method.
$result = $sClient->itemSearch($search);

If everything goes well, the XML results will appear ini $result. Here's how to access this object
foreach ($result->Items->Item as $item) {
    $attributes = $item->ItemAttributes;
    if (is_array($attributes->Artist)) {
        $artist = implode($attributes->Artist, ", ");
    } else {
        $artist = $attributes->Artist;
    }
    echo "artist: $artist; title: $attributes->Title
"; } ?>


Hope it helps.