You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

rcmail_output_json.php 7.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258
  1. <?php
  2. /**
  3. +-----------------------------------------------------------------------+
  4. | program/include/rcmail_output_json.php |
  5. | |
  6. | This file is part of the Roundcube Webmail client |
  7. | Copyright (C) 2008-2012, The Roundcube Dev Team |
  8. | |
  9. | Licensed under the GNU General Public License version 3 or |
  10. | any later version with exceptions for skins & plugins. |
  11. | See the README file for a full license statement. |
  12. | |
  13. | PURPOSE: |
  14. | Class to handle JSON (AJAX) output |
  15. +-----------------------------------------------------------------------+
  16. | Author: Thomas Bruederli <roundcube@gmail.com> |
  17. | Author: Aleksander Machniak <alec@alec.pl> |
  18. +-----------------------------------------------------------------------+
  19. */
  20. /**
  21. * View class to produce JSON responses
  22. *
  23. * @package Webmail
  24. * @subpackage View
  25. */
  26. class rcmail_output_json extends rcmail_output
  27. {
  28. protected $texts = array();
  29. protected $commands = array();
  30. protected $callbacks = array();
  31. protected $message = null;
  32. public $type = 'js';
  33. public $ajax_call = true;
  34. /**
  35. * Issue command to set page title
  36. *
  37. * @param string $title New page title
  38. */
  39. public function set_pagetitle($title)
  40. {
  41. if ($this->config->get('devel_mode') && !empty($_SESSION['username']))
  42. $name = $_SESSION['username'];
  43. else
  44. $name = $this->config->get('product_name');
  45. $this->command('set_pagetitle', empty($name) ? $title : $name . ' :: ' . $title);
  46. }
  47. /**
  48. * Register a template object handler
  49. *
  50. * @param string $obj Object name
  51. * @param string $func Function name to call
  52. */
  53. public function add_handler($obj, $func)
  54. {
  55. // ignore
  56. }
  57. /**
  58. * Register a list of template object handlers
  59. *
  60. * @param array $arr Hash array with object=>handler pairs
  61. */
  62. public function add_handlers($arr)
  63. {
  64. // ignore
  65. }
  66. /**
  67. * Call a client method
  68. *
  69. * @param string Method to call
  70. * @param ... Additional arguments
  71. */
  72. public function command()
  73. {
  74. $cmd = func_get_args();
  75. if (strpos($cmd[0], 'plugin.') === 0)
  76. $this->callbacks[] = $cmd;
  77. else
  78. $this->commands[] = $cmd;
  79. }
  80. /**
  81. * Add a localized label to the client environment
  82. */
  83. public function add_label()
  84. {
  85. $args = func_get_args();
  86. if (count($args) == 1 && is_array($args[0]))
  87. $args = $args[0];
  88. foreach ($args as $name) {
  89. $this->texts[$name] = $this->app->gettext($name);
  90. }
  91. }
  92. /**
  93. * Invoke display_message command
  94. *
  95. * @param string $message Message to display
  96. * @param string $type Message type [notice|confirm|error]
  97. * @param array $vars Key-value pairs to be replaced in localized text
  98. * @param boolean $override Override last set message
  99. * @param int $timeout Message displaying time in seconds
  100. * @uses self::command()
  101. */
  102. public function show_message($message, $type='notice', $vars=null, $override=true, $timeout=0)
  103. {
  104. if ($override || !$this->message) {
  105. if ($this->app->text_exists($message)) {
  106. if (!empty($vars)) {
  107. $vars = array_map(array('rcmail', 'Q'), $vars);
  108. }
  109. $msgtext = $this->app->gettext(array('name' => $message, 'vars' => $vars));
  110. }
  111. else
  112. $msgtext = $message;
  113. $this->message = $message;
  114. $this->command('display_message', $msgtext, $type, $timeout * 1000);
  115. }
  116. }
  117. /**
  118. * Delete all stored env variables and commands
  119. */
  120. public function reset()
  121. {
  122. parent::reset();
  123. $this->texts = array();
  124. $this->commands = array();
  125. }
  126. /**
  127. * Redirect to a certain url
  128. *
  129. * @param mixed $p Either a string with the action or url parameters as key-value pairs
  130. * @param int $delay Delay in seconds
  131. * @see rcmail::url()
  132. */
  133. public function redirect($p = array(), $delay = 1)
  134. {
  135. $location = $this->app->url($p);
  136. $this->remote_response(sprintf("window.setTimeout(function(){ %s.redirect('%s',true); }, %d);",
  137. self::JS_OBJECT_NAME, $location, $delay));
  138. exit;
  139. }
  140. /**
  141. * Send an AJAX response to the client.
  142. */
  143. public function send()
  144. {
  145. $this->remote_response();
  146. exit;
  147. }
  148. /**
  149. * Show error page and terminate script execution
  150. *
  151. * @param int $code Error code
  152. * @param string $message Error message
  153. */
  154. public function raise_error($code, $message)
  155. {
  156. if ($code == 403) {
  157. header('HTTP/1.1 403 Forbidden');
  158. die("Invalid Request");
  159. }
  160. $this->show_message("Application Error ($code): $message", 'error');
  161. $this->remote_response();
  162. exit;
  163. }
  164. /**
  165. * Send an AJAX response with executable JS code
  166. *
  167. * @param string $add Additional JS code
  168. * @param boolean True if output buffer should be flushed
  169. * @return void
  170. * @deprecated
  171. */
  172. protected function remote_response($add='')
  173. {
  174. static $s_header_sent = false;
  175. if (!$s_header_sent) {
  176. $s_header_sent = true;
  177. $this->nocacheing_headers();
  178. header('Content-Type: text/plain; charset=' . $this->get_charset());
  179. }
  180. // unset default env vars
  181. unset($this->env['task'], $this->env['action'], $this->env['comm_path']);
  182. $rcmail = rcmail::get_instance();
  183. $response['action'] = $rcmail->action;
  184. if ($unlock = rcube_utils::get_input_value('_unlock', rcube_utils::INPUT_GPC)) {
  185. $response['unlock'] = $unlock;
  186. }
  187. if (!empty($this->env))
  188. $response['env'] = $this->env;
  189. if (!empty($this->texts))
  190. $response['texts'] = $this->texts;
  191. // send function calls
  192. $response['exec'] = $this->get_js_commands() . $add;
  193. if (!empty($this->callbacks))
  194. $response['callbacks'] = $this->callbacks;
  195. // trigger generic hook where plugins can put additional content to the response
  196. $hook = $this->app->plugins->exec_hook("render_response", array('response' => $response));
  197. // save some memory
  198. $response = $hook['response'];
  199. unset($hook['response']);
  200. echo self::json_serialize($response);
  201. }
  202. /**
  203. * Return executable javascript code for all registered commands
  204. *
  205. * @return string $out
  206. */
  207. protected function get_js_commands()
  208. {
  209. $out = '';
  210. foreach ($this->commands as $i => $args) {
  211. $method = array_shift($args);
  212. foreach ($args as $i => $arg) {
  213. $args[$i] = self::json_serialize($arg);
  214. }
  215. $out .= sprintf(
  216. "this.%s(%s);\n",
  217. preg_replace('/^parent\./', '', $method),
  218. implode(',', $args)
  219. );
  220. }
  221. return $out;
  222. }
  223. }