ignore */ return false; } $msg = "[$errno] $errstr ($errfile at $errline)"; // display messages only once foreach ($ffErrors as $m) { if ($m['message'] == $msg) { return true; } } switch ($errno) { case E_USER_ERROR: case E_ERROR: $type = 'error'; break; case E_USER_WARNING: case E_WARNING: $type = 'warning'; break; case E_USER_NOTICE: case E_NOTICE: $type = 'notice'; break; case E_STRICT: case E_USER_DEPRECATED: case E_DEPRECATED: $type = "strict"; break; default: $type = 'unknown'; break; } if (forge_get_config('sysdebug_backtraces')) { $msg .= "\n" . '
' .
		    htmlentities(debug_string_backtrace()) . "
"; } $ffErrors[] = array( 'type' => $type, 'message' => $msg, ); /* Don't execute PHP internal error handler */ return true; } // output buffer finaliser function function ffOutputHandler($buffer) { global $ffErrors, $sysdebug_enable, $sysdebug__aborted, $sysdebug_lazymode_on, $sysdebug_doframe, $gfcommon, $sysDTDs, $sysXMLNSs, $HTML; if ($sysdebug__aborted) { /* called from exception handler, discard */ $p = strrpos($buffer, "\r\n"); return (($p === false) ? "" : substr($buffer, $p + 2)); } if (!getenv('SERVER_SOFTWARE')) { return $buffer; } /* in case we’re aborted */ if (!$sysdebug_enable) { return $buffer; } /* if content-type != text/html* assume abortion */ if ($sysdebug_lazymode_on) { $thdr = 'content-type:'; $tstr = 'content-type: text/html'; foreach (headers_list() as $h) { if (strncasecmp($h, $thdr, strlen($thdr))) { continue; } if (strncasecmp($h, $tstr, strlen($tstr))) { /* application/something, maybe */ return $buffer; } } } /* stop calling ffErrorHandler */ restore_error_handler(); $dtdpath = $gfcommon . 'include/'; // this is, sadly, necessary (especially in ff-plugin-mediawiki) $pre_tag = "
";

	$divstring = "\n\n" . '\n
\n" . 'Click to toggle' . "\n
"; if (!($doctype = util_ifsetor($HTML->doctype))) { $doctype = 'transitional'; } if ($sysdebug_doframe) { $initial = '' . $sysDTDs[$doctype]['doctype'] . 'AJAX frame\n"; $bufferstrip = strlen($initial); $buffer = $initial . $buffer . ''; } /* cut off (hopefully only) at the end */ $buffer = rtrim($buffer); /* spaces, newlines, etc. */ $bufend = array(false, substr($buffer, -100)); if (substr($buffer, -strlen("")) != "") { $bufend[0] = true; $ffErrors[] = array( 'type' => "error", 'message' => htmlentities("does not end with tag"), ); $buffer = str_ireplace("", "", $buffer); } else { $buffer = substr($buffer, 0, -strlen("")); } $buffer = rtrim($buffer); /* spaces, newlines, etc. */ if (substr($buffer, -strlen("")) != "") { $bufend[0] = true; $ffErrors[] = array( 'type' => "error", 'message' => htmlentities("does not end with tag"), ); $buffer = str_ireplace("", "", $buffer); } else { $buffer = substr($buffer, 0, -strlen("")); } $buffer = rtrim($buffer); /* spaces, newlines, etc. */ if ($bufend[0]) { $ffErrors[] = array( 'type' => "info", 'message' => "The output has ended thus: " . htmlentities($bufend[1]), ); } /* append errors, if any */ $has_div = false; foreach ($ffErrors as $msg) { if (!$has_div) { $buffer .= $divstring; $has_div = true; } $buffer .= "\n
' . $msg['message'] . "
"; } /* generate buffer for checking */ $cbuf = str_ireplace('http://www.w3.org/TR/xhtml1/DTD/', 'file://' . $dtdpath, $buffer); if ($has_div) { $cbuf .= "\n
"; } $cbuf .= "\n\n"; /* now check XHTML validity… two means */ $valck = array(); $appsrc = false; if (forge_get_config('sysdebug_xmlstarlet')) { /* xmlstarlet (well-formed, DTD and DOCTYPE, encoding */ $dspec = array( 0 => array("pipe", "r"), 1 => array("pipe", "w"), 2 => array("pipe", "w"), ); $xmlstarlet = proc_open("xmlstarlet val -d " . escapeshellarg($dtdpath . $sysDTDs[$doctype]['dtdfile']) . " -e -", $dspec, $pipes); $rv = 0; if (is_resource($xmlstarlet)) { fwrite($pipes[0], $cbuf); fclose($pipes[0]); $sout = stream_get_contents($pipes[1]); $serr = stream_get_contents($pipes[2]); fclose($pipes[1]); fclose($pipes[2]); $rv = proc_close($xmlstarlet); /* work around Debian #627158 */ $serr = join("\n", preg_grep( '/^-:[0-9]*: Entity'." 'nbsp' ".'not defined$/', explode("\n", $serr), PREG_GREP_INVERT)); } else { $valck[] = array( 'msg' => "could not run xmlstarlet", ); } if ($rv) { $valck[] = array( 'msg' => "xmlstarlet found that this document is not valid (errorlevel $rv)!", 'extra' => $pre_tag . htmlspecialchars(trim($serr . "\n\n" . $sout)) . "
", 'type' => "error", ); $appsrc = true; } } $sysdebug_akelos = forge_get_config('sysdebug_akelos'); if ($sysdebug_akelos) { /* Akelos XHTML Validator (most other stuff) */ require_once($gfcommon . "include/XhtmlValidator.php"); $XhtmlValidator = new XhtmlValidator(); $sbuf = explode("validate($vbuf) === false) { //$vbuf = $XhtmlValidator->highlightErrors($sbuf[1]); $errs = ''; $valck[] = array( 'msg' => "Akelos XHTML Validator found some errors on this document!", 'extra' => $errs, 'type' => "error", ); $appsrc = true; } } /* append XHTML source code, if validation failed */ if ($appsrc) { if (!$sysdebug_akelos || $vbuf == $sbuf[1]) { $vbuf = "
  1. " . $pre_tag . join("
  2. \n
  3. " . $pre_tag, explode("\n", htmlentities(rtrim($cbuf)))) . "
"; } else { $vbuf = $pre_tag . htmlentities(rtrim($sbuf[0])) . "" . $vbuf; } $valck[] = array( 'msg' => "Since XHTML validation failed, here’s the checked document for you to look at:", 'extra' => $vbuf, 'type' => 'normal', ); } /* append error messages from the validators */ foreach ($valck as $msg) { if (!$has_div) { $buffer .= $divstring; $has_div = true; } if (!isset($msg['type']) || !$msg['type']) { $msg['type'] = 'unknown'; } $buffer .= "\n
' . $msg['msg']; if (isset($msg['extra'])) { $buffer .= "\n
" . $msg['extra'] . "
\n "; } $buffer .= "
"; } /* return final buffer */ if ($has_div) { $buffer .= "\n"; } if ($sysdebug_doframe) { return substr($buffer, $bufferstrip); } else { return $buffer . "\n\n"; } } // exception handler function function ffExceptionHandler($e) { global $sysdebug__aborted; /* drop output buffers and error handler */ $sysdebug__aborted = true; while (ob_get_length() > 0 && ob_end_clean()) { /* loop */ ; } restore_error_handler(); /* issue exception information */ header('HTTP/1.0 500 Exception not handled'); header('Content-type: text/plain'); echo "\r\nUncaught exception:\n" . str_replace("\r", "", $e->getMessage() . "\n\nBacktrace:\n" . $e->getTraceAsString()) . "\n"; exit(1); } if (forge_get_config('sysdebug_phphandler')) { // set to the user defined error handler set_error_handler("ffErrorHandler"); } set_exception_handler("ffExceptionHandler"); $sysdebug_lazymode_on = false; $sysdebug_doframe = false; $sysdebug__aborted = false; ob_start("ffOutputHandler", 0, false); function sysdebug_ajaxbody($enable=true) { global $sysdebug_doframe; $sysdebug_doframe = $enable; } function sysdebug_off($hdr=false, $replace=true, $resp=false) { global $ffErrors, $sysdebug_enable; if ($sysdebug_enable) { $sysdebug_enable = false; $buf = @ob_get_flush(); if ($buf === false) { $buf = ""; } /* if we had any old errors, log them */ $olderrors = ""; foreach ($ffErrors as $msg) { $olderrors .= "\n(" . $msg['type'] . ") " . $msg['message']; } if ($olderrors) { if (!forge_get_config('sysdebug_backtraces')) { $olderrors .= "\n" . debug_string_backtrace(); } $olderrors = rtrim($olderrors); $pfx = ""; foreach (explode("\n", "sysdebug_off: previous errors found:" . $olderrors) as $olderrorline) { error_log($pfx . $olderrorline); /* followup lines get indented */ $pfx = ">>> "; } } } else { $buf = false; } if ($hdr !== false) { if ($resp === false) { header($hdr, $replace); } else { header($hdr, $replace, $resp); } } return $buf; } function sysdebug_lazymode($enable) { global $sysdebug_lazymode_on; $sysdebug_lazymode_on = $enable ? true : false; } function ffDebug($type, $intro, $pretext=false) { global $ffErrors; if (!$type) { $type = 'debug'; } $text = ""; if ($intro) { $text .= htmlentities($intro); } if ($pretext) { $text .= '
' .
		    htmlentities($pretext) . "
"; } $ffErrors[] = array( 'type' => $type, 'message' => $text, ); }