Location: PHPKode > scripts > pAjax > pajax/class.pAjax.php
<?php

/**
 * pAJAX - AJAX Requests Implementation
 *
 * This class provides an implementation to AJAX Requests, using JavaScript <-> PHP languages
 *
 * @package pAJAX
 *
 * @author Guilherme Blanco <hide@address.com>
 * @copyright Copyright® 2005, PontUKom Corp
 *
 * @access public
 */


/**
 * @global boolean AJAX Module Loaded
 */
if (!defined("CLASS_PAJAX"))
    define("CLASS_PAJAX", 1);

    
// Commom support between PHP versions
$XMLSupport = dirname(__FILE__)."/XMLSupport/xml_domit_include.php";
if (file_exists($XMLSupport)) require_once $XMLSupport;

// Load auxiliar class source
$pAjaxParser = dirname(__FILE__)."/class.pAjaxParser.php";
if (file_exists($pAjaxParser)) require_once $pAjaxParser;

// Removing used variables
unset($XMLSupport, $pAjaxParser);



class pAjax {
    /**
	 * @var array $exportList List of functions/methods that can be accessed
	 * @access private
	 */
    var $exportList = array();
    
    /**
	 * @var boolean $domainProtection Domain Protection Enabled/Disabled
	 * @access private
	 */
    var $domainProtection;

    /**
	 * @var boolean $exportProtection Export Protection Enabled/Disabled
	 * @access private
	 */
    var $exportProtection;


    /**
     * Constructor - Generates an pAjax Object
     *
     * @access public
     * @return object $this pAjax
     */
    function __construct() {
        $this->enableDomainProtection();
        $this->disableExportProtection();
    } // End of Method pAJAX


	/**
     * HandleRequest - Parses requests and redirect to correct calls
     *
     * @access public
     * @param string $charset XML Document charset (Default: UTF-8)
     * @return void
     */
    function handleRequest($charset = "UTF-8") {
        // Retrieving the request method
        $REQUEST_METHOD = strtoupper($_SERVER['REQUEST_METHOD']);

        // Checking if the request is valid
        if (!($REQUEST_METHOD == "POST" || ($REQUEST_METHOD == "GET" && isset($_GET['function']))))
            return;

        // If domain protection is enabled, validate it
        if ($this->domainProtection && !$this->isValidDomain()) {
            trigger_error("Domain is not valid to execute this script", E_USER_ERROR);
            return;
        }

        $data = pAjaxParser::getCallerArguments($charset);
        $func = $data['function'];
        $args = $data['arguments'];

        // If function export list is enabled, validate it
        if ($this->exportProtection && !$this->isValidFunction($func)) {
            trigger_error("Function does not exist in export list", E_USER_ERROR);
            return;
        }

        // Set the custom headers for response
        header("Content-type: text/xml; charset=".$charset);

        if ($REQUEST_METHOD == "GET") {
            header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
            header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
            header("Cache-Control: no-store, no-cache, must-revalidate");
            header("Cache-Control: post-check=0, pre-check=0", false);
            header("Pragma: no-cache");
        }

        // Effectively execute the function/method call
        ob_start();

        echo pAjaxParser::generateXmlResponse($this->execCall($func, $args), $charset);

        ob_end_flush();

        // Terminate the script
        exit;

        // Should never be excuted, but if, throw an error
        trigger_error("Unexpected behavior executing RPC call", E_USER_ERROR);
    }


    /**
	 * ShowJavaScript - Get the Ajax JavaScript Code Part
	 *
	 * @access public
	 * @param $baseDir Path of JavaScript files (Default: "." - same directory)
     * @return void
	 */
    function showJavaScript($baseDir = ".") {
        ob_start();

        echo "<script type=\"text/javascript\" src=\"{$baseDir}/pajax-commom.js\"></script>\n";
        echo "<script type=\"text/javascript\" src=\"{$baseDir}/pajax-parser.js\"></script>\n";
        echo "<script type=\"text/javascript\" src=\"{$baseDir}/pajax-core.js\"></script>\n";

        ob_end_flush();
    }


    /**
	 * ExecCall - Effectively execute the call and get its return
	 *
	 * @access private
	 * @param string $function Function/Method do be called
	 * @param array $arguments Arguments to be passed to the function/method call
     * @return array $data Array containing the function to be called and the arguments
	 */
    function execCall($function, $arguments) {
        if (is_array($arguments) && count($arguments) == 1) {
            $keys = array_keys($arguments);
            $arguments = $arguments[$keys[0]];
        }

        if ($function == "") {
            // [TODO]
        } elseif (strpos($function, ".") === false) {
			// Calling a procedure/function
		   	$result = call_user_func_array($function, $arguments);
		} else {
			// Calling a method inside an object
			$arrObjects = explode(".", $function);
            $numObjects = count($arrObjects) - 1;
            $object = null;

            // Find the object (or sub-object)
            for ($i = 0; $i < $numObjects; $i++) {
                $object = (is_object($object)) ? $object->$arrObjects[$i] : $GLOBALS[$arrObjects[$i]];
            }

            $method = $arrObjects[$numObjects];
            $result = call_user_func_array(array(&$object, $method), $arguments);
		}

		return $result;
    }


    /**
     * IsValidDomain - Checks is the request domain is the same than the server
     *
     * @access private
     * @return boolean Domain valid/not valid
     */
    function isValidDomain() {
        if (isset($_SERVER['HTTP_REFERER'])) {
            if (eregi("(http:\/\/)?([^\/]*)\/(.*)", $_SERVER['HTTP_REFERER'], $matches)) {
                if ($matches[2] == $_SERVER['SERVER_NAME']) return true;
            }
        } elseif (!isset($_SERVER['HTTP_REFERER']) && !$this->exportProtection)
            trigger_error("Invalid Referer. Export protection is disabled, could not continue executing", E_USER_ERROR);

        return false;
    }

    
    /**
     * IsValidFunction - Checks is the function is mapped in export list
     *
     * @access private
     * @param string $function Function/Method to be checked
     * @return boolean Function is valid/not valid
     */
    function isValidFunction($function) {
        // If exist any exportList function, try to find the selected one
        if (count($this->exportList) > 0) {
            foreach ($this->exportList as $k => $v) {
                if ($function == $v) return true;
            }
        }

        return false;
    }
    
    
    /**
     * Export - Map functions/methods that can be accessed
     *
     * @access public
     * @param array|string $function Function/Method that can be called from requests
     * @return void
     */
    function export() {
        // Support: export(string|array [, ...])
        $numArgs = func_num_args();

        for ($i = 0; $i < $numArgs; $i++) {
            $arg = func_get_arg($i);

            // Argument is an array, merge with existent list
            if (is_array($arg))
                $this->exportList = array_merge($this->exportList, $arg);
            //Argument is a string, add it
            else
                $this->exportList[] = $arg;
        }
    }


    /**
     * EnableDomainProtection - Activate Domain Protection
     *
     * @access public
     * @return void
     */
    function enableDomainProtection() { $this->domainProtection = true; }


    /**
     * EnableExportProtection - Activate Export Protection
     *
     * @access public
     * @return void
     */
    function enableExportProtection() { $this->exportProtection = true; }


    /**
     * DisableDomainProtection - Deactivate Domain Protection
     *
     * @access public
     * @return void
     */
    function disableDomainProtection() { $this->domainProtection = false; }


    /**
     * DisableExportProtection - Deactivate Export Protection
     *
     * @access public
     * @return void
     */
    function disableExportProtection() { $this->exportProtection = false; }
}

?>
Return current item: pAjax