/lenasys/trunk

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/lenasys/trunk
20.1.1 by galaxyAbstractor
* Added an simple admin panel to the codeviewer-cmssy stuff
1
<?php  if ( ! defined('BASEPATH')) exit('No direct script access allowed');
2
/**
3
 * CodeIgniter
4
 *
5
 * An open source application development framework for PHP 5.1.6 or newer
6
 *
7
 * @package		CodeIgniter
8
 * @author		ExpressionEngine Dev Team
9
 * @copyright	Copyright (c) 2008 - 2011, EllisLab, Inc.
10
 * @license		http://codeigniter.com/user_guide/license.html
11
 * @link		http://codeigniter.com
12
 * @since		Version 1.0
13
 * @filesource
14
 */
15
16
// ------------------------------------------------------------------------
17
18
/**
19
 * Output Class
20
 *
21
 * Responsible for sending final output to browser
22
 *
23
 * @package		CodeIgniter
24
 * @subpackage	Libraries
25
 * @category	Output
26
 * @author		ExpressionEngine Dev Team
27
 * @link		http://codeigniter.com/user_guide/libraries/output.html
28
 */
29
class CI_Output {
30
31
	/**
32
	 * Current output string
33
	 *
34
	 * @var string
35
	 * @access 	protected
36
	 */
37
	protected $final_output;
38
	/**
39
	 * Cache expiration time
40
	 *
41
	 * @var int
42
	 * @access 	protected
43
	 */
44
	protected $cache_expiration	= 0;
45
	/**
46
	 * List of server headers
47
	 *
48
	 * @var array
49
	 * @access 	protected
50
	 */
51
	protected $headers			= array();
52
	/**
53
	 * List of mime types
54
	 *
55
	 * @var array
56
	 * @access 	protected
57
	 */
58
	protected $mime_types		= array();
59
	/**
60
	 * Determines wether profiler is enabled
61
	 *
62
	 * @var book
63
	 * @access 	protected
64
	 */
65
	protected $enable_profiler	= FALSE;
66
	/**
67
	 * Determines if output compression is enabled
68
	 *
69
	 * @var bool
70
	 * @access 	protected
71
	 */
72
	protected $_zlib_oc			= FALSE;
73
	/**
74
	 * List of profiler sections
75
	 *
76
	 * @var array
77
	 * @access 	protected
78
	 */
79
	protected $_profiler_sections = array();
80
	/**
81
	 * Whether or not to parse variables like {elapsed_time} and {memory_usage}
82
	 *
83
	 * @var bool
84
	 * @access 	protected
85
	 */
86
	protected $parse_exec_vars	= TRUE;
87
88
	/**
89
	 * Constructor
90
	 *
91
	 */
92
	function __construct()
93
	{
94
		$this->_zlib_oc = @ini_get('zlib.output_compression');
95
96
		// Get mime types for later
97
		if (defined('ENVIRONMENT') AND file_exists(APPPATH.'config/'.ENVIRONMENT.'/mimes.php'))
98
		{
99
		    include APPPATH.'config/'.ENVIRONMENT.'/mimes.php';
100
		}
101
		else
102
		{
103
			include APPPATH.'config/mimes.php';
104
		}
105
106
107
		$this->mime_types = $mimes;
108
109
		log_message('debug', "Output Class Initialized");
110
	}
111
112
	// --------------------------------------------------------------------
113
114
	/**
115
	 * Get Output
116
	 *
117
	 * Returns the current output string
118
	 *
119
	 * @access	public
120
	 * @return	string
121
	 */
122
	function get_output()
123
	{
124
		return $this->final_output;
125
	}
126
127
	// --------------------------------------------------------------------
128
129
	/**
130
	 * Set Output
131
	 *
132
	 * Sets the output string
133
	 *
134
	 * @access	public
135
	 * @param	string
136
	 * @return	void
137
	 */
138
	function set_output($output)
139
	{
140
		$this->final_output = $output;
141
142
		return $this;
143
	}
144
145
	// --------------------------------------------------------------------
146
147
	/**
148
	 * Append Output
149
	 *
150
	 * Appends data onto the output string
151
	 *
152
	 * @access	public
153
	 * @param	string
154
	 * @return	void
155
	 */
156
	function append_output($output)
157
	{
158
		if ($this->final_output == '')
159
		{
160
			$this->final_output = $output;
161
		}
162
		else
163
		{
164
			$this->final_output .= $output;
165
		}
166
167
		return $this;
168
	}
169
170
	// --------------------------------------------------------------------
171
172
	/**
173
	 * Set Header
174
	 *
175
	 * Lets you set a server header which will be outputted with the final display.
176
	 *
177
	 * Note:  If a file is cached, headers will not be sent.  We need to figure out
178
	 * how to permit header data to be saved with the cache data...
179
	 *
180
	 * @access	public
181
	 * @param	string
182
	 * @param 	bool
183
	 * @return	void
184
	 */
185
	function set_header($header, $replace = TRUE)
186
	{
187
		// If zlib.output_compression is enabled it will compress the output,
188
		// but it will not modify the content-length header to compensate for
189
		// the reduction, causing the browser to hang waiting for more data.
190
		// We'll just skip content-length in those cases.
191
192
		if ($this->_zlib_oc && strncasecmp($header, 'content-length', 14) == 0)
193
		{
194
			return;
195
		}
196
197
		$this->headers[] = array($header, $replace);
198
199
		return $this;
200
	}
201
202
	// --------------------------------------------------------------------
203
204
	/**
205
	 * Set Content Type Header
206
	 *
207
	 * @access	public
208
	 * @param	string	extension of the file we're outputting
209
	 * @return	void
210
	 */
211
	function set_content_type($mime_type)
212
	{
213
		if (strpos($mime_type, '/') === FALSE)
214
		{
215
			$extension = ltrim($mime_type, '.');
216
217
			// Is this extension supported?
218
			if (isset($this->mime_types[$extension]))
219
			{
220
				$mime_type =& $this->mime_types[$extension];
221
222
				if (is_array($mime_type))
223
				{
224
					$mime_type = current($mime_type);
225
				}
226
			}
227
		}
228
229
		$header = 'Content-Type: '.$mime_type;
230
231
		$this->headers[] = array($header, TRUE);
232
233
		return $this;
234
	}
235
236
	// --------------------------------------------------------------------
237
238
	/**
239
	 * Set HTTP Status Header
240
	 * moved to Common procedural functions in 1.7.2
241
	 *
242
	 * @access	public
243
	 * @param	int		the status code
244
	 * @param	string
245
	 * @return	void
246
	 */
247
	function set_status_header($code = 200, $text = '')
248
	{
249
		set_status_header($code, $text);
250
251
		return $this;
252
	}
253
254
	// --------------------------------------------------------------------
255
256
	/**
257
	 * Enable/disable Profiler
258
	 *
259
	 * @access	public
260
	 * @param	bool
261
	 * @return	void
262
	 */
263
	function enable_profiler($val = TRUE)
264
	{
265
		$this->enable_profiler = (is_bool($val)) ? $val : TRUE;
266
267
		return $this;
268
	}
269
270
	// --------------------------------------------------------------------
271
272
	/**
273
	 * Set Profiler Sections
274
	 *
275
	 * Allows override of default / config settings for Profiler section display
276
	 *
277
	 * @access	public
278
	 * @param	array
279
	 * @return	void
280
	 */
281
	function set_profiler_sections($sections)
282
	{
283
		foreach ($sections as $section => $enable)
284
		{
285
			$this->_profiler_sections[$section] = ($enable !== FALSE) ? TRUE : FALSE;
286
		}
287
288
		return $this;
289
	}
290
291
	// --------------------------------------------------------------------
292
293
	/**
294
	 * Set Cache
295
	 *
296
	 * @access	public
297
	 * @param	integer
298
	 * @return	void
299
	 */
300
	function cache($time)
301
	{
302
		$this->cache_expiration = ( ! is_numeric($time)) ? 0 : $time;
303
304
		return $this;
305
	}
306
307
	// --------------------------------------------------------------------
308
309
	/**
310
	 * Display Output
311
	 *
312
	 * All "view" data is automatically put into this variable by the controller class:
313
	 *
314
	 * $this->final_output
315
	 *
316
	 * This function sends the finalized output data to the browser along
317
	 * with any server headers and profile data.  It also stops the
318
	 * benchmark timer so the page rendering speed and memory usage can be shown.
319
	 *
320
	 * @access	public
321
	 * @param 	string
322
	 * @return	mixed
323
	 */
324
	function _display($output = '')
325
	{
326
		// Note:  We use globals because we can't use $CI =& get_instance()
327
		// since this function is sometimes called by the caching mechanism,
328
		// which happens before the CI super object is available.
329
		global $BM, $CFG;
330
331
		// Grab the super object if we can.
332
		if (class_exists('CI_Controller'))
333
		{
334
			$CI =& get_instance();
335
		}
336
337
		// --------------------------------------------------------------------
338
339
		// Set the output data
340
		if ($output == '')
341
		{
342
			$output =& $this->final_output;
343
		}
344
345
		// --------------------------------------------------------------------
346
347
		// Do we need to write a cache file?  Only if the controller does not have its
348
		// own _output() method and we are not dealing with a cache file, which we
349
		// can determine by the existence of the $CI object above
350
		if ($this->cache_expiration > 0 && isset($CI) && ! method_exists($CI, '_output'))
351
		{
352
			$this->_write_cache($output);
353
		}
354
355
		// --------------------------------------------------------------------
356
357
		// Parse out the elapsed time and memory usage,
358
		// then swap the pseudo-variables with the data
359
360
		$elapsed = $BM->elapsed_time('total_execution_time_start', 'total_execution_time_end');
361
362
		if ($this->parse_exec_vars === TRUE)
363
		{
364
			$memory	 = ( ! function_exists('memory_get_usage')) ? '0' : round(memory_get_usage()/1024/1024, 2).'MB';
365
366
			$output = str_replace('{elapsed_time}', $elapsed, $output);
367
			$output = str_replace('{memory_usage}', $memory, $output);
368
		}
369
370
		// --------------------------------------------------------------------
371
372
		// Is compression requested?
373
		if ($CFG->item('compress_output') === TRUE && $this->_zlib_oc == FALSE)
374
		{
375
			if (extension_loaded('zlib'))
376
			{
377
				if (isset($_SERVER['HTTP_ACCEPT_ENCODING']) AND strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip') !== FALSE)
378
				{
379
					ob_start('ob_gzhandler');
380
				}
381
			}
382
		}
383
384
		// --------------------------------------------------------------------
385
386
		// Are there any server headers to send?
387
		if (count($this->headers) > 0)
388
		{
389
			foreach ($this->headers as $header)
390
			{
391
				@header($header[0], $header[1]);
392
			}
393
		}
394
395
		// --------------------------------------------------------------------
396
397
		// Does the $CI object exist?
398
		// If not we know we are dealing with a cache file so we'll
399
		// simply echo out the data and exit.
400
		if ( ! isset($CI))
401
		{
402
			echo $output;
403
			log_message('debug', "Final output sent to browser");
404
			log_message('debug', "Total execution time: ".$elapsed);
405
			return TRUE;
406
		}
407
408
		// --------------------------------------------------------------------
409
410
		// Do we need to generate profile data?
411
		// If so, load the Profile class and run it.
412
		if ($this->enable_profiler == TRUE)
413
		{
414
			$CI->load->library('profiler');
415
416
			if ( ! empty($this->_profiler_sections))
417
			{
418
				$CI->profiler->set_sections($this->_profiler_sections);
419
			}
420
421
			// If the output data contains closing </body> and </html> tags
422
			// we will remove them and add them back after we insert the profile data
423
			if (preg_match("|</body>.*?</html>|is", $output))
424
			{
425
				$output  = preg_replace("|</body>.*?</html>|is", '', $output);
426
				$output .= $CI->profiler->run();
427
				$output .= '</body></html>';
428
			}
429
			else
430
			{
431
				$output .= $CI->profiler->run();
432
			}
433
		}
434
435
		// --------------------------------------------------------------------
436
437
		// Does the controller contain a function named _output()?
438
		// If so send the output there.  Otherwise, echo it.
439
		if (method_exists($CI, '_output'))
440
		{
441
			$CI->_output($output);
442
		}
443
		else
444
		{
445
			echo $output;  // Send it to the browser!
446
		}
447
448
		log_message('debug', "Final output sent to browser");
449
		log_message('debug', "Total execution time: ".$elapsed);
450
	}
451
452
	// --------------------------------------------------------------------
453
454
	/**
455
	 * Write a Cache File
456
	 *
457
	 * @access	public
458
	 * @param 	string
459
	 * @return	void
460
	 */
461
	function _write_cache($output)
462
	{
463
		$CI =& get_instance();
464
		$path = $CI->config->item('cache_path');
465
466
		$cache_path = ($path == '') ? APPPATH.'cache/' : $path;
467
468
		if ( ! is_dir($cache_path) OR ! is_really_writable($cache_path))
469
		{
470
			log_message('error', "Unable to write cache file: ".$cache_path);
471
			return;
472
		}
473
474
		$uri =	$CI->config->item('base_url').
475
				$CI->config->item('index_page').
476
				$CI->uri->uri_string();
477
478
		$cache_path .= md5($uri);
479
480
		if ( ! $fp = @fopen($cache_path, FOPEN_WRITE_CREATE_DESTRUCTIVE))
481
		{
482
			log_message('error', "Unable to write cache file: ".$cache_path);
483
			return;
484
		}
485
486
		$expire = time() + ($this->cache_expiration * 60);
487
488
		if (flock($fp, LOCK_EX))
489
		{
490
			fwrite($fp, $expire.'TS--->'.$output);
491
			flock($fp, LOCK_UN);
492
		}
493
		else
494
		{
495
			log_message('error', "Unable to secure a file lock for file at: ".$cache_path);
496
			return;
497
		}
498
		fclose($fp);
499
		@chmod($cache_path, FILE_WRITE_MODE);
500
501
		log_message('debug', "Cache file written: ".$cache_path);
502
	}
503
504
	// --------------------------------------------------------------------
505
506
	/**
507
	 * Update/serve a cached file
508
	 *
509
	 * @access	public
510
	 * @param 	object	config class
511
	 * @param 	object	uri class
512
	 * @return	void
513
	 */
514
	function _display_cache(&$CFG, &$URI)
515
	{
516
		$cache_path = ($CFG->item('cache_path') == '') ? APPPATH.'cache/' : $CFG->item('cache_path');
517
518
		// Build the file path.  The file name is an MD5 hash of the full URI
519
		$uri =	$CFG->item('base_url').
520
				$CFG->item('index_page').
521
				$URI->uri_string;
522
523
		$filepath = $cache_path.md5($uri);
524
525
		if ( ! @file_exists($filepath))
526
		{
527
			return FALSE;
528
		}
529
530
		if ( ! $fp = @fopen($filepath, FOPEN_READ))
531
		{
532
			return FALSE;
533
		}
534
535
		flock($fp, LOCK_SH);
536
537
		$cache = '';
538
		if (filesize($filepath) > 0)
539
		{
540
			$cache = fread($fp, filesize($filepath));
541
		}
542
543
		flock($fp, LOCK_UN);
544
		fclose($fp);
545
546
		// Strip out the embedded timestamp
547
		if ( ! preg_match("/(\d+TS--->)/", $cache, $match))
548
		{
549
			return FALSE;
550
		}
551
552
		// Has the file expired? If so we'll delete it.
553
		if (time() >= trim(str_replace('TS--->', '', $match['1'])))
554
		{
555
			if (is_really_writable($cache_path))
556
			{
557
				@unlink($filepath);
558
				log_message('debug', "Cache file has expired. File deleted");
559
				return FALSE;
560
			}
561
		}
562
563
		// Display the cache
564
		$this->_display(str_replace($match['0'], '', $cache));
565
		log_message('debug', "Cache file is current. Sending it to browser.");
566
		return TRUE;
567
	}
568
569
570
}
571
// END Output Class
572
573
/* End of file Output.php */
574
/* Location: ./system/core/Output.php */