GetRemoteURI(); } function sajax_handle_client_request() { Sajax::Sajax()->HandleRequest(); } function sajax_get_common_js() { return Sajax::Sajax()->GetClientJS(); } function sajax_show_common_js() { echo Sajax::Sajax()->GetClientJS(); } function sajax_esc($val) { return Sajax::Sajax()->Escape($val); } function sajax_get_one_stub($func_name) { return Sajax::Sajax()->GetStubJS($func_name); } function sajax_show_one_stub($func_name) { echo Sajax::Sajax()->GetStubJS($func_name); } function sajax_export() { $args = func_get_args(); call_user_func_array(array(Sajax::Sajax(), 'Export'), $args); } function sajax_get_javascript() { return Sajax::Sajax()->GetJS(); } function sajax_show_javascript($renderScriptTag = false) { Sajax::Sajax()->ExportBlockJS(); } /** * Sajax Singleton Implementation. */ final class Sajax { private static $Sajax = null; /** * Additional JavaScript blocks we'll render script include tags for. */ private $Scripts = array(); /** * Additional inline JavaScript blocks to render in HEAD. */ private $ScriptBlocks = array(); /** * Hopefully helpful information to include in responses. */ private $DebugMessages = array(); /** * Construct the Sajax object. */ private function __construct() { $this->Initialize(); } /** * Add a debug message to be included in response. */ public function AddDebugMessage($msg = '') { if(strlen($msg) > 0) $this->DebugMessages[] = $msg; } /** * Used internally to add an export. */ private function AddExport($export) { global $sajax_export_list; $this->AddDebugMessage("Added $export to list of exports."); $sajax_export_list[] = $export; } /** * Add a block of JavaScript to render when the main client script is sent * via ExportBlockJS(). */ public function AddScriptBlock($block) { $this->ScriptBlocks[] = $block; } /** * Add additional externally-referenced JavaScript \n"; $buffer = ob_get_clean(); echo $buffer; $this->ScriptDisplayed = true; } /** * Creates a JavaScript include tag to include the exported script. */ public function ExportIncludeJS() { $uri = $this->GetClientScriptURI(); print "\n\t\t\n"; foreach($this->Scripts as $script) { print "\n\t\t\n"; } } /** * Returns all of the JavaScript stubs for the exported methods. */ public function GetAllStubJS() { global $sajax_export_list; ob_start(); foreach($sajax_export_list as $func_name) { echo $this->GetStubJS($func_name); } return ob_get_clean(); } /** * Renders the main JavasScript content to be used by the client as a string. */ public function GetClientJS() { global $sajax_debug_mode; global $sajax_request_type; global $sajax_remote_uri; global $sajax_failure_redirect; $t = strtoupper($sajax_request_type); if ($t != "" && $t != "GET" && $t != "POST") return "// Invalid type: $t.. \n\n"; ob_start(); ?> // remote scripting library // (c) copyright 2005 modernmethod, inc var sajax_debug_mode = ; var sajax_request_type = ""; var sajax_target_id = ""; var sajax_failure_redirect = ""; function sajax_debug(text) { if (sajax_debug_mode) alert(text); } function sajax_init_object() { sajax_debug("sajax_init_object() called..") var A; var msxmlhttp = new Array( 'Msxml2.XMLHTTP.5.0', 'Msxml2.XMLHTTP.4.0', 'Msxml2.XMLHTTP.3.0', 'Msxml2.XMLHTTP', 'Microsoft.XMLHTTP'); for (var i = 0; i < msxmlhttp.length; i++) { try { A = new ActiveXObject(msxmlhttp[i]); } catch (e) { A = null; } } if(!A && typeof XMLHttpRequest != 'undefined') A = new XMLHttpRequest(); if (!A) sajax_debug('Could not create connection object.'); return A; } var sajax_requests = new Array(); function sajax_cancel() { for (var i = 0; i < sajax_requests.length; i++) sajax_requests[i].abort(); } function sajax_get_classname(obj) { if (obj && obj.constructor && obj.constructor.toString) { var arr = obj.constructor.toString().match( /function\s*(\w+)/); if (arr && arr.length == 2) return arr[1]; } return 0; } function sajax_is_object(o) { var test = sajax_get_classname(o); return (typeof o == 'object' && test != 'Array' ? true : false); } function sajax_do_call(func_name, args) { var i, x, n; var uri; var post_data; var target_id; sajax_debug("in sajax_do_call().." + sajax_request_type + "/" + sajax_target_id); target_id = sajax_target_id; if (typeof(sajax_request_type) == "undefined" || sajax_request_type == "") sajax_request_type = "GET"; if (typeof args == 'object' && args.length > 1) { // Lame attempt at JSON encoding for (var i=0; i 0) arg += ','; with(o[j]) { arg += '"'+escape((name.length == 0 ? '_unknown'+j : name)) +'":"'+o[j].value+'"'; } } arg += '}'; args[i] = arg; } } } uri = ""; if (sajax_request_type == "GET") { if (uri.indexOf("?") == -1) uri += "?rs=" + escape(func_name); else uri += "&rs=" + escape(func_name); uri += "&rst=" + escape(sajax_target_id); uri += "&rsrnd=" + new Date().getTime(); for (i = 0; i < args.length-1; i++) uri += "&rsargs[]=" + escape(args[i]); post_data = null; } else if (sajax_request_type == "POST") { post_data = "rs=" + escape(func_name); post_data += "&rst=" + escape(sajax_target_id); post_data += "&rsrnd=" + new Date().getTime(); for (i = 0; i < args.length-1; i++) post_data = post_data + "&rsargs[]=" + escape(args[i]); } else { alert("Illegal request type: " + sajax_request_type); } x = sajax_init_object(); if (x == null) { if (sajax_failure_redirect != "") { location.href = sajax_failure_redirect; return false; } else { sajax_debug("NULL sajax object for user agent:\n" + navigator.userAgent); return false; } } else { x.open(sajax_request_type, uri, true); // window.open(uri); sajax_requests[sajax_requests.length] = x; if (sajax_request_type == "POST") { x.setRequestHeader("Method", "POST " + uri + " HTTP/1.1"); x.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); } x.onreadystatechange = function() { if (x.readyState != 4) return; sajax_debug("received " + x.responseText); var status; var data; var txt = x.responseText.replace(/^\s*|\s*$/g,""); status = txt.charAt(0); data = txt.substring(2); if (status == "") { // let's just assume this is a pre-response bailout and let it slide for now } else if (status == "-") alert("Error: " + data); else { if (target_id != "") document.getElementById(target_id).innerHTML = eval(data); else { try { var callback; var extra_data = false; if (typeof args[args.length-1] == "object") { callback = args[args.length-1].callback; extra_data = args[args.length-1].extra_data; } else { callback = args[args.length-1]; } callback(eval(data), extra_data); } catch (e) { sajax_debug("Caught error " + e + ": Could not eval " + data ); } } } } } sajax_debug(func_name + " uri = " + uri + "/post = " + post_data); x.send(post_data); sajax_debug(func_name + " waiting.."); delete x; return true; } function sajaxObject() { this.version = '0.14'; } var sajax = new sajaxObject(); ScriptURI)) return $this->ScriptURI; $uri = $this->GetRemoteURI(); $uri .= (strpos($uri, '?') > 0 ? "&gcs=true" : "?gcs=true"); return $uri; } /** * Used to determine what the JavaScript name for a method is. */ private function GetExportName($fname) { return str_replace('::', '__', $fname); } /** * Returns a string representing all the JavaScript to be exported * to the client. */ public function GetJS() { ob_start(); echo $this->GetClientJS(); echo $this->GetAllStubJS(); foreach($this->ScriptBlocks as $block) { print "\n$block\n"; } return ob_get_clean(); } /** * Renders the JavaScript stub for a single exported method. */ public function GetStubJS($fname) { ob_start(); $func_name = str_replace('::', '__', ($smart_name = $fname)); if(strpos($smart_name, '::') > 0) { $smart_name = str_replace('::', '__', substr($fname, strpos($fname, '::')+2)); } if(preg_match('/^Sajax.+/', $smart_name)) { $smart_name = substr($smart_name, 5); } ?> // Stub for function x_() { sajax_do_call("", x_.arguments); } sajax. = x_; RemoteURI) ? $this->RemoteURI : (isset($GLOBALS['sajax_remote_uri']) ? $GLOBALS['sajax_remote_uri'] : $_SERVER['REQUEST_URI'])); } /** * Handle a method call for the client. */ public function HandleRequest() { global $sajax_export_list, $sajax_debug_mode; if (!empty($_GET["gcs"]) && empty($_REQUEST["rs"])) { header ("Content-Type: text/javascript;"); echo $this->GetJS(); exit; } if (! empty($_GET["rs"])) $mode = "get"; if (!empty($_POST["rs"])) $mode = "post"; if (!isset($mode)) return; $target = ""; if ($mode == "get") { // Bust cache in the head header ("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); // Date in the past header ("Expires: " . gmdate("D, d M Y H:i:s", (time() - 86400)) . " GMT"); // always modified header ("Cache-Control: no-cache, must-revalidate"); // HTTP/1.1 header ("Pragma: no-cache"); // HTTP/1.0 $func_name = $_GET["rs"]; if (! empty($_GET["rsargs"])) $args = $_GET["rsargs"]; else $args = array(); } else { $func_name = $_POST["rs"]; if (! empty($_POST["rsargs"])) $args = $_POST["rsargs"]; else $args = array(); } // Decode JSON representations of objects. if(count($args) > 0) { for($i=0;$iResponseError($err); } else { if(strrpos($func_name, '::')) { $p = strrpos($func_name, '::'); $ns = substr($func_name, 0, $p); $mn = substr($func_name, $p+2); $this->AddDebugMessage("Calling object method: $func_name()"); if(!class_exists($ns)) $this->ResponseError("Class '$ns' not loaded in namespace."); else { $o = new $ns; $func_name = array(new $ns, $mn); if(!method_exists($o, $mn)) $this->ResponseError("Method '$mn' not implemented in class '$ns'."); } } if(!is_callable($func_name)) $this->ResponseError("The method ($func_name) was exported, but was NOT callable; verify that it exists."); $result = call_user_func_array($func_name, $args); $this->ResponseOK(trim(json_encode($result))); } } public function Initialize() { } /** * Used to filter Sajax methods from an object. */ private function IsSajaxMethod($fname) { return (preg_match('/^Sajax.+/', $fname) > 0); } /** * Send the response as an error. */ private function ResponseError($response) { echo "-:"; foreach($this->DebugMessages as $msg) { echo "\n/* $msg */ "; } echo "\n$response"; exit(); } /** * Send the response as successful. */ private function ResponseOK($response) { echo "+:"; foreach($this->DebugMessages as $msg) { echo "\n/* $msg */ "; } echo "\nvar res = " . $response . "; res;"; exit(); } /** * Get the singleton instance. */ public static function Sajax() { if(is_null(Sajax::$Sajax) || !isset(Sajax::$Sajax)) Sajax::$Sajax = new Sajax(); return Sajax::$Sajax; } /** * Set the URI of the resource to dispatch requests. */ public function SetRemoteURI($uri = '') { if(strlen($uri) > 0) $this->RemoteURI = $uri; } /** * Set the URI of the JavaScript source for handling client requests. */ public function SetScriptURI($uri = '') { $this->AddDebugMessage("Setting alternate JS source: $uri"); if(strlen($uri)) $this->ScriptURI = $uri; } } $SAJAX_INCLUDED = 1; } ?>