*/ /** * @class DisplayHandler * @author NAVER (developers@xpressengine.com) * DisplayHandler is responsible for displaying the execution result. \n * Depending on the request type, it can display either HTML or XML content.\n * Xml content is simple xml presentation of variables in oModule while html content * is the combination of the variables of oModue and template files/. */ class DisplayHandler extends Handler { var $content_size = 0; // /< The size of displaying contents var $gz_enabled = FALSE; // / gzhandler_enable ) { $this->gz_enabled = TRUE; } // Extract contents to display by the request method if(Context::get('xeVirtualRequestMethod') == 'xml') { require_once(_XE_PATH_ . "classes/display/VirtualXMLDisplayHandler.php"); $handler = new VirtualXMLDisplayHandler(); } else if(Context::getRequestMethod() == 'XMLRPC') { require_once(_XE_PATH_ . "classes/display/XMLDisplayHandler.php"); $handler = new XMLDisplayHandler(); if(strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE') !== FALSE) { $this->gz_enabled = FALSE; } } else if(Context::getRequestMethod() == 'JSON') { require_once(_XE_PATH_ . "classes/display/JSONDisplayHandler.php"); $handler = new JSONDisplayHandler(); } else if(Context::getRequestMethod() == 'JS_CALLBACK') { require_once(_XE_PATH_ . "classes/display/JSCallbackDisplayHandler.php"); $handler = new JSCallbackDisplayHandler(); } else { require_once(_XE_PATH_ . "classes/display/HTMLDisplayHandler.php"); $handler = new HTMLDisplayHandler(); } $output = $handler->toDoc($oModule); // call a trigger before display ModuleHandler::triggerCall('display', 'before', $output); // execute add-on $called_position = 'before_display_content'; $oAddonController = getController('addon'); $addon_file = $oAddonController->getCacheFilePath(Mobile::isFromMobilePhone() ? "mobile" : "pc"); if(file_exists($addon_file)) include($addon_file); if(method_exists($handler, "prepareToPrint")) { $handler->prepareToPrint($output); } // header output $httpStatusCode = $oModule->getHttpStatusCode(); if($httpStatusCode && $httpStatusCode != 200) { $this->_printHttpStatusCode($httpStatusCode); } else { if(Context::getResponseMethod() == 'JSON' || Context::getResponseMethod() == 'JS_CALLBACK') { $this->_printJSONHeader(); } else if(Context::getResponseMethod() != 'HTML') { $this->_printXMLHeader(); } else { $this->_printHTMLHeader(); } } // debugOutput output $this->content_size = strlen($output); $output .= $this->_debugOutput(); // disable gzip if output already exists ob_flush(); if(headers_sent()) { $this->gz_enabled = FALSE; } // results directly output if($this->gz_enabled) { header("Content-Encoding: gzip"); print ob_gzhandler($output, 5); } else { print $output; } // call a trigger after display ModuleHandler::triggerCall('display', 'after', $output); flushSlowlog(); } /** * Print debugging message to designated output source depending on the value set to __DEBUG_OUTPUT_. \n * This method only functions when __DEBUG__ variable is set to 1. * __DEBUG_OUTPUT__ == 0, messages are written in ./files/_debug_message.php * @return void */ function _debugOutput() { if(!__DEBUG__) { return; } $end = getMicroTime(); // Firebug console output if(__DEBUG_OUTPUT__ == 2 && version_compare(PHP_VERSION, '6.0.0') === -1) { static $firephp; if(!isset($firephp)) { $firephp = FirePHP::getInstance(true); } if(__DEBUG_PROTECT__ == 1 && __DEBUG_PROTECT_IP__ != $_SERVER['REMOTE_ADDR']) { $firephp->fb('Change the value of __DEBUG_PROTECT_IP__ into your IP address in config/config.user.inc.php or config/config.inc.php', 'The IP address is not allowed.'); return; } // display total execution time and Request/Response info if(__DEBUG__ & 2) { $firephp->fb( array( 'Request / Response info >>> ' . $_SERVER['REQUEST_METHOD'] . ' / ' . Context::getResponseMethod(), array( array('Request URI', 'Request method', 'Response method', 'Response contents size', 'Memory peak usage'), array( sprintf("%s:%s%s%s%s", $_SERVER['SERVER_NAME'], $_SERVER['SERVER_PORT'], $_SERVER['PHP_SELF'], $_SERVER['QUERY_STRING'] ? '?' : '', $_SERVER['QUERY_STRING']), $_SERVER['REQUEST_METHOD'], Context::getResponseMethod(), $this->content_size . ' byte', FileHandler::filesize(memory_get_peak_usage()) ) ) ), 'TABLE' ); $firephp->fb( array( 'Elapsed time >>> Total : ' . sprintf('%0.5f sec', $end - __StartTime__), array(array('DB queries', 'class file load', 'Template compile', 'XmlParse compile', 'PHP', 'Widgets', 'Trans Content'), array( sprintf('%0.5f sec', $GLOBALS['__db_elapsed_time__']), sprintf('%0.5f sec', $GLOBALS['__elapsed_class_load__']), sprintf('%0.5f sec (%d called)', $GLOBALS['__template_elapsed__'], $GLOBALS['__TemplateHandlerCalled__']), sprintf('%0.5f sec', $GLOBALS['__xmlparse_elapsed__']), sprintf('%0.5f sec', $end - __StartTime__ - $GLOBALS['__template_elapsed__'] - $GLOBALS['__xmlparse_elapsed__'] - $GLOBALS['__db_elapsed_time__'] - $GLOBALS['__elapsed_class_load__']), sprintf('%0.5f sec', $GLOBALS['__widget_excute_elapsed__']), sprintf('%0.5f sec', $GLOBALS['__trans_content_elapsed__']) ) ) ), 'TABLE' ); } // display DB query history if((__DEBUG__ & 4) && $GLOBALS['__db_queries__']) { $queries_output = array(array('Result/'.PHP_EOL.'Elapsed time', 'Query ID', 'Query')); foreach($GLOBALS['__db_queries__'] as $query) { $queries_output[] = array($query['result'] . PHP_EOL . sprintf('%0.5f', $query['elapsed_time']), str_replace(_XE_PATH_, '', $query['called_file']) . PHP_EOL . $query['called_method'] . '()' . PHP_EOL . $query['query_id'], $query['query']); } $firephp->fb( array( 'DB Queries >>> ' . count($GLOBALS['__db_queries__']) . ' Queries, ' . sprintf('%0.5f sec', $GLOBALS['__db_elapsed_time__']), $queries_output ), 'TABLE' ); } // dislpay the file and HTML comments } else { $buff = array(); // display total execution time and Request/Response info if(__DEBUG__ & 2) { if(__DEBUG_PROTECT__ == 1 && __DEBUG_PROTECT_IP__ != $_SERVER['REMOTE_ADDR']) { return; } // Request/Response information $buff[] = "\n- Request/ Response info"; $buff[] = sprintf("\tRequest URI \t\t\t: %s:%s%s%s%s", $_SERVER['SERVER_NAME'], $_SERVER['SERVER_PORT'], $_SERVER['PHP_SELF'], $_SERVER['QUERY_STRING'] ? '?' : '', $_SERVER['QUERY_STRING']); $buff[] = sprintf("\tRequest method \t\t\t: %s", $_SERVER['REQUEST_METHOD']); $buff[] = sprintf("\tResponse method \t\t: %s", Context::getResponseMethod()); $buff[] = sprintf("\tResponse contents size\t: %d byte", $this->content_size); // total execution time $buff[] = sprintf("\n- Total elapsed time : %0.5f sec", $end - __StartTime__); $buff[] = sprintf("\tclass file load elapsed time \t: %0.5f sec", $GLOBALS['__elapsed_class_load__']); $buff[] = sprintf("\tTemplate compile elapsed time\t: %0.5f sec (%d called)", $GLOBALS['__template_elapsed__'], $GLOBALS['__TemplateHandlerCalled__']); $buff[] = sprintf("\tXmlParse compile elapsed time\t: %0.5f sec", $GLOBALS['__xmlparse_elapsed__']); $buff[] = sprintf("\tPHP elapsed time \t\t\t\t: %0.5f sec", $end - __StartTime__ - $GLOBALS['__template_elapsed__'] - $GLOBALS['__xmlparse_elapsed__'] - $GLOBALS['__db_elapsed_time__'] - $GLOBALS['__elapsed_class_load__']); $buff[] = sprintf("\tDB class elapsed time \t\t\t: %0.5f sec", $GLOBALS['__dbclass_elapsed_time__'] - $GLOBALS['__db_elapsed_time__']); // widget execution time $buff[] = sprintf("\tWidgets elapsed time \t\t\t: %0.5f sec", $GLOBALS['__widget_excute_elapsed__']); // layout execution time $buff[] = sprintf("\tLayout compile elapsed time \t: %0.5f sec", $GLOBALS['__layout_compile_elapsed__']); // Widgets, the editor component replacement time $buff[] = sprintf("\tTrans Content \t\t\t\t\t: %0.5f sec", $GLOBALS['__trans_content_elapsed__']); } // DB Logging if(__DEBUG__ & 4) { if(__DEBUG_PROTECT__ == 1 && __DEBUG_PROTECT_IP__ != $_SERVER['REMOTE_ADDR']) { return; } if($GLOBALS['__db_queries__']) { $buff[] = sprintf("\n- DB Queries : %d Queries. %0.5f sec", count($GLOBALS['__db_queries__']), $GLOBALS['__db_elapsed_time__']); $num = 0; foreach($GLOBALS['__db_queries__'] as $query) { if($query['result'] == 'Success') { $query_result = "Query Success"; } else { $query_result = sprintf("Query $s : %d\n\t\t\t %s", $query['result'], $query['errno'], $query['errstr']); } $buff[] = sprintf("\t%02d. %s\n\t\t%0.6f sec. %s.", ++$num, $query['query'], $query['elapsed_time'], $query_result); $buff[] = sprintf("\t\tConnection: %s.", $query['connection']); $buff[] = sprintf("\t\tQuery ID: %s", $query['query_id']); $buff[] = sprintf("\t\tCalled: %s. %s()", str_replace(_XE_PATH_, '', $query['called_file']), $query['called_method']); } } } // Output in HTML comments if($buff && __DEBUG_OUTPUT__ == 1 && Context::getResponseMethod() == 'HTML') { $buff = implode("\r\n", $buff); $buff = sprintf("[%s %s:%d]\r\n%s", date('Y-m-d H:i:s'), $file_name, $line_num, print_r($buff, true)); if(__DEBUG_PROTECT__ == 1 && __DEBUG_PROTECT_IP__ != $_SERVER['REMOTE_ADDR']) { $buff = 'The IP address is not allowed. Change the value of __DEBUG_PROTECT_IP__ into your IP address in config/config.user.inc.php or config/config.inc.php'; } return ""; } // Output to a file if($buff && __DEBUG_OUTPUT__ == 0) { $debug_file = _XE_PATH_ . 'files/_debug_message.php'; $buff = implode(PHP_EOL, $buff); $buff = sprintf("[%s]\n%s", date('Y-m-d H:i:s'), print_r($buff, true)); $buff = str_repeat('=', 80) . "\n" . $buff . "\n" . str_repeat('-', 80); $buff = "\n\n"; if (!@file_put_contents($debug_file, $buff, FILE_APPEND|LOCK_EX)) { return; } } } } /** * print a HTTP HEADER for XML, which is encoded in UTF-8 * @return void */ function _printXMLHeader() { header("Content-Type: text/xml; charset=UTF-8"); header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT"); header("Cache-Control: no-store, no-cache, must-revalidate"); header("Cache-Control: post-check=0, pre-check=0", false); header("Pragma: no-cache"); } /** * print a HTTP HEADER for HTML, which is encoded in UTF-8 * @return void */ function _printHTMLHeader() { header("Content-Type: text/html; charset=UTF-8"); header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT"); header("Cache-Control: no-store, no-cache, must-revalidate"); header("Cache-Control: post-check=0, pre-check=0", false); header("Pragma: no-cache"); } /** * print a HTTP HEADER for JSON, which is encoded in UTF-8 * @return void */ function _printJSONHeader() { header("Content-Type: text/html; charset=UTF-8"); header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT"); header("Cache-Control: no-store, no-cache, must-revalidate"); header("Cache-Control: post-check=0, pre-check=0", false); header("Pragma: no-cache"); } /** * print a HTTP HEADER for HTML, which is encoded in UTF-8 * @return void */ function _printHttpStatusCode($code) { $statusMessage = Context::get('http_status_message'); header("HTTP/1.0 $code $statusMessage"); } } /* End of file DisplayHandler.class.php */ /* Location: ./classes/display/DisplayHandler.class.php */