PageRenderTime 45ms CodeModel.GetById 12ms RepoModel.GetById 0ms app.codeStats 1ms

/source/innomatic/core/classes/innomatic/ajax/Xajax.php

https://bitbucket.org/innoteam/innomatic
PHP | 1245 lines | 684 code | 101 blank | 460 comment | 173 complexity | 443bcb3f18a1ca11d708f691b4f1c464 MD5 | raw file
Possible License(s): BSD-3-Clause, Apache-2.0, LGPL-2.0, LGPL-2.1
  1. <?php
  2. require_once('innomatic/util/Singleton.php');
  3. require_once('innomatic/ajax/XajaxConfig.php');
  4. require_once('innomatic/ajax/XajaxResponse.php');
  5. require_once('innomatic/webapp/WebAppContainer.php');
  6. /**
  7. * xajax.inc.php :: Main xajax class and setup file
  8. *
  9. * xajax version 0.2.4
  10. * copyright (c) 2005 by Jared White & J. Max Wilson
  11. * http://www.xajaxproject.org
  12. *
  13. * xajax is an open source PHP class library for easily creating powerful
  14. * PHP-driven, web-based Ajax Applications. Using xajax, you can asynchronously
  15. * call PHP functions and update the content of your your webpage without
  16. * reloading the page.
  17. *
  18. * xajax is released under the terms of the LGPL license
  19. * http://www.gnu.org/copyleft/lesser.html#SEC3
  20. *
  21. * This library is free software; you can redistribute it and/or
  22. * modify it under the terms of the GNU Lesser General Public
  23. * License as published by the Free Software Foundation; either
  24. * version 2.1 of the License, or (at your option) any later version.
  25. *
  26. * This library is distributed in the hope that it will be useful,
  27. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  28. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  29. * Lesser General Public License for more details.
  30. *
  31. * You should have received a copy of the GNU Lesser General Public
  32. * License along with this library; if not, write to the Free Software
  33. * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  34. *
  35. * @package xajax
  36. * @version $Id: Xajax.php,v 1.2 2006/06/04 08:40:40 alex Exp $
  37. * @copyright Copyright (c) 2005-2006 by Jared White & J. Max Wilson
  38. * @license http://www.gnu.org/copyleft/lesser.html#SEC3 LGPL License
  39. */
  40. /*
  41. ----------------------------------------------------------------------------
  42. | Online documentation for this class is available on the xajax wiki at: |
  43. | http://wiki.xajaxproject.org/Documentation:xajax.inc.php |
  44. ----------------------------------------------------------------------------
  45. */
  46. /**
  47. * Define XAJAX_DEFAULT_CHAR_ENCODING that is used by both
  48. * the xajax and xajaxResponse classes
  49. */
  50. if (!defined ('XAJAX_DEFAULT_CHAR_ENCODING')) {
  51. define ('XAJAX_DEFAULT_CHAR_ENCODING', 'utf-8' );
  52. }
  53. /**
  54. * Communication Method Defines
  55. */
  56. if (!defined ('XAJAX_GET')) {
  57. define ('XAJAX_GET', 0);
  58. }
  59. if (!defined ('XAJAX_POST')) {
  60. define ('XAJAX_POST', 1);
  61. }
  62. /**
  63. * The xajax class generates the xajax javascript for your page including the
  64. * Javascript wrappers for the PHP functions that you want to call from your page.
  65. * It also handles processing and executing the command messages in the XML responses
  66. * sent back to your page from your PHP functions.
  67. *
  68. * @package xajax
  69. */
  70. class Xajax extends Singleton {
  71. /**#@+
  72. * @access protected
  73. */
  74. /**
  75. * @var array Array of PHP functions that will be callable through javascript wrappers
  76. */
  77. var $aFunctions;
  78. /**
  79. * @var array Array of object callbacks that will allow Javascript to call PHP methods (key=function name)
  80. */
  81. var $aObjects;
  82. /**
  83. * @var array Array of RequestTypes to be used with each function (key=function name)
  84. */
  85. var $aFunctionRequestTypes;
  86. /**
  87. * @var array Array of Include Files for any external functions (key=function name)
  88. */
  89. var $aFunctionIncludeFiles;
  90. /**
  91. * @var string Name of the PHP function to call if no callable function was found
  92. */
  93. var $sCatchAllFunction;
  94. /**
  95. * @var string Name of the PHP function to call before any other function
  96. */
  97. var $sPreFunction;
  98. /**
  99. * @var string The URI for making requests to the xajax object
  100. */
  101. var $sRequestURI;
  102. /**
  103. * @var string The prefix to prepend to the javascript wraper function name
  104. */
  105. var $sWrapperPrefix;
  106. /**
  107. * @var boolean Show debug messages (default false)
  108. */
  109. var $bDebug;
  110. /**
  111. * @var boolean Show messages in the client browser's status bar (default false)
  112. */
  113. var $bStatusMessages;
  114. /**
  115. * @var boolean Allow xajax to exit after processing a request (default true)
  116. */
  117. var $bExitAllowed;
  118. /**
  119. * @var boolean Use wait cursor in browser (default true)
  120. */
  121. var $bWaitCursor;
  122. /**
  123. * @var boolean Use an special xajax error handler so the errors are sent to the browser properly (default false)
  124. */
  125. var $bErrorHandler;
  126. /**
  127. * @var string Specify what, if any, file xajax should log errors to (and more information in a future release)
  128. */
  129. var $sLogFile;
  130. /**
  131. * @var boolean Clean all output buffers before outputting response (default false)
  132. */
  133. var $bCleanBuffer;
  134. /**
  135. * @var string String containing the character encoding used
  136. */
  137. var $sEncoding;
  138. /**
  139. * @var boolean Decode input request args from UTF-8 (default false)
  140. */
  141. var $bDecodeUTF8Input;
  142. /**
  143. * @var boolean Convert special characters to HTML entities (default false)
  144. */
  145. var $bOutputEntities;
  146. /**
  147. * @var array Array for parsing complex objects
  148. */
  149. var $aObjArray;
  150. /**
  151. * @var integer Position in $aObjArray
  152. */
  153. var $iPos;
  154. public $ajaxLoader = true;
  155. /**#@-*/
  156. /**
  157. * Constructor. You can set some extra xajax options right away or use
  158. * individual methods later to set options.
  159. *
  160. * @param string defaults to the current browser URI
  161. * @param string defaults to "xajax_";
  162. * @param string defaults to XAJAX_DEFAULT_CHAR_ENCODING defined above
  163. * @param boolean defaults to false
  164. */
  165. public function ___construct($sRequestURI='',$sWrapperPrefix="xajax_",$sEncoding=XAJAX_DEFAULT_CHAR_ENCODING,$bDebug=false) {
  166. $this->aFunctions = array();
  167. $this->aObjects = array();
  168. $this->aFunctionIncludeFiles = array();
  169. $this->sRequestURI = $sRequestURI;
  170. if ($this->sRequestURI == "")
  171. $this->sRequestURI = $this->_detectURI();
  172. $this->sWrapperPrefix = $sWrapperPrefix;
  173. $this->bDebug = $bDebug;
  174. $this->bStatusMessages = false;
  175. $this->bWaitCursor = true;
  176. $this->bExitAllowed = true;
  177. $this->bErrorHandler = false;
  178. $this->sLogFile = "";
  179. $this->bCleanBuffer = false;
  180. $this->setCharEncoding($sEncoding);
  181. $this->bDecodeUTF8Input = false;
  182. $this->bOutputEntities = false;
  183. }
  184. /**
  185. * Sets the URI to which requests will be made.
  186. * <i>Usage:</i> <kbd>$xajax->setRequestURI("http://www.xajaxproject.org");</kbd>
  187. *
  188. * @param string the URI (can be absolute or relative) of the PHP script
  189. * that will be accessed when an xajax request occurs
  190. */
  191. function setRequestURI($sRequestURI)
  192. {
  193. $this->sRequestURI = $sRequestURI;
  194. }
  195. /**
  196. * Sets the prefix that will be appended to the Javascript wrapper
  197. * functions (default is "xajax_").
  198. *
  199. * @param string
  200. */
  201. //
  202. function setWrapperPrefix($sPrefix)
  203. {
  204. $this->sWrapperPrefix = $sPrefix;
  205. }
  206. /**
  207. * Enables debug messages for xajax.
  208. * */
  209. function debugOn()
  210. {
  211. $this->bDebug = true;
  212. }
  213. /**
  214. * Disables debug messages for xajax (default behavior).
  215. */
  216. function debugOff()
  217. {
  218. $this->bDebug = false;
  219. }
  220. /**
  221. * Enables messages in the browser's status bar for xajax.
  222. */
  223. function statusMessagesOn()
  224. {
  225. $this->bStatusMessages = true;
  226. }
  227. /**
  228. * Disables messages in the browser's status bar for xajax (default behavior).
  229. */
  230. function statusMessagesOff()
  231. {
  232. $this->bStatusMessages = false;
  233. }
  234. /**
  235. * Enables the wait cursor to be displayed in the browser (default behavior).
  236. */
  237. function waitCursorOn()
  238. {
  239. $this->bWaitCursor = true;
  240. }
  241. /**
  242. * Disables the wait cursor to be displayed in the browser.
  243. */
  244. function waitCursorOff()
  245. {
  246. $this->bWaitCursor = false;
  247. }
  248. /**
  249. * Enables xajax to exit immediately after processing a request and
  250. * sending the response back to the browser (default behavior).
  251. */
  252. function exitAllowedOn()
  253. {
  254. $this->bExitAllowed = true;
  255. }
  256. /**
  257. * Disables xajax's default behavior of exiting immediately after
  258. * processing a request and sending the response back to the browser.
  259. */
  260. function exitAllowedOff()
  261. {
  262. $this->bExitAllowed = false;
  263. }
  264. /**
  265. * Turns on xajax's error handling system so that PHP errors that occur
  266. * during a request are trapped and pushed to the browser in the form of
  267. * a Javascript alert.
  268. */
  269. function errorHandlerOn()
  270. {
  271. $this->bErrorHandler = true;
  272. }
  273. /**
  274. * Turns off xajax's error handling system (default behavior).
  275. */
  276. function errorHandlerOff()
  277. {
  278. $this->bErrorHandler = false;
  279. }
  280. /**
  281. * Specifies a log file that will be written to by xajax during a request
  282. * (used only by the error handling system at present). If you don't invoke
  283. * this method, or you pass in "", then no log file will be written to.
  284. * <i>Usage:</i> <kbd>$xajax->setLogFile("/xajax_logs/errors.log");</kbd>
  285. */
  286. function setLogFile($sFilename)
  287. {
  288. $this->sLogFile = $sFilename;
  289. }
  290. /**
  291. * Causes xajax to clean out all output buffers before outputting a
  292. * response (default behavior).
  293. */
  294. function cleanBufferOn()
  295. {
  296. $this->bCleanBuffer = true;
  297. }
  298. /**
  299. * Turns off xajax's output buffer cleaning.
  300. */
  301. function cleanBufferOff()
  302. {
  303. $this->bCleanBuffer = false;
  304. }
  305. /**
  306. * Sets the character encoding for the HTTP output based on
  307. * <kbd>$sEncoding</kbd>, which is a string containing the character
  308. * encoding to use. You don't need to use this method normally, since the
  309. * character encoding for the response gets set automatically based on the
  310. * <kbd>XAJAX_DEFAULT_CHAR_ENCODING</kbd> constant.
  311. * <i>Usage:</i> <kbd>$xajax->setCharEncoding("utf-8");</kbd>
  312. *
  313. * @param string the encoding type to use (utf-8, iso-8859-1, etc.)
  314. */
  315. function setCharEncoding($sEncoding)
  316. {
  317. $this->sEncoding = $sEncoding;
  318. }
  319. /**
  320. * Causes xajax to decode the input request args from UTF-8 to the current
  321. * encoding if possible. Either the iconv or mb_string extension must be
  322. * present for optimal functionality.
  323. */
  324. function decodeUTF8InputOn()
  325. {
  326. $this->bDecodeUTF8Input = true;
  327. }
  328. /**
  329. * Turns off decoding the input request args from UTF-8 (default behavior).
  330. */
  331. function decodeUTF8InputOff()
  332. {
  333. $this->bDecodeUTF8Input = false;
  334. }
  335. /**
  336. * Tells the response object to convert special characters to HTML entities
  337. * automatically (only works if the mb_string extension is available).
  338. */
  339. function outputEntitiesOn()
  340. {
  341. $this->bOutputEntities = true;
  342. }
  343. /**
  344. * Tells the response object to output special characters intact. (default
  345. * behavior).
  346. */
  347. function outputEntitiesOff()
  348. {
  349. $this->bOutputEntities = false;
  350. }
  351. /**
  352. * Registers a PHP function or method to be callable through xajax in your
  353. * Javascript. If you want to register a function, pass in the name of that
  354. * function. If you want to register a static class method, pass in an
  355. * array like so:
  356. * <kbd>array("myFunctionName", "myClass", "myMethod")</kbd>
  357. * For an object instance method, use an object variable for the second
  358. * array element (and in PHP 4 make sure you put an & before the variable
  359. * to pass the object by reference). Note: the function name is what you
  360. * call via Javascript, so it can be anything as long as it doesn't
  361. * conflict with any other registered function name.
  362. *
  363. * <i>Usage:</i> <kbd>$xajax->registerFunction("myFunction");</kbd>
  364. * or: <kbd>$xajax->registerFunction(array("myFunctionName", &$myObject, "myMethod"));</kbd>
  365. *
  366. * @param mixed contains the function name or an object callback array
  367. * @param mixed request type (XAJAX_GET/XAJAX_POST) that should be used
  368. * for this function. Defaults to XAJAX_POST.
  369. */
  370. function registerFunction($mFunction,$sRequestType=XAJAX_POST)
  371. {
  372. if (is_array($mFunction)) {
  373. $this->aFunctions[$mFunction[0]] = 1;
  374. $this->aFunctionRequestTypes[$mFunction[0]] = $sRequestType;
  375. $this->aObjects[$mFunction[0]] = array_slice($mFunction, 1);
  376. }
  377. else {
  378. $this->aFunctions[$mFunction] = 1;
  379. $this->aFunctionRequestTypes[$mFunction] = $sRequestType;
  380. }
  381. }
  382. /**
  383. * Registers a PHP function to be callable through xajax which is located
  384. * in some other file. If the function is requested the external file will
  385. * be included to define the function before the function is called.
  386. *
  387. * <i>Usage:</i> <kbd>$xajax->registerExternalFunction("myFunction","myFunction.inc.php",XAJAX_POST);</kbd>
  388. *
  389. * @param string contains the function name or an object callback array
  390. * ({@link xajax::registerFunction() see registerFunction} for
  391. * more info on object callback arrays)
  392. * @param string contains the path and filename of the include file
  393. * @param mixed the RequestType (XAJAX_GET/XAJAX_POST) that should be used
  394. * for this function. Defaults to XAJAX_POST.
  395. */
  396. function registerExternalFunction($mFunction,$sIncludeFile,$sRequestType=XAJAX_POST)
  397. {
  398. $this->registerFunction($mFunction, $sRequestType);
  399. if (is_array($mFunction)) {
  400. $this->aFunctionIncludeFiles[$mFunction[0]] = $sIncludeFile;
  401. }
  402. else {
  403. $this->aFunctionIncludeFiles[$mFunction] = $sIncludeFile;
  404. }
  405. }
  406. /**
  407. * Registers a PHP function to be called when xajax cannot find the
  408. * function being called via Javascript. Because this is technically
  409. * impossible when using "wrapped" functions, the catch-all feature is
  410. * only useful when you're directly using the xajax.call() Javascript
  411. * method. Use the catch-all feature when you want more dynamic ability to
  412. * intercept unknown calls and handle them in a custom way.
  413. *
  414. * <i>Usage:</i> <kbd>$xajax->registerCatchAllFunction("myCatchAllFunction");</kbd>
  415. *
  416. * @param string contains the function name or an object callback array
  417. * ({@link xajax::registerFunction() see registerFunction} for
  418. * more info on object callback arrays)
  419. */
  420. function registerCatchAllFunction($mFunction)
  421. {
  422. if (is_array($mFunction)) {
  423. $this->sCatchAllFunction = $mFunction[0];
  424. $this->aObjects[$mFunction[0]] = array_slice($mFunction, 1);
  425. }
  426. else {
  427. $this->sCatchAllFunction = $mFunction;
  428. }
  429. }
  430. /**
  431. * Registers a PHP function to be called before xajax calls the requested
  432. * function. xajax will automatically add the request function's response
  433. * to the pre-function's response to create a single response. Another
  434. * feature is the ability to return not just a response, but an array with
  435. * the first element being false (a boolean) and the second being the
  436. * response. In this case, the pre-function's response will be returned to
  437. * the browser without xajax calling the requested function.
  438. *
  439. * <i>Usage:</i> <kbd>$xajax->registerPreFunction("myPreFunction");</kbd>
  440. *
  441. * @param string contains the function name or an object callback array
  442. * ({@link xajax::registerFunction() see registerFunction} for
  443. * more info on object callback arrays)
  444. */
  445. function registerPreFunction($mFunction)
  446. {
  447. if (is_array($mFunction)) {
  448. $this->sPreFunction = $mFunction[0];
  449. $this->aObjects[$mFunction[0]] = array_slice($mFunction, 1);
  450. }
  451. else {
  452. $this->sPreFunction = $mFunction;
  453. }
  454. }
  455. /**
  456. * Returns true if xajax can process the request, false if otherwise.
  457. * You can use this to determine if xajax needs to process the request or
  458. * not.
  459. *
  460. * @return boolean
  461. */
  462. function canProcessRequests()
  463. {
  464. if ($this->getRequestMode() != -1) return true;
  465. return false;
  466. }
  467. /**
  468. * Returns the current request mode (XAJAX_GET or XAJAX_POST), or -1 if
  469. * there is none.
  470. *
  471. * @return mixed
  472. */
  473. function getRequestMode()
  474. {
  475. if (!empty($_GET["xajax"]))
  476. return XAJAX_GET;
  477. if (!empty($_POST["xajax"]))
  478. return XAJAX_POST;
  479. return -1;
  480. }
  481. /**
  482. * This is the main communications engine of xajax. The engine handles all
  483. * incoming xajax requests, calls the apporiate PHP functions (or
  484. * class/object methods) and passes the XML responses back to the
  485. * Javascript response handler. If your RequestURI is the same as your Web
  486. * page then this function should be called before any headers or HTML has
  487. * been sent.
  488. */
  489. function processRequests()
  490. {
  491. $requestMode = -1;
  492. $sFunctionName = "";
  493. $bFoundFunction = true;
  494. $bFunctionIsCatchAll = false;
  495. $sFunctionNameForSpecial = "";
  496. $aArgs = array();
  497. $sPreResponse = "";
  498. $bEndRequest = false;
  499. $sResponse = "";
  500. $requestMode = $this->getRequestMode();
  501. if ($requestMode == -1) return;
  502. if ($requestMode == XAJAX_POST)
  503. {
  504. $sFunctionName = $_POST["xajax"];
  505. if (!empty($_POST["xajaxargs"]))
  506. $aArgs = $_POST["xajaxargs"];
  507. }
  508. else
  509. {
  510. header ("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
  511. header ("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
  512. header ("Cache-Control: no-cache, must-revalidate");
  513. header ("Pragma: no-cache");
  514. $sFunctionName = $_GET["xajax"];
  515. if (!empty($_GET["xajaxargs"]))
  516. $aArgs = $_GET["xajaxargs"];
  517. }
  518. // Use xajax error handler if necessary
  519. if ($this->bErrorHandler) {
  520. $GLOBALS['xajaxErrorHandlerText'] = "";
  521. set_error_handler("xajaxErrorHandler");
  522. }
  523. if ($this->sPreFunction) {
  524. if (!$this->_isFunctionCallable($this->sPreFunction)) {
  525. $bFoundFunction = false;
  526. $objResponse = new xajaxResponse();
  527. $objResponse->addAlert("Unknown Pre-Function ". $this->sPreFunction);
  528. $sResponse = $objResponse->getXML();
  529. }
  530. }
  531. //include any external dependencies associated with this function name
  532. if (array_key_exists($sFunctionName,$this->aFunctionIncludeFiles))
  533. {
  534. ob_start();
  535. include_once($this->aFunctionIncludeFiles[$sFunctionName]);
  536. ob_end_clean();
  537. }
  538. if ($bFoundFunction) {
  539. $sFunctionNameForSpecial = $sFunctionName;
  540. if (!array_key_exists($sFunctionName, $this->aFunctions))
  541. {
  542. if ($this->sCatchAllFunction) {
  543. $sFunctionName = $this->sCatchAllFunction;
  544. $bFunctionIsCatchAll = true;
  545. }
  546. else {
  547. $bFoundFunction = false;
  548. $objResponse = new xajaxResponse();
  549. $objResponse->addAlert("Unknown Function $sFunctionName.");
  550. $sResponse = $objResponse->getXML();
  551. }
  552. }
  553. else if ($this->aFunctionRequestTypes[$sFunctionName] != $requestMode)
  554. {
  555. $bFoundFunction = false;
  556. $objResponse = new xajaxResponse();
  557. $objResponse->addAlert("Incorrect Request Type.");
  558. $sResponse = $objResponse->getXML();
  559. }
  560. }
  561. if ($bFoundFunction)
  562. {
  563. for ($i = 0; $i < sizeof($aArgs); $i++)
  564. {
  565. // If magic quotes is on, then we need to strip the slashes from the args
  566. if (get_magic_quotes_gpc() == 1 && is_string($aArgs[$i])) {
  567. $aArgs[$i] = stripslashes($aArgs[$i]);
  568. }
  569. if (stristr($aArgs[$i],"<xjxobj>") != false)
  570. {
  571. $aArgs[$i] = $this->_xmlToArray("xjxobj",$aArgs[$i]);
  572. }
  573. else if (stristr($aArgs[$i],"<xjxquery>") != false)
  574. {
  575. $aArgs[$i] = $this->_xmlToArray("xjxquery",$aArgs[$i]);
  576. }
  577. else if ($this->bDecodeUTF8Input)
  578. {
  579. $aArgs[$i] = $this->_decodeUTF8Data($aArgs[$i]);
  580. }
  581. }
  582. if ($this->sPreFunction) {
  583. $mPreResponse = $this->_callFunction($this->sPreFunction, array($sFunctionNameForSpecial, $aArgs));
  584. if (is_array($mPreResponse) && $mPreResponse[0] === false) {
  585. $bEndRequest = true;
  586. $sPreResponse = $mPreResponse[1];
  587. }
  588. else {
  589. $sPreResponse = $mPreResponse;
  590. }
  591. if (is_a($sPreResponse, "xajaxResponse")) {
  592. $sPreResponse = $sPreResponse->getXML();
  593. }
  594. if ($bEndRequest) $sResponse = $sPreResponse;
  595. }
  596. if (!$bEndRequest) {
  597. if (!$this->_isFunctionCallable($sFunctionName)) {
  598. $objResponse = new xajaxResponse();
  599. $objResponse->addAlert("The Registered Function $sFunctionName Could Not Be Found.");
  600. $sResponse = $objResponse->getXML();
  601. }
  602. else {
  603. if ($bFunctionIsCatchAll) {
  604. $aArgs = array($sFunctionNameForSpecial, $aArgs);
  605. }
  606. $sResponse = $this->_callFunction($sFunctionName, $aArgs);
  607. }
  608. if (is_a($sResponse, "xajaxResponse")) {
  609. $sResponse = $sResponse->getXML();
  610. }
  611. if (!is_string($sResponse) || strpos($sResponse, "<xjx>") === FALSE) {
  612. $objResponse = new xajaxResponse();
  613. $objResponse->addAlert("No XML Response Was Returned By Function $sFunctionName.");
  614. $sResponse = $objResponse->getXML();
  615. }
  616. else if ($sPreResponse != "") {
  617. $sNewResponse = new xajaxResponse($this->sEncoding, $this->bOutputEntities);
  618. $sNewResponse->loadXML($sPreResponse);
  619. $sNewResponse->loadXML($sResponse);
  620. $sResponse = $sNewResponse->getXML();
  621. }
  622. }
  623. }
  624. $sContentHeader = "Content-type: text/xml;";
  625. if ($this->sEncoding && strlen(trim($this->sEncoding)) > 0)
  626. $sContentHeader .= " charset=".$this->sEncoding;
  627. header($sContentHeader);
  628. if ($this->bErrorHandler && !empty( $GLOBALS['xajaxErrorHandlerText'] )) {
  629. $sErrorResponse = new xajaxResponse();
  630. $sErrorResponse->addAlert("** PHP Error Messages: **" . $GLOBALS['xajaxErrorHandlerText']);
  631. if ($this->sLogFile) {
  632. $fH = @fopen($this->sLogFile, "a");
  633. if (!$fH) {
  634. $sErrorResponse->addAlert("** Logging Error **\n\nxajax was unable to write to the error log file:\n" . $this->sLogFile);
  635. }
  636. else {
  637. fwrite($fH, "** xajax Error Log - " . strftime("%b %e %Y %I:%M:%S %p") . " **" . $GLOBALS['xajaxErrorHandlerText'] . "\n\n\n");
  638. fclose($fH);
  639. }
  640. }
  641. $sErrorResponse->loadXML($sResponse);
  642. $sResponse = $sErrorResponse->getXML();
  643. }
  644. if ($this->bCleanBuffer) while (@ob_end_clean());
  645. print $sResponse;
  646. if ($this->bErrorHandler) restore_error_handler();
  647. if ($this->bExitAllowed)
  648. InnomaticContainer::instance('innomaticcontainer')->halt();
  649. }
  650. /**
  651. * Prints the xajax Javascript header and wrapper code into your page by
  652. * printing the output of the getJavascript() method. It should only be
  653. * called between the <pre><head> </head></pre> tags in your HTML page.
  654. * Remember, if you only want to obtain the result of this function, use
  655. * {@link xajax::getJavascript()} instead.
  656. *
  657. * <i>Usage:</i>
  658. * <code>
  659. * <head>
  660. * ...
  661. * < ?php $xajax->printJavascript(); ? >
  662. * </code>
  663. *
  664. * @param string the relative address of the folder where xajax has been
  665. * installed. For instance, if your PHP file is
  666. * "http://www.myserver.com/myfolder/mypage.php"
  667. * and xajax was installed in
  668. * "http://www.myserver.com/anotherfolder", then $sJsURI
  669. * should be set to "../anotherfolder". Defaults to assuming
  670. * xajax is in the same folder as your PHP file.
  671. * @param string the relative folder/file pair of the xajax Javascript
  672. * engine located within the xajax installation folder.
  673. * Defaults to xajax_js/xajax.js.
  674. */
  675. function printJavascript($sJsURI="", $sJsFile=NULL)
  676. {
  677. print $this->getJavascript($sJsURI, $sJsFile);
  678. }
  679. /**
  680. * Returns the xajax Javascript code that should be added to your HTML page
  681. * between the <kbd><head> </head></kbd> tags.
  682. *
  683. * <i>Usage:</i>
  684. * <code>
  685. * < ?php $xajaxJSHead = $xajax->getJavascript(); ? >
  686. * <head>
  687. * ...
  688. * < ?php echo $xajaxJSHead; ? >
  689. * </code>
  690. *
  691. * @param string the relative address of the folder where xajax has been
  692. * installed. For instance, if your PHP file is
  693. * "http://www.myserver.com/myfolder/mypage.php"
  694. * and xajax was installed in
  695. * "http://www.myserver.com/anotherfolder", then $sJsURI
  696. * should be set to "../anotherfolder". Defaults to assuming
  697. * xajax is in the same folder as your PHP file.
  698. * @param string the relative folder/file pair of the xajax Javascript
  699. * engine located within the xajax installation folder.
  700. * Defaults to xajax_js/xajax.js.
  701. * @return string
  702. */
  703. function getJavascript($sJsURI="", $sJsFile=NULL)
  704. {
  705. $html = $this->getJavascriptConfig();
  706. $html .= $this->getJavascriptInclude($sJsURI, $sJsFile);
  707. return $html;
  708. }
  709. /**
  710. * Returns a string containing inline Javascript that sets up the xajax
  711. * runtime (typically called internally by xajax from get/printJavascript).
  712. *
  713. * @return string
  714. */
  715. function getJavascriptConfig()
  716. {
  717. $html = "\t<script type=\"text/javascript\">\n";
  718. $html .= "var xajaxRequestUri=\"".$this->sRequestURI."\";\n";
  719. $html .= "var xajaxDebug=".($this->bDebug?"true":"false").";\n";
  720. $html .= "var xajaxStatusMessages=".($this->bStatusMessages?"true":"false").";\n";
  721. $html .= "var xajaxWaitCursor=".($this->bWaitCursor?"true":"false").";\n";
  722. $html .= "var xajaxDefinedGet=".XAJAX_GET.";\n";
  723. $html .= "var xajaxDefinedPost=".XAJAX_POST.";\n";
  724. $html .= "var xajaxLoaded=false;\n";
  725. foreach($this->aFunctions as $sFunction => $bExists) {
  726. $html .= $this->_wrap($sFunction,$this->aFunctionRequestTypes[$sFunction]);
  727. }
  728. $html .= "\t</script>\n";
  729. return $html;
  730. }
  731. /**
  732. * Returns a string containing a Javascript include of the xajax.js file
  733. * along with a check to see if the file loaded after six seconds
  734. * (typically called internally by xajax from get/printJavascript).
  735. *
  736. * @param string the relative address of the folder where xajax has been
  737. * installed. For instance, if your PHP file is
  738. * "http://www.myserver.com/myfolder/mypage.php"
  739. * and xajax was installed in
  740. * "http://www.myserver.com/anotherfolder", then $sJsURI
  741. * should be set to "../anotherfolder". Defaults to assuming
  742. * xajax is in the same folder as your PHP file.
  743. * @param string the relative folder/file pair of the xajax Javascript
  744. * engine located within the xajax installation folder.
  745. * Defaults to xajax_js/xajax.js.
  746. * @return string
  747. */
  748. function getJavascriptInclude($sJsURI="", $sJsFile=NULL)
  749. {
  750. if ($sJsFile == NULL) $sJsFile = "xajax_js/xajax.js";
  751. if ($sJsURI != "" && substr($sJsURI, -1) != "/") $sJsURI .= "/";
  752. $html = "\t<script type=\"text/javascript\" src=\"" . $sJsURI . $sJsFile . "\"></script>\n";
  753. $html .= "\t<script type=\"text/javascript\">\n";
  754. $html .= "window.setTimeout(function () { if (!xajaxLoaded) { alert('Error: the xajax Javascript file could not be included. Perhaps the URL is incorrect?\\nURL: {$sJsURI}{$sJsFile}'); } }, 6000);\n";
  755. $html .= "\t</script>\n";
  756. return $html;
  757. }
  758. /**
  759. * This method can be used to create a new xajax.js file out of the
  760. * xajax_uncompressed.js file (which will only happen if xajax.js doesn't
  761. * already exist on the filesystem).
  762. *
  763. * @param string an optional argument containing the full server file path
  764. * of xajax.js.
  765. */
  766. function autoCompressJavascript($sJsFullFilename=NULL)
  767. {
  768. $sJsFile = "xajax_js/xajax.js";
  769. if ($sJsFullFilename) {
  770. $realJsFile = $sJsFullFilename;
  771. }
  772. else {
  773. $realPath = realpath(dirname(__FILE__));
  774. $realJsFile = $realPath . "/". $sJsFile;
  775. }
  776. // Create a compressed file if necessary
  777. if (!file_exists($realJsFile)) {
  778. $srcFile = str_replace(".js", "_uncompressed.js", $realJsFile);
  779. if (!file_exists($srcFile)) {
  780. trigger_error("The xajax uncompressed Javascript file could not be found in the <b>" . dirname($realJsFile) . "</b> folder. Error ", E_USER_ERROR);
  781. }
  782. require_once('core/xajax/classes/XajaxCompressJavascript.php');
  783. //require(dirname(__FILE__)."/xajaxCompress.php");
  784. $javaScript = implode('', file($srcFile));
  785. $compressedScript = XajaxCompressJavascript($javaScript);
  786. $fH = @fopen($realJsFile, "w");
  787. if (!$fH) {
  788. trigger_error("The xajax compressed javascript file could not be written in the <b>" . dirname($realJsFile) . "</b> folder. Error ", E_USER_ERROR);
  789. }
  790. else {
  791. fwrite($fH, $compressedScript);
  792. fclose($fH);
  793. }
  794. }
  795. }
  796. /**
  797. * Returns the current URL based upon the SERVER vars.
  798. *
  799. * @access private
  800. * @return string
  801. */
  802. function _detectURI() {
  803. $aURL = array();
  804. // Try to get the request URL
  805. if (!empty($_SERVER['REQUEST_URI'])) {
  806. $aURL = parse_url($_SERVER['REQUEST_URI']);
  807. }
  808. // Fill in the empty values
  809. if (empty($aURL['scheme'])) {
  810. if (!empty($_SERVER['HTTP_SCHEME'])) {
  811. $aURL['scheme'] = $_SERVER['HTTP_SCHEME'];
  812. } else {
  813. $aURL['scheme'] = (!empty($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) != 'off') ? 'https' : 'http';
  814. }
  815. }
  816. if (empty($aURL['host'])) {
  817. if (!empty($_SERVER['HTTP_HOST'])) {
  818. if (strpos($_SERVER['HTTP_HOST'], ':') > 0) {
  819. list($aURL['host'], $aURL['port']) = explode(':', $_SERVER['HTTP_HOST']);
  820. } else {
  821. $aURL['host'] = $_SERVER['HTTP_HOST'];
  822. }
  823. } else if (!empty($_SERVER['SERVER_NAME'])) {
  824. $aURL['host'] = $_SERVER['SERVER_NAME'];
  825. } else {
  826. print "xajax Error: xajax failed to automatically identify your Request URI.";
  827. print "Please set the Request URI explicitly when you instantiate the xajax object.";
  828. InnomaticContainer::instance('innomaticcontainer')->halt();
  829. }
  830. }
  831. if (empty($aURL['port']) && !empty($_SERVER['SERVER_PORT'])) {
  832. $aURL['port'] = $_SERVER['SERVER_PORT'];
  833. }
  834. if (empty($aURL['path'])) {
  835. if (!empty($_SERVER['PATH_INFO'])) {
  836. $sPath = parse_url($_SERVER['PATH_INFO']);
  837. } else {
  838. $sPath = parse_url($_SERVER['PHP_SELF']);
  839. }
  840. $aURL['path'] = $sPath['path'];
  841. unset($sPath);
  842. }
  843. if (!empty($aURL['query'])) {
  844. $aURL['query'] = '?'.$aURL['query'];
  845. }
  846. // Build the URL: Start with scheme, user and pass
  847. $sURL = $aURL['scheme'].'://';
  848. if (!empty($aURL['user'])) {
  849. $sURL.= $aURL['user'];
  850. if (!empty($aURL['pass'])) {
  851. $sURL.= ':'.$aURL['pass'];
  852. }
  853. $sURL.= '@';
  854. }
  855. // Add the host
  856. $sURL.= $aURL['host'];
  857. // Add the port if needed
  858. if (!empty($aURL['port']) && (($aURL['scheme'] == 'http' && $aURL['port'] != 80) || ($aURL['scheme'] == 'https' && $aURL['port'] != 443))) {
  859. $sURL.= ':'.$aURL['port'];
  860. }
  861. // Add the path and the query string
  862. $sURL.= $aURL['path'].@$aURL['query'];
  863. // Clean up
  864. unset($aURL);
  865. return $sURL;
  866. }
  867. /**
  868. * Returns true if the function name is associated with an object callback,
  869. * false if not.
  870. *
  871. * @param string the name of the function
  872. * @access private
  873. * @return boolean
  874. */
  875. function _isObjectCallback($sFunction)
  876. {
  877. if (array_key_exists($sFunction, $this->aObjects)) return true;
  878. return false;
  879. }
  880. /**
  881. * Returns true if the function or object callback can be called, false if
  882. * not.
  883. *
  884. * @param string the name of the function
  885. * @access private
  886. * @return boolean
  887. */
  888. function _isFunctionCallable($sFunction)
  889. {
  890. if ($this->_isObjectCallback($sFunction)) {
  891. if (is_object($this->aObjects[$sFunction][0])) {
  892. return method_exists($this->aObjects[$sFunction][0], $this->aObjects[$sFunction][1]);
  893. }
  894. else {
  895. return is_callable($this->aObjects[$sFunction]);
  896. }
  897. }
  898. else {
  899. return function_exists($sFunction);
  900. }
  901. }
  902. /**
  903. * Calls the function, class method, or object method with the supplied
  904. * arguments.
  905. *
  906. * @param string the name of the function
  907. * @param array arguments to pass to the function
  908. * @access private
  909. * @return mixed the output of the called function or method
  910. */
  911. function _callFunction($sFunction, $aArgs)
  912. {
  913. if ($this->_isObjectCallback($sFunction)) {
  914. $mReturn = call_user_func_array($this->aObjects[$sFunction], $aArgs);
  915. }
  916. else {
  917. $mReturn = call_user_func_array($sFunction, $aArgs);
  918. }
  919. return $mReturn;
  920. }
  921. /**
  922. * Generates the Javascript wrapper for the specified PHP function.
  923. *
  924. * @param string the name of the function
  925. * @param mixed the request type
  926. * @access private
  927. * @return string
  928. */
  929. function _wrap($sFunction,$sRequestType=XAJAX_POST)
  930. {
  931. $js = "function ".$this->sWrapperPrefix."$sFunction(){".
  932. ( $this->ajaxLoader == false ? '' :
  933. "document.getElementById('stoppingAjax').style.display = 'none';".
  934. "document.getElementById('loadingAjax').style.display = 'inline';" ).
  935. "return xajax.call(\"$sFunction\", arguments, ".$sRequestType.");}\n";
  936. return $js;
  937. }
  938. /**
  939. * Takes a string containing xajax xjxobj XML or xjxquery XML and builds an
  940. * array representation of it to pass as an argument to the PHP function
  941. * being called.
  942. *
  943. * @param string the root tag of the XML
  944. * @param string XML to convert
  945. * @access private
  946. * @return array
  947. */
  948. function _xmlToArray($rootTag, $sXml)
  949. {
  950. $aArray = array();
  951. $sXml = str_replace("<$rootTag>","<$rootTag>|~|",$sXml);
  952. $sXml = str_replace("</$rootTag>","</$rootTag>|~|",$sXml);
  953. $sXml = str_replace("<e>","<e>|~|",$sXml);
  954. $sXml = str_replace("</e>","</e>|~|",$sXml);
  955. $sXml = str_replace("<k>","<k>|~|",$sXml);
  956. $sXml = str_replace("</k>","|~|</k>|~|",$sXml);
  957. $sXml = str_replace("<v>","<v>|~|",$sXml);
  958. $sXml = str_replace("</v>","|~|</v>|~|",$sXml);
  959. $sXml = str_replace("<q>","<q>|~|",$sXml);
  960. $sXml = str_replace("</q>","|~|</q>|~|",$sXml);
  961. $this->aObjArray = explode("|~|",$sXml);
  962. $this->iPos = 0;
  963. $aArray = $this->_parseObjXml($rootTag);
  964. return $aArray;
  965. }
  966. /**
  967. * A recursive function that generates an array from the contents of
  968. * $this->aObjArray.
  969. *
  970. * @param string the root tag of the XML
  971. * @access private
  972. * @return array
  973. */
  974. function _parseObjXml($rootTag)
  975. {
  976. $aArray = array();
  977. if ($rootTag == "xjxobj")
  978. {
  979. while(!stristr($this->aObjArray[$this->iPos],"</xjxobj>"))
  980. {
  981. $this->iPos++;
  982. if(stristr($this->aObjArray[$this->iPos],"<e>"))
  983. {
  984. $key = "";
  985. $value = null;
  986. $this->iPos++;
  987. while(!stristr($this->aObjArray[$this->iPos],"</e>"))
  988. {
  989. if(stristr($this->aObjArray[$this->iPos],"<k>"))
  990. {
  991. $this->iPos++;
  992. while(!stristr($this->aObjArray[$this->iPos],"</k>"))
  993. {
  994. $key .= $this->aObjArray[$this->iPos];
  995. $this->iPos++;
  996. }
  997. }
  998. if(stristr($this->aObjArray[$this->iPos],"<v>"))
  999. {
  1000. $this->iPos++;
  1001. while(!stristr($this->aObjArray[$this->iPos],"</v>"))
  1002. {
  1003. if(stristr($this->aObjArray[$this->iPos],"<xjxobj>"))
  1004. {
  1005. $value = $this->_parseObjXml("xjxobj");
  1006. $this->iPos++;
  1007. }
  1008. else
  1009. {
  1010. $value .= $this->aObjArray[$this->iPos];
  1011. if ($this->bDecodeUTF8Input)
  1012. {
  1013. $value = $this->_decodeUTF8Data($value);
  1014. }
  1015. }
  1016. $this->iPos++;
  1017. }
  1018. }
  1019. $this->iPos++;
  1020. }
  1021. $aArray[$key]=$value;
  1022. }
  1023. }
  1024. }
  1025. if ($rootTag == "xjxquery")
  1026. {
  1027. $sQuery = "";
  1028. $this->iPos++;
  1029. while(!stristr($this->aObjArray[$this->iPos],"</xjxquery>"))
  1030. {
  1031. if (stristr($this->aObjArray[$this->iPos],"<q>") || stristr($this->aObjArray[$this->iPos],"</q>"))
  1032. {
  1033. $this->iPos++;
  1034. continue;
  1035. }
  1036. $sQuery .= $this->aObjArray[$this->iPos];
  1037. $this->iPos++;
  1038. }
  1039. parse_str($sQuery, $aArray);
  1040. if ($this->bDecodeUTF8Input)
  1041. {
  1042. foreach($aArray as $key => $value)
  1043. {
  1044. $aArray[$key] = $this->_decodeUTF8Data($value);
  1045. }
  1046. }
  1047. // If magic quotes is on, then we need to strip the slashes from the
  1048. // array values because of the parse_str pass which adds slashes
  1049. if (get_magic_quotes_gpc() == 1) {
  1050. $newArray = array();
  1051. foreach ($aArray as $sKey => $sValue) {
  1052. if (is_string($sValue))
  1053. $newArray[$sKey] = stripslashes($sValue);
  1054. else
  1055. $newArray[$sKey] = $sValue;
  1056. }
  1057. $aArray = $newArray;
  1058. }
  1059. }
  1060. return $aArray;
  1061. }
  1062. /**
  1063. * Decodes string data from UTF-8 to the current xajax encoding.
  1064. *
  1065. * @param string data to convert
  1066. * @access private
  1067. * @return string converted data
  1068. */
  1069. function _decodeUTF8Data($sData)
  1070. {
  1071. $sValue = $sData;
  1072. if ($this->bDecodeUTF8Input)
  1073. {
  1074. $sFuncToUse = NULL;
  1075. if (function_exists('iconv'))
  1076. {
  1077. $sFuncToUse = "iconv";
  1078. }
  1079. else if (function_exists('mb_convert_encoding'))
  1080. {
  1081. $sFuncToUse = "mb_convert_encoding";
  1082. }
  1083. else if ($this->sEncoding == "ISO-8859-1")
  1084. {
  1085. $sFuncToUse = "utf8_decode";
  1086. }
  1087. else
  1088. {
  1089. trigger_error("The incoming xajax data could not be converted from UTF-8", E_USER_NOTICE);
  1090. }
  1091. if ($sFuncToUse)
  1092. {
  1093. if (is_string($sValue))
  1094. {
  1095. if ($sFuncToUse == "iconv")
  1096. {
  1097. $sValue = iconv("UTF-8", $this->sEncoding.'//TRANSLIT', $sValue);
  1098. }
  1099. else if ($sFuncToUse == "mb_convert_encoding")
  1100. {
  1101. $sValue = mb_convert_encoding($sValue, $this->sEncoding, "UTF-8");
  1102. }
  1103. else
  1104. {
  1105. $sValue = utf8_decode($sValue);
  1106. }
  1107. }
  1108. }
  1109. }
  1110. return $sValue;
  1111. }
  1112. }// end class xajax
  1113. /**
  1114. * This function is registered with PHP's set_error_handler() function if
  1115. * the xajax error handling system is turned on.
  1116. */
  1117. function xajaxErrorHandler($errno, $errstr, $errfile, $errline)
  1118. {
  1119. $errorReporting = error_reporting();
  1120. if (($errno & $errorReporting) == 0) return;
  1121. if ($errno == E_NOTICE) {
  1122. $errTypeStr = "NOTICE";
  1123. }
  1124. else if ($errno == E_WARNING) {
  1125. $errTypeStr = "WARNING";
  1126. }
  1127. else if ($errno == E_USER_NOTICE) {
  1128. $errTypeStr = "USER NOTICE";
  1129. }
  1130. else if ($errno == E_USER_WARNING) {
  1131. $errTypeStr = "USER WARNING";
  1132. }
  1133. else if ($errno == E_USER_ERROR) {
  1134. $errTypeStr = "USER FATAL ERROR";
  1135. }
  1136. else if ($errno == E_STRICT) {
  1137. return;
  1138. }
  1139. else {
  1140. $errTypeStr = "UNKNOWN: $errno";
  1141. }
  1142. $GLOBALS['xajaxErrorHandlerText'] .= "\n----\n[$errTypeStr] $errstr\nerror in line $errline of file $errfile";
  1143. }
  1144. ?>