PageRenderTime 49ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/system/core/core.output.php

https://github.com/danboy/Croissierd
PHP | 554 lines | 318 code | 119 blank | 117 comment | 80 complexity | 10a6af79d3a523aedcfe539127151ac1 MD5 | raw file
  1. <?php
  2. /*
  3. =====================================================
  4. ExpressionEngine - by EllisLab
  5. -----------------------------------------------------
  6. http://expressionengine.com/
  7. -----------------------------------------------------
  8. Copyright (c) 2003 - 2010 EllisLab, Inc.
  9. =====================================================
  10. THIS IS COPYRIGHTED SOFTWARE
  11. PLEASE READ THE LICENSE AGREEMENT
  12. http://expressionengine.com/docs/license.html
  13. =====================================================
  14. File: core.output.php
  15. -----------------------------------------------------
  16. Purpose: Display class. All browser output is
  17. managed by this file.
  18. =====================================================
  19. */
  20. if ( ! defined('EXT'))
  21. {
  22. exit('Invalid file request');
  23. }
  24. class Output {
  25. var $refresh_msg = TRUE; // TRUE/FALSE - whether to show the "You will be redirected in 5 seconds" message.
  26. var $resresh_time = 1; // Number of seconds for redirects - there is a silly typo here that for legacy reasons we're leaving in.
  27. var $out_type = 'webpage';
  28. var $out_queue = '';
  29. var $remove_unparsed_variables = TRUE; // whether to remove left-over variables that had bad syntax
  30. /** -------------------------------------------
  31. /** Build "output queue"
  32. /** -------------------------------------------*/
  33. function build_queue($output)
  34. {
  35. $this->out_queue = $output;
  36. }
  37. /* END */
  38. /** -------------------------------------------
  39. /** Sends Out an HTTP Status Header
  40. /** -------------------------------------------*/
  41. function http_status_header($code, $text='')
  42. {
  43. if ($text == '')
  44. {
  45. switch($code)
  46. {
  47. case 200:
  48. $text = 'OK';
  49. break;
  50. case 304:
  51. $text = 'Not Modified';
  52. break;
  53. case 401:
  54. $text = 'Unauthorized';
  55. break;
  56. case 404:
  57. $text = 'Not Found';
  58. break;
  59. }
  60. }
  61. if (substr(php_sapi_name(), 0, 3) == 'cgi')
  62. {
  63. @header("Status: {$code} {$text}", TRUE);
  64. }
  65. elseif ($_SERVER['SERVER_PROTOCOL'] == 'HTTP/1.1' OR $_SERVER['SERVER_PROTOCOL'] == 'HTTP/1.0')
  66. {
  67. @header($_SERVER['SERVER_PROTOCOL']." {$code} {$text}", TRUE, $code);
  68. }
  69. else
  70. {
  71. @header("HTTP/1.1 {$code} {$text}", TRUE, $code);
  72. }
  73. }
  74. /* END */
  75. /** -------------------------------------------
  76. /** Display the final browser output
  77. /** -------------------------------------------*/
  78. function display_final_output($output = '')
  79. {
  80. global $IN, $PREFS, $TMPL, $BM, $DB, $SESS, $FNS, $LOC;
  81. /** -----------------------------------
  82. /** Fetch the output
  83. /** -----------------------------------*/
  84. if ($output == '')
  85. $output = $this->out_queue;
  86. /** -----------------------------------
  87. /** Start output buffering
  88. /** -----------------------------------*/
  89. ob_start();
  90. /** -----------------------------------
  91. /** Generate HTTP headers
  92. /** -----------------------------------*/
  93. if ($PREFS->ini('send_headers') == 'y' && $this->out_type != 'rss' && $this->out_type != '404')
  94. {
  95. $this->http_status_header(200);
  96. @header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
  97. @header("Last-Modified: ".gmdate("D, d M Y H:i:s")." GMT");
  98. @header("Pragma: no-cache");
  99. }
  100. if ($this->out_type == 'webpage')
  101. {
  102. @header("Content-Type: text/html; charset=".$PREFS->ini('charset'));
  103. }
  104. /** -----------------------------------
  105. /** Generate 404 headers
  106. /** -----------------------------------*/
  107. if ($this->out_type == '404')
  108. {
  109. $this->http_status_header(404);
  110. @header("Date: ".gmdate("D, d M Y H:i:s")." GMT");
  111. }
  112. /** -----------------------------------
  113. /** Send CSS header
  114. /** -----------------------------------*/
  115. if ($this->out_type == 'css')
  116. {
  117. @header("Content-type: text/css");
  118. }
  119. /** -----------------------------------
  120. /** Send Script header
  121. /** -----------------------------------*/
  122. if ($this->out_type == 'js')
  123. {
  124. @header("Content-type: text/javascript");
  125. }
  126. /** -----------------------------------
  127. /** Send XML header
  128. /** -----------------------------------*/
  129. if ($this->out_type == 'xml')
  130. {
  131. //@header("Content-Type: text/xml; charset=".$PREFS->ini('charset'));
  132. @header("Content-Type: text/xml");
  133. $output = trim($output);
  134. }
  135. /** -----------------------------------
  136. /** Send RSS header
  137. /** -----------------------------------*/
  138. if ($this->out_type == 'rss')
  139. {
  140. $request = ( ! function_exists('getallheaders')) ? array() : @getallheaders();
  141. if (preg_match("|<ee\:last_update>(.*?)<\/ee\:last_update>|",$output,$matches))
  142. {
  143. $last_update = $matches['1'];
  144. $output = str_replace($matches['0'],'',$output);
  145. }
  146. else
  147. {
  148. $last_update = $LOC->set_gmt();
  149. }
  150. $output = trim($output);
  151. /** --------------------------------------------
  152. /** Check for the 'If-Modified-Since' Header
  153. /** --------------------------------------------*/
  154. if ($PREFS->ini('send_headers') == 'y' && isset($request['If-Modified-Since']) && trim($request['If-Modified-Since']) != '')
  155. {
  156. $x = explode(';',$request['If-Modified-Since']);
  157. $modify_tstamp = strtotime($x['0']);
  158. /** -------------------------------------
  159. /** If no new content, send no data
  160. /** -------------------------------------*/
  161. if ($last_update <= $modify_tstamp)
  162. {
  163. $this->http_status_header(304);
  164. @exit;
  165. }
  166. /** -------------------------------------------------
  167. /** Delta Done in RSS Module, send RFC3229 headers
  168. /** -------------------------------------------------*/
  169. if (isset($request['A-IM']) && (stristr($request['A-IM'],'feed') !== false OR stristr($request['A-IM'],'diffe') !== false))
  170. {
  171. $gzip_im = ($PREFS->ini('gzip_output') == 'y') ? ', gzip' : '';
  172. $main_im = (stristr($request['A-IM'],'diffe') !== false) ? 'diffe' : '';
  173. $main_im = (stristr($request['A-IM'],'feed') !== false) ? 'feed' : $main_im;
  174. /* The RFC-3229 spec says to use the 226 header code, but
  175. alas only dev versions of Apache use it. For the time
  176. being we will have to use the usual 200 OK response.
  177. Alternatively, someone could use the Speedy Feed Apache mod
  178. http://asdf.blogs.com/asdf/2004/09/mod_speedyfeed__3.html
  179. */
  180. $apache_modules = ( ! function_exists('apache_get_modules')) ? array() : @apache_get_modules();
  181. // Looks like this: Apache/1.3.29 (Unix) PHP/4.3.4
  182. $apache_version = ( ! function_exists('apache_get_version')) ? '' : @apache_get_version();
  183. $apache_version_string = explode(' ',$apache_version);
  184. $apache_version_number = explode('/',$apache_version_string['0']);
  185. $apache_version_points = explode('.',$apache_version_number['0']);
  186. if (in_array('mod_speedyfeed',$apache_modules))
  187. {
  188. @header('HTTP/1.1 226 IM Used');
  189. }
  190. else
  191. {
  192. $this->http_status_header(200);
  193. }
  194. @header('Cache-Control: no-store, im');
  195. @header('IM: '.$main_im.$gzip_im);
  196. @header('Last-Modified: '.gmdate('D, d M Y H:i:s', $last_update).' GMT');
  197. }
  198. else
  199. {
  200. $this->http_status_header(200);
  201. @header('Expires: '.gmdate('D, d M Y H:i:s', $last_update+(60*60)).' GMT'); // One hour
  202. @header('Last-Modified: '.gmdate('D, d M Y H:i:s', $last_update).' GMT');
  203. @header("Cache-Control: no-store, no-cache, must-revalidate");
  204. @header("Cache-Control: post-check=0, pre-check=0", false);
  205. @header("Pragma: no-cache");
  206. }
  207. }
  208. else
  209. {
  210. $this->http_status_header(200);
  211. @header('Expires: '.gmdate('D, d M Y H:i:s', $last_update+(60*60)).' GMT'); // One hour
  212. @header('Last-Modified: '.gmdate('D, d M Y H:i:s', $last_update).' GMT');
  213. @header("Cache-Control: no-store, no-cache, must-revalidate");
  214. @header("Cache-Control: post-check=0, pre-check=0", false);
  215. @header("Pragma: no-cache");
  216. }
  217. @header("Content-Type: text/xml; charset=".$PREFS->ini('charset'));
  218. /** -----------------------------------
  219. /** Swap XML declaration for RSS files
  220. /** -----------------------------------*/
  221. $output = preg_replace("/{\?xml(.+?)\?}/", "<?xml\\1?".">", $output);
  222. }
  223. /** -----------------------------------
  224. /** Fetch the buffered output
  225. /** -----------------------------------*/
  226. echo $output;
  227. $buffer = ob_get_contents();
  228. ob_end_clean();
  229. /** -------------------------------------
  230. /** Parse elapsed time and query count
  231. /** -------------------------------------*/
  232. $BM->mark('end');
  233. if (REQ == 'CP')
  234. {
  235. $buffer = str_replace('{cp:elapsed_time}', $BM->elapsed('start', 'end'), $buffer);
  236. }
  237. else
  238. {
  239. $buffer = str_replace(LD.'elapsed_time'.RD, $BM->elapsed('start', 'end'), $buffer);
  240. $buffer = str_replace(LD.'total_queries'.RD, $DB->q_count, $buffer);
  241. /** --------------------------------------
  242. /** Remove bad variables
  243. /** --------------------------------------*/
  244. // If 'debug' is turned off, we will remove any variables that didn't get parsed due to syntax errors.
  245. if ($PREFS->ini('debug') == 0 AND $this->remove_unparsed_variables == TRUE)
  246. {
  247. $buffer = preg_replace("/".LD."[^;\n]+?".RD."/", '', $buffer);
  248. }
  249. }
  250. /** ---------------------------------------
  251. /** Show queries if enabled for debugging
  252. /** ---------------------------------------*/
  253. // For security reasons, we won't show the queries
  254. // unless the current user is a logged-in Super Admin
  255. if ($DB->show_queries === TRUE AND isset($DB->queries))
  256. {
  257. if ($SESS->userdata['group_id'] == 1 && (REQ == 'CP' OR (is_object($TMPL) && $TMPL->template_type != 'js')))
  258. {
  259. $i = 1;
  260. $buffer .= '<div style="color: #333; background-color: #ededed; margin:10px; padding-bottom:10px;">';
  261. $buffer .= "<div style=\"text-align: left; font-family: Sans-serif; font-size: 11px; margin: 12px; padding: 6px\"><hr size='1'><b>SQL QUERIES</b><hr size='1'></div>";
  262. $highlight = array('SELECT', 'FROM', 'WHERE', 'AND', 'LEFT JOIN', 'ORDER BY', 'LIMIT', 'INSERT', 'INTO', 'VALUES', 'UPDATE');
  263. foreach ($DB->queries as $val)
  264. {
  265. $val = htmlspecialchars($val, ENT_QUOTES);
  266. foreach ($highlight as $bold)
  267. {
  268. $val = str_replace($bold, '<b>'.$bold.'</b>', $val);
  269. }
  270. $buffer .= "<div style=\"text-align: left; font-family: Sans-serif; font-size: 11px; margin: 12px; padding: 6px\"><hr size='1'>";
  271. $buffer .= "<h5>".$i.'</h5>';
  272. $buffer .= str_replace("\t", " ", $val);
  273. $buffer .= "</div>";
  274. $i++;
  275. }
  276. $buffer .= '</div>';
  277. }
  278. }
  279. if (is_object($TMPL) && isset($TMPL->debugging) && $TMPL->debugging === TRUE && $TMPL->template_type != 'js')
  280. {
  281. if ($SESS->userdata['group_id'] == 1)
  282. {
  283. $buffer .= '<div style="color: #333; background-color: #ededed; margin:10px; padding-bottom:10px;">';
  284. $buffer .= "<div style=\"text-align: left; font-family: Sans-serif; font-size: 11px; margin: 12px; padding: 6px\"><hr size='1'><b>TEMPLATE DEBUGGING</b><hr size='1'></div>";
  285. foreach ($TMPL->log as $val)
  286. {
  287. $val = str_replace(array("\t", '&amp;nbsp;'), array(' ', '&nbsp;'), htmlentities($val, ENT_QUOTES));
  288. $x = explode(':', $val, 2);
  289. if (sizeof($x) > 1)
  290. {
  291. $val = '<strong>'.$x['0'].':</strong>'.$x['1'];
  292. }
  293. else
  294. {
  295. $val = '<strong>'.$val.'</strong>';
  296. }
  297. $buffer .= "<div style=\"text-align: left; font-family: Sans-serif; font-size: 11px; margin: 12px 12px 6px 22px;\">".$val."</div>";
  298. }
  299. if (function_exists('memory_get_usage') AND ($usage = memory_get_usage()) != '')
  300. {
  301. $buffer .= "<div style='text-align: left; font-family: Sans-serif; font-size: 11px; margin: 12px 12px 6px 22px;'><strong>Memory Usage: ".number_format($usage)." bytes</strong></div>";
  302. }
  303. $buffer .= '</div>';
  304. }
  305. }
  306. /** -----------------------------------
  307. /** Compress the output
  308. /** -----------------------------------*/
  309. if ($PREFS->ini('gzip_output') == 'y' AND REQ == 'PAGE')
  310. {
  311. ob_start('ob_gzhandler');
  312. }
  313. /** -----------------------------------
  314. /** Send it to the browser
  315. /** -----------------------------------*/
  316. echo $buffer;
  317. }
  318. /* END */
  319. /** -------------------------------------------
  320. /** Display fatal error message
  321. /** -------------------------------------------*/
  322. function fatal_error($error_msg = '', $use_lang = TRUE)
  323. {
  324. global $LANG;
  325. $heading = ($use_lang == TRUE && is_object($LANG)) ? $LANG->line('error') : 'Error Message';
  326. $data = array( 'title' => $heading,
  327. 'heading' => $heading,
  328. 'content' => '<p>'.$error_msg.'</p>'
  329. );
  330. $this->show_message($data);
  331. }
  332. /* END */
  333. /** -------------------------------------------
  334. /** System is off message
  335. /** -------------------------------------------*/
  336. function system_off_msg()
  337. {
  338. global $LANG, $DB, $PREFS;
  339. $query = $DB->query("SELECT template_data FROM exp_specialty_templates WHERE site_id = '".$DB->escape_str($PREFS->ini('site_id'))."' AND template_name = 'offline_template'");
  340. echo $query->row['template_data'];
  341. exit;
  342. }
  343. /* END */
  344. /** ----------------------------------------
  345. /** Show message
  346. /** ----------------------------------------*/
  347. // This function and the next enable us to show error
  348. // messages to users when needed. For example, when
  349. // a form is submitted without the required info.
  350. // This is not used in the control panel, only with
  351. // publicly accessible pages.
  352. function show_message($data, $xhtml = TRUE)
  353. {
  354. global $LANG, $DB, $PREFS, $REGX;
  355. foreach (array('title', 'heading', 'content', 'redirect', 'rate', 'link') as $val)
  356. {
  357. if ( ! isset($data[$val]))
  358. {
  359. $data[$val] = '';
  360. }
  361. }
  362. if ( ! is_numeric($data['rate']) OR $data['rate'] == '')
  363. {
  364. $data['rate'] = $this->resresh_time; // There is a silly typo here that for legacy reasons we're leaving in.
  365. }
  366. $data['meta_refresh'] = ($data['redirect'] != '') ? "<meta http-equiv='refresh' content='".$data['rate']."; url=".$REGX->xss_clean($data['redirect'])."'>" : '';
  367. $data['charset'] = $PREFS->ini('charset');
  368. if (is_array($data['link']) AND count($data['link']) > 0)
  369. {
  370. $refresh_msg = ($data['redirect'] != '' AND $this->refresh_msg == TRUE) ? $LANG->line('click_if_no_redirect') : '';
  371. $ltitle = ($refresh_msg == '') ? $data['link']['1'] : $refresh_msg;
  372. $url = (strtolower($data['link']['0']) == 'javascript:history.go(-1)') ? $data['link']['0'] : $REGX->xss_clean($data['link']['0']);
  373. $data['link'] = "<a href='".$url."'>".$ltitle."</a>";
  374. }
  375. if ($xhtml == TRUE)
  376. {
  377. if ( ! class_exists('Typography'))
  378. {
  379. require PATH_CORE.'core.typography'.EXT;
  380. }
  381. $TYPE = new Typography;
  382. $data['content'] = $TYPE->parse_type(stripslashes($data['content']), array('text_format' => 'xhtml'));
  383. }
  384. $query = $DB->query("SELECT template_data FROM exp_specialty_templates WHERE site_id = '".$DB->escape_str($PREFS->ini('site_id'))."' AND template_name = 'message_template'");
  385. foreach ($data as $key => $val)
  386. {
  387. $query->row['template_data'] = str_replace('{'.$key.'}', $val, $query->row['template_data']);
  388. }
  389. echo stripslashes($query->row['template_data']);
  390. exit;
  391. }
  392. /* END */
  393. /** ----------------------------------------
  394. /** Show user error
  395. /** ----------------------------------------*/
  396. function show_user_error($type = 'submission', $errors, $heading = '')
  397. {
  398. global $LANG;
  399. if ($type != 'off')
  400. {
  401. switch($type)
  402. {
  403. case 'submission' : $heading = $LANG->line('submission_error');
  404. break;
  405. case 'general' : $heading = $LANG->line('general_error');
  406. break;
  407. default : $heading = $LANG->line('submission_error');
  408. break;
  409. }
  410. }
  411. $content = '<ul>';
  412. if ( ! is_array($errors))
  413. {
  414. $content.= "<li>".$errors."</li>\n";
  415. }
  416. else
  417. {
  418. foreach ($errors as $val)
  419. {
  420. $content.= "<li>".$val."</li>\n";
  421. }
  422. }
  423. $content .= "</ul>";
  424. $data = array( 'title' => $LANG->line('error'),
  425. 'heading' => $heading,
  426. 'content' => $content,
  427. 'redirect' => '',
  428. 'link' => array('JavaScript:history.go(-1)', $LANG->line('return_to_previous'))
  429. );
  430. $this->show_message($data, 0);
  431. }
  432. /* END */
  433. }
  434. // END CLASS
  435. ?>