Response.class.php 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380
  1. <?php
  2. /* vim: set expandtab sw=4 ts=4 sts=4: */
  3. /**
  4. * Manages the rendering of pages in PMA
  5. *
  6. * @package PhpMyAdmin
  7. */
  8. if (! defined('PHPMYADMIN')) {
  9. exit;
  10. }
  11. require_once 'libraries/OutputBuffering.class.php';
  12. require_once 'libraries/Header.class.php';
  13. require_once 'libraries/Footer.class.php';
  14. /**
  15. * Singleton class used to manage the rendering of pages in PMA
  16. *
  17. * @package PhpMyAdmin
  18. */
  19. class PMA_Response
  20. {
  21. /**
  22. * PMA_Response instance
  23. *
  24. * @access private
  25. * @static
  26. * @var PMA_Response
  27. */
  28. private static $_instance;
  29. /**
  30. * PMA_Header instance
  31. *
  32. * @access private
  33. * @var PMA_Header
  34. */
  35. private $_header;
  36. /**
  37. * HTML data to be used in the response
  38. *
  39. * @access private
  40. * @var string
  41. */
  42. private $_HTML;
  43. /**
  44. * An array of JSON key-value pairs
  45. * to be sent back for ajax requests
  46. *
  47. * @access private
  48. * @var array
  49. */
  50. private $_JSON;
  51. /**
  52. * PMA_Footer instance
  53. *
  54. * @access private
  55. * @var PMA_Footer
  56. */
  57. private $_footer;
  58. /**
  59. * Whether we are servicing an ajax request.
  60. * We can't simply use $GLOBALS['is_ajax_request']
  61. * here since it may have not been initialised yet.
  62. *
  63. * @access private
  64. * @var bool
  65. */
  66. private $_isAjax;
  67. /**
  68. * Whether we are servicing an ajax request for a page
  69. * that was fired using the generic page handler in JS.
  70. *
  71. * @access private
  72. * @var bool
  73. */
  74. private $_isAjaxPage;
  75. /**
  76. * Whether there were any errors druing the processing of the request
  77. * Only used for ajax responses
  78. *
  79. * @access private
  80. * @var bool
  81. */
  82. private $_isSuccess;
  83. /**
  84. * Workaround for PHP bug
  85. *
  86. * @access private
  87. * @var bool
  88. */
  89. private $_CWD;
  90. /**
  91. * Creates a new class instance
  92. */
  93. private function __construct()
  94. {
  95. if (! defined('TESTSUITE')) {
  96. $buffer = PMA_OutputBuffering::getInstance();
  97. $buffer->start();
  98. }
  99. $this->_header = new PMA_Header();
  100. $this->_HTML = '';
  101. $this->_JSON = array();
  102. $this->_footer = new PMA_Footer();
  103. $this->_isSuccess = true;
  104. $this->_isAjax = false;
  105. $this->_isAjaxPage = false;
  106. if (isset($_REQUEST['ajax_request']) && $_REQUEST['ajax_request'] == true) {
  107. $this->_isAjax = true;
  108. }
  109. if (isset($_REQUEST['ajax_page_request'])
  110. && $_REQUEST['ajax_page_request'] == true
  111. ) {
  112. $this->_isAjaxPage = true;
  113. }
  114. $this->_header->setAjax($this->_isAjax);
  115. $this->_footer->setAjax($this->_isAjax);
  116. $this->_CWD = getcwd();
  117. }
  118. /**
  119. * Returns the singleton PMA_Response object
  120. *
  121. * @return PMA_Response object
  122. */
  123. public static function getInstance()
  124. {
  125. if (empty(self::$_instance)) {
  126. self::$_instance = new PMA_Response();
  127. }
  128. return self::$_instance;
  129. }
  130. /**
  131. * Set the status of an ajax response,
  132. * whether it is a success or an error
  133. *
  134. * @param bool $state Whether the request was successfully processed
  135. *
  136. * @return void
  137. */
  138. public function isSuccess($state)
  139. {
  140. $this->_isSuccess = ($state == true);
  141. }
  142. /**
  143. * Returns true or false depending on whether
  144. * we are servicing an ajax request
  145. *
  146. * @return bool
  147. */
  148. public function isAjax()
  149. {
  150. return $this->_isAjax;
  151. }
  152. /**
  153. * Returns the path to the current working directory
  154. * Necessary to work around a PHP bug where the CWD is
  155. * reset after the initial script exits
  156. *
  157. * @return string
  158. */
  159. public function getCWD()
  160. {
  161. return $this->_CWD;
  162. }
  163. /**
  164. * Disables the rendering of the header
  165. * and the footer in responses
  166. *
  167. * @return void
  168. */
  169. public function disable()
  170. {
  171. $this->_header->disable();
  172. $this->_footer->disable();
  173. }
  174. /**
  175. * Returns a PMA_Header object
  176. *
  177. * @return PMA_Header
  178. */
  179. public function getHeader()
  180. {
  181. return $this->_header;
  182. }
  183. /**
  184. * Returns a PMA_Footer object
  185. *
  186. * @return PMA_Footer
  187. */
  188. public function getFooter()
  189. {
  190. return $this->_footer;
  191. }
  192. /**
  193. * Add HTML code to the response
  194. *
  195. * @param string $content A string to be appended to
  196. * the current output buffer
  197. *
  198. * @return void
  199. */
  200. public function addHTML($content)
  201. {
  202. if (is_array($content)) {
  203. foreach ($content as $msg) {
  204. $this->addHTML($msg);
  205. }
  206. } elseif ($content instanceof PMA_Message) {
  207. $this->_HTML .= $content->getDisplay();
  208. } else {
  209. $this->_HTML .= $content;
  210. }
  211. }
  212. /**
  213. * Add JSON code to the response
  214. *
  215. * @param mixed $json Either a key (string) or an
  216. * array or key-value pairs
  217. * @param mixed $value Null, if passing an array in $json otherwise
  218. * it's a string value to the key
  219. *
  220. * @return void
  221. */
  222. public function addJSON($json, $value = null)
  223. {
  224. if (is_array($json)) {
  225. foreach ($json as $key => $value) {
  226. $this->addJSON($key, $value);
  227. }
  228. } else {
  229. if ($value instanceof PMA_Message) {
  230. $this->_JSON[$json] = $value->getDisplay();
  231. } else {
  232. $this->_JSON[$json] = $value;
  233. }
  234. }
  235. }
  236. /**
  237. * Renders the HTML response text
  238. *
  239. * @return string
  240. */
  241. private function _getDisplay()
  242. {
  243. // The header may contain nothing at all,
  244. // if its content was already rendered
  245. // and, in this case, the header will be
  246. // in the content part of the request
  247. $retval = $this->_header->getDisplay();
  248. $retval .= $this->_HTML;
  249. $retval .= $this->_footer->getDisplay();
  250. return $retval;
  251. }
  252. /**
  253. * Sends an HTML response to the browser
  254. *
  255. * @return void
  256. */
  257. private function _htmlResponse()
  258. {
  259. echo $this->_getDisplay();
  260. }
  261. /**
  262. * Sends a JSON response to the browser
  263. *
  264. * @return void
  265. */
  266. private function _ajaxResponse()
  267. {
  268. if (! isset($this->_JSON['message'])) {
  269. $this->_JSON['message'] = $this->_getDisplay();
  270. } else if ($this->_JSON['message'] instanceof PMA_Message) {
  271. $this->_JSON['message'] = $this->_JSON['message']->getDisplay();
  272. }
  273. if ($this->_isSuccess) {
  274. $this->_JSON['success'] = true;
  275. } else {
  276. $this->_JSON['success'] = false;
  277. $this->_JSON['error'] = $this->_JSON['message'];
  278. unset($this->_JSON['message']);
  279. }
  280. if ($this->_isAjaxPage && $this->_isSuccess) {
  281. $this->addJSON('_title', $this->getHeader()->getTitleTag());
  282. $menuHash = $this->getHeader()->getMenu()->getHash();
  283. $this->addJSON('_menuHash', $menuHash);
  284. $hashes = array();
  285. if (isset($_REQUEST['menuHashes'])) {
  286. $hashes = explode('-', $_REQUEST['menuHashes']);
  287. }
  288. if (! in_array($menuHash, $hashes)) {
  289. $this->addJSON('_menu', $this->getHeader()->getMenu()->getDisplay());
  290. }
  291. $this->addJSON('_scripts', $this->getHeader()->getScripts()->getFiles());
  292. $this->addJSON('_selflink', $this->getFooter()->getSelfUrl('unencoded'));
  293. $this->addJSON('_displayMessage', $this->getHeader()->getMessage());
  294. $errors = $this->_footer->getErrorMessages();
  295. if (strlen($errors)) {
  296. $this->addJSON('_errors', $errors);
  297. }
  298. if (empty($GLOBALS['error_message'])) {
  299. // set current db, table and sql query in the querywindow
  300. $query = '';
  301. $maxChars = $GLOBALS['cfg']['MaxCharactersInDisplayedSQL'];
  302. if (isset($GLOBALS['sql_query'])
  303. && strlen($GLOBALS['sql_query']) < $maxChars
  304. ) {
  305. $query = PMA_escapeJsString($GLOBALS['sql_query']);
  306. }
  307. $this->addJSON(
  308. '_reloadQuerywindow',
  309. array(
  310. 'db' => PMA_ifSetOr($GLOBALS['db'], ''),
  311. 'table' => PMA_ifSetOr($GLOBALS['table'], ''),
  312. 'sql_query' => $query
  313. )
  314. );
  315. if (! empty($GLOBALS['focus_querywindow'])) {
  316. $this->addJSON('_focusQuerywindow', $query);
  317. }
  318. if (! empty($GLOBALS['reload'])) {
  319. $this->addJSON('_reloadNavigation', 1);
  320. }
  321. $this->addJSON('_params', $this->getHeader()->getJsParams());
  322. }
  323. }
  324. // Set the Content-Type header to JSON so that jQuery parses the
  325. // response correctly.
  326. if (! defined('TESTSUITE')) {
  327. header('Cache-Control: no-cache');
  328. header('Content-Type: application/json');
  329. }
  330. echo json_encode($this->_JSON);
  331. }
  332. /**
  333. * Sends an HTML response to the browser
  334. *
  335. * @static
  336. * @return void
  337. */
  338. public static function response()
  339. {
  340. $response = PMA_Response::getInstance();
  341. chdir($response->getCWD());
  342. $buffer = PMA_OutputBuffering::getInstance();
  343. if (empty($response->_HTML)) {
  344. $response->_HTML = $buffer->getContents();
  345. }
  346. if ($response->isAjax()) {
  347. $response->_ajaxResponse();
  348. } else {
  349. $response->_htmlResponse();
  350. }
  351. $buffer->flush();
  352. exit;
  353. }
  354. }
  355. ?>