PageRenderTime 23ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

/examples/dynamictable/public/phpolait/phpolait.php

https://bitbucket.org/pendletongp/pyjamas
PHP | 486 lines | 179 code | 55 blank | 252 comment | 30 complexity | b44f6499ac5b62117de2a9fa431696da MD5 | raw file
Possible License(s): Apache-2.0, BSD-3-Clause
  1. <?php
  2. /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
  3. /**
  4. * JSON RPC Wrapper for PHP Objects.
  5. *
  6. * PHP versions 4 and 5 (not tested under 5)
  7. *
  8. * LICENSE: LGPL
  9. *
  10. * Version: 0.5.1
  11. *
  12. */
  13. /**
  14. * Utility Function. Returns an includer-relative path to a file that is relative to the CURRENT file.
  15. * NOTE: They MUST both be in the same virtual root, I think - crossing virtual servers or aliases will
  16. * cause problems.
  17. *
  18. */
  19. function getIncluderRelativePath($relFromHere, $thisDir = null, $callingDir = null) {
  20. // Absolute URL's are always absolute
  21. if (($relFromHere{0}=='/') || (substr($relFromHere,0,7)=="http://") || (substr($relFromHere,0,8)=="https://"))
  22. return $relFromHere;
  23. /*
  24. * The concept:
  25. * The includING file is : /var/html/test/serverRoot/relDir/example/includer.php
  26. * The URL path of includer.php is: /relDir/example/includer.php
  27. * This file is: /var/html/test/serverRoot/relDir/lib/this.php
  28. *
  29. * Reduce the directories to
  30. * includeING file: /example
  31. * included file: /lib
  32. * Now for each directory we must strip from the including file's path, we have to add a parent to the destination file.
  33. */
  34. if ($thisDir==null)
  35. $thisDir = str_replace("\\","/", dirname(__FILE__)); // This is the current directory of this file
  36. if ($callingDir==null)
  37. $callingDir = str_replace("\\", "/", realpath(".") ); // PATH_TRANSLATED under PHP4
  38. // Reduce to the path elements that differ
  39. $thisPaths = explode('/', $thisDir);
  40. $callingPaths = explode('/',$callingDir);
  41. $maxElements = max(count($thisPaths), count( $callingPaths));
  42. $i = 0;
  43. while (($thisPaths[$i]==$callingPaths[$i]) && ($i<$maxElements)) {
  44. $i++;
  45. }
  46. // Now from the calling page, we must go up by count($callingPaths)-$i
  47. $relPath = str_repeat("../", count($callingPaths)-$i);
  48. $relPath .= implode("/", array_slice($thisPaths,$i));
  49. return $relPath . "/" . $relFromHere;
  50. }
  51. /**
  52. * Location and filename of the JSON-PHP library. If you're using PHP-JSON (the C
  53. * extension for PHP), you don't need to worry about this value.
  54. * Note, you can also set this value dynamically in the $config['jsonlib'] parameter passed
  55. * to the constructor of JSONRpcServer.
  56. */
  57. define(JSON_PHP_FILE, "JSON.php");
  58. /**
  59. * Root location of the jsolait libraries. The jsolait directory should exist off this location. So, you should
  60. * find init.js as ${JSOLAIT_ROOT}/jsolait/init.js.
  61. * Note, you can also set this value dynamically in the $config['jsolaitlib'] parameter passed
  62. * to the constructor of JSONRpcServer.
  63. */
  64. define(JSOLAIT_ROOT, getIncluderRelativePath("."));
  65. /**
  66. * Requirement for the HttpWrapper classes.
  67. */
  68. require_once("httpwrap.php");
  69. /**
  70. * Simple function to return true if this is PHP version 5 or greater.
  71. */
  72. function isPHP5() {
  73. return (!version_compare(phpversion(), "5.0", "<"));
  74. }
  75. /**
  76. * JSON RPC Wrapper for PHP Objects.
  77. *
  78. * JSON RPC Wrapper function that JSON-RPC enables any PHP class, transparently bridges PHP and JavaScript using Ajax and JSON, and provides
  79. * a PHP-JSON-RPC proxy class for transparently calling JSON Servers across PHP.
  80. *
  81. * @author Craig Mason-Jones <craig@lateral.co.za>
  82. * @copyright 2006 Craig Mason-Jones
  83. * @link http://www.sourceforge.net/projects/phpolait
  84. * @since File available since Release 0.5
  85. * Author: Craig Mason-Jones (craig@lateral.co.za)
  86. *
  87. * Requirements:
  88. * JSON.php (from PEAR: http://mike.teczno.com/json.html)
  89. * or php-json (from http://www.aurore.net/projects/php-json/)
  90. * jsolait (from http://jsolait.net)
  91. *
  92. * Usage: server / client integration.
  93. *
  94. * 1. Create the JSONRpcServer object that will handle any incoming JSON-RPC requests, serving the methods off the given object.
  95. * $server = JSONRpcServer( $object_to_proxy );
  96. * 2. Insert the appropriate javascript into your HTML source so that you can call name_of_jsproxy.method(params) to call any of your methods on the proxied PHP object.
  97. * $server->javascript( name_of_jsproxy );
  98. *
  99. * Usage: JSON-Rpc Server
  100. *
  101. * 1. Create the JSONRpcServer object that will handle any incoming JSON-RPC requests, serving the methods off the given object:
  102. * $server = JSONRpcServer( $object_to_proxy );
  103. *
  104. * Usage: Call remote JSON-Rpc Services
  105. *
  106. * 1. Create a JSONRpcProxy
  107. * $proxy = new JSONRpcProxy("server.php");
  108. * 2. Call remote methods:
  109. * list( $result, $error, $errorAdditional) = $proxy->echo('This is an echo') ;
  110. * if ($result!=null) {
  111. * echo $result;
  112. * } else {
  113. * echo "ERROR OCCURRED: $error<hr />$errorAdditional<hr />";
  114. * }
  115. *
  116. * That's it. See doc/index.html for more advanced reference and additional classes.
  117. *
  118. */
  119. // {{{ PHPJsonWrapper
  120. /**
  121. * Wrapper for the appropriate JSON Libraries.
  122. *
  123. * This utility class wraps the JSON encode / decode libraries. If you are using
  124. * the JSON.php PEAR package (http://mike.teczno.com/json.html), you will need to
  125. * set the JSON_PHP_FILE above to locate the package appropriately. If you have
  126. * installed the php-json C module (http://www.aurore.net/projects/php-json/), the
  127. * PHPJsonWrapper class will locate it and use the C language PHP functions for JSON
  128. * encoding / decoding.
  129. *
  130. * @author Craig Mason-Jones <craig@lateral.co.za>
  131. * @link http://www.sourceforge.net/projects/phpolait
  132. * @since Class available since Release 0.5
  133. *
  134. * @access protected
  135. */
  136. class PHPJsonWrapper {
  137. // {{{ properties
  138. /**
  139. * Services_JSON object used if the json module is not loaded.
  140. *
  141. * If the module 'json' is not loaded, the JSON.php file is included, and its
  142. * Services_JSON class is used to provide JSON encoding and decoding.
  143. * This object will hold an instance of the class for that encoding / decoding.
  144. *
  145. * @var Object
  146. */
  147. var $json;
  148. /**
  149. * Boolean indication of whether to use the json module, or the Services_JSON class from
  150. * JSON.php
  151. *
  152. * If the module 'json' is located, the json_encode and json_decode functions are used
  153. * for json encoding and decoding.
  154. *
  155. * @var boolean
  156. */
  157. var $use_module;
  158. // }}}
  159. /**
  160. * Constructor determines whether the json module is loaded, and uses the json module
  161. * functions if it is. Otherwise, the JSON.php PEAR module is used.
  162. */
  163. function PHPJsonWrapper($json_php_file)
  164. {
  165. $this->use_module = extension_loaded('json');
  166. if (!$this->use_module) {
  167. include_once $json_php_file;
  168. $this->json = new Services_JSON();
  169. }
  170. }
  171. /**
  172. * Decodes the given JSON string.
  173. *
  174. * Decodes the given JSON string using either the json module or the
  175. * Services_JSON class from JSON.php.
  176. *
  177. * @param string $str The string to decode.
  178. * @return Object The decoded JSON object.
  179. */
  180. function decode($str)
  181. {
  182. if ($this->use_module) {
  183. return json_decode($str);
  184. } else {
  185. return $this->json->decode($str);
  186. }
  187. }
  188. /**
  189. * JSON encodes the given PHP object.
  190. *
  191. * Encodes the given PHP object into a JSON string.
  192. * If the json module is available, it is used, otherwise the Services_JSON class
  193. * from JSON.php is used.
  194. *
  195. * @param Object $obj The object to JSON encode.
  196. * @return string The PHP object in JSON encoding.
  197. */
  198. function encode($obj)
  199. {
  200. if ($this->use_module) {
  201. return json_encode($obj);
  202. } else {
  203. return $this->json->encode($obj);
  204. }
  205. }
  206. } // End of class PHPJsonWrapper
  207. // }}}
  208. // {{{ JSONRpcServer
  209. /**
  210. * Serves the methods on the given object as JSON RPC methods if a JSON-Rpc request is detected.
  211. *
  212. * Exposes any methods, or a given list of methods, on the given object, as JSON
  213. * RPC methods. Accepts an incoming JSON request across HTTP, and outputs the
  214. * JSON-encoded response string, terminating script processing.
  215. * NB: If a request has been made, it terminates processing of the page.
  216. * If a request has not been made, processing continues, and the class is prepared to insert the PHP-Javascript code to provide transparent server-side calls in client-side
  217. * javascript.
  218. *
  219. * @author Craig Mason-Jones <craig@lateral.co.za>
  220. * @copyright 2006 Craig Mason-Jones
  221. * @license LGPL
  222. * @version Release: 0.5
  223. * @link http://www.sourceforge.net/phpolait
  224. * @since Class available since Release 0.5
  225. *
  226. * @access public
  227. */
  228. class JSONRpcServer
  229. {
  230. // {{{ properties
  231. /**
  232. * The object that is to be JSON served.
  233. * @var object
  234. */
  235. var $object;
  236. /**
  237. * Contains a mapping of actual method names to desired method names.
  238. * @var Associative Array
  239. */
  240. var $methodMap;
  241. /**
  242. * Path to the jsolait library.
  243. *
  244. * @var string or null
  245. */
  246. var $jsolaitlib;
  247. /// }}}
  248. /**
  249. * Constructor will serve any JSON-RPC request received and terminate processing, or return
  250. * control to the page to continue.
  251. * @param Object $object The object whose methods will be made available for JSON RPC calls.
  252. * @param Array $methodMap An optional associative array that can be used to map RPC method
  253. * names to object methods, permitting renaming of methods. This is
  254. * useful for providing PHP reserved words as methods, such as 'echo',
  255. * and can be used for restricting access to methods. If this parameter
  256. * is provided, but a method is not listed in the array, access to the method
  257. * is denied.
  258. * @param Array $config Optional configuration array. Two associative values are supported:
  259. * 'jsonlib' The location of the JSON-PHP library file.
  260. * 'jsolaitlib' The directory off which jsolait has been installed.
  261. *
  262. * @return None If a valid JSON RPC Request has been received, JSONRpcServer will return a response and terminate
  263. * the page. If no such request has been received, JSON RPC will pass control back to the web page, and
  264. * a call to JSONRpcServer::javascript( proxyName ) will insert the appropriate JavaScript proxy code into your
  265. * web page source.
  266. *
  267. */
  268. function JSONRpcServer($object, $methodMap = null, $config = null) {
  269. /*
  270. * NOTE: The request object ($request) is parsed into an object, but the response object
  271. * is an associative array. Writing this code, this distinction caused me headaches. Just a
  272. * warning :-)
  273. */
  274. $this->jsonlib = JSON_PHP_FILE;
  275. $this->jsolaitlib = JSOLAIT_ROOT;
  276. if ($config!=null) {
  277. if (array_key_exists("jsonlib", $config)) {
  278. $this->jsonlib = $config["jsonlib"];
  279. }
  280. if (array_key_exists("jsolait", $config)) {
  281. $this->jsolaitlib = $config["jsolait"];
  282. }
  283. }
  284. $json = new PHPJsonWrapper($this->jsonlib);
  285. $additionalMethods = array();
  286. $input = file_get_contents("php://input");
  287. $request = $json->decode($input);
  288. /*
  289. * If we have no request object, we are processing our page, so prepare the js Wrappers
  290. */
  291. if ($request==null) {
  292. $this->object = $object;
  293. $this->methodMap = $methodMap;
  294. return;
  295. }
  296. $return = array (
  297. "id" => $request->id,
  298. "result" => null,
  299. "error" => null
  300. );
  301. /* We've got the incoming JSON request object in request - we need to identify the method and the parameters */
  302. $method = $request->method;
  303. /* The methodMap parameter can convert a named method as follows:
  304. * string => string - simply rename the method
  305. * string => anything else - permit access to the method (the actual boolean value does not matter)
  306. */
  307. if ($methodMap!=null) {
  308. if (array_key_exists($method, $methodMap)) {
  309. if (is_string($methodMap[$method])) {
  310. $method = $methodMap[$method];
  311. }
  312. } else {
  313. $return['error'] = "No such method (" . $method . ") permitted on this server.";
  314. return $json->encode($return);
  315. }
  316. }
  317. if (is_object($object)) {
  318. if (!method_exists($object, $method)) {
  319. $return['error'] = "No such method (" . $method . ") exists on this server.";
  320. } else {
  321. /*
  322. * TODO: Try to catch an error in the call: use set_error_handler and restore_error_handler...?
  323. */
  324. $return['result'] = call_user_func_array(array(&$object, $method), $request->params);
  325. }
  326. } else {
  327. decho("/* object = $object */");
  328. if (!function_exists($method)) {
  329. $return['error'] = "No such function (" . $method . ") exists on this server.";
  330. } else {
  331. $return['result'] = call_user_func_array($method, $request->params);
  332. }
  333. }
  334. print ($json->encode($return));
  335. exit(0);
  336. }
  337. /**
  338. * Add a method on a different URL that one wants to access
  339. */
  340. function addMethod($url, $method, $methodName) {
  341. if ($methodName==null) $methodName = $method;
  342. array_push($this->additionalMethods, array ("url"=>$url, "method"=>$method, "name"=>$methodName));
  343. }
  344. /**
  345. * Prepares the javascript wrappers that will be presented on the client side.
  346. * @param string $proxyvar The name of the proxy variable for accessing the JSON-RPC methods.
  347. */
  348. function javascript($proxyvar) {
  349. if ($this->methodMap==null) { // This is the easy case
  350. $methods = get_class_methods( $this->object );
  351. } else {
  352. $methods = array_keys( $this->methodMap );
  353. }
  354. $this->jsWrapperHeader( $_SERVER["PHP_SELF"], $methods, $this->jsolaitlib);
  355. foreach ($methods as $name) {
  356. $this->jsWrapperMethod($name);
  357. }
  358. $this->jsWrapperFooter($proxyvar);
  359. }
  360. /**
  361. * @param string $pageUrl URL of this page.
  362. * @param array $methodArray List of methods to be called on the server.
  363. */
  364. function jsWrapperHeader($pageUrl, $methodArray, $jsolaitPath) {
  365. $header = <<<EOJS
  366. <script type="text/javascript" src="$jsolaitPath/jsolait/init.js"></script>
  367. <script type="text/javascript" src="$jsolaitPath/jsolait/lib/urllib.js"></script>
  368. <script type="text/javascript" src="$jsolaitPath/jsolait/lib/jsonrpc.js"></script>
  369. <script language="javascript">
  370. function PHPOLait() {
  371. var serviceURL = "$pageUrl";
  372. var methods = [%METHODLIST%];
  373. var jsonrpc = null;
  374. var server = null;
  375. try{
  376. jsolait.baseURL = '$jsolaitPath';
  377. jsolait.libURL = '$jsolaitPath/jsolait';
  378. jsonrpc = importModule("jsonrpc");
  379. server = new jsonrpc.ServiceProxy(serviceURL, methods);
  380. }catch(e){
  381. reportException(e);
  382. throw "importing of jsonrpc module failed.";
  383. }
  384. this._doJSON = function(method, args) {
  385. try {
  386. return server[method].apply(server,args);
  387. } catch (e) {
  388. alert(e);
  389. }
  390. }
  391. EOJS;
  392. $header = str_replace("%PAGE_NAME%", $pageUrl, $header);
  393. $methodList = "'" . implode($methodArray, "','") . "'";
  394. $header = str_replace("%METHODLIST%", $methodList, $header);
  395. print $header;
  396. }
  397. /**
  398. * Closes the class definition and sets the global variable for accessing the methods.
  399. * @param string varName Name of the global variable by which to access the JSON methods.
  400. */
  401. function jsWrapperFooter($varName) {
  402. print <<<EOJS
  403. }
  404. var $varName = new PHPOLait();
  405. </script>
  406. EOJS;
  407. }
  408. function jsWrapperMethod($method) {
  409. print <<< EOJS
  410. this.$method = function() { return this._doJSON('$method', arguments); };
  411. EOJS;
  412. }
  413. }
  414. // }}} // end of class JSONRpcServer
  415. /**
  416. *
  417. */
  418. // {{{ JSONRpcProxy
  419. if (isPHP5()) {
  420. require_once("rpcproxy.php5");
  421. } else {
  422. require_once("rpcproxy.php4");
  423. }
  424. /*
  425. * Local variables:
  426. * tab-width: 4
  427. * c-basic-offset: 4
  428. * c-hanging-comment-ender-p: nil
  429. * End:
  430. */
  431. ?>