PageRenderTime 25ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/core/model/modx/modconnectorresponse.class.php

https://github.com/francisreboucas/revolution
PHP | 203 lines | 101 code | 17 blank | 85 comment | 38 complexity | 2a1bba42f931e6c329df138c37f07e19 MD5 | raw file
  1. <?php
  2. /**
  3. * modConnectorResponse
  4. *
  5. * @package modx
  6. */
  7. require_once MODX_CORE_PATH . 'model/modx/modresponse.class.php';
  8. /**
  9. * Encapsulates an HTTP response from the MODX manager.
  10. *
  11. * {@inheritdoc}
  12. *
  13. * @package modx
  14. * @extends modResponse
  15. */
  16. class modConnectorResponse extends modResponse {
  17. /**
  18. * The base location of the processors called by the connectors.
  19. *
  20. * @var string
  21. * @access private
  22. */
  23. protected $_directory;
  24. /**
  25. * Creates a modConnectorResponse object.
  26. *
  27. * {@inheritdoc}
  28. */
  29. function __construct(modX & $modx) {
  30. parent :: __construct($modx);
  31. $this->setDirectory();
  32. }
  33. /**
  34. * Overrides modResponse::outputContent to provide connector-specific
  35. * processing.
  36. *
  37. * {@inheritdoc}
  38. */
  39. public function outputContent(array $options = array()) {
  40. /* variable pointer for easier access */
  41. $modx =& $this->modx;
  42. /* backwards compat */
  43. $error =& $this->modx->error;
  44. $siteId = $_SESSION["modx.{$this->modx->context->get('key')}.user.token"];
  45. /* ensure headers are sent for proper authentication */
  46. if (!isset($_SERVER['HTTP_MODAUTH']) && !isset($_REQUEST['HTTP_MODAUTH'])) {
  47. $this->body = $modx->error->failure($modx->lexicon('access_denied'));
  48. } else if (isset($_SERVER['HTTP_MODAUTH']) && $_SERVER['HTTP_MODAUTH'] != $siteId) {
  49. $this->body = $modx->error->failure($modx->lexicon('access_denied'));
  50. } else if (isset($_REQUEST['HTTP_MODAUTH']) && $_REQUEST['HTTP_MODAUTH'] != $siteId) {
  51. $this->body = $modx->error->failure($modx->lexicon('access_denied'));
  52. /* verify the location and action */
  53. } else if (!isset($options['location']) || !isset($options['action'])) {
  54. $this->body = $this->modx->error->failure($modx->lexicon('action_err_ns'));
  55. } else if (empty($options['action'])) {
  56. $this->body = $this->modx->error->failure($modx->lexicon('action_err_ns'));
  57. /* execute a processor and format the response */
  58. } else {
  59. /* prevent browsing of subdirectories for security */
  60. $target = str_replace('../','',$options['action']);
  61. /* create scriptProperties array from HTTP GPC vars */
  62. if (!isset($_POST)) $_POST = array();
  63. if (!isset($_GET)) $_GET = array();
  64. $scriptProperties = array_merge($_GET,$_POST);
  65. if (isset($_FILES) && !empty($_FILES)) {
  66. $scriptProperties = array_merge($scriptProperties,$_FILES);
  67. }
  68. /* run processor */
  69. $this->response = $this->modx->runProcessor($target,$scriptProperties,$options);
  70. if (!$this->response) {
  71. $this->body = $this->modx->error->failure($this->modx->lexicon('processor_err_nf',array(
  72. 'target' => $target,
  73. )));
  74. } else {
  75. $this->body = $this->response->getResponse();
  76. }
  77. }
  78. /* if files sent, this means that the browser needs it in text/plain,
  79. * so ignore text/json header type
  80. */
  81. if (!isset($_FILES)) {
  82. header("Content-Type: text/json; charset=UTF-8");
  83. }
  84. if (is_array($this->header)) {
  85. foreach ($this->header as $header) header($header);
  86. }
  87. if (is_array($this->body)) {
  88. @session_write_close();
  89. die($this->modx->toJSON(array(
  90. 'success' => isset($this->body['success']) ? $this->body['success'] : 0,
  91. 'message' => isset($this->body['message']) ? $this->body['message'] : $this->modx->lexicon('error'),
  92. 'total' => (isset($this->body['total']) && $this->body['total'] > 0)
  93. ? intval($this->body['total'])
  94. : (isset($this->body['errors'])
  95. ? count($this->body['errors'])
  96. : 1),
  97. 'data' => isset($this->body['errors']) ? $this->body['errors'] : array(),
  98. 'object' => isset($this->body['object']) ? $this->body['object'] : array(),
  99. )));
  100. } else {
  101. @session_write_close();
  102. die($this->body);
  103. }
  104. }
  105. /**
  106. * Return arrays of objects (with count) converted to JSON.
  107. *
  108. * The JSON result includes two main elements, total and results. This format is used for list
  109. * results.
  110. *
  111. * @access public
  112. * @param array $array An array of data objects.
  113. * @param mixed $count The total number of objects. Used for pagination.
  114. * @return string The JSON output.
  115. */
  116. public function outputArray(array $array,$count = false) {
  117. if (!is_array($array)) return false;
  118. if ($count === false) { $count = count($array); }
  119. return '({"total":"'.$count.'","results":'.$this->modx->toJSON($array).'})';
  120. }
  121. /**
  122. * Set the physical location of the processor directory for the response handler.
  123. *
  124. * This allows for dynamic processor locations.
  125. *
  126. * @access public
  127. * @param string $dir The directory to set as the processors directory.
  128. */
  129. public function setDirectory($dir = '') {
  130. if ($dir == '') {
  131. $this->_directory = $this->modx->getOption('processors_path');
  132. } else {
  133. $this->_directory = $dir;
  134. }
  135. }
  136. /**
  137. * Converts PHP to JSON with JavaScript literals left in-tact.
  138. *
  139. * JSON does not allow JavaScript literals, but this function encodes certain identifiable
  140. * literals and decodes them back into literals after modX::toJSON() formats the data.
  141. *
  142. * @access public
  143. * @param mixed $data The PHP data to be converted.
  144. * @return string The extended JSON-encoded string.
  145. */
  146. public function toJSON($data) {
  147. if (is_array($data)) {
  148. array_walk_recursive($data, array(&$this, '_encodeLiterals'));
  149. }
  150. return $this->_decodeLiterals($this->modx->toJSON($data));
  151. }
  152. /**
  153. * Encodes certain JavaScript literal strings for later decoding.
  154. *
  155. * @access protected
  156. * @param mixed &$value A reference to the value to be encoded if it is identified as a literal.
  157. * @param integer|string $key The array key corresponding to the value.
  158. */
  159. protected function _encodeLiterals(&$value, $key) {
  160. if (is_string($value)) {
  161. /* properly handle common literal structures */
  162. if (strpos($value, 'function(') === 0
  163. || strpos($value, 'this.') === 0
  164. || strpos($value, 'new Function(') === 0
  165. || strpos($value, 'Ext.') === 0) {
  166. $value = '@@' . base64_encode($value) . '@@';
  167. }
  168. }
  169. }
  170. /**
  171. * Decodes strings encoded by _encodeLiterals to restore JavaScript literals.
  172. *
  173. * @access protected
  174. * @param string $string The JSON-encoded string with encoded literals.
  175. * @return string The JSON-encoded string with literals restored.
  176. */
  177. protected function _decodeLiterals($string) {
  178. $pattern = '/"@@(.*?)@@"/';
  179. $string = preg_replace_callback(
  180. $pattern,
  181. create_function('$matches', 'return base64_decode($matches[1]);'),
  182. $string
  183. );
  184. return $string;
  185. }
  186. }