AjaxDispatcher.php 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. <?php
  2. /**
  3. * Handle ajax requests and send them to the proper handler.
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation; either version 2 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License along
  16. * with this program; if not, write to the Free Software Foundation, Inc.,
  17. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  18. * http://www.gnu.org/copyleft/gpl.html
  19. *
  20. * @file
  21. * @ingroup Ajax
  22. */
  23. use MediaWiki\MediaWikiServices;
  24. /**
  25. * @defgroup Ajax Ajax
  26. */
  27. /**
  28. * Object-Oriented Ajax functions.
  29. * @ingroup Ajax
  30. */
  31. class AjaxDispatcher {
  32. /**
  33. * The way the request was made, either a 'get' or a 'post'
  34. * @var string $mode
  35. */
  36. private $mode;
  37. /**
  38. * Name of the requested handler
  39. * @var string $func_name
  40. */
  41. private $func_name;
  42. /** Arguments passed
  43. * @var array $args
  44. */
  45. private $args;
  46. /**
  47. * @var Config
  48. */
  49. private $config;
  50. /**
  51. * Load up our object with user supplied data
  52. * @param Config $config
  53. */
  54. function __construct( Config $config ) {
  55. $this->config = $config;
  56. $this->mode = "";
  57. if ( !empty( $_GET["rs"] ) ) {
  58. $this->mode = "get";
  59. }
  60. if ( !empty( $_POST["rs"] ) ) {
  61. $this->mode = "post";
  62. }
  63. switch ( $this->mode ) {
  64. case 'get':
  65. $this->func_name = isset( $_GET["rs"] ) ? $_GET["rs"] : '';
  66. if ( !empty( $_GET["rsargs"] ) ) {
  67. $this->args = $_GET["rsargs"];
  68. } else {
  69. $this->args = [];
  70. }
  71. break;
  72. case 'post':
  73. $this->func_name = isset( $_POST["rs"] ) ? $_POST["rs"] : '';
  74. if ( !empty( $_POST["rsargs"] ) ) {
  75. $this->args = $_POST["rsargs"];
  76. } else {
  77. $this->args = [];
  78. }
  79. break;
  80. default:
  81. return;
  82. # Or we could throw an exception:
  83. # throw new MWException( __METHOD__ . ' called without any data (mode empty).' );
  84. }
  85. }
  86. /**
  87. * Pass the request to our internal function.
  88. * BEWARE! Data are passed as they have been supplied by the user,
  89. * they should be carefully handled in the function processing the
  90. * request.
  91. *
  92. * @param User $user
  93. */
  94. function performAction( User $user ) {
  95. if ( empty( $this->mode ) ) {
  96. return;
  97. }
  98. if ( !in_array( $this->func_name, $this->config->get( 'AjaxExportList' ) ) ) {
  99. wfDebug( __METHOD__ . ' Bad Request for unknown function ' . $this->func_name . "\n" );
  100. wfHttpError(
  101. 400,
  102. 'Bad Request',
  103. "unknown function " . $this->func_name
  104. );
  105. } elseif ( !User::isEveryoneAllowed( 'read' ) && !$user->isAllowed( 'read' ) ) {
  106. wfHttpError(
  107. 403,
  108. 'Forbidden',
  109. 'You are not allowed to view pages.' );
  110. } else {
  111. wfDebug( __METHOD__ . ' dispatching ' . $this->func_name . "\n" );
  112. try {
  113. $result = call_user_func_array( $this->func_name, $this->args );
  114. if ( $result === false || $result === null ) {
  115. wfDebug( __METHOD__ . ' ERROR while dispatching ' .
  116. $this->func_name . "(" . var_export( $this->args, true ) . "): " .
  117. "no data returned\n" );
  118. wfHttpError( 500, 'Internal Error',
  119. "{$this->func_name} returned no data" );
  120. } else {
  121. if ( is_string( $result ) ) {
  122. $result = new AjaxResponse( $result );
  123. }
  124. // Make sure DB commit succeeds before sending a response
  125. $lbFactory = MediaWikiServices::getInstance()->getDBLoadBalancerFactory();
  126. $lbFactory->commitMasterChanges( __METHOD__ );
  127. $result->sendHeaders();
  128. $result->printText();
  129. wfDebug( __METHOD__ . ' dispatch complete for ' . $this->func_name . "\n" );
  130. }
  131. } catch ( Exception $e ) {
  132. wfDebug( __METHOD__ . ' ERROR while dispatching ' .
  133. $this->func_name . "(" . var_export( $this->args, true ) . "): " .
  134. get_class( $e ) . ": " . $e->getMessage() . "\n" );
  135. if ( !headers_sent() ) {
  136. wfHttpError( 500, 'Internal Error',
  137. $e->getMessage() );
  138. } else {
  139. print $e->getMessage();
  140. }
  141. }
  142. }
  143. }
  144. }