Hash: $hash" : ""; //'.$h_hash.' if (PHP_SAPI === 'cli' || PHP_SAPI == 'phpdbg') { print("Trace: "); $t = array_reverse($e->getTrace()); foreach ($t as $n => $f) { $c = $f['class'] ?? ''; $t = $f['type'] ?? ''; $a = implode(", ", array_map("stringer", $f['args'])); print("$n: {$f['file']}({$f['line']}): {$c}{$t}{$f['function']}({$a})\n"); } print("Message: $message\n"); if (isset($e->query)) { print("Query: {$e->query}\n"); } print("Version: $version (on $phpver)\n"); } else { $q = (!isset($e->query) || is_null($e->query)) ? "" : "
Query: " . html_escape($e->query); header("HTTP/1.0 500 Internal Error"); echo '
Message: '.html_escape($message).' '.$q.'
Version: '.$version.' (on '.$phpver.') '; } } /** * Turn ^^ into ^ and ^s into / * * Necessary because various servers and various clients * think that / is special... */ function _decaret(string $str): string { $out = ""; $length = strlen($str); for ($i=0; $i<$length; $i++) { if ($str[$i] == "^") { $i++; if ($str[$i] == "^") { $out .= "^"; } if ($str[$i] == "s") { $out .= "/"; } if ($str[$i] == "b") { $out .= "\\"; } } else { $out .= $str[$i]; } } return $out; } function _get_user(): User { global $config, $page; $my_user = null; if ($page->get_cookie("user") && $page->get_cookie("session")) { $tmp_user = User::by_session($page->get_cookie("user"), $page->get_cookie("session")); if (!is_null($tmp_user)) { $my_user = $tmp_user; } } if (is_null($my_user)) { $my_user = User::by_id($config->get_int("anon_id", 0)); } assert(!is_null($my_user)); return $my_user; } function _get_query(): string { return (@$_POST["q"]?:@$_GET["q"])?:"/"; } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * Code coverage * \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ function _start_coverage(): void { if (function_exists("xdebug_start_code_coverage")) { #xdebug_start_code_coverage(XDEBUG_CC_UNUSED|XDEBUG_CC_DEAD_CODE); xdebug_start_code_coverage(XDEBUG_CC_UNUSED); } } function _end_coverage(): void { if (function_exists("xdebug_get_code_coverage")) { // Absolute path is necessary because working directory // inside register_shutdown_function is unpredictable. $absolute_path = dirname(dirname(__FILE__)) . "/data/coverage"; if (!file_exists($absolute_path)) { mkdir($absolute_path); } $n = 0; $t = time(); while (file_exists("$absolute_path/$t.$n.log")) { $n++; } file_put_contents("$absolute_path/$t.$n.log", gzdeflate(serialize(xdebug_get_code_coverage()))); } } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ * HTML Generation * \* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /** * Give a HTML string which shows an IP (if the user is allowed to see IPs), * and a link to ban that IP (if the user is allowed to ban IPs) * * FIXME: also check that IP ban ext is installed */ function show_ip(string $ip, string $ban_reason): string { global $user; $u_reason = url_escape($ban_reason); $u_end = url_escape("+1 week"); $ban = $user->can(Permissions::BAN_IP) ? ", Ban" : ""; $ip = $user->can(Permissions::VIEW_IP) ? $ip.$ban : ""; return $ip; } /** * Make a form tag with relevant auth token and stuff */ function make_form(string $target, string $method="POST", bool $multipart=false, string $form_id="", string $onsubmit=""): string { global $user; if ($method == "GET") { $link = html_escape($target); $target = make_link($target); $extra_inputs = ""; } else { $extra_inputs = $user->get_auth_html(); } $extra = empty($form_id) ? '' : 'id="'. $form_id .'"'; if ($multipart) { $extra .= " enctype='multipart/form-data'"; } if ($onsubmit) { $extra .= ' onsubmit="'.$onsubmit.'"'; } return '