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