PageRenderTime 64ms CodeModel.GetById 28ms RepoModel.GetById 0ms app.codeStats 0ms

/cms/xajax/xajax.inc.php

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