static function rescue_in_public($exception, $title, $request) { /* kill all buffered output */ while (count(@ob_list_handlers())) { @ob_end_clean(); } if (HALFMOON_ENV == "development" && ini_get("display_errors")) { require_once __DIR__ . "/rescue.phtml"; } else { /* production mode, try to handle gracefully */ if ($exception instanceof \HalfMoon\RoutingException || $exception instanceof \HalfMoon\UndefinedFunction || $exception instanceof \ActiveRecord\RecordNotFound) { Request::send_status_header(404); if (file_exists($f = HALFMOON_ROOT . "/public/404.html")) { Log::error("Rendering " . $f); require_once $f; } else { /* failsafe */ ?> <html> <head> <title>File Not Found</title> </head> <body> <h1>File Not Found</h1> The file you requested could not be found. An additional error occured while processing the error document. </body> </html> <?php } } elseif ($exception instanceof \HalfMoon\BadRequest) { Request::send_status_header(400); if (file_exists($f = HALFMOON_ROOT . "/public/400.html")) { Log::error("Rendering " . $f); require_once $f; } } elseif ($exception instanceof \HalfMoon\InvalidAuthenticityToken) { /* be like rails and give the odd 422 status */ Request::send_status_header(422); if (file_exists($f = HALFMOON_ROOT . "/public/422.html")) { Log::error("Rendering " . $f); require_once $f; } else { /* failsafe */ ?> <html> <head> <title>Change Rejected</title> </head> <body> <h1>Change Rejected</h1> The change you submitted was rejected due to a security problem. An additional error occured while processing the error document. </body> </html> <?php } } else { Request::send_status_header(500); if (file_exists($f = HALFMOON_ROOT . "/public/500.html")) { Log::error("Rendering " . $f); require_once $f; } else { /* failsafe */ ?> <html> <head> <title>Application Error</title> </head> <body> <h1>Application Error</h1> An internal application error occured while processing your request. Additionally, an error occured while processing the error document. </body> </html> <?php } } } static::$already_rescued = true; /* that's it, end of the line */ exit; }
public function process() { if (Config::log_level_at_least("short")) { register_shutdown_function(array("\\HalfMoon\\Request", "log_runtime"), $this); } try { ob_start(); Router::instance()->takeRouteForRequest($this); /* if we received an If-None-Match header from the client and our * generated etag matches it, send a not-modified header and no * data */ if (empty($this->redirected_to) && $this->etag_matches_inm()) { $headers = (array) headers_sent(); ob_end_clean(); foreach ($headers as $header) { header($header); } Request::send_status_header(304); } else { if (empty($this->redirected_to)) { $this->send_etag_header(); } if (ob_get_level()) { ob_end_flush(); } } } catch (\Exception $e) { /* rescue, log, notify (if necessary), exit */ if (class_exists("\\HalfMoon\\Rescuer")) { Rescuer::rescue_exception($e, $this); } else { throw $e; } } }
public function render($template, $vars = array()) { /* render(array("partial" => "somedir/file"), array("v" => $v)) */ if (!is_array($template)) { $template = array("action" => $template); } if (isset($template["status"])) { Request::send_status_header($template["status"]); } $collection = array(); if (isset($template["collection"]) && is_array($template["collection"])) { if (isset($template["as"])) { $collection = array($template["as"] => $template["collection"]); } else { /* figure out the type of things in the collection */ $cl = strtolower(get_class($template["collection"][0])); if ($cl != "") { $cl = \ActiveRecord\Utils::singularize($cl); } if ($cl == "") { throw new HalfMoonException("could not figure out type of " . "collection"); } $collection = array($cl => $template["collection"]); } } /* just render text with no layout */ if (is_array($template) && array_key_exists("text", $template)) { if (!$this->content_type_set()) { $this->content_type = "text/plain"; } if (Config::log_level_at_least("full")) { Log::info("Rendering text"); } print $template["text"]; } elseif (is_array($template) && array_key_exists("html", $template)) { if (!$this->content_type_set()) { $this->content_type = "text/html"; } if (Config::log_level_at_least("full")) { Log::info("Rendering HTML"); } print $template["html"]; } elseif (is_array($template) && array_key_exists("json", $template)) { if (!$this->content_type_set()) { $this->content_type = "application/json"; } if (Config::log_level_at_least("full")) { Log::info("Rendering json"); } /* there's no way to know if we were passed a json-encoded string, * or a string that needs to be encoded, so just encode everything * and hope the user figures it out */ print json_encode($template["json"]); } elseif (is_array($template) && array_key_exists("js", $template)) { if (!$this->content_type_set()) { $this->content_type = "text/javascript"; } if (Config::log_level_at_least("full")) { Log::info("Rendering javascript"); } print $template["js"]; } else { $tf = ""; /* render a partial template */ if (is_array($template) && isset($template["partial"])) { $tf = $template["partial"]; } elseif (is_array($template) && isset($template["action"])) { $tf = $template["action"]; } elseif (is_array($template)) { $tf = join("", array_values($template)); } else { $tf = $template; } if (substr($tf, 0, 1) == "/") { /* full path, just use it */ } elseif (strpos($tf, "/") !== false) { /* path relative to base view path */ $tf = HALFMOON_ROOT . "/views/" . $tf; } else { /* just a file in this controller's directory * (AdminSomethingController -> admin_something) */ $tf = $this->view_template_path() . $tf; } /* partial template files start with _ */ if (is_array($template) && isset($template["partial"])) { $tf = dirname($tf) . "/_" . basename($tf); } /* do the actual renders */ $filename = null; /* regular php/html */ if (file_exists($filename = $tf . ".phtml")) { if (!$this->content_type_set()) { $this->content_type = "text/html"; } } elseif (file_exists($filename = $tf . ".pxml")) { if (!$this->content_type_set()) { $this->content_type = "application/xml"; } } elseif (file_exists($filename = $tf . ".pjs")) { if (!$this->content_type_set()) { $this->content_type = "text/javascript"; } } else { throw new MissingTemplate("no template file " . $tf . ".p{html,xml,js}"); } if (count($collection)) { $ck = Utils::A(array_keys($collection), 0); /* it would be nice to be able to just read the template * into a string and eval() it each time to save on i/o, * but php won't let us catch parse errors properly and * there may be some other fallout */ foreach ($collection[$ck] as $cobj) { $vars[$ck] = $cobj; $this->_really_render_file($filename, $vars); } } else { $this->_really_render_file($filename, $vars); } } if (!$this->in_view) { if (is_array($template) && array_key_exists("layout", $template)) { $this::$layout = $template["layout"]; } elseif ($this->content_type_set() && $this->content_type != static::$DEFAULT_CONTENT_TYPE) { /* if we were called from the controller, we're not outputting * html, and no layout was explicitly specified, we probably * don't want a layout */ $this::$layout = false; } } $this->did_render = true; }