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.

rcube_output.php 8.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294
  1. <?php
  2. /**
  3. +-----------------------------------------------------------------------+
  4. | This file is part of the Roundcube PHP suite |
  5. | Copyright (C) 2005-2014 The Roundcube Dev Team |
  6. | |
  7. | Licensed under the GNU General Public License version 3 or |
  8. | any later version with exceptions for skins & plugins. |
  9. | See the README file for a full license statement. |
  10. | |
  11. | CONTENTS: |
  12. | Abstract class for output generation |
  13. +-----------------------------------------------------------------------+
  14. | Author: Thomas Bruederli <roundcube@gmail.com> |
  15. | Author: Aleksander Machniak <alec@alec.pl> |
  16. +-----------------------------------------------------------------------+
  17. */
  18. /**
  19. * Class for output generation
  20. *
  21. * @package Framework
  22. * @subpackage View
  23. */
  24. abstract class rcube_output
  25. {
  26. public $browser;
  27. protected $app;
  28. protected $config;
  29. protected $charset = RCUBE_CHARSET;
  30. protected $env = array();
  31. protected $skins = array();
  32. /**
  33. * Object constructor
  34. */
  35. public function __construct()
  36. {
  37. $this->app = rcube::get_instance();
  38. $this->config = $this->app->config;
  39. $this->browser = new rcube_browser();
  40. }
  41. /**
  42. * Magic getter
  43. */
  44. public function __get($var)
  45. {
  46. // allow read-only access to some members
  47. switch ($var) {
  48. case 'env': return $this->env;
  49. case 'skins': return $this->skins;
  50. case 'charset': return $this->charset;
  51. }
  52. return null;
  53. }
  54. /**
  55. * Setter for output charset.
  56. * To be specified in a meta tag and sent as http-header
  57. *
  58. * @param string $charset Charset name
  59. */
  60. public function set_charset($charset)
  61. {
  62. $this->charset = $charset;
  63. }
  64. /**
  65. * Getter for output charset
  66. *
  67. * @return string Output charset name
  68. */
  69. public function get_charset()
  70. {
  71. return $this->charset;
  72. }
  73. /**
  74. * Set environment variable
  75. *
  76. * @param string $name Property name
  77. * @param mixed $value Property value
  78. */
  79. public function set_env($name, $value)
  80. {
  81. $this->env[$name] = $value;
  82. }
  83. /**
  84. * Environment variable getter.
  85. *
  86. * @param string $name Property name
  87. *
  88. * @return mixed Property value
  89. */
  90. public function get_env($name)
  91. {
  92. return $this->env[$name];
  93. }
  94. /**
  95. * Delete all stored env variables and commands
  96. */
  97. public function reset()
  98. {
  99. $this->env = array();
  100. }
  101. /**
  102. * Invoke display_message command
  103. *
  104. * @param string $message Message to display
  105. * @param string $type Message type [notice|confirm|error]
  106. * @param array $vars Key-value pairs to be replaced in localized text
  107. * @param boolean $override Override last set message
  108. * @param int $timeout Message displaying time in seconds
  109. */
  110. abstract function show_message($message, $type = 'notice', $vars = null, $override = true, $timeout = 0);
  111. /**
  112. * Redirect to a certain url.
  113. *
  114. * @param mixed $p Either a string with the action or url parameters as key-value pairs
  115. * @param int $delay Delay in seconds
  116. */
  117. abstract function redirect($p = array(), $delay = 1);
  118. /**
  119. * Send output to the client.
  120. */
  121. abstract function send();
  122. /**
  123. * Send HTTP headers to prevent caching a page
  124. */
  125. public function nocacheing_headers()
  126. {
  127. if (headers_sent()) {
  128. return;
  129. }
  130. header("Expires: ".gmdate("D, d M Y H:i:s")." GMT");
  131. header("Last-Modified: ".gmdate("D, d M Y H:i:s")." GMT");
  132. // We need to set the following headers to make downloads work using IE in HTTPS mode.
  133. if ($this->browser->ie && rcube_utils::https_check()) {
  134. header('Pragma: private');
  135. header("Cache-Control: private, must-revalidate");
  136. }
  137. else {
  138. header("Cache-Control: private, no-cache, no-store, must-revalidate, post-check=0, pre-check=0");
  139. header("Pragma: no-cache");
  140. }
  141. }
  142. /**
  143. * Send header with expire date 30 days in future
  144. *
  145. * @param int Expiration time in seconds
  146. */
  147. public function future_expire_header($offset = 2600000)
  148. {
  149. if (headers_sent()) {
  150. return;
  151. }
  152. header("Expires: " . gmdate("D, d M Y H:i:s", time()+$offset) . " GMT");
  153. header("Cache-Control: max-age=$offset");
  154. header("Pragma: ");
  155. }
  156. /**
  157. * Send browser compatibility/security/etc. headers
  158. */
  159. public function common_headers()
  160. {
  161. if (headers_sent()) {
  162. return;
  163. }
  164. // Unlock IE compatibility mode
  165. if ($this->browser->ie) {
  166. header('X-UA-Compatible: IE=edge');
  167. }
  168. // Request browser to disable DNS prefetching (CVE-2010-0464)
  169. header("X-DNS-Prefetch-Control: off");
  170. // send CSRF and clickjacking protection headers
  171. if ($xframe = $this->app->config->get('x_frame_options', 'sameorigin')) {
  172. header('X-Frame-Options: ' . $xframe);
  173. }
  174. }
  175. /**
  176. * Show error page and terminate script execution
  177. *
  178. * @param int $code Error code
  179. * @param string $message Error message
  180. */
  181. public function raise_error($code, $message)
  182. {
  183. // STUB: to be overloaded by specific output classes
  184. fputs(STDERR, "Error $code: $message\n");
  185. exit(-1);
  186. }
  187. /**
  188. * Create an edit field for inclusion on a form
  189. *
  190. * @param string $col Field name
  191. * @param string $value Field value
  192. * @param array $attrib HTML element attributes for the field
  193. * @param string $type HTML element type (default 'text')
  194. *
  195. * @return string HTML field definition
  196. */
  197. public static function get_edit_field($col, $value, $attrib, $type = 'text')
  198. {
  199. static $colcounts = array();
  200. $fname = '_'.$col;
  201. $attrib['name'] = $fname . ($attrib['array'] ? '[]' : '');
  202. $attrib['class'] = trim($attrib['class'] . ' ff_' . $col);
  203. if ($type == 'checkbox') {
  204. $attrib['value'] = '1';
  205. $input = new html_checkbox($attrib);
  206. }
  207. else if ($type == 'textarea') {
  208. $attrib['cols'] = $attrib['size'];
  209. $input = new html_textarea($attrib);
  210. }
  211. else if ($type == 'select') {
  212. $input = new html_select($attrib);
  213. $input->add('---', '');
  214. $input->add(array_values($attrib['options']), array_keys($attrib['options']));
  215. }
  216. else if ($type == 'password' || $attrib['type'] == 'password') {
  217. $input = new html_passwordfield($attrib);
  218. }
  219. else {
  220. if ($attrib['type'] != 'text' && $attrib['type'] != 'hidden') {
  221. $attrib['type'] = 'text';
  222. }
  223. $input = new html_inputfield($attrib);
  224. }
  225. // use value from post
  226. if (isset($_POST[$fname])) {
  227. $postvalue = rcube_utils::get_input_value($fname, rcube_utils::INPUT_POST, true);
  228. $value = $attrib['array'] ? $postvalue[intval($colcounts[$col]++)] : $postvalue;
  229. }
  230. $out = $input->show($value);
  231. return $out;
  232. }
  233. /**
  234. * Convert a variable into a javascript object notation
  235. *
  236. * @param mixed $input Input value
  237. * @param boolean $pretty Enable JSON formatting
  238. * @param boolean $inline Enable inline mode (generates output safe for use inside HTML)
  239. *
  240. * @return string Serialized JSON string
  241. */
  242. public static function json_serialize($input, $pretty = false, $inline = true)
  243. {
  244. // The input need to be valid UTF-8 to use with json_encode()
  245. $input = rcube_charset::clean($input);
  246. $options = 0;
  247. // JSON_HEX_TAG is needed for inlining JSON inside of the <script> tag
  248. // if input contains a html tag it will cause issues (#6207)
  249. if ($inline) {
  250. $options |= JSON_HEX_TAG;
  251. }
  252. if ($pretty) {
  253. $options |= JSON_PRETTY_PRINT;
  254. }
  255. // sometimes even using rcube_charset::clean() the input contains invalid UTF-8 sequences
  256. // that's why we have @ here
  257. return @json_encode($input, $options);
  258. }
  259. }