The following post is meant to show a simple programming paradigm. This mechanism is kept as simple as possible and it is heavily influenced by the design decisions introduced in the modern Unix/Linux command shell but it works primary on the Web. The idea is to escape the complexity of the modern Web Application development world and dive into the world of Web Utilities. In this post I will show you how.

Anyone who has been involved with developing Web Applications knows how painful they can get. Even if you switch to Ruby on Rails or any other Web Application development framework, it does not get any easier. The reason for that is because Web Application development practices are not goal-centric but rather design-oriented. It is time to break/escape from the Web Application development dogma and breath air from the free world.

How can we build goal-oriented applications? For start, we have to look at things that are already working that way. The Unix (Bash, CSH, etc) is build around the principles to solve simple problems by applying simple scripts which can be very rapidly coded on the fly, a.k.a utilities. This seems exactly what we are looking for. By combining what we have learned from the SAS (Software as a Service) world with the power of shell scripts, we come up with a different model which could work better. Let’s see how. The following code is what will help us to get the initial base. It is written in PHP because the language is widely supported and it has very short learning curve. So, let’s see what it does.

<?php
#
# VERSION
#
define('EXPORT_VERSION', '1.0');
define('EXPORT_AUTHOR', 'Petko D. Petkov; pdp');

#
# PARAMETERS
#
$_PARAMS = array_merge($_GET, $_POST);

#
# HELPERS
#
function is_assoc($php_val) {
        return is_array($php_val) && array_keys($php_val) !== range(0, sizeof($php_val) - 1);
}

function to_json($php_val) {
        if (is_assoc($php_val)) {
                $tmp = array();

                foreach ($php_val as $key => $val) {
                        $tmp[] = to_json($key).':'.to_json($val);
                }

                return '{'.join($tmp, ',').'}';
        } else if (is_array($php_val)) {
                        $tmp = array();

                        foreach ($php_val as $val) {
                                $tmp[] = to_json($val);
                        }

                        return '['.join($tmp, ',').']';
        } else if (is_object($php_val)) {
                return to_json(get_object_vars($php_val));
        } else if (is_string($php_val)) {
                return "'".str_replace(array("\b", "\t", "\n", "\f", "\r", "'"), array('\b', '\t', '\n', '\f', '\r'                                          , "\'"), stripslashes($php_val))."'";
        } else if (is_bool($php_val)){
                return $php_val?'true':'false';
        } else if (!isset($php_val)) {
                return 'undefined';
        } else {
                return $php_val;
        }
}

#
# EXPORTERS
#
function export_raw($php_val) {
        header('Content-type: text/plain');

        echo $php_val;
}

function export_php($php_val) {
        header('Content-type: text/plain');

        print_r($php_val);
}

function export_json($php_val) {
        global $_PARAMS;

        header('Content-type: text/javascript');

        if (isset($_PARAMS['_callback'])) {
                echo $_PARAMS['_callback'].'('.to_json($php_val).');';
        } else {
                echo to_json($php_val);
        }
}

function export_serialized($php_val) {
        header('Content-type: text/plain');

        echo serialize($php_val);
}

#
# EXPORT
#
function export($php_val) {
        global $_PARAMS;

        if (isset($_PARAMS['_output']) && function_exists('export_'.$_PARAMS['_output'])) {
                call_user_func('export_'.$_PARAMS['_output'], $php_val);
        } else {
                call_user_func('export_json', $php_val);
        }
}

It is very simple, isn’t it? The PHP code simply exports a couple of functions, the most important of which is called export. In fact, this is the only one that matters. The rest of the functions are mostly helpers. Also, we should keep in mind another library construct called $_PARAMS. Just like the default $_GET and $_POST, this variable contains user supplied input. However, this input is the combined total of both $_GET and $_POST with $_POST having a higher priority over $_GET. So far, so good, but where are the utilities? The reason we need this library is to make our work around the data delivery process slightly easier. Thing about these functions much like standard built in PHP functions. That will help you to abstract your thought from the traditional ways you used to program on the PHP platform.

The next step is to abstract the library out from the utility scripts. The easiest way to do that is to write a simple .htaccess file or modify the Apache (if you are running PHP on the Apache platform) config file with the following directives. This is a necessary step because we don’t want to deal with the library in any way. We simply want to use it without knowing about its existence. Treat it as the .bashrc file:

<Directory /path/to/utilities>
php_value auto_prepend_file /path/to/export/library.php
</Directory>

It is time to write the first utility script. It is very simple indeed:

<?php

if (isset($_PARAMS['_usage']) || !isset($_PARAMS['message'])) {
  echo 'message=<message>';
  exit;
}

export('message:'.$_PARAMS['message']);

?>

Effectively, this simple utility script is a full blown service just because the export function handles various export formats. We can not only use it as part of the command line via tools such as wget or curl, but we can also use it within Web Application with the help of JavaScript callbacks or even with the XMLHttpRequest object.

The reason why I wrote this article is to show you that simple things does work all the time and they work well. Equipped with this technique you can become truly Web Compatible utility guru. Now you can put an army of these scripts on any server and start mixing and matching them until you get the right result.

Hacking is not a trick. It is a survival instinct.